From c764027070e1d8820d1542c8a2cb8842aba4132b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 14 Feb 2017 20:32:34 +0100 Subject: [PATCH 1/3] heredoc starting to work; goto do multiple heredoc and execution part --- 42sh/Makefile | 3 +++ 42sh/includes/lexer.h | 11 +++++++--- 42sh/src/exec/process_redirect.c | 7 +++--- 42sh/src/exec/redirect_greatand.c | 1 + 42sh/src/lexer/get_lexer_stack.c | 6 ++++++ 42sh/src/lexer/lexer_end.c | 15 ++++++++++--- 42sh/src/lexer/lexer_init.c | 10 +++++++++ 42sh/src/lexer/lexer_less.c | 8 ++++--- 42sh/src/lexer/lexer_lex.c | 6 ++++-- 42sh/src/lexer/stack_to_prompt.c | 2 ++ 42sh/src/lexer_dless.c | 36 +++++++++++++++++++++++++++++++ 42sh/src/main/main.c | 25 +++++++++++---------- 12 files changed, 104 insertions(+), 26 deletions(-) create mode 100644 42sh/src/lexer/get_lexer_stack.c create mode 100644 42sh/src/lexer/lexer_init.c create mode 100644 42sh/src/lexer_dless.c diff --git a/42sh/Makefile b/42sh/Makefile index bf3af16f..4a034b0a 100644 --- a/42sh/Makefile +++ b/42sh/Makefile @@ -138,6 +138,7 @@ job-control/sigttin_handler.c\ job-control/sigttou_handler.c\ lexer/command_getoutput.c\ lexer/expand_bquotes.c\ +lexer/get_lexer_stack.c\ lexer/get_state_global.c\ lexer/get_state_redir.c\ lexer/lexer_backslash.c\ @@ -149,6 +150,7 @@ lexer/lexer_dquote.c\ lexer/lexer_end.c\ lexer/lexer_great.c\ lexer/lexer_greatand.c\ +lexer/lexer_init.c\ lexer/lexer_less.c\ lexer/lexer_lessand.c\ lexer/lexer_lex.c\ @@ -165,6 +167,7 @@ lexer/token_cmp_type.c\ lexer/token_free.c\ lexer/token_init.c\ lexer/token_print.c\ +lexer_dless.c\ line-editing/builtin_history.c\ line-editing/completion.c\ line-editing/control_c_and_d.c\ diff --git a/42sh/includes/lexer.h b/42sh/includes/lexer.h index 687203de..d89b0a54 100644 --- a/42sh/includes/lexer.h +++ b/42sh/includes/lexer.h @@ -45,10 +45,11 @@ enum e_lexstate SEP, WORD, NUMBER, - GREAT, LESS, - GREATAND, + GREAT, LESSAND, + GREATAND, + DLESS, QUOTE, DQUOTE, BQUOTE, @@ -74,6 +75,7 @@ struct s_lexer int pos; t_lexstate state; t_list *stack; + t_list *heredoc_stack; }; @@ -101,6 +103,8 @@ char *stack_to_prompt(t_list *stack); t_lexstate get_state_global(t_lexer *lexer); t_lexstate get_state_redir(t_lexer *lexer); +int get_lexer_stack(t_lexer lexer); +void lexer_init(t_lexer *lexer); int lexer_lex(t_list **alst, t_lexer *lexer); int lexer_default(t_list **alst, t_lexer *lexer); int lexer_newline(t_list **alst, t_lexer *lexer); @@ -110,8 +114,9 @@ int lexer_word(t_list **alst, t_lexer *lexer); int lexer_number(t_list **alst, t_lexer *lexer); int lexer_less(t_list **alst, t_lexer *lexer); int lexer_great(t_list **alst, t_lexer *lexer); -int lexer_lessand(t_list **alst, t_lexer *lexer); int lexer_greatand(t_list **alst, t_lexer *lexer); +int lexer_lessand(t_list **alst, t_lexer *lexer); +int lexer_dless(t_list **alst, t_lexer *lexer); int lexer_quote(t_list **alst, t_lexer *lexer); int lexer_dquote(t_list **alst, t_lexer *lexer); int lexer_bquote(t_list **alst, t_lexer *lexer); diff --git a/42sh/src/exec/process_redirect.c b/42sh/src/exec/process_redirect.c index a5560582..574448f0 100644 --- a/42sh/src/exec/process_redirect.c +++ b/42sh/src/exec/process_redirect.c @@ -30,14 +30,13 @@ int process_redirect(t_process *p) int i; redirs = p->redirs; + DG("process redirect"); while (redirs) { redir = redirs->content; + DG("process redirect 2, type=[%i]", redir->type); if (redir->n > 9) - { - bad_fd(redir->n); - exit(1); - } + return (bad_fd(redir->n)); i = 0; while (g_redirmap[i].type) { diff --git a/42sh/src/exec/redirect_greatand.c b/42sh/src/exec/redirect_greatand.c index 6e4bf37f..70658424 100644 --- a/42sh/src/exec/redirect_greatand.c +++ b/42sh/src/exec/redirect_greatand.c @@ -17,6 +17,7 @@ int redirect_greatand(t_redir *redir) int fdold; int fdnew; + DG("redir greatand"); if (redir->close) { close(redir->n); diff --git a/42sh/src/lexer/get_lexer_stack.c b/42sh/src/lexer/get_lexer_stack.c new file mode 100644 index 00000000..10ce9b70 --- /dev/null +++ b/42sh/src/lexer/get_lexer_stack.c @@ -0,0 +1,6 @@ +#include "lexer.h" + +int get_lexer_stack(t_lexer lexer) +{ + return (lexer.stack ? *(int*)lexer.stack->content : 0); +} diff --git a/42sh/src/lexer/lexer_end.c b/42sh/src/lexer/lexer_end.c index f7650e81..7dccf710 100644 --- a/42sh/src/lexer/lexer_end.c +++ b/42sh/src/lexer/lexer_end.c @@ -5,14 +5,23 @@ int lexer_end(t_list **alst, t_lexer *lexer) t_token *token; DG("check"); - if (*alst && (lexer->state == QUOTE + if ((*alst && (lexer->state == QUOTE || lexer->state == DQUOTE || lexer->state == BQUOTE)) + || get_lexer_stack(*lexer) == DLESS) { - token = (*alst)->content; ft_strappend(&lexer->str, (char[]){'\n', 0}); - token_append(token, lexer, 1, 0); lexer->pos++; + if (get_lexer_stack(*lexer) == DLESS) + { + token = (*(t_list**)lexer->heredoc_stack->content)->content; + token_append_char(token, '\n', 0, 0); + } + else + { + token = (*alst)->content; + token_append_char(token, '\n', 1, 0); + } return (0); } return (0); diff --git a/42sh/src/lexer/lexer_init.c b/42sh/src/lexer/lexer_init.c new file mode 100644 index 00000000..230ee3f6 --- /dev/null +++ b/42sh/src/lexer/lexer_init.c @@ -0,0 +1,10 @@ +#include "lexer.h" + +void lexer_init(t_lexer *lexer) +{ + lexer->str = NULL; + lexer->pos = 0; + lexer->state = DEFAULT; + lexer->stack = NULL; + lexer->heredoc_stack = NULL; +} diff --git a/42sh/src/lexer/lexer_less.c b/42sh/src/lexer/lexer_less.c index 00798f44..4f8eae63 100644 --- a/42sh/src/lexer/lexer_less.c +++ b/42sh/src/lexer/lexer_less.c @@ -28,11 +28,13 @@ int lexer_less(t_list **alst, t_lexer *lexer) } if (lexer->str[lexer->pos + 1] == '<') { + token_free(token, 0); + (*alst)->content = token_init(); token->type = TK_DLESS; - lexer->pos++; - token_append(token, lexer, 0, 0); - lexer->pos++; + lexer->pos += 2; + push(&lexer->stack, DLESS); lexer->state = DEFAULT; + ft_lsteadd(&lexer->heredoc_stack, ft_lstnew(alst, sizeof(alst))); return (lexer_lex(&(*alst)->next, lexer)); } else diff --git a/42sh/src/lexer/lexer_lex.c b/42sh/src/lexer/lexer_lex.c index 9472a565..2defdb6d 100644 --- a/42sh/src/lexer/lexer_lex.c +++ b/42sh/src/lexer/lexer_lex.c @@ -20,10 +20,11 @@ int (*g_lexer[])(t_list **alst, t_lexer *lexer) = &lexer_sep, &lexer_word, &lexer_number, - &lexer_great, &lexer_less, - &lexer_greatand, + &lexer_great, &lexer_lessand, + &lexer_greatand, + &lexer_dless, &lexer_quote, &lexer_dquote, &lexer_bquote, @@ -43,6 +44,7 @@ int lexer_lex(t_list **alst, t_lexer *lexer) { t_token *token; + DG("check 01, state=[%i]", lexer->state); if (lexer->str[lexer->pos] == 0) return (lexer_end(alst, lexer)); if (!*alst) diff --git a/42sh/src/lexer/stack_to_prompt.c b/42sh/src/lexer/stack_to_prompt.c index 385ffc89..b79c208b 100644 --- a/42sh/src/lexer/stack_to_prompt.c +++ b/42sh/src/lexer/stack_to_prompt.c @@ -31,6 +31,8 @@ char *stack_to_prompt(t_list *stack) return ("dquote bquote> "); else if (top == PAREN) return ("subsh> "); + else if (top == DLESS) + return ("heredoc> "); else return ("error> "); } diff --git a/42sh/src/lexer_dless.c b/42sh/src/lexer_dless.c new file mode 100644 index 00000000..cd9cba17 --- /dev/null +++ b/42sh/src/lexer_dless.c @@ -0,0 +1,36 @@ +#include "lexer.h" + +int lexer_dless(t_list **alst, t_lexer *lexer) +{ + t_list *heredoc_lst; + t_token *eof_tok; + t_token *heredoc_tok; + + (void)alst; + (void)lexer; + heredoc_lst = *(t_list**)lexer->heredoc_stack->content; + heredoc_tok = heredoc_lst->content; + if (!(heredoc_lst->next)) + { + ft_dprintf(2, "{red}%s: parse error near `\\n'{eoc}\n", SHELL_NAME); + return (1); + } + eof_tok = heredoc_lst->next->content; + if (!(eof_tok->type == TK_WORD)) + { + ft_dprintf(2, "{red}%s: expected word token after <<{eoc}\n", SHELL_NAME); + return (1); + } + DG("heredoc contains [%s]", heredoc_tok->data); + DG("heredoc ends at [%s]", eof_tok->data); + DG("input is [%s]", lexer->str + lexer->pos); + if (ft_strcmp(eof_tok->data, lexer->str + lexer->pos) == 0) + { + pop(&lexer->stack); + pop(&lexer->heredoc_stack); + return (0); + } + while (lexer->str[lexer->pos]) + token_append_char(heredoc_tok, lexer->str[lexer->pos++], 0, 0); + return (lexer_end(alst, lexer)); +} diff --git a/42sh/src/main/main.c b/42sh/src/main/main.c index 7416749f..17c882bc 100644 --- a/42sh/src/main/main.c +++ b/42sh/src/main/main.c @@ -18,10 +18,8 @@ int non_interactive_shell(char *command) t_lexer lexer; t_btree *ast; - lexer.pos = 0; - lexer.state = DEFAULT; + lexer_init(&lexer); lexer.str = command; - lexer.stack = NULL; token = NULL; ast = NULL; while (lexer.str[lexer.pos]) @@ -43,6 +41,7 @@ int non_interactive_shell(char *command) } return (0); } + int interactive_shell() { t_list *token; @@ -50,21 +49,25 @@ int interactive_shell() t_lexer lexer; t_btree *ast; - lexer.pos = 0; - lexer.state = DEFAULT; - lexer.str = NULL; + lexer_init(&lexer); token = NULL; - lexer.stack = NULL; ast = NULL; do { ft_strappend(&lexer.str, readline(stack_to_prompt(lexer.stack))); - if (lexer.stack && *(int*)lexer.stack->content == BACKSLASH) + DG("check 0"); + if (get_lexer_stack(lexer) == BACKSLASH) pop(&lexer.stack); + else if (get_lexer_stack(lexer) == DLESS) + lexer.state = DLESS; + DG("check 1"); ltoken = ft_lstlast(token); - lexer_lex((token ? <oken : &token), &lexer); + if (lexer_lex((token ? <oken : &token), &lexer)) + return (1); + DG("check 2"); DG("[{mag}%s{eoc}] stack=[%i] state=[%i]", lexer.str, lexer.stack ? *(int*)lexer.stack->content : 0, lexer.state); + DG("check 3"); token_print(token); - } while (lexer.stack); + } while (get_lexer_stack(lexer)); if (bquotes_expand(&token)) return (1); if (!token) @@ -85,7 +88,7 @@ int main(int ac, char **av) data = data_singleton(); setlocale(LC_ALL, ""); shell_init(ac, av); - DG("{inv}{bol}{gre}start of shell{eoc} pid=%i pgrp=%i job_control is %s", getpid(), getpgrp(), SH_HAS_JOBC(data->opts) ? "ON" : "OFF"); + DG("{inv}{bol}{gre}start of shell{eoc} JOBC is %s", SH_HAS_JOBC(data->opts)?"ON":"OFF"); if (SH_IS_INTERACTIVE(data->opts)) { while (1) From 3f984ad4988233c2d3ef12f5ddb4db3712325576 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 15 Feb 2017 00:00:39 +0100 Subject: [PATCH 2/3] multiple heredocs on one line word OK --- 42sh/src/exec/process_redirect.c | 2 -- 42sh/src/job-control/job_wait.c | 1 - 42sh/src/lexer/lexer_end.c | 1 - 42sh/src/lexer/lexer_lex.c | 1 - 42sh/src/lexer/lexer_sep.c | 1 + 42sh/src/lexer_dless.c | 8 +++++--- 42sh/src/main/main.c | 5 ----- 7 files changed, 6 insertions(+), 13 deletions(-) diff --git a/42sh/src/exec/process_redirect.c b/42sh/src/exec/process_redirect.c index 574448f0..6b45872d 100644 --- a/42sh/src/exec/process_redirect.c +++ b/42sh/src/exec/process_redirect.c @@ -30,11 +30,9 @@ int process_redirect(t_process *p) int i; redirs = p->redirs; - DG("process redirect"); while (redirs) { redir = redirs->content; - DG("process redirect 2, type=[%i]", redir->type); if (redir->n > 9) return (bad_fd(redir->n)); i = 0; diff --git a/42sh/src/job-control/job_wait.c b/42sh/src/job-control/job_wait.c index 6cd87253..62f5ebef 100644 --- a/42sh/src/job-control/job_wait.c +++ b/42sh/src/job-control/job_wait.c @@ -17,7 +17,6 @@ int job_wait(int id) pid_t pid; int status; - DG("gonna wait [%i]", id); if (job_is_stopped(id)) return (0); job_update_status(); diff --git a/42sh/src/lexer/lexer_end.c b/42sh/src/lexer/lexer_end.c index 7dccf710..2ec70dd2 100644 --- a/42sh/src/lexer/lexer_end.c +++ b/42sh/src/lexer/lexer_end.c @@ -4,7 +4,6 @@ int lexer_end(t_list **alst, t_lexer *lexer) { t_token *token; - DG("check"); if ((*alst && (lexer->state == QUOTE || lexer->state == DQUOTE || lexer->state == BQUOTE)) diff --git a/42sh/src/lexer/lexer_lex.c b/42sh/src/lexer/lexer_lex.c index 2defdb6d..f6614e5a 100644 --- a/42sh/src/lexer/lexer_lex.c +++ b/42sh/src/lexer/lexer_lex.c @@ -44,7 +44,6 @@ int lexer_lex(t_list **alst, t_lexer *lexer) { t_token *token; - DG("check 01, state=[%i]", lexer->state); if (lexer->str[lexer->pos] == 0) return (lexer_end(alst, lexer)); if (!*alst) diff --git a/42sh/src/lexer/lexer_sep.c b/42sh/src/lexer/lexer_sep.c index 581f2395..a393f714 100644 --- a/42sh/src/lexer/lexer_sep.c +++ b/42sh/src/lexer/lexer_sep.c @@ -18,6 +18,7 @@ int lexer_sep(t_list **alst, t_lexer *lexer) char c; char cn; + lexer->state = DEFAULT; if (*alst) { token = (*alst)->content; diff --git a/42sh/src/lexer_dless.c b/42sh/src/lexer_dless.c index cd9cba17..6f0644b9 100644 --- a/42sh/src/lexer_dless.c +++ b/42sh/src/lexer_dless.c @@ -28,9 +28,11 @@ int lexer_dless(t_list **alst, t_lexer *lexer) { pop(&lexer->stack); pop(&lexer->heredoc_stack); - return (0); + while (lexer->str[++lexer->pos]) + ; } - while (lexer->str[lexer->pos]) - token_append_char(heredoc_tok, lexer->str[lexer->pos++], 0, 0); + else + while (lexer->str[lexer->pos]) + token_append_char(heredoc_tok, lexer->str[lexer->pos++], 0, 0); return (lexer_end(alst, lexer)); } diff --git a/42sh/src/main/main.c b/42sh/src/main/main.c index 17c882bc..3d2df86d 100644 --- a/42sh/src/main/main.c +++ b/42sh/src/main/main.c @@ -54,25 +54,20 @@ int interactive_shell() ast = NULL; do { ft_strappend(&lexer.str, readline(stack_to_prompt(lexer.stack))); - DG("check 0"); if (get_lexer_stack(lexer) == BACKSLASH) pop(&lexer.stack); else if (get_lexer_stack(lexer) == DLESS) lexer.state = DLESS; - DG("check 1"); ltoken = ft_lstlast(token); if (lexer_lex((token ? <oken : &token), &lexer)) return (1); - DG("check 2"); DG("[{mag}%s{eoc}] stack=[%i] state=[%i]", lexer.str, lexer.stack ? *(int*)lexer.stack->content : 0, lexer.state); - DG("check 3"); token_print(token); } while (get_lexer_stack(lexer)); if (bquotes_expand(&token)) return (1); if (!token) return (0); - token_print(token); if (ft_parse(&ast, &token)) return (1); btree_print(STDBUG, ast, &ft_putast); From 16cfada91f8bfd2bf97360deea2db2f083172aa1 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 15 Feb 2017 00:13:02 +0100 Subject: [PATCH 3/3] heredoc redirection done, looks to work OK --- 42sh/Makefile | 1 + 42sh/src/exec/process_redirect.c | 2 +- 42sh/src/exec/redirect_dless.c | 27 +++++++++++++++++++++++++++ 42sh/src/lexer_dless.c | 3 +++ 42sh/src/parser/parse_dless.c | 3 ++- 5 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 42sh/src/exec/redirect_dless.c diff --git a/42sh/Makefile b/42sh/Makefile index 4a034b0a..5d9d4f2d 100644 --- a/42sh/Makefile +++ b/42sh/Makefile @@ -72,6 +72,7 @@ exec/process_setexec.c\ exec/process_setgroup.c\ exec/process_setsig.c\ exec/redirect_dgreat.c\ +exec/redirect_dless.c\ exec/redirect_great.c\ exec/redirect_greatand.c\ exec/redirect_less.c\ diff --git a/42sh/src/exec/process_redirect.c b/42sh/src/exec/process_redirect.c index 6b45872d..eec4d26d 100644 --- a/42sh/src/exec/process_redirect.c +++ b/42sh/src/exec/process_redirect.c @@ -16,7 +16,7 @@ t_redirmap g_redirmap[] = { {TK_LESS, redirect_less}, {TK_GREAT, redirect_great}, - /* {TK_DLESS, redirect_dless}, */ + {TK_DLESS, redirect_dless}, {TK_DGREAT, redirect_dgreat}, {TK_LESSAND, redirect_lessand}, {TK_GREATAND, redirect_greatand}, diff --git a/42sh/src/exec/redirect_dless.c b/42sh/src/exec/redirect_dless.c new file mode 100644 index 00000000..241f6e1f --- /dev/null +++ b/42sh/src/exec/redirect_dless.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_dless.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: jhalford +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/02/06 22:09:53 by jhalford #+# #+# */ +/* Updated: 2017/02/07 16:05:09 by jhalford ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "exec.h" + +int redirect_dless(t_redir *redir) +{ + int fds[2]; + char *str; + + pipe(fds); + str = redir->word.word; + write(fds[PIPE_WRITE], str, ft_strlen(str)); + close(fds[PIPE_WRITE]); + dup2(fds[PIPE_READ], 0); + close(fds[PIPE_READ]); + return (0); +} diff --git a/42sh/src/lexer_dless.c b/42sh/src/lexer_dless.c index 6f0644b9..f0e0ee4d 100644 --- a/42sh/src/lexer_dless.c +++ b/42sh/src/lexer_dless.c @@ -30,6 +30,9 @@ int lexer_dless(t_list **alst, t_lexer *lexer) pop(&lexer->heredoc_stack); while (lexer->str[++lexer->pos]) ; + ft_strappend(&lexer->str, (char[]){'\n', 0}); + lexer->pos++; + return (0); } else while (lexer->str[lexer->pos]) diff --git a/42sh/src/parser/parse_dless.c b/42sh/src/parser/parse_dless.c index 20d91421..1b75baa2 100644 --- a/42sh/src/parser/parse_dless.c +++ b/42sh/src/parser/parse_dless.c @@ -26,7 +26,8 @@ int parse_dless(t_btree **ast, t_list **start, t_list **lst) next_tok = (*lst)->next->content; if (next_tok->type != TK_WORD) return (1); - node->data.redir.word.word = ft_strdup(next_tok->data); + node->data.redir.word.word = ft_strdup(tok->data); + node->data.redir.n = 0; ft_lst_delif(start, (*lst)->content, &ft_addrcmp, &token_free); ft_lst_delif(start, (*lst)->next->content, &ft_addrcmp, &token_free); ft_parse(&(*ast)->left, start);