diff options
Diffstat (limited to '42sh/src/ast/ast.c')
| -rw-r--r-- | 42sh/src/ast/ast.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/42sh/src/ast/ast.c b/42sh/src/ast/ast.c new file mode 100644 index 0000000..41b7a55 --- /dev/null +++ b/42sh/src/ast/ast.c @@ -0,0 +1,164 @@ +#include "ast/ast.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "ast/ast_accessors.h" + +static const size_t ast_size_ltable[] = { + [AST_COMMAND] = sizeof(struct ast_command), + [AST_IF] = sizeof(struct ast_if), + [AST_LOGICAL] = sizeof(struct ast_logical), + [AST_LIST] = sizeof(struct ast_list), + [AST_REDIRECTION] = sizeof(struct ast_redirection), + [AST_PIPELINE] = sizeof(struct ast_pipeline), + [AST_WHILE] = sizeof(struct ast_while), + [AST_ASSIGN] = sizeof(struct ast_assign), + [AST_FOR] = sizeof(struct ast_for), + [AST_FUNCTION] = sizeof(struct ast_function), + [AST_SUBSHELL] = sizeof(struct ast_subshell) +}; + +struct ast *ast_create(enum ast_node type) +{ + struct ast *a = calloc(1, ast_size_ltable[type]); + if (!a) + { + fprintf(stderr, "ast_create: calloc failed.\n"); + return NULL; + } + + a->type = type; + return a; +} + +static void free_str_args(struct string **args) +{ + if (!args) + { + return; + } + size_t i = 0; + while (args[i]) + { + string_free(args[i]); + i++; + } + free(args); +} + +static void _free_ast_command(struct ast *ast) +{ + free_str_args(((struct ast_command *)ast)->args); + free(ast); +} + +static void _free_ast_if(struct ast *ast) +{ + ast_free(get_i(ast, 0)); + ast_free(get_i(ast, 1)); + ast_free(get_i(ast, 2)); + free(ast); +} + +static void _free_ast_list(struct ast *ast) +{ + for (size_t i = 0; i < ((struct ast_list *)ast)->nb_children; i++) + { + ast_free(get_i(ast, i)); + } + free(((struct ast_list *)ast)->children); + free(ast); +} + +static void _free_ast_logical(struct ast *ast) +{ + ast_free(((struct ast_logical *)ast)->left); + ast_free(((struct ast_logical *)ast)->right); + free(ast); +} + +static void _free_ast_pipeline(struct ast *ast) +{ + ast_free(((struct ast_pipeline *)ast)->left); + ast_free(((struct ast_pipeline *)ast)->right); + free(ast); +} + +static void _free_redir_struct(struct ast *ast) +{ + struct ast_redirection *ast_r = ((struct ast_redirection *)ast); + string_free(ast_r->redirect.fd); + string_free(ast_r->redirect.file); + string_free(ast_r->redirect.redir); +} + +static void _free_ast_redirection(struct ast *ast) +{ + ast_free(((struct ast_redirection *)ast)->expr); + _free_redir_struct(ast); + free(ast); +} + +static void _free_ast_while(struct ast *ast) +{ + ast_free(((struct ast_while *)ast)->cond); + ast_free(((struct ast_while *)ast)->body); + free(ast); +} + +static void _free_ast_assign(struct ast *ast) +{ + string_free(((struct ast_assign *)ast)->name); + string_free(((struct ast_assign *)ast)->val); + free(ast); +} + +static void _free_ast_for(struct ast *ast) +{ + struct ast_for *ast_f = ((struct ast_for *)ast); + ast_free(ast_f->left); + ast_free(ast_f->right); + string_free(ast_f->var); + // Someone probably forgot to free the ast itself + free(ast); +} + +static void _free_ast_function(struct ast *ast) +{ + struct ast_function *ast_fun = ((struct ast_function *)ast); + ast_free(ast_fun->body); + string_free(ast_fun->name); + free(ast); +} + +static void _free_ast_subshell(struct ast *ast) +{ + ast_free(((struct ast_subshell *)ast)->body); + free(ast); +} + +typedef void (*free_fct)(struct ast *); + +static const free_fct free_function_ltable[] = { + [AST_COMMAND] = _free_ast_command, + [AST_IF] = _free_ast_if, + [AST_LOGICAL] = _free_ast_logical, + [AST_LIST] = _free_ast_list, + [AST_PIPELINE] = _free_ast_pipeline, + [AST_REDIRECTION] = _free_ast_redirection, + [AST_WHILE] = _free_ast_while, + [AST_ASSIGN] = _free_ast_assign, + [AST_FOR] = _free_ast_for, + [AST_FUNCTION] = _free_ast_function, + [AST_SUBSHELL] = _free_ast_subshell +}; + +void ast_free(struct ast *ast) +{ + if (!ast) + { + return; + } + free_function_ltable[ast->type](ast); +} |
