Merge branch 'dev' of gitlab.cri.epita.fr:guillem.george/42sh into dev

This commit is contained in:
Jean Herail 2026-01-22 16:49:12 +01:00
commit f2e44d93f4
14 changed files with 89 additions and 46 deletions

View file

@ -18,8 +18,8 @@ bin_PROGRAMS = 42sh
parser/libparser.a \
lexer/liblexer.a \
io_backend/libio_backend.a \
expansion/libexpansion.a \
execution/libexecution.a \
expansion/libexpansion.a \
utils/libutils.a
# ================ TESTS ================

View file

@ -9,7 +9,9 @@
#include <sys/wait.h>
#include <unistd.h>
#include "../expansion/expansion.h"
#include "../utils/ast/ast.h"
#include "../utils/hash_map/hash_map.h"
// --- Helpers ---
@ -205,7 +207,7 @@ static int exec_command(struct ast_command *command)
* @param ast The AST to execute
* @return int The exit status of the last executed command.
*/
int execution(struct ast *ast)
int execution(struct ast *ast, struct hash_map *vars)
{
if (!ast)
{
@ -214,23 +216,26 @@ int execution(struct ast *ast)
switch (ast->type)
{
case AST_VOID:
case AST_END: {
return 0;
}
case AST_CMD: {
struct ast_command *command = ast_get_command(ast);
if (!expand(command, vars))
fprintf(stderr, "Error: Variable expansion failed\n");
return exec_command(command);
}
case AST_IF: {
struct ast_if *if_node = ast_get_if(ast);
int cond = execution(if_node->condition);
int cond = execution(if_node->condition, vars);
if (cond == 0) // True
{
return execution(if_node->then_clause);
return execution(if_node->then_clause, vars);
}
else // False
{
return execution(if_node->else_clause);
return execution(if_node->else_clause, vars);
}
}
case AST_LIST: {
@ -240,25 +245,25 @@ int execution(struct ast *ast)
while (cur)
{
struct ast *child = (struct ast *)cur->data;
ret = execution(child);
ret = execution(child, vars);
cur = cur->next;
}
return ret;
}
case AST_AND_OR: {
struct ast_and_or *ao_node = ast_get_and_or(ast);
int left_ret = execution(ao_node->left);
int left_ret = execution(ao_node->left, vars);
if (ao_node->type == AST_AND_OR_TYPE_AND)
{
if (left_ret == 0)
return execution(ao_node->right);
return execution(ao_node->right, vars);
return left_ret;
}
else // OR
{
if (left_ret != 0)
return execution(ao_node->right);
return execution(ao_node->right, vars);
return left_ret;
}
}
@ -335,7 +340,7 @@ int execution(struct ast *ast)
close(new_fd);
}
int ret = execution(redir->child);
int ret = execution(redir->child, vars);
if (saved_fd != -1)
{

View file

@ -3,6 +3,7 @@
#include "../utils/ast/ast.h"
#include "../utils/lists/lists.h"
#include "../utils/hash_map/hash_map.h"
/**
* @brief Execute the AST
@ -10,6 +11,6 @@
* @param ast Pointer to the AST structure
* @return int Execution status code of the last command
*/
int execution(struct ast *ast);
int execution(struct ast *ast, struct hash_map *vars);
#endif /* ! EXECUTION_H */

View file

@ -115,11 +115,10 @@ static bool expand_var(char **str, size_t pos, const struct hash_map *vars)
return false;
}
struct ast_command *expand(struct ast_command *command,
const struct hash_map *vars)
bool expand(struct ast_command *command, const struct hash_map *vars)
{
if (command == NULL)
return NULL;
return false;
char *str;
size_t len;
@ -150,7 +149,7 @@ struct ast_command *expand(struct ast_command *command,
// variable expansion
bool r = expand_var(&str, i, vars);
if (r == false || str == NULL)
return NULL;
return false;
i--; // -1 because loop will increment i
}
@ -160,7 +159,7 @@ struct ast_command *expand(struct ast_command *command,
{
// error: quote not closed
fprintf(stderr, "Error: quote not closed in string: %s\n", str);
return NULL;
return false;
}
if (len != strlen(str))
@ -169,12 +168,12 @@ struct ast_command *expand(struct ast_command *command,
if (new_str == NULL)
{
// error: realloc fail
return NULL;
return false;
}
l->data = new_str;
}
l = l->next;
}
return command;
return true;
}

View file

@ -1,6 +1,7 @@
#ifndef EXPANSION_H
#define EXPANSION_H
#include <stdbool.h>
#include <stddef.h>
#include "../utils/hash_map/hash_map.h"
@ -20,7 +21,6 @@ size_t parse_var_name(char *str, char **res);
* @param vars The hash map containing variables.
* @return A new AST command with variables expanded, or NULL on error.
*/
struct ast_command *expand(struct ast_command *command,
const struct hash_map *vars);
bool expand(struct ast_command *command, const struct hash_map *vars);
#endif /* ! EXPANSION_H */

View file

@ -85,7 +85,11 @@ ssize_t stream_read(char **stream)
if (nread == -1)
{
state = IOB_STATE_FINISHED;
return 0;
// MAGNIFICO
// malloc(1);
*stream_buf = EOF;
*stream = stream_buf;
return 1;
}
else if (nread < 0)
state = IOB_STATE_ERROR;
@ -99,7 +103,7 @@ ssize_t stream_read(char **stream)
*stream = context.args;
size_t len = strlen(context.args);
context.args[len] = EOF;
return len;
return len + 1;
}
else
{

View file

@ -19,7 +19,7 @@ static bool is_special_char(char c)
if (c == EOF)
return true;
char special_chars[] = "\n'\"`;#|&\\$(){}<>*";
char special_chars[] = "\n'\"`;#|&\\(){}<>*";
return strchr(special_chars, c) != NULL;
}

View file

@ -45,9 +45,6 @@ static void set_token_spechar(struct token *tok, char *begin, ssize_t size)
case '\\':
tok->type = TOKEN_BACKSLASH;
break;
case '$':
tok->type = TOKEN_DOLLAR;
break;
case '(':
tok->type = TOKEN_LEFT_PAREN;
break;

View file

@ -84,8 +84,14 @@ int main(int argc, char **argv)
// Main parse-execute loop
while (command_ast != NULL && command_ast->type != AST_END)
{
// Execute AST
return_code = execution(command_ast);
if (command_ast->type != AST_VOID)
{
// Execute AST
return_code = execution(command_ast, vars);
// set $? variable
set_var_int(vars, "?", return_code);
}
ast_free(&command_ast);

View file

@ -14,7 +14,6 @@
// === Static functions
/* Returns true if c is a command terminator, false otherwise
*/
static bool isterminator(struct token *token)
{
if (token == NULL)
@ -31,6 +30,8 @@ static bool isterminator(struct token *token)
}
}
*/
/* @brief: returns true if token is an end of list indicator.
* @warning: not used
*/
@ -77,8 +78,8 @@ struct ast *parse_list(struct lexer_context *ctx)
while (token->type == TOKEN_SEMICOLON)
{
token = POP_TOKEN();
if (!isterminator(token)) // Follow(list)
{
// if (!isterminator(token)) // Follow(list)
// {
current_node = parse_and_or(ctx);
if (current_node == NULL)
{
@ -87,8 +88,8 @@ struct ast *parse_list(struct lexer_context *ctx)
return NULL;
}
result_list = list_append(result_list, current_node);
token = PEEK_TOKEN();
}
// }
token = PEEK_TOKEN();
}
// result_list = list_append(result_list, current_node);

View file

@ -1,6 +1,7 @@
#include "string_utils.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -42,3 +43,11 @@ char *insert_into(char *dest, const char *src, size_t pos, size_t len)
return realloc(dest, new_len + 1);
return dest;
}
void int_to_str(int value, char *buffer)
{
if (buffer == NULL)
return;
snprintf(buffer, 11, "%d", value);
}

View file

@ -18,4 +18,13 @@ char *trim_blank_left(char *str);
*/
char *insert_into(char *dest, const char *src, size_t pos, size_t len);
/**
* Converts an integer to its string representation.
* @param value The integer value to convert.
* @param buffer A character array where the resulting string will be stored.
* The buffer must be at least 11 bytes long to accommodate the largest
* 32-bit integer and the null terminator.
*/
void int_to_str(int value, char *buffer);
#endif /* STRING_UTILS_H */

View file

@ -9,23 +9,27 @@
#include <unistd.h>
#include "../hash_map/hash_map.h"
#include "../string_utils/string_utils.h"
#define VARS_INITIAL_SIZE 16
struct hash_map *vars_init(void)
{
return hash_map_init(VARS_INITIAL_SIZE);
}
void vars_default(struct hash_map *vars)
static void vars_default(struct hash_map *vars)
{
set_var_copy(vars, "?", "0");
pid_t pid = getpid();
char pid_str[20];
snprintf(pid_str, sizeof(pid_str), "%d", pid);
char pid_str[11];
int_to_str(pid, pid_str);
set_var_copy(vars, "$", pid_str);
}
struct hash_map *vars_init(void)
{
struct hash_map *vars = hash_map_init(VARS_INITIAL_SIZE);
if (vars != NULL)
vars_default(vars);
return vars;
}
short short_random(void)
{
static bool seeded = false;
@ -68,3 +72,10 @@ bool set_var_copy(struct hash_map *vars, const char *key, const char *value)
free(value_copy);
return res;
}
bool set_var_int(struct hash_map *vars, const char *key, int value)
{
char value_str[11];
int_to_str(value, value_str);
return set_var_copy(vars, key, value_str);
}

View file

@ -10,11 +10,6 @@
*/
struct hash_map *vars_init(void);
/**
* Set default variables.
*/
void vars_default(struct hash_map *vars);
/**
* Generate a random short integer (16 bits positive [0-32767]).
*/
@ -45,4 +40,10 @@ bool set_var(struct hash_map *vars, const char *key, const char *value,
*/
bool set_var_copy(struct hash_map *vars, const char *key, const char *value);
/**
* Set the value of a variable to an integer. Behavior is similar to
* set_var_copy.
*/
bool set_var_int(struct hash_map *vars, const char *key, int value);
#endif /* ! VARS_H */