diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-03-31 21:31:26 +0200 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-03-31 21:31:26 +0200 |
| commit | 808d1499f5708ad4eda3612416e62efe6fdff021 (patch) | |
| tree | 1a2da935d99724de64dfc9b77347c1f5805d9256 | |
| parent | 941099778b59da6b904c284e8a82affe4766124b (diff) | |
| download | minishell-808d1499f5708ad4eda3612416e62efe6fdff021.tar.gz minishell-808d1499f5708ad4eda3612416e62efe6fdff021.tar.bz2 minishell-808d1499f5708ad4eda3612416e62efe6fdff021.zip | |
More specific AST struct and evaluation start
| -rw-r--r-- | include/ast.h | 80 | ||||
| -rw-r--r-- | include/minishell.h | 13 | ||||
| -rw-r--r-- | include/ms_eval.h | 71 | ||||
| -rw-r--r-- | include/ms_parse.h | 42 | ||||
| m--------- | libft | 0 | ||||
| -rw-r--r-- | src/builtin/env.c | 6 | ||||
| -rw-r--r-- | src/eval/eval.c | 128 | ||||
| -rw-r--r-- | src/eval/read.c | 89 | ||||
| -rw-r--r-- | src/eval/val.c | 69 | ||||
| -rw-r--r-- | src/main.c | 2 | ||||
| -rw-r--r-- | src/parse/ast.c | 72 | ||||
| -rw-r--r-- | src/utils.c | 13 |
12 files changed, 228 insertions, 357 deletions
diff --git a/include/ast.h b/include/ast.h new file mode 100644 index 0000000..4ee3396 --- /dev/null +++ b/include/ast.h @@ -0,0 +1,80 @@ +#ifndef AST_H +# define AST_H + +/** +** \file ast.h +** \brief AST structs +*/ + +/** +** \brief Separator type +** \param SEP_END Regular command end `;` +** \param SEP_PIPE Pipe output of left to right `|` +** \param SEP_AND Execute right if left status == 0 `&&` +** \param SEP_OR Execute right if left status != 0 `||` +*/ + +typedef enum +{ + SEP_END, + SEP_PIPE, + SEP_AND, + SEP_OR, +} t_sep; + +typedef struct s_ast t_ast; +/** +** \brief Line struct +** \param left AST to the left of separator +** \param right AST to the right of separator +** \param sep Type of separator +*/ + +typedef struct +{ + t_ast *left; + t_ast *right; + t_sep sep; +} t_line; + +/** +** \brief Command struct +** \param argv Array of string, all arguments beginning with executable name +** \param in STDIN redirection filename +** \param out STDOUT redirection filename +** \param is_append True if out redirection is append to file +*/ + +typedef struct +{ + char **argv; + char *in; + char *out; + bool is_append; +} t_cmd; + +typedef enum +{ + TAG_CMD, + TAG_LINE, +} t_ast_tag; + +/** +** \brief AST node struct +** \param type Node type +** \param data Union containning possible node data +** \param data::cmd Command struct +** \param data::line Line struct +*/ + +struct s_ast +{ + t_ast_tag tag; + union + { + t_line line; + t_cmd cmd; + } data; +}; + +#endif diff --git a/include/minishell.h b/include/minishell.h index 9931b15..6a00ca8 100644 --- a/include/minishell.h +++ b/include/minishell.h @@ -35,18 +35,25 @@ # include "libft_util.h" # include "ms_parse.h" +// # include "ms_eval.h" + +/** +** \brief Value of pipe entry if closed +*/ + +# define PIPE_CLOSED -1 /** ** \brief Pipe write index */ -# define MS_PIPE_WRITE 1 +# define PIPE_WRITE 1 /** ** \brief Pipe read index */ -# define MS_PIPE_READ 0 +# define PIPE_READ 0 typedef t_ftht* t_path; typedef t_ftht* t_env; @@ -80,6 +87,6 @@ int ms_exit(void); ** util.c - various utilitary functions */ -void ms_ht_del_str_entry(t_ftht_content *content); +void ms_ht_del_str_entry(t_ftht_entry *entry); #endif diff --git a/include/ms_eval.h b/include/ms_eval.h index 12c2b7e..b53b845 100644 --- a/include/ms_eval.h +++ b/include/ms_eval.h @@ -6,71 +6,38 @@ ** \brief Evaluation module */ -/* -** arg: -** type ARG -** value string -** -** redir in: -** type REDIRIN -** value fd -** -** redir out: -** type REDIROUT -** value fd -** -** redir append: -** type REDIRAPPEND -** value fd -*/ +# include "minishell.h" /** -** \enum t_val_type -** \brief A type for an evaluation node -** -** \param VAL_ERR error -** \param VAL_ERR argument -** \param VAL_REDIR redirection -** \param VAL_SEXPR S-expression +** \brief Evaluation state struct */ -typedef enum +typedef struct { - VAL_ERR, - VAL_ARG, - VAL_EXEC, - VAL_REDIR_IN, - VAL_REDIR_OUT, - VAL_REDIR_APPEND, - VAL_CMD, - VAL_SEXPR, -} t_val_type; + int status; + int in_pipe[2]; // need stack pipe + int out_pipe[2]; + t_path path; + t_env env; +} t_eval_state; /** -** \brief An evaluation node struct -** \param type type of node -** \param data union of possible data -** \param data::fd file descriptor for redirection node -** \param data::str string for error, arguments, command +** \brief Evaluation status struct */ typedef struct { - t_val_type type; - union - { - char *str; - int code; - int fd; - } data; -} t_val; + char *err; + int status; +} t_eval_status; + /** -** \brief evaluate an AST -** \param path path to commands executable -** \param env environment variables -** \param ast Abstract syntax tree to evaluate +** \brief Evaluate an AST +** \param state State of the evaluation +** \param ast Abstract syntax tree to evaluate */ -int ms_eval(t_path path, t_env env, t_ast *ast); + +int ms_eval(t_eval_state *state, t_ast *ast); #endif diff --git a/include/ms_parse.h b/include/ms_parse.h index 0810ec2..0a33ccf 100644 --- a/include/ms_parse.h +++ b/include/ms_parse.h @@ -14,6 +14,7 @@ # define MS_PARSE_H # include "minishell.h" +# include "ast.h" /** ** \file ms_parse.h @@ -41,16 +42,16 @@ ** \param TAG_REDIR_APPEND `>>` */ -typedef enum -{ - TAG_STRING, - TAG_SEP, - TAG_REDIR_OUT, - TAG_REDIR_IN, - TAG_REDIR_APPEND, - TAG_CMD, - TAG_LINE, -} t_tag; +// typedef enum +// { +// TAG_STRING, +// TAG_SEP, +// TAG_REDIR_OUT, +// TAG_REDIR_IN, +// TAG_REDIR_APPEND, +// TAG_CMD, +// TAG_LINE, +// } t_ast_tag; /** ** \brief AST (Abstract Syntax Tree) @@ -60,14 +61,13 @@ typedef enum ** \param children children nodes */ -typedef struct s_ast -{ - t_tag tag; - char* content; - int children_num; - struct s_ast** children; -} t_ast; - +// typedef struct s_ast +// { +// t_tag tag; +// char* content; +// int children_num; +// struct s_ast** children; +// } t_ast; /* ** lexer.c @@ -85,8 +85,8 @@ t_ast *ms_parse(char *input); ** ast.c */ -t_ast *ms_ast_new(t_tag tag); -void ms_ast_destroy(t_ast *ast); -void ms_ast_iter(t_ast *ast, void (*f)(void *f_arg, t_ast *children), void *arg); +// t_ast *ms_ast_new(t_tag tag); +// void ms_ast_destroy(t_ast *ast); +// void ms_ast_iter(t_ast *ast, void (*f)(void *f_arg, t_ast *children), void *arg); #endif diff --git a/libft b/libft -Subproject 901402c99018422c994bdb297e3ba404969c88e +Subproject dd5d60dc4cf8052feb00847f9b2276cf105b055 diff --git a/src/builtin/env.c b/src/builtin/env.c index 226b5b9..4855917 100644 --- a/src/builtin/env.c +++ b/src/builtin/env.c @@ -5,11 +5,11 @@ #include "minishell.h" -void st_print_env_variable(t_ftht_content *content) +void st_print_env_variable(t_ftht_entry *entry) { - ft_putstr(content->key); + ft_putstr(entry->key); ft_putchar('='); - ft_putstr((char*)content->value); + ft_putstr((char*)entry->value); ft_putchar('\n'); } diff --git a/src/eval/eval.c b/src/eval/eval.c index 8fca2c1..a5e2c71 100644 --- a/src/eval/eval.c +++ b/src/eval/eval.c @@ -3,101 +3,75 @@ ** \brief Evaluation of an AST */ -#include "minishell.h" +#include "ms_eval.h" - -static bool check_node(t_ast *ast) +static int eval_line(t_eval_state *state, t_line *line) { + int status; + if (line->right == NULL) + return (ms_eval(state, line->left)); + status = ms_eval(state, line->left); + if ((line->sep == SEP_AND && status != 0) || + (line->sep == SEP_OR && status == 0)) + return (status); + return (ms_eval(state, line->right)); } -static int eval_sep(t_ast *ast) +static char *search_exec_path(t_path path, char *path_var, char *exec_name) { - if (ast->children_num != 2) - return (-1); - if (ast->tag == TAG_ENDCMD) - { - ms_eval(path, env, ast->children[0]); - return (ms_eval(path, env, ast->children[1])); - } - if (ast->tag == TAG_AND) - { - status = ms_eval(path, env, ast->children[0]); - if (status == 0) - return (ms_eval(path, env, ast->children[1])); - else - return (status); - } - if (ast->tag == TAG_OR) + char *exec_path; + + // try current first + if ((exec_path = ft_htget(path, exec_name)) == NULL) { - status = ms_eval(path, env, ast->children[0]); - if (status != 0) - return (ms_eval(path, env, ast->children[1])); - else - return (status); + if (ms_path_update(path, path_var) == NULL) + return (NULL); + if ((exec_path = ft_htget(path, exec_name)) == NULL) + return (NULL); } - return (-1); + return exec_path; } -static char **get_args(t_ast *ast) +static int eval_cmd(t_eval_state *state, t_cmd *cmd) { - int i; - int counter; - char **argv; + int child_pid; + char *exec_path; - if (ast->tag != TAG_CMD) - return (NULL); - counter = 0; - i = -1; - while (++i < ast->children_num) - if (ast->children[i]->tag == TAG_ARG) - counter++; - if ((argv = (char**)ft_calloc(counter + 1, sizeof(char*))) == NULL) - return (NULL); - counter = 0; - i = -1; - while (++i < ast->children_num) + if ((exec_path = search_exec_path(state->path, ft_htget(state->env, "PATH"), cmd->argv[0])) == NULL) + return (-1); + if (cmd->in != NULL) { - if (ast->children[i]->tag != TAG_ARG) - continue ; - if ((argv[counter] = ft_strdup(ast->children[i]->content)) == NULL) - { - ft_split_destroy(argv); - return (NULL); - } + if ((state->in_pipe[PIPE_WRITE] = open(cmd->in, O_RDONLY)) < 0) + return (-1); + } + if (cmd->out != NULL) + { + if ((state->out_pipe[PIPE_READ] = open(cmd->out, + (cmd->is_append ? O_WRONLY : O_APPEND) | O_CREAT)) < 0) + return (-1); } - return (argv); - - /* maybe - int i; - char *tmp; - t_vec *vec; - if ((vec = ft_vecnew(sizeof(char*))) == NULL) - return (NULL); - i = -1; - while (++i < ast->children_num) + if ((child_pid = fork()) == -1) + return (-1); + if (child_pid == 0) { - if (ast->children[i]->tag != TAG_ARG) - continue ; - if ((tmp = ft_strdup(ast->children[i]->content)) == NULL - || ft_vecpush(vec, tmp) == NULL)) - { - ft_vecdestroy(vec, free); - return (NULL); - } + if (state->in_pipe[PIPE_READ] != PIPE_CLOSED) + dup2(STDIN_FILENO, state->in_pipe[PIPE_READ]); + if (state->out_pipe[PIPE_WRITE] != PIPE_CLOSED) + dup2(STDOUT_FILENO, state->out_pipe[PIPE_WRITE]); + if (execve(exec_path, cmd->argv, NULL /*env_array*/) == -1) + exit(EXIT_FAILURE); } - return (vec); - */ + wait(&child_pid); + return (WEXITSTATUS(child_pid)); } -//reduce? -int ms_eval(t_path path, t_env env, t_ast *ast) +int ms_eval(t_eval_state *state, t_ast *ast) { - int status; - - if (ast->tag == TAG_ENDCMD || ast->tag == TAG_AND - || ast->tag == TAG_OR || ast->tag == TAG_PIPE) - return (eval_sep(ast)); - + if (ast->tag == TAG_LINE) + return eval_line(state, &ast->data.line); + if (ast->tag == TAG_CMD) + return eval_cmd(state, &ast->data.cmd); + return (-1); } diff --git a/src/eval/read.c b/src/eval/read.c deleted file mode 100644 index 1364fca..0000000 --- a/src/eval/read.c +++ /dev/null @@ -1,89 +0,0 @@ -/** -** \file read.c -** \brief Convert AST to value tree -*/ - -#include "ms_evalue.h" - -static t_value *read_cmd_args(t_value *value_cmd, t_ast *cmd) -{ - -} - -/* static void arg_count_iterator(int *counter, t_ast *child) */ -/* { */ -/* if (child == TAG_STRING) */ -/* (*counter)++; */ -/* } */ -/* */ -/* static void arg_add_iterator(t_value *value_cmd, t_ast *child) */ -/* { */ -/* if (child != TAG_STRING) */ -/* return ; */ -/* value_cmd_push( */ -/* } */ - -/** -** \brief Convert a command AST to a value -** \param cmd Command AST -** \return Converted value -*/ - -static t_value *read_cmd(t_ast *cmd) -{ - int i; - int arg_num; - t_value *value_cmd; - - if (ast->children_num < 1 || ast->children[0]->type != TAG_STRING) - return (value_new_string(VAL_ERR, "Empty command"); - arg_num = 0; - i = -1; - while (++i < ast->children_num) - if (ast->children[i]->type == TAG_STRING) - arg_num++; - if ((value_cmd = value_new_cmd(arg_num)) == NULL) - return (NULL); - i = -1; - while (++i < ast->children_num) - if (ast->children[i]->type == TAG_STRING) - { - if ((value_cmd->args[arg_num++] = - ft_strdup(ast->children[i]->contents)) == NULL) - return (NULL); - } - while (i-- > 0) - if (ast->children[i]->type != TAG_STRING) - { - if (ast->children[i]->tag == TAG_REDIR_IN - && value_cmd->in == NULL) - value_cmd->in = value_new_redir(VAL_REDIR_IN); // check null - else if (ast->children[i]->tag == TAG_REDIR_OUT - && value_cmd->out == NULL)) - value_cmd->out = value_new_redir(VAL_REDIR_OUT); - else if (ast->children[i]->tag == TAG_REDIR_APPEND - && value_cmd->append == NULL)) - value_cmd->append = value_new_redir(VAL_REDIR_APPEND); - } - return (value_cmd); -} - -/** -** \brief Convert an AST to value -** \param ast AST to convert -** \return Converted value -*/ - -t_value *eval_read(t_ast *ast) -{ - t_value *value; - - /* if (ast->tag == TAG_REDIR_IN) */ - /* return (value_new_redir(VAL_REDIR_IN)); */ - /* else if (ast->tag == TAG_REDIR_OUT) */ - /* return (value_new_redir(VAL_REDIR_OUT)); */ - /* else if (ast->tag == TAG_REDIR_APPEND) */ - /* return (value_new_redir(VAL_REDIR_APPEND)); */ - else if (ast->tag == TAG_CMD) - return (read_cmd(ast)); -} diff --git a/src/eval/val.c b/src/eval/val.c deleted file mode 100644 index 3293972..0000000 --- a/src/eval/val.c +++ /dev/null @@ -1,69 +0,0 @@ -/** -** \file val.c -** \brief Evaluation value manipulation -*/ - -#include "ms_evalue.h" - -/** -** \brief Allocate memory for a t_value and set his type -** \param type Type of valueue -** \return The allocated value -*/ - -t_value *value_new(t_value_type type) -{ - t_value *value; - - if ((value = (t_value*)malloc(sizeof(t_value*))) == NULL) - return (NULL); - value->type = type; - return (value); -} - -/** -** \brief Create a new redirection value from a filename -** \param type Type of redirection and value -** \param filename Name of the file to open -** \return Redirection value -** \warning Undefined behavior on none redirection type. -*/ - -t_value *value_new_redir(t_value_type type, char *filename) -{ - t_value *value; - - if ((value = value_new(type)) == NULL) - return (NULL); - if (type == VAL_REDIR_IN) - value->data.fd = open(filename, O_RDONLY); - else if (type == VAL_REDIR_OUT) - value->data.fd = open(filename, O_WRONLY | O_CREAT); - else if (type == VAL_REDIR_APPEND) - value->data.fd = open(filename, O_APPEND | O_CREAT); - if (value->data.fd < 0) - { - free(value); - return (NULL); - } - return (value); -} - -/** -** \brief Create a new string value (i.e error, arg, cmd) -** \param type String value type -** \param str String data -** \return String value -*/ - -t_value *value_new_string(t_value_type type, char *str) -{ - t_value *value; - - if ((value == malloc(sizeof(t_value))) == NULL) - return (NULL); - value->type = type; - if ((value->data.str = ft_strdup(str)) == NULL) - return (NULL); - return (value); -} @@ -35,7 +35,7 @@ int main(int argc, char **argv, const char **envp) (void)argc; (void)argv; env = ms_env_from_array((char**)envp); - path = ms_path_update(NULL, ft_htget(env, MS_PATH_KEY)); + path = ms_path_update(NULL, ft_htget(env, "PATH")); printf("%s\n", (char*)ft_htget(path, "nmap")); /* ms_env(env); */ diff --git a/src/parse/ast.c b/src/parse/ast.c index f566832..44a36cd 100644 --- a/src/parse/ast.c +++ b/src/parse/ast.c @@ -11,18 +11,18 @@ ** \return The allocated node */ -t_ast *ms_ast_new(t_tag tag) -{ - t_ast *ast; - - if ((ast = (t_ast*)malloc(sizeof(t_ast))) == NULL) - return (NULL); - ast->tag = tag; - ast->content = NULL; - ast->children_num = 0; - ast->children = NULL; - return (ast); -} +/* t_ast *ms_ast_new(t_ast_tag tag) */ +/* { */ +/* t_ast *ast; */ +/* */ +/* if ((ast = (t_ast*)malloc(sizeof(t_ast))) == NULL) */ +/* return (NULL); */ +/* ast->tag = tag; */ +/* ast->content = NULL; */ +/* ast->children_num = 0; */ +/* ast->children = NULL; */ +/* return (ast); */ +/* } */ /** ** \brief Destroy an allocated AST @@ -30,19 +30,19 @@ t_ast *ms_ast_new(t_tag tag) ** \param ast AST to destroy */ -void ms_ast_destroy(t_ast *ast) -{ - int i; - - if (ast == NULL) - return ; - i = -1; - while (++i < ast->children_num) - ms_ast_destroy(ast->children[i]); - free(ast->children); - free(ast->content); - free(ast); -} +/* void ms_ast_destroy(t_ast *ast) */ +/* { */ +/* int i; */ +/* */ +/* if (ast == NULL) */ +/* return ; */ +/* i = -1; */ +/* while (++i < ast->children_num) */ +/* ms_ast_destroy(ast->children[i]); */ +/* free(ast->children); */ +/* free(ast->content); */ +/* free(ast); */ +/* } */ /** ** \brief Iterate over an AST node's childs @@ -50,14 +50,14 @@ void ms_ast_destroy(t_ast *ast) ** \param arg Pointer that will be passed to `f`, to keep information between iterations */ -void ms_ast_iter( - t_ast *ast, - void (*f)(void *f_arg, t_ast *children), - void *arg) -{ - int i; - - i = -1; - while (++i < ast->children_num) - f(arg, ast->children[i]); -} +/* void ms_ast_iter( */ +/* t_ast *ast, */ +/* void (*f)(void *f_arg, t_ast *children), */ +/* void *arg) */ +/* { */ +/* int i; */ +/* */ +/* i = -1; */ +/* while (++i < ast->children_num) */ +/* f(arg, ast->children[i]); */ +/* } */ diff --git a/src/utils.c b/src/utils.c index 2b655bf..815e8e3 100644 --- a/src/utils.c +++ b/src/utils.c @@ -19,14 +19,15 @@ /** ** \brief Delete function for a entry containing a allocated key and value -** \param content Hash table entry content +** \param entry Hash table entry +** */ -void ms_ht_del_str_entry(t_ftht_content *content) +void ms_ht_del_str_entry(t_ftht_entry *entry) { - if (content == NULL) + if (entry == NULL) return ; - free(content->key); - free(content->value); - free(content); + free(entry->key); + free(entry->value); + free(entry); } |
