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/parser/grammar_basic.c b/src/parser/grammar_basic.c index d4a740f..17e006f 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 (token->type == TOKEN_WORD) + if (is_first(*token, RULE_SIMPLE_COMMAND)) { - return parse_simple_command(ctx); + result = parse_simple_command(ctx); } - else if (token->type == TOKEN_IF) + else if (is_first(*token, RULE_SHELL_COMMAND)) { - return parse_shell_command(ctx); + parse_shell_command(ctx); } else { @@ -168,64 +169,102 @@ struct ast *parse_command(struct lexer_context *ctx) } } +/* @brief: frees command_elements and redirections lists (helper func) + * @return: NULL + */ +static void *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 + + 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(); + } + } - // WORD - struct token *token = POP_TOKEN(); if (token->type != TOKEN_WORD) { - perror("Expected a command but got a different token type"); - return NULL; + if (!has_prefix) + { + perror("Expected a command but got a different token type"); + return err_simple_command(command_elements, redirections); + } + // else : only prefixes } - char *command = strdup(token->data); - command_elements = list_append(command_elements, command); - - token = PEEK_TOKEN(); - - // Eventual elements - while (is_first(*token, RULE_ELEMENT)) + else { - // Get element - struct ast *element = parse_element(ctx); - if (element == NULL) + if (token->type == TOKEN_WORD) { - list_deep_destroy(command_elements); - return NULL; - } + char *command = strdup(token->data); + command_elements = list_append(command_elements, command); - // Get element type - if (ast_is_word(element)) - { - struct ast_word *element_word = ast_get_word(element); - command_elements = - list_append(command_elements, element_word->word); + POP_TOKEN(); + token = PEEK_TOKEN(); } - else if (ast_is_redir(element)) + // Eventual elements + while (is_first(*token, RULE_ELEMENT)) { - // TODO - perror("NOT IMPLEMENTED"); - return NULL; - } - else - { - perror("Internal error: unexpected return value from parse_element " - "in parse_simple_command"); - list_deep_destroy(command_elements); - return NULL; - } + // 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); + 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 - 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); - return NULL; + return err_simple_command(command_elements, redirections); } return result; } @@ -254,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 @@ -272,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 @@ -311,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; 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. 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, // >&