From c764027070e1d8820d1542c8a2cb8842aba4132b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 14 Feb 2017 20:32:34 +0100 Subject: [PATCH] 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)