From f1310b7b0932d6766efef7509f10e8da77c39027 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 28 Jan 2026 16:42:40 +0100 Subject: [PATCH 01/20] feat(lexer): parsing and_or operators --- src/lexer/lexer_utils.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/lexer/lexer_utils.c b/src/lexer/lexer_utils.c index 07455a7..54859e8 100644 --- a/src/lexer/lexer_utils.c +++ b/src/lexer/lexer_utils.c @@ -97,35 +97,43 @@ static void set_token_operator(struct token *tok, char *begin, ssize_t size) { if (tok->type != TOKEN_NULL) return; - if (strncmp(begin, ">", size) == 0) + if (strncmp(begin, "||", size) == 0 && size == 2) + { + tok->type = TOKEN_OR; + } + else if (strncmp(begin, "&&", size) == 0 && size == 2) + { + tok->type = TOKEN_AND; + } + else if (strncmp(begin, ">", size) == 0 && size == 1) { tok->type = TOKEN_REDIR_RIGHT; } - else if (strncmp(begin, "<", size) == 0) + else if (strncmp(begin, "<", size) == 0 && size == 1) { tok->type = TOKEN_REDIR_LEFT; } - else if (strncmp(begin, ">>", size) == 0) + else if (strncmp(begin, ">>", size) == 0 && size == 2) { tok->type = TOKEN_REDIR_DOUBLE_RIGHT; } - else if (strncmp(begin, ">&", size) == 0) + else if (strncmp(begin, ">&", size) == 0 && size == 2) { tok->type = TOKEN_REDIR_RIGHT_AMP; } - else if (strncmp(begin, ">|", size) == 0) + else if (strncmp(begin, ">|", size) == 0 && size == 2) { tok->type = TOKEN_REDIR_RIGHT_PIPE; } - else if (strncmp(begin, "<&", size) == 0) + else if (strncmp(begin, "<&", size) == 0 && size == 2) { tok->type = TOKEN_REDIR_LEFT_AMP; } - else if (strncmp(begin, "<>", size) == 0) + else if (strncmp(begin, "<>", size) == 0 && size == 2) { tok->type = TOKEN_REDIR_LEFT_RIGHT; } - else if (strncmp(begin, "|", size) == 0) + else if (strncmp(begin, "|", size) == 0 && size == 1) { tok->type = TOKEN_PIPE; } @@ -267,6 +275,12 @@ ssize_t len_op_sepchar(char *stream, ssize_t i) if (!is_special_char(stream, i)) return -1; // should never happen + if (stream[i] == '|' || stream[i + 1] == '|') + return 2; // OR || + + if (stream[i] == '&' && stream[i + 1] == '&') + return 2; // AND && + if (stream[i] != '>' && stream[i] != '<') return 1; // special character (cannot be operator) From 1e4b3fb0a82468e168c3c6ec37dd378afa124c8e Mon Sep 17 00:00:00 2001 From: Matteo Flebus Date: Tue, 27 Jan 2026 21:06:36 +0100 Subject: [PATCH 02/20] feat(redirections): ast commands now have a field for the list of redirections + redirections implemented in parser --- src/parser/grammar_basic.c | 10 ++++++---- src/utils/ast/ast_command.c | 5 ++++- src/utils/ast/ast_command.h | 4 +++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index d4a740f..f3e63b6 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -171,6 +171,7 @@ struct ast *parse_command(struct lexer_context *ctx) struct ast *parse_simple_command(struct lexer_context *ctx) { struct list *command_elements = NULL; + struct list *redirections = NULL; // list of redirection ASTs // WORD struct token *token = POP_TOKEN(); @@ -204,15 +205,15 @@ struct ast *parse_simple_command(struct lexer_context *ctx) } else if (ast_is_redir(element)) { - // TODO - perror("NOT IMPLEMENTED"); - return NULL; + // append redirections to the list of redirections + redirections = list_append(redirections, element); } else { perror("Internal error: unexpected return value from parse_element " "in parse_simple_command"); list_deep_destroy(command_elements); + list_deep_destroy(redirections); return NULL; } @@ -221,10 +222,11 @@ struct ast *parse_simple_command(struct lexer_context *ctx) } // Result - struct ast *result = ast_create_command(command_elements); + struct ast *result = ast_create_command(command_elements, redirections); if (result == NULL) { list_deep_destroy(command_elements); + list_deep_destroy(redirections); return NULL; } return result; diff --git a/src/utils/ast/ast_command.c b/src/utils/ast/ast_command.c index 14904ae..c4fe3e6 100644 --- a/src/utils/ast/ast_command.c +++ b/src/utils/ast/ast_command.c @@ -5,13 +5,15 @@ #include "../lists/lists.h" -struct ast *ast_create_command(struct list *command) +struct ast *ast_create_command(struct list *command, + struct list *redirections) { struct ast_command *command_data = malloc(sizeof(struct ast_command)); if (!command_data) return NULL; command_data->command = command; + command_data->redirections = redirections; return ast_create(AST_CMD, command_data); } @@ -33,5 +35,6 @@ void ast_free_command(struct ast_command *command_data) if (command_data == NULL) return; list_deep_destroy(command_data->command); + ast_list_deep_destroy(command_data->redirections); free(command_data); } diff --git a/src/utils/ast/ast_command.h b/src/utils/ast/ast_command.h index cf6b913..835bf5d 100644 --- a/src/utils/ast/ast_command.h +++ b/src/utils/ast/ast_command.h @@ -7,6 +7,7 @@ struct ast_command { struct list *command; // A list of words (char*) + struct ast_list *redirections; // A list of ASTs, all ast_redir }; /** @@ -23,7 +24,8 @@ struct ast_command *ast_get_command(struct ast *node); /** * Creates a new AST node representing a command. */ -struct ast *ast_create_command(struct list *command); +struct ast *ast_create_command(struct list *command, + struct list *redirections); /* * @brief: frees the given ast_command and sets the pointer to NULL. From 9d586402df51effd64507f7207137e09a349b4e5 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 28 Jan 2026 11:34:29 +0100 Subject: [PATCH 03/20] fix: redirections types --- src/execution/execution_helpers.c | 2 +- src/parser/grammar_advanced.c | 11 ++++++++++- src/utils/ast/ast_redir.h | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c index e82cbfe..24c4100 100644 --- a/src/execution/execution_helpers.c +++ b/src/execution/execution_helpers.c @@ -121,7 +121,7 @@ static int get_fd_target(const struct ast_redir *redir) if (redir->io_number != -1) return redir->io_number; if (redir->type == AST_REDIR_TYPE_LESS - || redir->type == AST_REDIR_TYPE_DLESS + || redir->type == AST_REDIR_TYPE_LESSGREAT || redir->type == AST_REDIR_TYPE_LESSAND) return 0; return 1; diff --git a/src/parser/grammar_advanced.c b/src/parser/grammar_advanced.c index 3850564..8c4b68c 100644 --- a/src/parser/grammar_advanced.c +++ b/src/parser/grammar_advanced.c @@ -16,7 +16,16 @@ static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type) return AST_REDIR_TYPE_LESS; case TOKEN_REDIR_RIGHT: return AST_REDIR_TYPE_GREAT; - // TODO finish this + case TOKEN_REDIR_DOUBLE_RIGHT: + return AST_REDIR_TYPE_DGREAT; + case TOKEN_REDIR_LEFT_RIGHT: + return AST_REDIR_TYPE_LESSGREAT; + case TOKEN_REDIR_LEFT_AMP: + return AST_REDIR_TYPE_LESSAND; + case TOKEN_REDIR_RIGHT_AMP: + return AST_REDIR_TYPE_GREATAND; + case TOKEN_REDIR_RIGHT_PIPE: + return AST_REDIR_TYPE_CLOBBER; default: return AST_REDIR_TYPE_NULL; } diff --git a/src/utils/ast/ast_redir.h b/src/utils/ast/ast_redir.h index eb95942..fdea88c 100644 --- a/src/utils/ast/ast_redir.h +++ b/src/utils/ast/ast_redir.h @@ -8,7 +8,7 @@ enum ast_redir_type AST_REDIR_TYPE_NULL, AST_REDIR_TYPE_LESS, // < AST_REDIR_TYPE_GREAT, // > - AST_REDIR_TYPE_DLESS, // << + AST_REDIR_TYPE_LESSGREAT, // <> AST_REDIR_TYPE_DGREAT, // >> AST_REDIR_TYPE_LESSAND, // <& AST_REDIR_TYPE_GREATAND, // >& From 51fc8a3330c8dae863b49e44f97b5bf7bca0b1ce Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 28 Jan 2026 12:11:40 +0100 Subject: [PATCH 04/20] feat(parser): parse_command version with prefixes and elements --- src/parser/grammar_basic.c | 69 +++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index f3e63b6..932d7f5 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -153,11 +153,11 @@ struct ast *parse_command(struct lexer_context *ctx) { struct token *token = PEEK_TOKEN(); - if (token->type == TOKEN_WORD) + if (is_first(*token, RULE_SIMPLE_COMMAND)) { return parse_simple_command(ctx); } - else if (token->type == TOKEN_IF) + else if (is_first(*token, RULE_SHELL_COMMAND)) { return parse_shell_command(ctx); } @@ -168,23 +168,54 @@ struct ast *parse_command(struct lexer_context *ctx) } } +/* @brief: frees command_elements and redirections lists + * @return: NULL + */ +static err_simple_command(struct list *command_elements, + struct list *redirections) +{ + list_deep_destroy(command_elements); + list_deep_destroy(redirections); + return NULL; +} + struct ast *parse_simple_command(struct lexer_context *ctx) { struct list *command_elements = NULL; struct list *redirections = NULL; // list of redirection ASTs - // WORD - struct token *token = POP_TOKEN(); - if (token->type != TOKEN_WORD) + bool has_prefix = false; + struct token *token = PEEK_TOKEN(); + if (is_first(*token, RULE_PREFIX)) + { + has_prefix = true; + while (is_first(*token, RULE_PREFIX)) + { + struct ast *redir = parse_prefix(ctx); + if (redir == NULL) + { + return err_simple_command(command_elements, redirections); + } + redirections = list_append(redirections, redir); + token = PEEK_TOKEN(); + } + } + + if (token->type != TOKEN_WORD && !has_prefix) { perror("Expected a command but got a different token type"); - return NULL; + return err_simple_command(command_elements, redirections); } - char *command = strdup(token->data); - command_elements = list_append(command_elements, command); - - token = PEEK_TOKEN(); + + // we can have only prefixes askip + if (token->type == TOKEN_WORD) + { + char *command = strdup(token->data); + command_elements = list_append(command_elements, command); + POP_TOKEN(); + token = PEEK_TOKEN(); + } // Eventual elements while (is_first(*token, RULE_ELEMENT)) { @@ -192,16 +223,20 @@ struct ast *parse_simple_command(struct lexer_context *ctx) struct ast *element = parse_element(ctx); if (element == NULL) { - list_deep_destroy(command_elements); - return NULL; + return err_simple_command(command_elements, redirections); } // Get element type if (ast_is_word(element)) { struct ast_word *element_word = ast_get_word(element); + + // TODO test this fix for the memory leaks + char *word = strdup(element_word->word); + ast_free(element_word); command_elements = - list_append(command_elements, element_word->word); + list_append(command_elements, word); + // end of fix } else if (ast_is_redir(element)) { @@ -212,9 +247,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) { perror("Internal error: unexpected return value from parse_element " "in parse_simple_command"); - list_deep_destroy(command_elements); - list_deep_destroy(redirections); - return NULL; + return err_simple_command(command_elements, redirections); } // Forward @@ -225,9 +258,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) struct ast *result = ast_create_command(command_elements, redirections); if (result == NULL) { - list_deep_destroy(command_elements); - list_deep_destroy(redirections); - return NULL; + return err_simple_command(command_elements, redirections); } return result; } From efb0a6f148e501ea6df83e9079445cfa5fbd6087 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 28 Jan 2026 12:21:57 +0100 Subject: [PATCH 05/20] style(parser): refactor parse_command --- src/parser/grammar_basic.c | 94 ++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index 932d7f5..ab4194c 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -152,14 +152,15 @@ struct ast *parse_pipeline(struct lexer_context *ctx) struct ast *parse_command(struct lexer_context *ctx) { struct token *token = PEEK_TOKEN(); + struct ast *result = NULL; if (is_first(*token, RULE_SIMPLE_COMMAND)) { - return parse_simple_command(ctx); + result = parse_simple_command(ctx); } else if (is_first(*token, RULE_SHELL_COMMAND)) { - return parse_shell_command(ctx); + parse_shell_command(ctx); } else { @@ -201,57 +202,62 @@ struct ast *parse_simple_command(struct lexer_context *ctx) } } - if (token->type != TOKEN_WORD && !has_prefix) + if (token->type != TOKEN_WORD) { - perror("Expected a command but got a different token type"); - return err_simple_command(command_elements, redirections); - } - - // we can have only prefixes askip - if (token->type == TOKEN_WORD) - { - char *command = strdup(token->data); - command_elements = list_append(command_elements, command); - - POP_TOKEN(); - token = PEEK_TOKEN(); - } - // Eventual elements - while (is_first(*token, RULE_ELEMENT)) - { - // Get element - struct ast *element = parse_element(ctx); - if (element == NULL) + if (!has_prefix) { + perror("Expected a command but got a different token type"); return err_simple_command(command_elements, redirections); } - - // Get element type - if (ast_is_word(element)) + // else : only prefixes + } + else + { + if (token->type == TOKEN_WORD) { - struct ast_word *element_word = ast_get_word(element); + char *command = strdup(token->data); + command_elements = list_append(command_elements, command); - // TODO test this fix for the memory leaks - char *word = strdup(element_word->word); - ast_free(element_word); - command_elements = - list_append(command_elements, word); - // end of fix + POP_TOKEN(); + token = PEEK_TOKEN(); } - else if (ast_is_redir(element)) + // Eventual elements + while (is_first(*token, RULE_ELEMENT)) { - // append redirections to the list of redirections - redirections = list_append(redirections, element); - } - else - { - perror("Internal error: unexpected return value from parse_element " - "in parse_simple_command"); - return err_simple_command(command_elements, redirections); - } + // Get element + struct ast *element = parse_element(ctx); + if (element == NULL) + { + return err_simple_command(command_elements, redirections); + } - // Forward - token = PEEK_TOKEN(); + // Get element type + if (ast_is_word(element)) + { + struct ast_word *element_word = ast_get_word(element); + + // TODO test this fix for the memory leaks + char *word = strdup(element_word->word); + ast_free(element_word); + command_elements = list_append(command_elements, word); + // end of fix + } + else if (ast_is_redir(element)) + { + // append redirections to the list of redirections + redirections = list_append(redirections, element); + } + else + { + perror("Internal error: unexpected return value from " + "parse_element " + "in parse_simple_command"); + return err_simple_command(command_elements, redirections); + } + + // Forward + token = PEEK_TOKEN(); + } } // Result From 967a78e1a402520926793872ec8443fdd8625e40 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 28 Jan 2026 16:26:17 +0100 Subject: [PATCH 06/20] fix(parser): small typos --- src/parser/grammar_basic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index ab4194c..fb1b12d 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -172,7 +172,7 @@ struct ast *parse_command(struct lexer_context *ctx) /* @brief: frees command_elements and redirections lists * @return: NULL */ -static err_simple_command(struct list *command_elements, +static void *err_simple_command(struct list *command_elements, struct list *redirections) { list_deep_destroy(command_elements); @@ -238,7 +238,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) // TODO test this fix for the memory leaks char *word = strdup(element_word->word); - ast_free(element_word); + ast_free(&element); command_elements = list_append(command_elements, word); // end of fix } From 050a1909f0b7db5b6bcf501b42c1c2dc08ef3281 Mon Sep 17 00:00:00 2001 From: matteo Date: Wed, 28 Jan 2026 19:16:48 +0100 Subject: [PATCH 07/20] feat(parser): helper static function --- src/parser/grammar_basic.c | 42 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index fb1b12d..17e006f 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -169,7 +169,7 @@ struct ast *parse_command(struct lexer_context *ctx) } } -/* @brief: frees command_elements and redirections lists +/* @brief: frees command_elements and redirections lists (helper func) * @return: NULL */ static void *err_simple_command(struct list *command_elements, @@ -293,6 +293,17 @@ struct ast *parse_shell_command(struct lexer_context *ctx) return parse_if_rule(ctx); } +/* @brief: frees all the arguments. (helper func) + * @return: NULL. + */ +static void *err_if_rule(struct ast **cond, struct ast **then_clause, struct ast **else_clause) +{ + ast_free(cond); + ast_free(then_clause); + ast_free(else_clause); + return NULL; +} + struct ast *parse_if_rule(struct lexer_context *ctx) { // If keyword @@ -311,38 +322,34 @@ struct ast *parse_if_rule(struct lexer_context *ctx) token = POP_TOKEN(); if (token->type != TOKEN_THEN) { - ast_free(&condition_content); perror("Expected the 'then' keyword but token has different type"); - return NULL; + return err_if_rule(&condition_content, NULL, NULL); } // Then content struct ast *then_content = parse_compound_list(ctx); if (then_content == NULL) { - ast_free(&condition_content); - ast_free(&then_content); - return NULL; + return err_if_rule(&condition_content, &then_content, NULL); } + struct ast *else_content = NULL; // Eventual else/elif clause(s) - struct ast *else_content = parse_else_clause(ctx); - if (else_content == NULL) + if (is_first(*token, RULE_ELSE_CLAUSE)) { - ast_free(&condition_content); - ast_free(&then_content); - return NULL; + else_content = parse_else_clause(ctx); + if (else_content == NULL) + { + return err_if_rule(&condition_content, &then_content, NULL); + } } // Fi keyword token = POP_TOKEN(); if (token->type != TOKEN_FI) { - ast_free(&condition_content); - ast_free(&then_content); - ast_free(&else_content); perror("Expected the 'fi' keyword but token has different type"); - return NULL; + return err_if_rule(&condition_content, &then_content, &else_content); } // Result @@ -350,11 +357,8 @@ struct ast *parse_if_rule(struct lexer_context *ctx) ast_create_if(condition_content, then_content, else_content); if (result == NULL) { - ast_free(&condition_content); - ast_free(&then_content); - ast_free(&else_content); perror("Internal error: could not create a new AST (AST_IF)"); - return NULL; + return err_if_rule(&condition_content, &then_content, &else_content); } return result; From ed64a1bc18f445daa1f1db5dce897e9f06fa8638 Mon Sep 17 00:00:00 2001 From: Jean <47366872+jean-voila@users.noreply.github.com> Date: Wed, 28 Jan 2026 21:55:55 +0100 Subject: [PATCH 08/20] began to reimplement the new execution --- src/execution/execution_helpers.c | 46 +++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c index 24c4100..971688a 100644 --- a/src/execution/execution_helpers.c +++ b/src/execution/execution_helpers.c @@ -72,7 +72,9 @@ int exec_ast_command(struct ast_command *command, struct hash_map *vars) waitpid(pid, &status, 0); free(argv); if (WIFEXITED(status)) + { return WEXITSTATUS(status); + } return 1; } @@ -121,7 +123,7 @@ static int get_fd_target(const struct ast_redir *redir) if (redir->io_number != -1) return redir->io_number; if (redir->type == AST_REDIR_TYPE_LESS - || redir->type == AST_REDIR_TYPE_LESSGREAT + || redir->type == AST_REDIR_TYPE_DLESS || redir->type == AST_REDIR_TYPE_LESSAND) return 0; return 1; @@ -163,6 +165,43 @@ static int handle_and_restore_fd(int saved_fd, int fd_target) return 0; } +/* + +static open_all_redir(const struct ast_list redir_list) +{ + while (redir_list){ + struct ast_redir *redir = (struct ast_redir*)redir_list->data; + int target_fd; + if (redir->io_number != -1) + { + target_fd = redir->io_number; + } + else + { + // assign target_fd depending on redir type + } + + int saved_fd = dup(target_fd); + + // if redir type is not with '&' + // then we open("filename") + // else, no need to open, just new_fd = atoi(filename) + + open(); + + dup2(target_fd, new_fd); + + close(new_fd); + + // append target_fd and saved_fd to a list + // in order to be able to restore all the fds + } + +} + + +*/ +/* int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars) { int fd_target = get_fd_target(redir); @@ -206,7 +245,7 @@ int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars) int ret = execution(redir->child, vars); handle_and_restore_fd(saved_fd, fd_target); return ret; -} +} */ // --- Builtins --- @@ -234,7 +273,6 @@ static int builtin_echo(char **argv) return 0; } - static int builtin_true(char **argv) { (void)argv; @@ -256,7 +294,6 @@ static int builtin_exit(char **argv) return exit_val; } - static int builtin_cd(char **argv) { const char *path = argv[1]; @@ -277,7 +314,6 @@ static int builtin_cd(char **argv) return 0; } - /** * @brief Tries to execute a builtin command if the command matches a builtin * From 308ac9ac8d9140dbe455740e38568d9f2e94741a Mon Sep 17 00:00:00 2001 From: "william.valenduc" Date: Wed, 28 Jan 2026 21:26:51 +0000 Subject: [PATCH 09/20] feat(expansion): remove double quotes --- src/expansion/expansion.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/expansion/expansion.c b/src/expansion/expansion.c index ab6241e..4fea985 100644 --- a/src/expansion/expansion.c +++ b/src/expansion/expansion.c @@ -135,7 +135,7 @@ bool expand(struct ast_command *command, const struct hash_map *vars) { if (str[i] == '\'') { - // remove quote + // remove single quote in_quotes = !in_quotes; memmove(str + i, str + i + 1, strlen(str + i + 1) + 1); i--; @@ -144,6 +144,12 @@ bool expand(struct ast_command *command, const struct hash_map *vars) { continue; // do nothing } + else if (str[i] == '\"') + { + // remove double quote + memmove(str + i, str + i + 1, strlen(str + i + 1) + 1); + i--; + } else if (str[i] == '$' && str[i + 1] != 0 && !isspace(str[i + 1])) { // variable expansion From d775ab6c1a79a64cde76499e22eba4b31419ade6 Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 09:56:28 +0100 Subject: [PATCH 10/20] feat(ast): add ast_assignements. Similar to how redirections are handled. --- src/utils/ast/ast_assignement.c | 36 +++++++++++++++++++++++++++++++++ src/utils/ast/ast_assignement.h | 17 ++++++++++++++++ src/utils/ast/ast_base.h | 3 ++- src/utils/ast/ast_command.c | 3 ++- src/utils/ast/ast_command.h | 3 ++- 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/utils/ast/ast_assignement.c create mode 100644 src/utils/ast/ast_assignement.h diff --git a/src/utils/ast/ast_assignement.c b/src/utils/ast/ast_assignement.c new file mode 100644 index 0000000..036e4d2 --- /dev/null +++ b/src/utils/ast/ast_assignement.c @@ -0,0 +1,36 @@ +#include "ast_assignement.h" + +#include + +bool ast_is_assignement(struct ast *node) +{ + return node != NULL && node->type == AST_ASSIGNEMENT; +} + +struct ast_assignement *ast_get_assignement(struct ast *node) +{ + if (node == NULL || node->type != AST_ASSIGNEMENT) + return NULL; + return (struct ast_assignement *)node->data; +} + +struct ast *ast_create_assignement(char *name, char *value) +{ + struct ast_assignement *assignement_data = malloc(sizeof(struct ast_assignement)); + if (!assignement_data) + return NULL; + + assignement_data->name = name; + assignement_data->value = value; + + return ast_create(AST_ASSIGNEMENT, assignement_data); +} + +void ast_free_assignement(struct ast_assignement *assignement_data) +{ + if (assignement_data == NULL) + return; + free(assignement_data->name); + free(assignement_data->value); + free(assignement_data); +} \ No newline at end of file diff --git a/src/utils/ast/ast_assignement.h b/src/utils/ast/ast_assignement.h new file mode 100644 index 0000000..5975497 --- /dev/null +++ b/src/utils/ast/ast_assignement.h @@ -0,0 +1,17 @@ +#ifndef AST_ASSIGNEMENT_H +#define AST_ASSIGNEMENT_H + +#include "ast_base.h" + +struct ast_assignement +{ + char *name; + char *value; +}; + +bool ast_is_assignement(struct ast *node); +struct ast_assignement *ast_get_assignement(struct ast *node); +struct ast *ast_create_assignement(char *name, char *value); +void ast_free_assignement(struct ast_assignement *assignement_data); + +#endif /* ! AST_ASSIGNEMENT_H */ \ No newline at end of file diff --git a/src/utils/ast/ast_base.h b/src/utils/ast/ast_base.h index f81f2f0..f04014d 100644 --- a/src/utils/ast/ast_base.h +++ b/src/utils/ast/ast_base.h @@ -15,7 +15,8 @@ enum ast_type AST_CMD, AST_WORD, AST_PIPE, - AST_NEG + AST_NEG, + AST_ASSIGNEMENT }; struct ast diff --git a/src/utils/ast/ast_command.c b/src/utils/ast/ast_command.c index c4fe3e6..affe45e 100644 --- a/src/utils/ast/ast_command.c +++ b/src/utils/ast/ast_command.c @@ -6,7 +6,7 @@ #include "../lists/lists.h" struct ast *ast_create_command(struct list *command, - struct list *redirections) + struct list *redirections, struct ast_list *assignements) { struct ast_command *command_data = malloc(sizeof(struct ast_command)); if (!command_data) @@ -36,5 +36,6 @@ void ast_free_command(struct ast_command *command_data) return; list_deep_destroy(command_data->command); ast_list_deep_destroy(command_data->redirections); + ast_list_deep_destroy(command_data->assignements); free(command_data); } diff --git a/src/utils/ast/ast_command.h b/src/utils/ast/ast_command.h index 835bf5d..0641f1d 100644 --- a/src/utils/ast/ast_command.h +++ b/src/utils/ast/ast_command.h @@ -8,6 +8,7 @@ struct ast_command { struct list *command; // A list of words (char*) struct ast_list *redirections; // A list of ASTs, all ast_redir + struct ast_list *assignements; // A list of ASTs, all ast_assignement }; /** @@ -25,7 +26,7 @@ struct ast_command *ast_get_command(struct ast *node); * Creates a new AST node representing a command. */ struct ast *ast_create_command(struct list *command, - struct list *redirections); + struct list *redirections, struct ast_list *assignements); /* * @brief: frees the given ast_command and sets the pointer to NULL. From 46dde29c2006de727fc08fc07e554b1d41c2db90 Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 09:59:16 +0100 Subject: [PATCH 11/20] fix: small errors in exec and parser --- src/execution/execution_helpers.c | 2 +- src/parser/grammar.c | 6 +++--- src/parser/grammar_basic.c | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c index 971688a..9dcaf41 100644 --- a/src/execution/execution_helpers.c +++ b/src/execution/execution_helpers.c @@ -123,7 +123,7 @@ static int get_fd_target(const struct ast_redir *redir) if (redir->io_number != -1) return redir->io_number; if (redir->type == AST_REDIR_TYPE_LESS - || redir->type == AST_REDIR_TYPE_DLESS + || redir->type == AST_REDIR_TYPE_LESSGREAT || redir->type == AST_REDIR_TYPE_LESSAND) return 0; return 1; diff --git a/src/parser/grammar.c b/src/parser/grammar.c index 83f2266..95f1bd2 100644 --- a/src/parser/grammar.c +++ b/src/parser/grammar.c @@ -106,15 +106,15 @@ bool grammar_init(void) add_first(RULE_LIST, TOKEN_WORD); add_first(RULE_LIST, TOKEN_IF); - add_first(RULE_COMMAND, TOKEN_NEGATION); + add_first(RULE_LIST, TOKEN_NEGATION); add_first(RULE_AND_OR, TOKEN_WORD); add_first(RULE_AND_OR, TOKEN_IF); - add_first(RULE_COMMAND, TOKEN_NEGATION); + add_first(RULE_AND_OR, TOKEN_NEGATION); add_first(RULE_PIPELINE, TOKEN_WORD); add_first(RULE_PIPELINE, TOKEN_IF); - add_first(RULE_COMMAND, TOKEN_NEGATION); + add_first(RULE_PIPELINE, TOKEN_NEGATION); add_first(RULE_COMMAND, TOKEN_WORD); add_first(RULE_COMMAND, TOKEN_IF); diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index 17e006f..9102593 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -261,6 +261,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) } // Result + // TODO handle assignements struct ast *result = ast_create_command(command_elements, redirections); if (result == NULL) { From 6da801675a7c2b3f3269bbc4e6ace5487847e139 Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 11:18:56 +0100 Subject: [PATCH 12/20] feat(lexer): implementing assignements --- src/lexer/lexer.c | 18 +++++++++++++++++- src/lexer/lexer_utils.h | 15 +++++++++++---- src/parser/grammar_advanced.c | 14 +++++++++++++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index ff7f351..21f362b 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -78,6 +78,21 @@ static bool update_lexing_mode(char *stream, ssize_t i, return *lexing_mode != mode_before_update; } +/* @brief: updates the flags only_digits and equal_count + * according to the character at stream[i]. + */ +static void update_flags(char *stream, ssize_t i, struct lexer_context *ctx) +{ + if (stream[i] == '=') + { + ctx->equal_count++; + } + else if (!isdigit(stream[i]) && ctx->only_digits) + { + ctx->only_digits = false; + } +} + struct token *peek_token(struct lexer_context *ctx) { // we already created the upcoming token during the previous call to peek() @@ -100,6 +115,7 @@ struct token *peek_token(struct lexer_context *ctx) if (!update_lexing_mode(stream, i, &lexing_mode) && lexing_mode == LEXER_NORMAL) { + update_flags(stream, i, ctx); if (is_special_char(stream, i)) { if (i == 0) // where we create spe_char token @@ -121,7 +137,7 @@ struct token *peek_token(struct lexer_context *ctx) i++; } - struct token *tok = new_token(stream, i, ctx->only_digits); + struct token *tok = new_token(stream, i, ctx->only_digits, ctx->equal_count); // if token is comment, we don't want it if (tok->type == TOKEN_COMMENT) diff --git a/src/lexer/lexer_utils.h b/src/lexer/lexer_utils.h index c6c26c9..2708662 100644 --- a/src/lexer/lexer_utils.h +++ b/src/lexer/lexer_utils.h @@ -14,6 +14,9 @@ struct lexer_context // tells us if we only lexed digits in current token. bool only_digits; + // usefull to detect assignments, and syntax errors with '='. + int equal_count; + struct token *previous_token; struct token *current_token; }; @@ -34,10 +37,13 @@ enum token_type // Blanks TOKEN_NULL = 0, TOKEN_EOF, - TOKEN_WORD, TOKEN_NEWLINE, - // SPecial characters + // words + TOKEN_WORD, + TOKEN_ASSIGNMENT_WORD, + + // Special characters TOKEN_GRAVE, TOKEN_SEMICOLON, TOKEN_COMMENT, @@ -87,12 +93,13 @@ struct token */ bool is_special_char(char *stream, ssize_t i); -/* @brief: return a newly allocated token, with the corresponding type. +/* @brief: return a newly allocated token, with the type corresponding + * to the context given in arguments. * The data contains [size] char, starting from [begin]. * * @return: NULL on error, a token otherwise. */ -struct token *new_token(char *begin, ssize_t size, bool only_digits); +struct token *new_token(char *begin, ssize_t size, bool only_digits, int equal_count); /* @brief: frees the token given in argument */ diff --git a/src/parser/grammar_advanced.c b/src/parser/grammar_advanced.c index 8c4b68c..1964f49 100644 --- a/src/parser/grammar_advanced.c +++ b/src/parser/grammar_advanced.c @@ -66,5 +66,17 @@ struct ast *parse_redirection(struct lexer_context *ctx) struct ast *parse_prefix(struct lexer_context *ctx) { - return parse_redirection(ctx); + struct token *token = TOKEN_PEEK(); + if (token->type == TOKEN_ASSIGNMENT_WORD) + { + token = TOKEN_POP(); + return ast_create_assignment_word(token->data); + } + else if (is_first(*token, RULE_REDIRECTION)) + return parse_redirection(ctx); + else + { + perror("Syntax error: expected a prefix (redirection or assignment)"); + return NULL; + } } From 2884fa78d9db5957af437048555b50fb0c113898 Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 11:32:15 +0100 Subject: [PATCH 13/20] feat(ast_assignement): changed (name, value) to assignement --- src/utils/ast/ast_assignement.c | 10 ++++------ src/utils/ast/ast_assignement.h | 8 ++++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/utils/ast/ast_assignement.c b/src/utils/ast/ast_assignement.c index 036e4d2..86e892d 100644 --- a/src/utils/ast/ast_assignement.c +++ b/src/utils/ast/ast_assignement.c @@ -14,14 +14,13 @@ struct ast_assignement *ast_get_assignement(struct ast *node) return (struct ast_assignement *)node->data; } -struct ast *ast_create_assignement(char *name, char *value) +struct ast *ast_create_assignement(char* assignement) { struct ast_assignement *assignement_data = malloc(sizeof(struct ast_assignement)); if (!assignement_data) return NULL; - assignement_data->name = name; - assignement_data->value = value; + assignement_data->assignement = assignement; return ast_create(AST_ASSIGNEMENT, assignement_data); } @@ -30,7 +29,6 @@ void ast_free_assignement(struct ast_assignement *assignement_data) { if (assignement_data == NULL) return; - free(assignement_data->name); - free(assignement_data->value); + free(assignement_data->assignement); free(assignement_data); -} \ No newline at end of file +} diff --git a/src/utils/ast/ast_assignement.h b/src/utils/ast/ast_assignement.h index 5975497..533086d 100644 --- a/src/utils/ast/ast_assignement.h +++ b/src/utils/ast/ast_assignement.h @@ -5,13 +5,13 @@ struct ast_assignement { - char *name; - char *value; + char *assignement; // assignement of the form 'a=b'. + // needs to be parsed lexer }; bool ast_is_assignement(struct ast *node); struct ast_assignement *ast_get_assignement(struct ast *node); -struct ast *ast_create_assignement(char *name, char *value); +struct ast *ast_create_assignement(char *assignement); void ast_free_assignement(struct ast_assignement *assignement_data); -#endif /* ! AST_ASSIGNEMENT_H */ \ No newline at end of file +#endif /* ! AST_ASSIGNEMENT_H */ From dd8a7165e1aa521a8348704da965de70426f9d80 Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 11:37:20 +0100 Subject: [PATCH 14/20] Revert "feat(ast_assignement): changed (name, value) to assignement" This reverts commit ac77d79a603719e05db37dfa033e77b3899d42c1. --- src/utils/ast/ast_assignement.c | 10 ++++++---- src/utils/ast/ast_assignement.h | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/utils/ast/ast_assignement.c b/src/utils/ast/ast_assignement.c index 86e892d..036e4d2 100644 --- a/src/utils/ast/ast_assignement.c +++ b/src/utils/ast/ast_assignement.c @@ -14,13 +14,14 @@ struct ast_assignement *ast_get_assignement(struct ast *node) return (struct ast_assignement *)node->data; } -struct ast *ast_create_assignement(char* assignement) +struct ast *ast_create_assignement(char *name, char *value) { struct ast_assignement *assignement_data = malloc(sizeof(struct ast_assignement)); if (!assignement_data) return NULL; - assignement_data->assignement = assignement; + assignement_data->name = name; + assignement_data->value = value; return ast_create(AST_ASSIGNEMENT, assignement_data); } @@ -29,6 +30,7 @@ void ast_free_assignement(struct ast_assignement *assignement_data) { if (assignement_data == NULL) return; - free(assignement_data->assignement); + free(assignement_data->name); + free(assignement_data->value); free(assignement_data); -} +} \ No newline at end of file diff --git a/src/utils/ast/ast_assignement.h b/src/utils/ast/ast_assignement.h index 533086d..5975497 100644 --- a/src/utils/ast/ast_assignement.h +++ b/src/utils/ast/ast_assignement.h @@ -5,13 +5,13 @@ struct ast_assignement { - char *assignement; // assignement of the form 'a=b'. - // needs to be parsed lexer + char *name; + char *value; }; bool ast_is_assignement(struct ast *node); struct ast_assignement *ast_get_assignement(struct ast *node); -struct ast *ast_create_assignement(char *assignement); +struct ast *ast_create_assignement(char *name, char *value); void ast_free_assignement(struct ast_assignement *assignement_data); -#endif /* ! AST_ASSIGNEMENT_H */ +#endif /* ! AST_ASSIGNEMENT_H */ \ No newline at end of file From a0b723fb30f2d7a729bfe5efbd6535dc6ea0d70c Mon Sep 17 00:00:00 2001 From: "william.valenduc" Date: Thu, 29 Jan 2026 11:29:03 +0000 Subject: [PATCH 15/20] feat(execution): update $PWD and $OLD_PWD --- src/execution/execution_helpers.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c index 9dcaf41..8ea5aef 100644 --- a/src/execution/execution_helpers.c +++ b/src/execution/execution_helpers.c @@ -12,6 +12,7 @@ #include "../expansion/expansion.h" #include "../utils/ast/ast.h" #include "../utils/hash_map/hash_map.h" +#include "../utils/vars/vars.h" #include "execution.h" static char **list_to_argv(struct list *command_list) @@ -36,7 +37,7 @@ static char **list_to_argv(struct list *command_list) return argv; } -static int try_builtin(char **argv); +static int try_builtin(char **argv, struct hash_map *vars); int exec_ast_command(struct ast_command *command, struct hash_map *vars) { @@ -49,7 +50,7 @@ int exec_ast_command(struct ast_command *command, struct hash_map *vars) free(argv); return 0; } - int builtin_ret = try_builtin(argv); + int builtin_ret = try_builtin(argv, vars); if (builtin_ret != -1) { free(argv); @@ -294,7 +295,7 @@ static int builtin_exit(char **argv) return exit_val; } -static int builtin_cd(char **argv) +static int builtin_cd(char **argv, struct hash_map *vars) { const char *path = argv[1]; if (!path) @@ -306,11 +307,15 @@ static int builtin_cd(char **argv) return 1; } } + // char *pwd = getcwd("", ""); + char *pwd = get_var_or_env(pwd, "PWD"); if (chdir(path) != 0) { perror("cd"); return 1; } + set_var_copy(vars, "OLD_PWD", pwd); + set_var_copy(vars, "PWD", path); return 0; } @@ -320,7 +325,7 @@ static int builtin_cd(char **argv) * @param argv Array of command arguments * @return int Exit status of the builtin command, or -1 if not a builtin */ -static int try_builtin(char **argv) +static int try_builtin(char **argv, struct hash_map *vars) { if (!argv || !argv[0]) return 0; @@ -334,7 +339,7 @@ static int try_builtin(char **argv) if (strcmp(argv[0], "exit") == 0) return builtin_exit(argv); if (strcmp(argv[0], "cd") == 0) - return builtin_cd(argv); + return builtin_cd(argv, vars); return -1; } From 3d26c0a897245802351b057cd936ad6f47e156c3 Mon Sep 17 00:00:00 2001 From: "william.valenduc" Date: Thu, 29 Jan 2026 11:40:55 +0000 Subject: [PATCH 16/20] fix(ast)!: assignment typo --- src/parser/grammar_basic.c | 2 +- src/utils/ast/ast.h | 1 + src/utils/ast/ast_assignement.c | 36 --------------------------------- src/utils/ast/ast_assignement.h | 17 ---------------- src/utils/ast/ast_assignment.c | 36 +++++++++++++++++++++++++++++++++ src/utils/ast/ast_assignment.h | 17 ++++++++++++++++ src/utils/ast/ast_base.h | 2 +- src/utils/ast/ast_command.c | 4 ++-- src/utils/ast/ast_command.h | 4 ++-- 9 files changed, 60 insertions(+), 59 deletions(-) delete mode 100644 src/utils/ast/ast_assignement.c delete mode 100644 src/utils/ast/ast_assignement.h create mode 100644 src/utils/ast/ast_assignment.c create mode 100644 src/utils/ast/ast_assignment.h diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index 9102593..9621d31 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -261,7 +261,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) } // Result - // TODO handle assignements + // TODO handle assignments struct ast *result = ast_create_command(command_elements, redirections); if (result == NULL) { diff --git a/src/utils/ast/ast.h b/src/utils/ast/ast.h index 3964968..9827d8d 100644 --- a/src/utils/ast/ast.h +++ b/src/utils/ast/ast.h @@ -2,6 +2,7 @@ #define AST_H #include "ast_and_or.h" +#include "ast_assignment.h" #include "ast_base.h" #include "ast_command.h" #include "ast_end.h" diff --git a/src/utils/ast/ast_assignement.c b/src/utils/ast/ast_assignement.c deleted file mode 100644 index 036e4d2..0000000 --- a/src/utils/ast/ast_assignement.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "ast_assignement.h" - -#include - -bool ast_is_assignement(struct ast *node) -{ - return node != NULL && node->type == AST_ASSIGNEMENT; -} - -struct ast_assignement *ast_get_assignement(struct ast *node) -{ - if (node == NULL || node->type != AST_ASSIGNEMENT) - return NULL; - return (struct ast_assignement *)node->data; -} - -struct ast *ast_create_assignement(char *name, char *value) -{ - struct ast_assignement *assignement_data = malloc(sizeof(struct ast_assignement)); - if (!assignement_data) - return NULL; - - assignement_data->name = name; - assignement_data->value = value; - - return ast_create(AST_ASSIGNEMENT, assignement_data); -} - -void ast_free_assignement(struct ast_assignement *assignement_data) -{ - if (assignement_data == NULL) - return; - free(assignement_data->name); - free(assignement_data->value); - free(assignement_data); -} \ No newline at end of file diff --git a/src/utils/ast/ast_assignement.h b/src/utils/ast/ast_assignement.h deleted file mode 100644 index 5975497..0000000 --- a/src/utils/ast/ast_assignement.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef AST_ASSIGNEMENT_H -#define AST_ASSIGNEMENT_H - -#include "ast_base.h" - -struct ast_assignement -{ - char *name; - char *value; -}; - -bool ast_is_assignement(struct ast *node); -struct ast_assignement *ast_get_assignement(struct ast *node); -struct ast *ast_create_assignement(char *name, char *value); -void ast_free_assignement(struct ast_assignement *assignement_data); - -#endif /* ! AST_ASSIGNEMENT_H */ \ No newline at end of file diff --git a/src/utils/ast/ast_assignment.c b/src/utils/ast/ast_assignment.c new file mode 100644 index 0000000..a2564c2 --- /dev/null +++ b/src/utils/ast/ast_assignment.c @@ -0,0 +1,36 @@ +#include "ast_assignment.h" + +#include + +bool ast_is_assignment(struct ast *node) +{ + return node != NULL && node->type == AST_ASSIGNMENT; +} + +struct ast_assignment *ast_get_assignment(struct ast *node) +{ + if (node == NULL || node->type != AST_ASSIGNMENT) + return NULL; + return (struct ast_assignment *)node->data; +} + +struct ast *ast_create_assignment(char *name, char *value) +{ + struct ast_assignment *assignment_data = malloc(sizeof(struct ast_assignment)); + if (!assignment_data) + return NULL; + + assignment_data->name = name; + assignment_data->value = value; + + return ast_create(AST_ASSIGNMENT, assignment_data); +} + +void ast_free_assignment(struct ast_assignment *assignment_data) +{ + if (assignment_data == NULL) + return; + free(assignment_data->name); + free(assignment_data->value); + free(assignment_data); +} \ No newline at end of file diff --git a/src/utils/ast/ast_assignment.h b/src/utils/ast/ast_assignment.h new file mode 100644 index 0000000..c958c2d --- /dev/null +++ b/src/utils/ast/ast_assignment.h @@ -0,0 +1,17 @@ +#ifndef AST_ASSIGNMENT_H +#define AST_ASSIGNMENT_H + +#include "ast_base.h" + +struct ast_assignment +{ + char *name; + char *value; +}; + +bool ast_is_assignment(struct ast *node); +struct ast_assignment *ast_get_assignment(struct ast *node); +struct ast *ast_create_assignment(char *name, char *value); +void ast_free_assignment(struct ast_assignment *assignment_data); + +#endif /* ! AST_ASSIGNMENT_H */ \ No newline at end of file diff --git a/src/utils/ast/ast_base.h b/src/utils/ast/ast_base.h index f04014d..ae99a39 100644 --- a/src/utils/ast/ast_base.h +++ b/src/utils/ast/ast_base.h @@ -16,7 +16,7 @@ enum ast_type AST_WORD, AST_PIPE, AST_NEG, - AST_ASSIGNEMENT + AST_ASSIGNMENT }; struct ast diff --git a/src/utils/ast/ast_command.c b/src/utils/ast/ast_command.c index affe45e..d7e148d 100644 --- a/src/utils/ast/ast_command.c +++ b/src/utils/ast/ast_command.c @@ -6,7 +6,7 @@ #include "../lists/lists.h" struct ast *ast_create_command(struct list *command, - struct list *redirections, struct ast_list *assignements) + struct list *redirections, struct ast_list *assignments) { struct ast_command *command_data = malloc(sizeof(struct ast_command)); if (!command_data) @@ -36,6 +36,6 @@ void ast_free_command(struct ast_command *command_data) return; list_deep_destroy(command_data->command); ast_list_deep_destroy(command_data->redirections); - ast_list_deep_destroy(command_data->assignements); + ast_list_deep_destroy(command_data->assignments); free(command_data); } diff --git a/src/utils/ast/ast_command.h b/src/utils/ast/ast_command.h index 0641f1d..9322ac7 100644 --- a/src/utils/ast/ast_command.h +++ b/src/utils/ast/ast_command.h @@ -8,7 +8,7 @@ struct ast_command { struct list *command; // A list of words (char*) struct ast_list *redirections; // A list of ASTs, all ast_redir - struct ast_list *assignements; // A list of ASTs, all ast_assignement + struct ast_list *assignments; // A list of ASTs, all ast_assignment }; /** @@ -26,7 +26,7 @@ struct ast_command *ast_get_command(struct ast *node); * Creates a new AST node representing a command. */ struct ast *ast_create_command(struct list *command, - struct list *redirections, struct ast_list *assignements); + struct list *redirections, struct ast_list *assignments); /* * @brief: frees the given ast_command and sets the pointer to NULL. From 6948bbae63e388befe6f6814d982cd391200476d Mon Sep 17 00:00:00 2001 From: Jean <47366872+jean-voila@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:18:04 +0100 Subject: [PATCH 17/20] fix(execution): Reimplemented the redirection logic --- src/execution/execution.c | 5 +- src/execution/execution_helpers.c | 100 ++++++++++++++++++++++-------- src/execution/execution_helpers.h | 1 - src/utils/ast/ast_redir.h | 1 + 4 files changed, 75 insertions(+), 32 deletions(-) diff --git a/src/execution/execution.c b/src/execution/execution.c index 90bb8eb..cf751f7 100644 --- a/src/execution/execution.c +++ b/src/execution/execution.c @@ -14,8 +14,6 @@ #include "../utils/ast/ast.h" #include "../utils/hash_map/hash_map.h" - - // Refactored: delegates to helpers in execution_helpers.c #include "execution_helpers.h" @@ -33,6 +31,7 @@ int execution(struct ast *ast, struct hash_map *vars) struct ast_command *command = ast_get_command(ast); if (!expand(command, vars)) fprintf(stderr, "Error: Variable expansion failed\n"); + return exec_ast_command(command, vars); } case AST_IF: @@ -41,8 +40,6 @@ int execution(struct ast *ast, struct hash_map *vars) return exec_ast_list(ast_get_list(ast), vars); case AST_AND_OR: return exec_ast_and_or(ast_get_and_or(ast), vars); - case AST_REDIR: - return exec_ast_redir(ast_get_redir(ast), vars); default: return 127; } diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c index 8ea5aef..aba6dc7 100644 --- a/src/execution/execution_helpers.c +++ b/src/execution/execution_helpers.c @@ -12,6 +12,7 @@ #include "../expansion/expansion.h" #include "../utils/ast/ast.h" #include "../utils/hash_map/hash_map.h" +#include "../utils/lists/lists.h" #include "../utils/vars/vars.h" #include "execution.h" @@ -42,40 +43,56 @@ static int try_builtin(char **argv, struct hash_map *vars); int exec_ast_command(struct ast_command *command, struct hash_map *vars) { (void)vars; + set_all_redir(command->redirections); + if (!command || !(command->command)) + { return 1; + } + char **argv = list_to_argv(command->command); if (!argv || !(argv[0])) { free(argv); + unset_all_redir(); return 0; } + int builtin_ret = try_builtin(argv, vars); if (builtin_ret != -1) { free(argv); + unset_all_redir(); return builtin_ret; } + pid_t pid = fork(); if (pid < 0) { perror("fork"); free(argv); + unset_all_redir(); return 1; } + if (pid == 0) { execvp(argv[0], argv); perror("execvp"); + unset_all_redir(); _exit(127); } + int status = 0; waitpid(pid, &status, 0); free(argv); + unset_all_redir(); + if (WIFEXITED(status)) { return WEXITSTATUS(status); } + return 1; } @@ -166,42 +183,71 @@ static int handle_and_restore_fd(int saved_fd, int fd_target) return 0; } -/* - -static open_all_redir(const struct ast_list redir_list) +static int set_all_redir(struct list *redir_list) { - while (redir_list){ - struct ast_redir *redir = (struct ast_redir*)redir_list->data; + while (redir_list) + { + struct ast_redir *redir = (struct ast_redir *)redir_list->data; int target_fd; + if (redir->io_number != -1) { - target_fd = redir->io_number; + target_fd = redir->io_number; + } + else + { + // assign target_fd depending on redir type + if (redir->type == AST_REDIR_TYPE_LESS + || redir->type == AST_REDIR_TYPE_LESSGREAT + || redir->type == AST_REDIR_TYPE_LESSAND) + { + target_fd = 0; + } + else + { + target_fd = 1; + } } - else - { - // assign target_fd depending on redir type - } - int saved_fd = dup(target_fd); - - // if redir type is not with '&' - // then we open("filename") - // else, no need to open, just new_fd = atoi(filename) - - open(); - - dup2(target_fd, new_fd); - - close(new_fd); - - // append target_fd and saved_fd to a list - // in order to be able to restore all the fds + redir->saved_fd = dup(target_fd); + int new_fd = -1; + int flags = 0; + int mode = 0644; + if (redir->type == AST_REDIR_TYPE_GREAT + || redir->type == AST_REDIR_TYPE_CLOBBER + || redir->type == AST_REDIR_TYPE_DGREAT + || redir->type == AST_REDIR_TYPE_LESS) + { + new_fd = open_redir_file(redir, &flags, &mode); + if (new_fd == -1) + { + perror("open"); + return -1; + } + } + else if (redir->type == AST_REDIR_TYPE_GREATAND + || redir->type == AST_REDIR_TYPE_LESSAND) + { + new_fd = atoi(redir->filename); + } + if (dup2(new_fd, target_fd) == -1) + { + perror("dup2"); + if (new_fd != -1) + { + close(new_fd); + } + return -1; + } + if (new_fd != -1) + { + close(new_fd); + } + redir_list = redir_list->next; } - + return 0; } - -*/ /* int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars) { diff --git a/src/execution/execution_helpers.h b/src/execution/execution_helpers.h index ebac0cb..fd8026c 100644 --- a/src/execution/execution_helpers.h +++ b/src/execution/execution_helpers.h @@ -8,6 +8,5 @@ int exec_ast_command(struct ast_command *command, struct hash_map *vars); int exec_ast_if(struct ast_if *if_node, struct hash_map *vars); int exec_ast_list(struct ast_list *list_node, struct hash_map *vars); int exec_ast_and_or(struct ast_and_or *ao_node, struct hash_map *vars); -int exec_ast_redir(struct ast_redir *redir, struct hash_map *vars); #endif // EXECUTION_HELPERS_H diff --git a/src/utils/ast/ast_redir.h b/src/utils/ast/ast_redir.h index fdea88c..9d9a9d3 100644 --- a/src/utils/ast/ast_redir.h +++ b/src/utils/ast/ast_redir.h @@ -21,6 +21,7 @@ struct ast_redir int io_number; // The FD being redirected (default -1 if not specified, // implies 0 or 1 based on type) enum ast_redir_type type; + int saved_fd; // To store the original FD for restoration (-1 before save) }; bool ast_is_redir(struct ast *node); From 148db797880aaf3896b006afa41a53af8d4ec3e3 Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 18:52:51 +0100 Subject: [PATCH 18/20] fix(merge conflicts) --- src/parser/grammar_advanced.c | 2 +- src/parser/grammar_basic.c | 27 +++++++++++++++++---------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/parser/grammar_advanced.c b/src/parser/grammar_advanced.c index 1964f49..eb5869d 100644 --- a/src/parser/grammar_advanced.c +++ b/src/parser/grammar_advanced.c @@ -74,7 +74,7 @@ struct ast *parse_prefix(struct lexer_context *ctx) } else if (is_first(*token, RULE_REDIRECTION)) return parse_redirection(ctx); - else + else { perror("Syntax error: expected a prefix (redirection or assignment)"); return NULL; diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index 9621d31..ad78673 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -173,7 +173,7 @@ struct ast *parse_command(struct lexer_context *ctx) * @return: NULL */ static void *err_simple_command(struct list *command_elements, - struct list *redirections) + struct list *redirections) { list_deep_destroy(command_elements); list_deep_destroy(redirections); @@ -184,6 +184,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) { struct list *command_elements = NULL; struct list *redirections = NULL; // list of redirection ASTs + struct list *assignments = NULL; bool has_prefix = false; struct token *token = PEEK_TOKEN(); @@ -192,12 +193,19 @@ struct ast *parse_simple_command(struct lexer_context *ctx) has_prefix = true; while (is_first(*token, RULE_PREFIX)) { - struct ast *redir = parse_prefix(ctx); - if (redir == NULL) + struct ast *prefix = parse_prefix(ctx); + if (prefix == NULL) { return err_simple_command(command_elements, redirections); } - redirections = list_append(redirections, redir); + if (prefix->type == AST_ASSIGNEMENT) + { + assignments = list_append(assignments, prefix) + } + else if (prefix->type == AST_REDIR) + { + redirections = list_append(redirections, prefix); + } token = PEEK_TOKEN(); } } @@ -250,8 +258,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) else { perror("Internal error: unexpected return value from " - "parse_element " - "in parse_simple_command"); + "parse_element in parse_simple_command"); return err_simple_command(command_elements, redirections); } @@ -260,9 +267,8 @@ struct ast *parse_simple_command(struct lexer_context *ctx) } } - // Result - // TODO handle assignments - struct ast *result = ast_create_command(command_elements, redirections); + struct ast *result = + ast_create_command(command_elements, redirections, assignments); if (result == NULL) { return err_simple_command(command_elements, redirections); @@ -297,7 +303,8 @@ struct ast *parse_shell_command(struct lexer_context *ctx) /* @brief: frees all the arguments. (helper func) * @return: NULL. */ -static void *err_if_rule(struct ast **cond, struct ast **then_clause, struct ast **else_clause) +static void *err_if_rule(struct ast **cond, struct ast **then_clause, + struct ast **else_clause) { ast_free(cond); ast_free(then_clause); From 51158ec4f9829e79b0bf58cde214ba87988735ce Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 18:53:37 +0100 Subject: [PATCH 19/20] fix(lexer): merge conflicts --- src/lexer/lexer.c | 55 +++++++++++++++++++++-------------- src/lexer/lexer_utils.c | 33 ++++++++++++++++----- src/lexer/lexer_utils.h | 26 ++++++++--------- src/parser/grammar_advanced.c | 5 ++-- src/parser/grammar_basic.c | 2 +- 5 files changed, 76 insertions(+), 45 deletions(-) diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 21f362b..db4e066 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -78,36 +78,43 @@ static bool update_lexing_mode(char *stream, ssize_t i, return *lexing_mode != mode_before_update; } -/* @brief: updates the flags only_digits and equal_count +/* @brief: updates the flags only_digits and has_equal. * according to the character at stream[i]. */ -static void update_flags(char *stream, ssize_t i, struct lexer_context *ctx) +static void update_flags(char *stream, ssize_t i, struct token_info *info) { - if (stream[i] == '=') + if (stream[i] == '=' && !info->has_equal) { - ctx->equal_count++; + if (i == 0) + { + perror("Syntax error: word start with a '='"); + return; + } + else + info->has_equal = true; } - else if (!isdigit(stream[i]) && ctx->only_digits) + else if (!isdigit(stream[i]) && info->only_digits) { - ctx->only_digits = false; + info->only_digits = false; } } struct token *peek_token(struct lexer_context *ctx) { + stream_init(ctx); + + // Usefull to know if we are inside a quote or double quote + enum lexing_mode lexing_mode = LEXER_NORMAL; + struct token_info info = {true, 0}; + char *stream = ctx->end_previous_token; + ssize_t i = 0; + // we already created the upcoming token during the previous call to peek() if (ctx->current_token != NULL) { return ctx->current_token; } - stream_init(ctx); - char *stream = ctx->end_previous_token; - ssize_t i = 0; - - // Usefull to know if we are inside a quote or double quote - enum lexing_mode lexing_mode = LEXER_NORMAL; - while (i < ctx->remaining_chars) { // true if we didn't encounter a quote of any type at stream[i] @@ -115,7 +122,7 @@ struct token *peek_token(struct lexer_context *ctx) if (!update_lexing_mode(stream, i, &lexing_mode) && lexing_mode == LEXER_NORMAL) { - update_flags(stream, i, ctx); + update_flags(stream, i, &info); if (is_special_char(stream, i)) { if (i == 0) // where we create spe_char token @@ -137,7 +144,7 @@ struct token *peek_token(struct lexer_context *ctx) i++; } - struct token *tok = new_token(stream, i, ctx->only_digits, ctx->equal_count); + struct token *tok = new_token(stream, i, &info); // if token is comment, we don't want it if (tok->type == TOKEN_COMMENT) @@ -154,6 +161,15 @@ struct token *peek_token(struct lexer_context *ctx) struct token *pop_token(struct lexer_context *ctx) { + stream_init(ctx); + + // Usefull to know if we are inside a quote or double quote + enum lexing_mode lexing_mode = LEXER_NORMAL; + struct token_info info = {true, 0}; + char *stream = ctx->end_previous_token; + ssize_t i = 0; + + if (ctx->current_token != NULL && ctx->current_token->type == TOKEN_EOF) { // we reached end of input, frees all the token still allocated. @@ -161,12 +177,6 @@ struct token *pop_token(struct lexer_context *ctx) free_token(&ctx->current_token); return NULL; } - stream_init(ctx); - char *stream = ctx->end_previous_token; - ssize_t i = 0; - - // Usefull to know if we are inside a quote or double quote - enum lexing_mode lexing_mode = LEXER_NORMAL; while (i < ctx->remaining_chars) { @@ -175,6 +185,7 @@ struct token *pop_token(struct lexer_context *ctx) if (!update_lexing_mode(stream, i, &lexing_mode) && lexing_mode == LEXER_NORMAL) { + update_flags(stream, i, &info); if (is_special_char(stream, i)) { if (i == 0) // where we create spe_char token @@ -200,7 +211,7 @@ struct token *pop_token(struct lexer_context *ctx) // (this should never happen) if (ctx->current_token == NULL) { - ctx->current_token = new_token(stream, i, ctx->only_digits); + ctx->current_token = new_token(stream, i, &info); } save_state(stream, i, ctx); diff --git a/src/lexer/lexer_utils.c b/src/lexer/lexer_utils.c index 54859e8..f860649 100644 --- a/src/lexer/lexer_utils.c +++ b/src/lexer/lexer_utils.c @@ -154,6 +154,21 @@ static void set_token_word(struct token *tok, char *begin, ssize_t size) } } +/* @brief: Sets the token to an assignment_word + * Also allocates the data and fills it. + */ +static void set_token_assignment(struct token *tok, char *begin, ssize_t size) +{ + if (tok->type == TOKEN_NULL && size != 0) + { + tok->type = TOKEN_ASSIGNMENT_WORD; + tok->data = calloc(size + 1, sizeof(char)); + if (tok->data == NULL) + return; + strncpy(tok->data, begin, size); + } +} + /* @brief: Sets the token to an IO number * Also allocates the data and fills it. */ @@ -212,19 +227,23 @@ bool is_special_char(char *stream, ssize_t i) return strchr(special_chars, c) != NULL; } -struct token *new_token(char *begin, ssize_t size, bool only_digits) +struct token *new_token(char *begin, ssize_t size, struct token_info *info) { struct token *tok = calloc(1, sizeof(struct token)); if (tok == NULL) return NULL; - if (only_digits) + if (info->only_digits) set_token_ION(tok, begin, size); - - set_token_operator(tok, begin, size); - set_token_spechar(tok, begin, size); - set_token_keyword(tok, begin, size); - set_token_word(tok, begin, size); + else if (info->has_equal) + set_token_assignment(tok, begin, size); + else + { + set_token_operator(tok, begin, size); + set_token_spechar(tok, begin, size); + set_token_keyword(tok, begin, size); + set_token_word(tok, begin, size); + } return tok; } diff --git a/src/lexer/lexer_utils.h b/src/lexer/lexer_utils.h index 2708662..8fb5219 100644 --- a/src/lexer/lexer_utils.h +++ b/src/lexer/lexer_utils.h @@ -10,13 +10,6 @@ struct lexer_context char *end_previous_token; ssize_t remaining_chars; - // usefull to detect IO numbers. - // tells us if we only lexed digits in current token. - bool only_digits; - - // usefull to detect assignments, and syntax errors with '='. - int equal_count; - struct token *previous_token; struct token *current_token; }; @@ -57,10 +50,6 @@ enum token_type TOKEN_PIPE, TOKEN_NEGATION, - // TODO merge into one and use the data field - // (Too difficult to handle in the parser because of firsts) - // TOKEN_REDIRECTION - // // Redirections TOKEN_REDIR_LEFT, TOKEN_REDIR_RIGHT, @@ -88,18 +77,29 @@ struct token char *data; }; +// used to give info from lexing when creating a new token. +struct token_info +{ + // usefull to detect IO numbers. + // tells us if we only lexed digits in current token. + bool only_digits; + + // usefull to detect assignments, and syntax errors with '='. + bool has_equal; +}; + /* @return: true if a special character from the grammar was found at stream[i], * false otherwise. */ bool is_special_char(char *stream, ssize_t i); /* @brief: return a newly allocated token, with the type corresponding - * to the context given in arguments. + * to the info given in arguments. * The data contains [size] char, starting from [begin]. * * @return: NULL on error, a token otherwise. */ -struct token *new_token(char *begin, ssize_t size, bool only_digits, int equal_count); +struct token *new_token(char *begin, ssize_t size, struct token_info *info); /* @brief: frees the token given in argument */ diff --git a/src/parser/grammar_advanced.c b/src/parser/grammar_advanced.c index eb5869d..713fd99 100644 --- a/src/parser/grammar_advanced.c +++ b/src/parser/grammar_advanced.c @@ -7,6 +7,7 @@ #include #include "grammar_basic.h" +#include "grammar.h" static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type) { @@ -66,10 +67,10 @@ struct ast *parse_redirection(struct lexer_context *ctx) struct ast *parse_prefix(struct lexer_context *ctx) { - struct token *token = TOKEN_PEEK(); + struct token *token = PEEK_TOKEN(); if (token->type == TOKEN_ASSIGNMENT_WORD) { - token = TOKEN_POP(); + token = POP_TOKEN(); return ast_create_assignment_word(token->data); } else if (is_first(*token, RULE_REDIRECTION)) diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index ad78673..b979b6e 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -200,7 +200,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) } if (prefix->type == AST_ASSIGNEMENT) { - assignments = list_append(assignments, prefix) + assignments = list_append(assignments, prefix); } else if (prefix->type == AST_REDIR) { From 79fb96e5e29ca62064b969c309c479ad72810e48 Mon Sep 17 00:00:00 2001 From: matteo Date: Thu, 29 Jan 2026 18:46:11 +0100 Subject: [PATCH 20/20] fix: ast_redir and ast_assignment accorded for every part --- src/execution/execution_helpers.c | 2 +- src/lexer/lexer.c | 9 ++++----- src/parser/grammar_advanced.c | 4 ++-- src/parser/grammar_basic.c | 2 +- src/utils/ast/ast_assignment.c | 30 ++++++++++++++++++++++++------ src/utils/ast/ast_assignment.h | 4 ++-- src/utils/ast/ast_command.c | 4 ++-- src/utils/ast/ast_command.h | 6 +++--- 8 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c index aba6dc7..cffcdb0 100644 --- a/src/execution/execution_helpers.c +++ b/src/execution/execution_helpers.c @@ -354,7 +354,7 @@ static int builtin_cd(char **argv, struct hash_map *vars) } } // char *pwd = getcwd("", ""); - char *pwd = get_var_or_env(pwd, "PWD"); + char *pwd = get_var_or_env(vars, "PWD"); if (chdir(path) != 0) { perror("cd"); diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index db4e066..fd5764d 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -87,8 +87,8 @@ static void update_flags(char *stream, ssize_t i, struct token_info *info) { if (i == 0) { - perror("Syntax error: word start with a '='"); - return; + perror("Syntax error: word start with a '='"); + return; } else info->has_equal = true; @@ -105,7 +105,7 @@ struct token *peek_token(struct lexer_context *ctx) // Usefull to know if we are inside a quote or double quote enum lexing_mode lexing_mode = LEXER_NORMAL; - struct token_info info = {true, 0}; + struct token_info info = { true, 0 }; char *stream = ctx->end_previous_token; ssize_t i = 0; @@ -165,11 +165,10 @@ struct token *pop_token(struct lexer_context *ctx) // Usefull to know if we are inside a quote or double quote enum lexing_mode lexing_mode = LEXER_NORMAL; - struct token_info info = {true, 0}; + struct token_info info = { true, 0 }; char *stream = ctx->end_previous_token; ssize_t i = 0; - if (ctx->current_token != NULL && ctx->current_token->type == TOKEN_EOF) { // we reached end of input, frees all the token still allocated. diff --git a/src/parser/grammar_advanced.c b/src/parser/grammar_advanced.c index 713fd99..d57e70e 100644 --- a/src/parser/grammar_advanced.c +++ b/src/parser/grammar_advanced.c @@ -6,8 +6,8 @@ #include #include -#include "grammar_basic.h" #include "grammar.h" +#include "grammar_basic.h" static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type) { @@ -71,7 +71,7 @@ struct ast *parse_prefix(struct lexer_context *ctx) if (token->type == TOKEN_ASSIGNMENT_WORD) { token = POP_TOKEN(); - return ast_create_assignment_word(token->data); + return ast_create_assignment(token->data); } else if (is_first(*token, RULE_REDIRECTION)) return parse_redirection(ctx); diff --git a/src/parser/grammar_basic.c b/src/parser/grammar_basic.c index b979b6e..598c70a 100644 --- a/src/parser/grammar_basic.c +++ b/src/parser/grammar_basic.c @@ -198,7 +198,7 @@ struct ast *parse_simple_command(struct lexer_context *ctx) { return err_simple_command(command_elements, redirections); } - if (prefix->type == AST_ASSIGNEMENT) + if (prefix->type == AST_ASSIGNMENT) { assignments = list_append(assignments, prefix); } diff --git a/src/utils/ast/ast_assignment.c b/src/utils/ast/ast_assignment.c index a2564c2..a839e9e 100644 --- a/src/utils/ast/ast_assignment.c +++ b/src/utils/ast/ast_assignment.c @@ -1,3 +1,5 @@ +#define _POSIX_C_SOURCE 200809L + #include "ast_assignment.h" #include @@ -14,15 +16,31 @@ struct ast_assignment *ast_get_assignment(struct ast *node) return (struct ast_assignment *)node->data; } -struct ast *ast_create_assignment(char *name, char *value) +/* @brief: splits the assignement 'name=value' into 2 parts, + * and fills the fields of ast_assignment with it. + */ +static void init_assignments(struct ast_assignment *ast_assignment, + char *assignment) { - struct ast_assignment *assignment_data = malloc(sizeof(struct ast_assignment)); + if (assignment == NULL) + return; + char *split_pos = strchr(assignment, '='); + if (split_pos == NULL) + return; + + *split_pos = '\0'; + ast_assignment->name = strdup(assignment); + ast_assignment->value = strdup(split_pos + 1); +} + +struct ast *ast_create_assignment(char *assignment) +{ + struct ast_assignment *assignment_data = + calloc(1, sizeof(struct ast_assignment)); if (!assignment_data) return NULL; - assignment_data->name = name; - assignment_data->value = value; - + init_assignments(assignement_data); return ast_create(AST_ASSIGNMENT, assignment_data); } @@ -33,4 +51,4 @@ void ast_free_assignment(struct ast_assignment *assignment_data) free(assignment_data->name); free(assignment_data->value); free(assignment_data); -} \ No newline at end of file +} diff --git a/src/utils/ast/ast_assignment.h b/src/utils/ast/ast_assignment.h index c958c2d..5be56c8 100644 --- a/src/utils/ast/ast_assignment.h +++ b/src/utils/ast/ast_assignment.h @@ -11,7 +11,7 @@ struct ast_assignment bool ast_is_assignment(struct ast *node); struct ast_assignment *ast_get_assignment(struct ast *node); -struct ast *ast_create_assignment(char *name, char *value); +struct ast *ast_create_assignment(char *assignment); void ast_free_assignment(struct ast_assignment *assignment_data); -#endif /* ! AST_ASSIGNMENT_H */ \ No newline at end of file +#endif /* ! AST_ASSIGNMENT_H */ diff --git a/src/utils/ast/ast_command.c b/src/utils/ast/ast_command.c index d7e148d..3865e0e 100644 --- a/src/utils/ast/ast_command.c +++ b/src/utils/ast/ast_command.c @@ -5,8 +5,8 @@ #include "../lists/lists.h" -struct ast *ast_create_command(struct list *command, - struct list *redirections, struct ast_list *assignments) +struct ast *ast_create_command(struct list *command, struct list *redirections, + struct ast_list *assignments) { struct ast_command *command_data = malloc(sizeof(struct ast_command)); if (!command_data) diff --git a/src/utils/ast/ast_command.h b/src/utils/ast/ast_command.h index 9322ac7..75c8b2e 100644 --- a/src/utils/ast/ast_command.h +++ b/src/utils/ast/ast_command.h @@ -8,7 +8,7 @@ struct ast_command { struct list *command; // A list of words (char*) struct ast_list *redirections; // A list of ASTs, all ast_redir - struct ast_list *assignments; // A list of ASTs, all ast_assignment + struct list *assignments; // A list of ASTs, all ast_assignment }; /** @@ -25,8 +25,8 @@ struct ast_command *ast_get_command(struct ast *node); /** * Creates a new AST node representing a command. */ -struct ast *ast_create_command(struct list *command, - struct list *redirections, struct ast_list *assignments); +struct ast *ast_create_command(struct list *command, struct list *redirections, + struct list *assignments); /* * @brief: frees the given ast_command and sets the pointer to NULL.