summaryrefslogtreecommitdiff
path: root/42sh/src/ast/ast.c
diff options
context:
space:
mode:
Diffstat (limited to '42sh/src/ast/ast.c')
-rw-r--r--42sh/src/ast/ast.c164
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);
+}