diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2020-10-06 15:57:29 +0200 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2020-10-06 15:57:29 +0200 |
| commit | 54394620893f7245c7697a57d724d430d06b57d1 (patch) | |
| tree | 8e51b671bcb2cdba4306165eaba39cc1f99f1cf4 | |
| parent | 930bb63605984abeda8c887a6333109c004d3b00 (diff) | |
| download | minishell-54394620893f7245c7697a57d724d430d06b57d1.tar.gz minishell-54394620893f7245c7697a57d724d430d06b57d1.tar.bz2 minishell-54394620893f7245c7697a57d724d430d06b57d1.zip | |
Added pipeline ast and pipeline evaluation (not working when first command is infinite)
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | include/parser.h | 23 | ||||
| -rw-r--r-- | src/ast.c | 7 | ||||
| -rw-r--r-- | src/debug.c | 167 | ||||
| -rw-r--r-- | src/eval/eval.c | 8 | ||||
| -rw-r--r-- | src/eval/operation.c | 105 | ||||
| -rw-r--r-- | src/main.c | 4 | ||||
| -rw-r--r-- | src/parser/parser.c | 44 |
9 files changed, 241 insertions, 123 deletions
@@ -9,3 +9,4 @@ tmp/* a.out vgcore.* *.orig +*.dSYM @@ -6,7 +6,7 @@ # By: cacharle <marvin@42.fr> +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/02/03 04:14:24 by cacharle #+# #+# # -# Updated: 2020/09/14 19:10:10 by charles ### ########.fr # +# Updated: 2020/10/02 12:52:19 by cacharle ### ########.fr # # # # **************************************************************************** # @@ -25,7 +25,8 @@ OBJDIRS = $(shell find $(SRCDIR) -type d | sed 's/src/$(OBJDIR)/') INCLUDE = $(shell find $(INCLUDEDIR) -name "*.h") -SRC = $(shell find $(SRCDIR) -name "*.c") +SRC = $(shell find $(SRCDIR) -type f -name "*.c") + OBJ = $(SRC:$(SRCDIR)/%.c=$(OBJDIR)/%.o) diff --git a/include/parser.h b/include/parser.h index ff644ed..d2d3351 100644 --- a/include/parser.h +++ b/include/parser.h @@ -6,7 +6,7 @@ /* By: cacharle <cacharle@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 09:00:00 by cacharle #+# #+# */ -/* Updated: 2020/08/28 10:06:44 by charles ### ########.fr */ +/* Updated: 2020/10/06 08:35:42 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -54,17 +54,19 @@ typedef struct s_op } t_op; /* -** \brief AST node tag (type) -** \param TAG_CMD Command AST node -** \param TAG_OP Operation AST node -** \param TAG_PARENT Parenthesis AST node +** \brief AST node tag (type) +** \param TAG_CMD Command AST node +** \param TAG_OP Operation AST node +** \param TAG_PARENT Parenthesis AST node +** \param TAG_PIPELINE Pipeline AST node */ -enum e_ast +enum e_ast { AST_CMD, AST_OP, AST_PARENT, + AST_PIPELINE, }; /* @@ -72,6 +74,7 @@ enum e_ast ** \param tag Node tag ** \param op Operation struct ** \param cmd_argv Command argv tokens +** \param pipline List of commands in a pipeline ** \param parend_ast AST inside parenthesis ** \param redirs Redirections tokens */ @@ -83,6 +86,7 @@ typedef struct s_ast { t_op op; t_tok_lst *cmd_argv; + t_ftlst *pipeline; struct s_ast *parent_ast; }; t_tok_lst *redirs; @@ -102,18 +106,13 @@ void ast_destroy(t_ast *ast); typedef struct s_parsed { bool syntax_error; - union - { - t_ast *ast; - t_tok_lst *redir; // more general - }; + t_ast *ast; t_tok_lst *rest; } t_parsed; t_parsed *parsed_new(t_ast *ast, t_tok_lst *rest); t_parsed *parsed_error(const char *format, ...); - /* ** parse.c */ @@ -6,7 +6,7 @@ /* By: charles <charles@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/01 17:05:42 by charles #+# #+# */ -/* Updated: 2020/08/27 20:31:48 by charles ### ########.fr */ +/* Updated: 2020/10/06 09:58:35 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -57,6 +57,11 @@ void ast_destroy(t_ast *ast) ast_destroy(ast->op.right); } else if (ast->tag == AST_PARENT) + { ast_destroy(ast->parent_ast); + tok_lst_destroy(&ast->redirs, free); + } + else if (ast->tag == AST_PIPELINE) + ft_lstdestroy(&ast->pipeline, (void (*)(void*))ast_destroy); free(ast); } diff --git a/src/debug.c b/src/debug.c index 3fe7784..42c34eb 100644 --- a/src/debug.c +++ b/src/debug.c @@ -6,19 +6,31 @@ /* By: charles <me@cacharle.xyz> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/09/16 15:58:35 by charles #+# #+# */ -/* Updated: 2020/09/16 16:18:11 by charles ### ########.fr */ +/* Updated: 2020/10/06 13:14:44 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ #include <stdio.h> #include "lexer.h" +#include "parser.h" void debug_tok_lst(t_tok_lst *tokens) { while (tokens != NULL) { // FIXME libft for safer correction - printf("[%#06x] |%s|%s\n", tokens->tag, tokens->content, tokens->tag & TAG_STICK ? " STICK" : ""); + printf("[%#06x] |%s|%s\n", tokens->tag, tokens->content, + tokens->tag & TAG_STICK ? " STICK" : ""); + tokens = tokens->next; + } +} + +void debug_tok_lst_line(t_tok_lst *tokens) +{ + while (tokens != NULL) + { + // FIXME libft for safer correction + printf("|%s| ", tokens->content); tokens = tokens->next; } } @@ -35,66 +47,91 @@ int debug_lexer(char *input) return (status); } -/* void token_debug(void *v) */ -/* { */ -/* t_token *t; */ -/* */ -/* t= v; */ -/* printf("[%4d %d] (%s)\n", t->tag, !!(t->tag & TAG_STICK), t->content); */ -/* } */ -/* */ -/* void token_put(void *v) */ -/* { */ -/* t_token *t; */ -/* */ -/* t= v; */ -/* printf("%s ", t->content); */ -/* } */ -/* */ -/* void print_level(int level) */ -/* { */ -/* while (level-- > 0) */ -/* printf(" "); */ -/* } */ -/* */ -/* void ast_print(int level, t_ast *ast) */ -/* { */ -/* if (ast->tag == AST_PARENT) */ -/* { */ -/* print_level(level); */ -/* printf("parent: redir [ "); */ -/* ft_lstiter(ast->redirs, token_put); */ -/* printf(" ]\n"); */ -/* ast_print(level + 1, ast->parent_ast); */ -/* } */ -/* else if (ast->tag == AST_CMD) */ -/* { */ -/* print_level(level); */ -/* printf("cmd: [ "); */ -/* ft_lstiter(ast->cmd_argv, token_put); */ -/* printf(" ] redirs: ["); */ -/* ft_lstiter(ast->redirs, token_put); */ -/* printf(" ]"); */ -/* } */ -/* else if (ast->tag == AST_OP) { */ -/* #<{(| printf("SEP: %d\n", ast->op.sep); |)}># */ -/* print_level(level); */ -/* #<{(| printf("redirs: ["); |)}># */ -/* #<{(| ft_lstiter(ast->redirs, token_put); |)}># */ -/* #<{(| printf(" ] "); |)}># */ -/* printf("{\n"); */ -/* */ -/* print_level(level); */ -/* printf(" left:\n"); */ -/* ast_print(level + 1, ast->op.left); */ -/* */ -/* printf("\n"); */ -/* print_level(level); */ -/* printf(" right:\n"); */ -/* ast_print(level + 1, ast->op.right); */ -/* */ -/* printf("\n"); */ -/* print_level(level); */ -/* printf("}\n"); */ -/* } */ -/* } */ +void print_level(int level) +{ + while (level-- > 0) + printf(" "); +} + +void ast_print(int level, t_ast *ast) +{ + /* printf("%p\n", ast); */ + if (ast == NULL) + return ; + if (ast->tag == AST_PARENT) + { + print_level(level); + printf("parent: redir [ "); + debug_tok_lst_line(ast->redirs); + printf(" ]\n"); + ast_print(level + 1, ast->parent_ast); + } + else if (ast->tag == AST_PIPELINE) + { + print_level(level); + printf("pipeline: {\n"); + t_ftlst *curr = ast->pipeline; + /* printf("%p\n", curr); */ + /* printf("%p\n", curr->next); */ + /* printf("%p\n", curr->next->next); */ + + /* printf("%p\n", curr->data); */ + /* printf("%p\n", curr->next->); */ + while (curr != NULL) + { + ast_print(level + 1, (t_ast*)curr->data); + printf("\n"); + curr = curr->next; + } + print_level(level); + printf(" }\n"); + } + else if (ast->tag == AST_CMD) + { + print_level(level); + printf("cmd: [ "); + debug_tok_lst_line(ast->cmd_argv); + printf(" ] redirs: ["); + debug_tok_lst_line(ast->redirs); + printf(" ]"); + } + else if (ast->tag == AST_OP) { + /* printf("SEP: %d\n", ast->op.sep); */ + /* printf("redirs: ["); */ + /* ft_lstiter(ast->redirs, token_put); */ + /* printf(" ] "); */ + printf("{\n"); + + print_level(level); + printf(" left:\n"); + ast_print(level + 1, ast->op.left); + + printf("\n"); + print_level(level); + printf(" right:\n"); + ast_print(level + 1, ast->op.right); + + printf("\n"); + print_level(level); + printf("}\n"); + } +} + +int debug_parser(char *input) +{ + int status; + t_tok_lst *out; + + status = lexer(input, &out); + if (status != 0) + { + printf("Lexer error\n"); + debug_tok_lst(out); + return (status); + } + t_parsed *ret = parse(out); + if (ret == NULL || ret->syntax_error) + return (1); + ast_print(0, ret->ast); + return (status); +} diff --git a/src/eval/eval.c b/src/eval/eval.c index 2775f9e..d2eb822 100644 --- a/src/eval/eval.c +++ b/src/eval/eval.c @@ -6,7 +6,7 @@ /* By: charles <me@cacharle.xyz> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/09/13 20:38:06 by charles #+# #+# */ -/* Updated: 2020/09/16 16:29:20 by charles ### ########.fr */ +/* Updated: 2020/10/06 12:57:33 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -74,11 +74,13 @@ int fork_wrap( int eval(int fds[2], t_env env, t_ast *ast, pid_t *child_pid, int fd_to_close) { - if (ast->tag == AST_PARENT) - return (eval_parenthesis(fds, env, ast, child_pid, fd_to_close)); if (ast->tag == AST_OP) return (eval_operation(fds, env, ast)); if (ast->tag == AST_CMD) return (eval_cmd(fds, env, ast, child_pid, fd_to_close)); + if (ast->tag == AST_PIPELINE) + return (eval_pipeline(fds, env, ast)); + if (ast->tag == AST_PARENT) + return (eval_parenthesis(fds, env, ast, child_pid, fd_to_close)); return (EVAL_FATAL); } diff --git a/src/eval/operation.c b/src/eval/operation.c index fbdf5bb..a54b657 100644 --- a/src/eval/operation.c +++ b/src/eval/operation.c @@ -6,7 +6,7 @@ /* By: charles <charles.cabergs@gmail.com> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/06/17 15:27:22 by charles #+# #+# */ -/* Updated: 2020/09/15 20:30:27 by charles ### ########.fr */ +/* Updated: 2020/10/06 15:53:12 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,51 +17,84 @@ int eval_operation(int fds[2], t_env env, t_ast *ast) int status; int left_fds[2]; int right_fds[2]; - int p[2]; left_fds[FD_READ] = fds[FD_READ]; left_fds[FD_WRITE] = FD_NONE; right_fds[FD_READ] = FD_NONE; right_fds[FD_WRITE] = fds[FD_WRITE]; - if (ast->op.sep == TAG_PIPE) - { - pipe(p); - left_fds[FD_WRITE] = p[FD_WRITE]; - right_fds[FD_READ] = p[FD_READ]; - - pid_t left_pid; - pid_t right_pid; - - /* left_pid = fork(); */ - /* if (left_pid != 0) */ - /* { */ - /* dup2(p[FD_WRITE], STDOUT_FILENO); */ - /* close(p[FD_READ]); */ - /* exit(eval(left_fds, env, ast->op.left, NULL)); */ - /* } */ - /* */ - /* right_pid = fork(); */ - /* if (right_pid != 0) */ - /* { */ - /* dup2(p[FD_READ], STDIN_FILENO); */ - /* close(p[FD_WRITE]); */ - /* exit(eval(right_fds, env, ast->op.right, NULL)); */ - /* } */ - eval(left_fds, env, ast->op.left, &left_pid, p[FD_READ]); - close(p[FD_WRITE]); - status = eval(right_fds, env, ast->op.right, &right_pid, p[FD_WRITE]); - close(p[FD_READ]); - - wait(&left_pid); - wait(&left_pid); - return (status); - } if ((status = eval(left_fds, env, ast->op.left, NULL, FD_NONE)) == EVAL_FATAL) return (EVAL_FATAL); g_state.last_status = status; if ((ast->op.sep == TAG_AND && status != 0) || - (ast->op.sep == TAG_PIPE && status != 0) || (ast->op.sep == TAG_OR && status == 0)) return (status); return (eval(right_fds, env, ast->op.right, NULL, FD_NONE)); } + +/* pid_t run_piped_child(t_env env, t_ast *ast, int copied, int closed) */ +/* { */ +/* pid_t pid; */ +/* int fds[2]; */ +/* */ +/* pid = fork(); */ +/* if (pid == 0) */ +/* { */ +/* dup2(copied, STDOUT_FILENO); */ +/* close(closed); */ +/* fds[0] = FD_NONE; */ +/* fds[1] = FD_NONE; */ +/* exit(eval(fds, env, ast, NULL, FD_NONE)); */ +/* } */ +/* return (pid); */ +/* } */ + +int eval_pipeline(int fds[2], t_env env, t_ast *ast) +{ + t_ftlst *curr; + /* t_ftvec *pids; */ + int p[2]; + int prev_output; + + /* pids = ft_vecnew(16); */ + + prev_output = STDIN_FILENO; + curr = ast->pipeline; + + + // create pipe + // fork + // dup2 pipe write -> stdout + // dup2 prev_output -> stdin + + while (curr->next != NULL) + { + pipe(p); + + int pid = fork(); + if (pid == 0) + { + dup2(p[FD_WRITE], STDOUT_FILENO); + if (prev_output != STDIN_FILENO) + dup2(prev_output, STDIN_FILENO); + close(p[FD_READ]); + exit(eval(fds, env, curr->data, NULL, FD_NONE)); + } + close(p[FD_WRITE]); + prev_output = p[FD_READ]; + curr = curr->next; + } + + int pid = fork(); + if (pid == 0) + { + /* dup2(p[FD_WRITE], STDOUT_FILENO); */ + if (prev_output != STDIN_FILENO) + dup2(prev_output, STDIN_FILENO); + close(p[FD_WRITE]); + exit(eval(fds, env, curr->data, NULL, FD_NONE)); + } + + while (wait(NULL) != -1) + ; + return (0); +} @@ -6,7 +6,7 @@ /* By: cacharle <cacharle@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/02/28 11:45:44 by cacharle #+# #+# */ -/* Updated: 2020/09/16 19:51:55 by charles ### ########.fr */ +/* Updated: 2020/10/06 10:36:28 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -110,6 +110,8 @@ int main(int argc, char **argv, char **envp) g_state.last_status = 0; if (argc == 3 && ft_strcmp(argv[1], "-l") == 0) return (debug_lexer(argv[2])); + if (argc == 3 && ft_strcmp(argv[1], "-p") == 0) + return (debug_parser(argv[2])); if (argc == 3 && ft_strcmp(argv[1], "-c") == 0) { status = execute(env, argv[2]); diff --git a/src/parser/parser.c b/src/parser/parser.c index 3a61a2c..0e3fbaf 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -6,7 +6,7 @@ /* By: nahaddac <nahaddac@student.42.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/06/17 18:09:04 by nahaddac #+# #+# */ -/* Updated: 2020/09/17 11:20:53 by charles ### ########.fr */ +/* Updated: 2020/10/06 11:22:14 by cacharle ### ########.fr */ /* */ /* ************************************************************************** */ @@ -80,6 +80,43 @@ t_parsed *parse_cmd(t_tok_lst *input) return (parsed_new(ast, input)); } +t_parsed *parse_pipeline(t_tok_lst *input) +{ + t_parsed *expr; + t_parsed *tail; + t_ast *expr_ast; + + expr = parse_expr(input); + if (expr == NULL || expr->syntax_error || + expr->rest == NULL || expr->rest->tag != TAG_PIPE) + return (expr); + tail = parse_pipeline(expr->rest->next); + if (tail == NULL || tail->syntax_error) + return (tail); + expr_ast = expr->ast; + free(expr); + t_ast *pipeline_ast; + if (tail->ast->tag == AST_CMD) + { + pipeline_ast = ast_new(AST_PIPELINE); + if ((pipeline_ast->pipeline = ft_lstnew(tail->ast)) == NULL) + { + /* ast_destroy(expr_ast); */ + /* ft_lstdestroy(&tail, NULL); */ + return (NULL); + } + } + else + pipeline_ast = tail->ast; + if (ft_lstpush_front_node(&pipeline_ast->pipeline, expr_ast) == NULL) + { + /* ast_destroy(expr_ast); */ + /* ft_lstdestroy(&tail, NULL); */ + return (NULL); + } + return (parsed_new(pipeline_ast, tail->rest)); +} + /* ** parse and operation (| ; && ||) */ @@ -91,7 +128,7 @@ t_parsed *parse_op(t_tok_lst *input) t_parsed *right; enum e_tok sep_tag; - left = parse_expr(input); + left = parse_pipeline(input); if (left == NULL || left->syntax_error) return (left); input = left->rest; @@ -99,7 +136,8 @@ t_parsed *parse_op(t_tok_lst *input) return (left); sep_tag = input->tag; if (!(sep_tag & TAG_IS_SEP)) - return (parsed_error("syntax error near unexpected token `%s'\n", g_sep_str_lookup[sep_tag])); + return (parsed_error("syntax error near unexpected token `%s'\n", + g_sep_str_lookup[sep_tag])); ft_lstpop_front((t_ftlst**)&input, free); if (input == NULL && sep_tag == TAG_END) return (left); |
