From 3229f51902efd28976b2cf226b77d2551e85a608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Luttringer?= Date: Thu, 19 Oct 2006 00:25:54 +0000 Subject: [PATCH] -- correction bug de non initialisation des redirection dans ast_red.c, cela plant realloc. -- support complet de la libefence dans configure.ac (ajout du header automatique) -- ajout le prompt PS2 lorsque l'on parse sur plusieurs ligne dans le parser -- gestion correct du case -- ajout fonction destruct du noeud sans recurstion correction des leaks dans les fonctions de destruction -- ajout des possibilitees d'un parser ll1 dans le lexer -- parse d'une fonction -- parse correct de toute la grammaire !! -- moulette de test -- prompt a desormais le nom du program par defaut -- correction bug dans le lexer pour les chaines sur plusieurs lignes -- lexer previent le parser en cas d'erreur de lex ! --- AUTHORS | 2 +- TODO | 25 ++-- configure.ac | 21 +++- src/ast/ast.h | 198 +++++++++++++++++++++++-------- src/ast/ast_and.c | 9 +- src/ast/ast_bang.c | 10 +- src/ast/ast_case.c | 29 ++++- src/ast/ast_cmd.c | 7 +- src/ast/ast_destruct.c | 33 +++++- src/ast/ast_for.c | 13 +- src/ast/ast_funcdec.c | 12 +- src/ast/ast_if.c | 9 +- src/ast/ast_or.c | 9 +- src/ast/ast_pipe.c | 10 +- src/ast/ast_red.c | 17 ++- src/ast/ast_sep.c | 10 +- src/ast/ast_sepand.c | 10 +- src/ast/ast_subshell.c | 9 +- src/ast/ast_while.c | 9 +- src/common/macro.h | 2 +- src/parser/getline.c | 9 +- src/parser/lexer.c | 77 ++++++++---- src/parser/parser.c | 86 ++++++++------ src/parser/parser.h | 22 +++- src/shell/prompt.c | 14 +-- src/shell/shell.h | 2 +- test/parse/bad/compoundlist_1.sh | 1 + test/parse/bad/eof.sh | 3 + test/parse/bad/freetext.sh | 7 ++ test/parse/bad/if_1.sh | 11 ++ test/parse/bad/reserved_1.sh | 1 + test/parse/bad/reserved_2.sh | 1 + test/parse/good/big_1.sh | 63 ++++++++++ test/parse/good/big_command.sh | 1 + test/parse/good/brace_1.sh | 1 + test/parse/good/brace_2.sh | 1 + test/parse/good/case_1.sh | 14 +++ test/parse/good/empty.sh | 0 test/parse/good/funcdec.sh | 4 + test/parse/good/heredocs.sh | 8 ++ test/parse/good/if_1.sh | 7 ++ test/parse/good/if_2.sh | 21 ++++ test/parse/good/if_3.sh | 9 ++ test/parse/good/if_4.sh | 7 ++ test/parse/good/sheebang.sh | 1 + test/parse/good/simple_for.sh | 1 + test/parse/moulette.sh | 15 +++ tools/last-ast.sh | 2 +- 48 files changed, 661 insertions(+), 172 deletions(-) create mode 100644 test/parse/bad/compoundlist_1.sh create mode 100644 test/parse/bad/eof.sh create mode 100644 test/parse/bad/freetext.sh create mode 100644 test/parse/bad/if_1.sh create mode 100644 test/parse/bad/reserved_1.sh create mode 100644 test/parse/bad/reserved_2.sh create mode 100644 test/parse/good/big_1.sh create mode 100644 test/parse/good/big_command.sh create mode 100644 test/parse/good/brace_1.sh create mode 100644 test/parse/good/brace_2.sh create mode 100644 test/parse/good/case_1.sh create mode 100644 test/parse/good/empty.sh create mode 100644 test/parse/good/funcdec.sh create mode 100644 test/parse/good/heredocs.sh create mode 100644 test/parse/good/if_1.sh create mode 100644 test/parse/good/if_2.sh create mode 100644 test/parse/good/if_3.sh create mode 100644 test/parse/good/if_4.sh create mode 100644 test/parse/good/sheebang.sh create mode 100644 test/parse/good/simple_for.sh create mode 100755 test/parse/moulette.sh diff --git a/AUTHORS b/AUTHORS index 3c0df24..b226e54 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1 @@ -Sebastien Luttringer \ No newline at end of file +Sebastien LUTTRINGER diff --git a/TODO b/TODO index b8a50c5..b7a43da 100644 --- a/TODO +++ b/TODO @@ -1,17 +1,8 @@ ----- -Revoir les free dans le parser a cause de ast_destruct qui rentre dans les fils. -il faudrait ecrire des fonctions qui ne le fasse pas! Voir aussi au niveau de la -boucle general si ast_destruct est appele alors qu'une erreur de parse est surevenur -(le cas echeant, le supprimer) ----- -Voir probleme de syntax que j'accepte lorsque un EOF apparait avant une quote -fermante. Le token est valide alors que sous bash non ----- -ajotuer le prompt PS3 lorsque l'on parse sur plusieurs ligne ----- -parse du case ----- -parse du funcdec ----- -corriger le bug - ./42sh ** ** Started on Sun Jul 30 04:40:03 2006 Seblu -** Last update Wed Oct 11 14:58:42 2006 seblu +** Last update Tue Oct 17 17:14:49 2006 seblu */ #ifndef AST_H_ @@ -106,7 +106,7 @@ typedef struct cmd_node ** Binary ast node ** Generic node, it's a contener ! ** T_PIPE, T_SEP* , T_AND, T_OR : binary operator -** T_BANG : unary operator but ts_bin_op with right pointer is always NULL +** T_BANG : unary operator */ typedef struct bin_node { @@ -158,6 +158,7 @@ typedef union node_item s_for_node child_for; s_case_node child_case; s_while_node child_while; + s_red_node child_red; s_cmd_node child_cmd; s_bin_node child_and; s_bin_node child_or; @@ -167,7 +168,6 @@ typedef union node_item s_bin_node child_pipe; s_bin_node child_sep; s_bin_node child_sepand; - s_red_node child_red; } u_node_item; /* @@ -205,6 +205,14 @@ void ast_print_node(s_ast_node *ast, FILE *fs, unsigned int *node_id); */ void ast_destruct(s_ast_node *ast); +/*! +** Destroy node and only this node. All childs will survive. +** +** @param ast mother node to destroy +** +*/ +void ast_destruct_node(s_ast_node *ast); + /*! ** Create an if ast node ** @@ -227,7 +235,14 @@ s_ast_node *ast_if_create(s_ast_node *cond, void ast_if_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct an if ast node +** Destruct an if ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_if_destruct_node(s_ast_node *node); + +/*! +** Destruct an if ast node. Destruct child nodes. ** ** @param node node to destroy */ @@ -257,7 +272,14 @@ s_ast_node *ast_for_create(char *varname, void ast_for_print(s_ast_node *node, FILE *fs, unsigned *node_id); /*! -** Destruct a for ast node +** Destruct a for ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_for_destruct_node(s_ast_node *node); + +/*! +** Destruct a for ast node. Destruct child nodes. ** ** @param node node to destroy */ @@ -294,7 +316,14 @@ void ast_case_add_item(s_ast_node *node, void ast_case_print(s_ast_node *node, FILE *fs, unsigned *node_id); /*! -** Destruct a case ast node +** Destruct a case ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_case_destruct_node(s_ast_node *node); + +/*! +** Destruct a case ast node. Destruct child node. ** ** @param node node to destroy */ @@ -320,12 +349,62 @@ s_ast_node *ast_while_create(s_ast_node *cond, s_ast_node *exec); void ast_while_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct a while ast node +** Destruct a while ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_while_destruct_node(s_ast_node *node); + +/*! +** Destruct a while ast node. Destruct all child nodes. ** ** @param node node to destroy */ void ast_while_destruct(s_ast_node *node); +/*! +** Create a redirection ast node +** +** @return the node +*/ +s_ast_node *ast_red_create(void); + +/*! +** Add a redirection to a redirection node +** +** @param node node where add +** @param type type of redirection +** @param fd fd parameter of redirection +** @param word file or word parameter of redirection +*/ +void ast_red_add(s_ast_node *node, + e_red_type type, + int fd, + char *word); + +/*! +** Print an ast red node +** +** @param ast ast node to add to file +** @param fs file stream where print ast +** @param node_id first free node id +*/ +void ast_red_print(s_ast_node *node, FILE *fs, unsigned int *node_id); + +/*! +** Destruct a red ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_red_destruct_node(s_ast_node *node); + +/*! +** Destruct a red ast node. Destruct child nodes. +** +** @param node node to destroy +*/ +void ast_red_destruct(s_ast_node *node); + /*! ** Create a cmd ast node ** @@ -359,7 +438,14 @@ void ast_cmd_add_prefix(s_ast_node *node, char *assignment_word); void ast_cmd_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct a cmd node +** Destruct a cmd ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_cmd_destruct_node(s_ast_node *node); + +/*! +** Destruct a cmd node. All child nodes will be destruct. ** ** @param node node to destroy */ @@ -385,7 +471,14 @@ s_ast_node *ast_and_create(s_ast_node *lhs, s_ast_node *rhs); void ast_and_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct an and (&&) node +** Destruct an and ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_and_destruct_node(s_ast_node *node); + +/*! +** Destruct an and (&&) node. Destruct all child nodes. ** ** @param node node to destroy */ @@ -411,7 +504,14 @@ s_ast_node *ast_or_create(s_ast_node *lhs, s_ast_node *rhs); void ast_or_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct an or (||) node +** Destruct an or ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_or_destruct_node(s_ast_node *node); + +/*! +** Destruct an or (||) ast node. Destruct child nodes. ** ** @param node node to destroy */ @@ -436,7 +536,14 @@ s_ast_node *ast_subshell_create(s_ast_node *child); void ast_subshell_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct a subshell (()) node +** Destruct a subshell (()) ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_subshell_destruct_node(s_ast_node *node); + +/*! +** Destruct a subshell (()) ast node. Destruct child nodes. ** ** @param node node to destroy */ @@ -462,7 +569,14 @@ s_ast_node *ast_funcdec_create(char *name, s_ast_node *body); void ast_funcdec_print(s_ast_node *node, FILE *fs, unsigned *node_id); /*! -** Destruct a funcdec ast node +** Destruct a funcdec ast node. Don't destruct child nodes. +** +** @param node node to free +*/ +void ast_funcdec_destruct_node(s_ast_node *node); + +/*! +** Destruct a funcdec ast node. Destruct child nodes. ** ** @param node node to destroy */ @@ -487,7 +601,14 @@ s_ast_node *ast_bang_create(s_ast_node *child); void ast_bang_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct a bang (!) node +** Destruct a bang (!) ast node. Don't destruct child nodes. +** +** @param node node to destroy +*/ +void ast_bang_destruct_node(s_ast_node *node); + +/*! +** Destruct a bang (!) ast node. Destruct child nodes. ** ** @param node node to destroy */ @@ -512,6 +633,12 @@ s_ast_node *ast_pipe_create(s_ast_node *lhs, s_ast_node *rhs); */ void ast_pipe_print(s_ast_node *node, FILE *fs, unsigned int *node_id); +/*! +** Destruct a pipe (|) ast node. Don't destruct child nodes. +** +** @param node node to destroy +*/ +void ast_pipe_destruct_node(s_ast_node *node); /*! ** Destruct a pipe (|) node ** @@ -539,7 +666,13 @@ s_ast_node *ast_sep_create(s_ast_node *lhs, s_ast_node *rhs); void ast_sep_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct a sep (;) node +** Destruct a sep (;) ast node. Don't destruct child nodes. +** +** @param node node to destroy +*/ +void ast_sep_destruct_node(s_ast_node *node); +/*! +** Destruct a sep (;) ast node. Destruct child nodes. ** ** @param node node to destroy */ @@ -565,46 +698,17 @@ s_ast_node *ast_sepand_create(s_ast_node *lhs, s_ast_node *rhs); void ast_sepand_print(s_ast_node *node, FILE *fs, unsigned int *node_id); /*! -** Destruct a sepand (&) node +** Destruct a sepand (&) ast node. Don't destruct child nodes. ** ** @param node node to destroy */ -void ast_sepand_destruct(s_ast_node *node); - -/*! -** Create a redirection ast node -** -** @return the node -*/ -s_ast_node *ast_red_create(void); - -/*! -** Add a redirection to a redirection node -** -** @param node node where add -** @param type type of redirection -** @param fd fd parameter of redirection -** @param word file or word parameter of redirection -*/ -void ast_red_add(s_ast_node *node, - e_red_type type, - int fd, - char *word); - -/*! -** Print an ast red node -** -** @param ast ast node to add to file -** @param fs file stream where print ast -** @param node_id first free node id -*/ -void ast_red_print(s_ast_node *node, FILE *fs, unsigned int *node_id); +void ast_sepand_destruct_node(s_ast_node *node); /*! -** Destruct a red node +** Destruct a sepand (&) ast node. Destruct child nodes. ** ** @param node node to destroy */ -void ast_red_destruct(s_ast_node *node); +void ast_sepand_destruct(s_ast_node *node); #endif /* !AST_H_ */ diff --git a/src/ast/ast_and.c b/src/ast/ast_and.c index 02c5d7d..b629910 100644 --- a/src/ast/ast_and.c +++ b/src/ast/ast_and.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Sep 26 17:45:16 2006 Seblu +** Last update Tue Oct 17 16:50:32 2006 seblu */ #include "ast.h" @@ -36,6 +36,13 @@ void ast_and_print(s_ast_node *node, FILE *fs, unsigned int *node_id) fprintf(fs, "%u -> %u\n", cur_id, rhs_id); } +void ast_and_destruct_node(s_ast_node *node) +{ + if (node->type != T_AND) + return; + free(node); +} + void ast_and_destruct(s_ast_node *node) { if (node->type != T_AND) diff --git a/src/ast/ast_bang.c b/src/ast/ast_bang.c index 50df098..acb8ca9 100644 --- a/src/ast/ast_bang.c +++ b/src/ast/ast_bang.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Sep 26 17:45:45 2006 Seblu +** Last update Tue Oct 17 17:12:13 2006 seblu */ #include "ast.h" @@ -33,6 +33,13 @@ void ast_bang_print(s_ast_node *node, FILE *fs, unsigned int *node_id) fprintf(fs, "%u -> %u\n", cur_id, lhs_id); } +void ast_bang_destruct_node(s_ast_node *node) +{ + if (node->type != T_BANG) + return; + free(node); +} + void ast_bang_destruct(s_ast_node *node) { if (node->type != T_BANG) @@ -40,4 +47,3 @@ void ast_bang_destruct(s_ast_node *node) ast_destruct(node->body.child_bang.lhs); free(node); } - diff --git a/src/ast/ast_case.c b/src/ast/ast_case.c index 7e7cbc8..fd5ecfe 100644 --- a/src/ast/ast_case.c +++ b/src/ast/ast_case.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Wed Oct 11 13:07:50 2006 seblu +** Last update Tue Oct 17 16:36:25 2006 seblu */ #include "ast.h" @@ -34,7 +34,7 @@ void ast_case_add_item(s_ast_node *node, item->pattern = pattern; item->exec = exec; item->next = NULL; - for (this = &node->body.child_case.items; *this; *this = (*this)->next) + for (this = &node->body.child_case.items; *this; this = &(*this)->next) ; //do nothing *this = item; } @@ -44,17 +44,19 @@ void ast_case_print(s_ast_node *node, FILE *fs, unsigned *node_id) unsigned cur_node; s_case_item *item; unsigned item_id; + unsigned item_node; if (node->type != T_CASE) return; fprintf(fs, "%u [label = \"CASE\\nword: %s\"];\n", cur_node = *node_id, node->body.child_case.word); ++*node_id; + //show items for (item = node->body.child_case.items, item_id = 0; item; item = item->next, ++item_id) { fprintf(fs, "%u -> %u\n", cur_node, *node_id); - fprintf(fs, "%u [ label = \"Item %u\\n", *node_id, item_id); + fprintf(fs, "%u [label = \"Item %u\\n", item_node = *node_id, item_id); ++*node_id; //print pattern if (item->pattern) @@ -62,11 +64,30 @@ void ast_case_print(s_ast_node *node, FILE *fs, unsigned *node_id) fprintf(fs, "%s\\n", item->pattern[i]); fprintf(fs, "\"];\n"); //print exec - if (item->exec) + if (item->exec) { + fprintf(fs, "%u -> %u\n", item_node, *node_id); ast_print_node(item->exec, fs, node_id); + } } } +void ast_case_destruct_node(s_ast_node *node) +{ + s_case_item *this, *buf; + + if (node->type != T_CASE) + return; + free(node->body.child_case.word); + for (this = node->body.child_case.items; this; this = buf) { + for (register int i = 0; this->pattern[i]; ++i) + free(this->pattern[i]); + free(this->pattern); + buf = this->next; + free(this); + } + free(node); +} + void ast_case_destruct(s_ast_node *node) { s_case_item *this, *buf; diff --git a/src/ast/ast_cmd.c b/src/ast/ast_cmd.c index 8ab6062..97d6689 100644 --- a/src/ast/ast_cmd.c +++ b/src/ast/ast_cmd.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Fri Aug 18 22:13:51 2006 Seblu -** Last update Tue Oct 10 14:27:02 2006 seblu +** Last update Tue Oct 17 17:00:22 2006 seblu */ #include "ast.h" @@ -83,6 +83,11 @@ void ast_cmd_print(s_ast_node *node, FILE *fs, unsigned int *node_id) fprintf(fs, "\"];\n"); } +void ast_cmd_destruct_node(s_ast_node *node) +{ + ast_cmd_destruct(node); +} + void ast_cmd_destruct(s_ast_node *node) { if (node->type != T_CMD) diff --git a/src/ast/ast_destruct.c b/src/ast/ast_destruct.c index 095126a..9f8c17c 100644 --- a/src/ast/ast_destruct.c +++ b/src/ast/ast_destruct.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sat Mar 25 23:11:01 2006 Seblu -** Last update Mon Oct 16 18:10:35 2006 seblu +** Last update Tue Oct 17 16:43:29 2006 seblu */ #include "ast.h" @@ -32,10 +32,28 @@ struct ast_destruct_switch destruction_table[NODE_TYPE_COUNT] = {T_PIPE, ast_pipe_destruct}, {T_SEPAND, ast_sepand_destruct}, {T_SEP, ast_sep_destruct}, - {T_CASE, ast_sepand_destruct}, + {T_CASE, ast_case_destruct}, {T_RED, ast_red_destruct} }; +struct ast_destruct_switch destruction_node_table[NODE_TYPE_COUNT] = + { + {T_IF, ast_if_destruct_node}, + {T_FOR, ast_for_destruct_node}, + {T_WHILE, ast_while_destruct_node}, + {T_CMD, ast_cmd_destruct_node}, + {T_AND, ast_and_destruct_node}, + {T_OR, ast_or_destruct_node}, + {T_SUBSHELL, ast_subshell_destruct_node}, + {T_FUNCDEC, ast_funcdec_destruct_node}, + {T_BANG, ast_bang_destruct_node}, + {T_PIPE, ast_pipe_destruct_node}, + {T_SEPAND, ast_sepand_destruct_node}, + {T_SEP, ast_sep_destruct_node}, + {T_CASE, ast_case_destruct_node}, + {T_RED, ast_red_destruct_node} + }; + void ast_destruct(s_ast_node *ast) { if (ast == NULL) @@ -46,3 +64,14 @@ void ast_destruct(s_ast_node *ast) return; } } + +void ast_destruct_node(s_ast_node *ast) +{ + if (ast == NULL) + return; + for (register int i = 0; i < NODE_TYPE_COUNT; ++i) + if (destruction_node_table[i].type == ast->type) { + (destruction_node_table[i].fct)(ast); + return; + } +} diff --git a/src/ast/ast_for.c b/src/ast/ast_for.c index f3c800d..2c1b81b 100644 --- a/src/ast/ast_for.c +++ b/src/ast/ast_for.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Thu Oct 12 16:01:04 2006 seblu +** Last update Tue Oct 17 17:15:27 2006 seblu */ #include "ast.h" @@ -49,7 +49,7 @@ void ast_for_print(s_ast_node *node, FILE *fs, unsigned *node_id) } } -void ast_for_destruct(s_ast_node *node) +void ast_for_destruct_node(s_ast_node *node) { if (node->type != T_FOR) return; @@ -57,6 +57,13 @@ void ast_for_destruct(s_ast_node *node) for (register int i = 0; node->body.child_for.values[i]; ++i) free(node->body.child_for.values[i]); free(node->body.child_for.values); - ast_destruct(node->body.child_for.exec); free(node); } + +void ast_for_destruct(s_ast_node *node) +{ + if (node->type != T_FOR) + return; + ast_destruct(node->body.child_for.exec); + ast_for_destruct_node(node); +} diff --git a/src/ast/ast_funcdec.c b/src/ast/ast_funcdec.c index 3fc38e7..5421520 100644 --- a/src/ast/ast_funcdec.c +++ b/src/ast/ast_funcdec.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Oct 10 14:40:44 2006 seblu +** Last update Wed Oct 18 17:14:16 2006 seblu */ #include "ast.h" @@ -27,13 +27,21 @@ void ast_funcdec_print(s_ast_node *node, FILE *fs, unsigned *node_id) if (node->type != T_FUNCDEC) return; - fprintf(fs, "%u [label = \"FuncDec\\nName: %s\"];\n", + fprintf(fs, "%u [label = \"FuncDec\\nname: %s\"];\n", cur_id = *node_id, node->body.child_funcdec.name); lhs_id = ++*node_id; ast_print_node(node->body.child_funcdec.body, fs, node_id); fprintf(fs, "%u -> %u\n", cur_id, lhs_id); } +void ast_funcdec_destruct_node(s_ast_node *node) +{ + if (node->type != T_FUNCDEC) + return; + free(node->body.child_funcdec.name); + free(node); +} + void ast_funcdec_destruct(s_ast_node *node) { if (node->type != T_FUNCDEC) diff --git a/src/ast/ast_if.c b/src/ast/ast_if.c index a4d846e..6d8d0da 100644 --- a/src/ast/ast_if.c +++ b/src/ast/ast_if.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Oct 10 17:15:53 2006 seblu +** Last update Tue Oct 17 16:30:23 2006 seblu */ #include "ast.h" @@ -49,6 +49,13 @@ void ast_if_print(s_ast_node *node, FILE *fs, unsigned *node_id) } } +void ast_if_destruct_node(s_ast_node *node) +{ + if (node->type != T_IF) + return; + free(node); +} + void ast_if_destruct(s_ast_node *node) { if (node->type != T_IF) diff --git a/src/ast/ast_or.c b/src/ast/ast_or.c index 2110f69..485ba66 100644 --- a/src/ast/ast_or.c +++ b/src/ast/ast_or.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Sep 26 17:45:54 2006 Seblu +** Last update Tue Oct 17 17:01:20 2006 seblu */ #include "ast.h" @@ -36,6 +36,13 @@ void ast_or_print(s_ast_node *node, FILE *fs, unsigned int *node_id) fprintf(fs, "%u -> %u\n", cur_id, rhs_id); } +void ast_or_destruct_node(s_ast_node *node) +{ + if (node->type != T_OR) + return; + free(node); +} + void ast_or_destruct(s_ast_node *node) { if (node->type != T_OR) diff --git a/src/ast/ast_pipe.c b/src/ast/ast_pipe.c index 826c1bf..8c880d8 100644 --- a/src/ast/ast_pipe.c +++ b/src/ast/ast_pipe.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Sep 26 17:45:33 2006 Seblu +** Last update Tue Oct 17 17:12:46 2006 seblu */ #include "ast.h" @@ -36,6 +36,13 @@ void ast_pipe_print(s_ast_node *node, FILE *fs, unsigned int *node_id) fprintf(fs, "%u -> %u\n", cur_id, rhs_id); } +void ast_pipe_destruct_node(s_ast_node *node) +{ + if (node->type != T_PIPE) + return; + free(node); +} + void ast_pipe_destruct(s_ast_node *node) { if (node->type != T_PIPE) @@ -44,4 +51,3 @@ void ast_pipe_destruct(s_ast_node *node) ast_destruct(node->body.child_pipe.rhs); free(node); } - diff --git a/src/ast/ast_red.c b/src/ast/ast_red.c index dac0bef..5d2f992 100644 --- a/src/ast/ast_red.c +++ b/src/ast/ast_red.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Fri Aug 18 22:13:51 2006 Seblu -** Last update Mon Oct 16 17:26:11 2006 seblu +** Last update Tue Oct 17 17:16:40 2006 seblu */ #include "ast.h" @@ -17,6 +17,9 @@ s_ast_node *ast_red_create(void) secmalloc(node, sizeof (s_ast_node)); node->type = T_RED; node->body.child_red.size = 0; + node->body.child_red.type = NULL; + node->body.child_red.fd = NULL; + node->body.child_red.word = NULL; node->body.child_red.mhs = NULL; return node; } @@ -58,7 +61,7 @@ void ast_red_print(s_ast_node *node, FILE *fs, unsigned *node_id) ast_print_node(reds->mhs, fs, node_id); } -void ast_red_destruct(s_ast_node *node) +void ast_red_destruct_node(s_ast_node *node) { s_red_node *reds; @@ -68,9 +71,17 @@ void ast_red_destruct(s_ast_node *node) if (reds->size) { free(reds->type); free(reds->fd); - for (register size_t i = 0; i < node->body.child_red.size; ++i) + for (register size_t i = 0; i < reds->size; ++i) free(reds->word[i]); free(reds->word); } free(node); } + +void ast_red_destruct(s_ast_node *node) +{ + if (node->type != T_RED) + return; + ast_destruct(node->body.child_red.mhs); + ast_red_destruct_node(node); +} diff --git a/src/ast/ast_sep.c b/src/ast/ast_sep.c index e7c520c..fbd154b 100644 --- a/src/ast/ast_sep.c +++ b/src/ast/ast_sep.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Thu Oct 12 13:11:35 2006 seblu +** Last update Tue Oct 17 17:13:30 2006 seblu */ #include "ast.h" @@ -37,6 +37,13 @@ void ast_sep_print(s_ast_node *node, FILE *fs, unsigned int *node_id) } } +void ast_sep_destruct_node(s_ast_node *node) +{ + if (node->type != T_SEP) + return; + free(node); +} + void ast_sep_destruct(s_ast_node *node) { if (node->type != T_SEP) @@ -45,4 +52,3 @@ void ast_sep_destruct(s_ast_node *node) ast_destruct(node->body.child_sep.rhs); free(node); } - diff --git a/src/ast/ast_sepand.c b/src/ast/ast_sepand.c index 964b7d1..4cc9886 100644 --- a/src/ast/ast_sepand.c +++ b/src/ast/ast_sepand.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Thu Oct 12 13:12:13 2006 seblu +** Last update Tue Oct 17 17:14:00 2006 seblu */ #include "ast.h" @@ -38,6 +38,13 @@ void ast_sepand_print(s_ast_node *node, FILE *fs, unsigned int *node_id) } } +void ast_sepand_destruct_node(s_ast_node *node) +{ + if (node->type != T_SEPAND) + return; + free(node); +} + void ast_sepand_destruct(s_ast_node *node) { if (node->type != T_SEPAND) @@ -46,4 +53,3 @@ void ast_sepand_destruct(s_ast_node *node) ast_destruct(node->body.child_sepand.rhs); free(node); } - diff --git a/src/ast/ast_subshell.c b/src/ast/ast_subshell.c index e8bfe8d..587e212 100644 --- a/src/ast/ast_subshell.c +++ b/src/ast/ast_subshell.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Sep 26 17:43:33 2006 Seblu +** Last update Tue Oct 17 17:02:57 2006 seblu */ #include "ast.h" @@ -33,6 +33,13 @@ void ast_subshell_print(s_ast_node *node, FILE *fs, unsigned int *node_id) fprintf(fs, "%u -> %u\n", cur_id, lhs_id); } +void ast_subshell_destruct_node(s_ast_node *node) +{ + if (node->type != T_SUBSHELL) + return; + free(node); +} + void ast_subshell_destruct(s_ast_node *node) { if (node->type != T_SUBSHELL) diff --git a/src/ast/ast_while.c b/src/ast/ast_while.c index a62b208..a49ad61 100644 --- a/src/ast/ast_while.c +++ b/src/ast/ast_while.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Thu Aug 3 02:41:37 2006 Seblu -** Last update Tue Sep 26 17:44:08 2006 Seblu +** Last update Tue Oct 17 16:44:13 2006 seblu */ #include "ast.h" @@ -36,6 +36,13 @@ void ast_while_print(s_ast_node *node, FILE *fs, unsigned int *node_id) fprintf(fs, "%u -> %u\n", cur_id, rhs_id); } +void ast_while_destruct_node(s_ast_node *node) +{ + if (node->type != T_WHILE) + return; + free(node); +} + void ast_while_destruct(s_ast_node *node) { if (node->type != T_WHILE) diff --git a/src/common/macro.h b/src/common/macro.h index bf39c39..d61e09e 100644 --- a/src/common/macro.h +++ b/src/common/macro.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Fri Aug 25 03:32:54 2006 Seblu -** Last update Fri Oct 13 14:33:10 2006 seblu +** Last update Tue Oct 17 10:15:20 2006 seblu */ #ifndef MACRO_H_ diff --git a/src/parser/getline.c b/src/parser/getline.c index 049dd7e..bb7a42c 100644 --- a/src/parser/getline.c +++ b/src/parser/getline.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 2 01:25:01 2006 Seblu -** Last update Tue Aug 29 02:20:32 2006 Seblu +** Last update Tue Oct 17 09:51:30 2006 seblu */ #include @@ -33,16 +33,15 @@ static void buf_str(char **str, char *append, unsigned n) unsigned j; ln = sstrlen(*str); - if ((*str = realloc(*str, (ln + n + 1) * sizeof (char))) == NULL) - exit(1); + secrealloc(*str, *str, (ln + n + 1) * sizeof (char)); for (i = ln, j = 0; i < ln + n; i++, j++) (*str)[i] = append[j]; (*str)[ln + n] = 0; } -s_getline *getline_open(int fd) +s_getline *getline_open(int fd) { - s_getline *new_buf; + s_getline *new_buf; secmalloc(new_buf, sizeof (s_getline)); new_buf->fd = fd; diff --git a/src/parser/lexer.c b/src/parser/lexer.c index 63dc48d..7c6a365 100644 --- a/src/parser/lexer.c +++ b/src/parser/lexer.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sun Jul 30 04:36:53 2006 Seblu -** Last update Thu Oct 12 15:45:20 2006 seblu +** Last update Wed Oct 18 18:27:39 2006 seblu */ #include @@ -158,6 +158,14 @@ static int lexer_cut(s_lexer *lexer); */ static void token_set(s_token *token, e_tokenid id, char *s); +/*! +** Move a token to another. Token source, will become token +** NONE. +** +** @param src source token +** @param dst destination token +*/ +static void token_move(s_token *src, s_token *dst); /* ** =========== @@ -173,14 +181,16 @@ s_lexer *lexer_init(int fd) new->stream = getline_open(fd); new->buf = NULL; new->buf_size = new->buf_pos = 0; - token_set(&new->token, TOK_NONE, NULL); + token_set(&new->previous, TOK_NONE, NULL); + token_set(&new->current, TOK_NONE, NULL); new->eof = 0; return new; } void lexer_flush(s_lexer *lexer) { - token_set(&lexer->token, TOK_NONE, NULL); + token_set(&lexer->previous, TOK_NONE, NULL); + token_set(&lexer->current, TOK_NONE, NULL); if (lexer->buf) free(lexer->buf); lexer->buf = NULL; @@ -189,20 +199,34 @@ void lexer_flush(s_lexer *lexer) s_token lexer_lookahead(s_lexer *lexer) { - if (lexer->token.id == TOK_NONE) + if (lexer->previous.id == TOK_NONE && lexer->current.id == TOK_NONE) lexer_eattoken(lexer); - return lexer->token; + return (lexer->previous.id != TOK_NONE) ? lexer->previous : lexer->current; +} + +s_token lexer_lookahead2(s_lexer *lexer) +{ + if (lexer->current.id == TOK_NONE) + lexer_eattoken(lexer); + if (lexer->previous.id == TOK_NONE) { + token_move(&lexer->current, &lexer->previous); + lexer_eattoken(lexer); + } + return lexer->current; } s_token lexer_gettoken(s_lexer *lexer) { s_token buf; + s_token *victim; - if (lexer->token.id == TOK_NONE) + if (lexer->previous.id != TOK_NONE) + victim = &lexer->previous; + else + victim = &lexer->current; + if (lexer->current.id == TOK_NONE) lexer_eattoken(lexer); - buf = lexer->token; - lexer->token.id = TOK_NONE; - lexer->token.str = NULL; + token_move(victim, &buf); return buf; } @@ -240,6 +264,14 @@ static void token_set(s_token *token, e_tokenid id, char *s) else token->len = 0; } +static void token_move(s_token *src, s_token *dst) +{ + *dst = *src; + src->id = TOK_NONE; + src->str = NULL; + src->len = 0; +} + static void lexer_eattoken(s_lexer *lexer) { //if last char was read free buffer @@ -256,7 +288,7 @@ static void lexer_eattoken(s_lexer *lexer) //if eof is read, bye bye if (!lexer->buf) { lexer->eof = 1; - token_set(&lexer->token, TOK_EOF, "EOF"); + token_set(&lexer->current, TOK_EOF, "EOF"); return; } //cut a slice of stream @@ -270,8 +302,7 @@ static int lexer_eatline(s_lexer *lexer) assert(lexer->buf); buf = lexer->buf; - if (lexer->buf_size > 0 && buf[lexer->buf_size - 1] == '\n') - buf[lexer->buf_size - 1] = 0; + //remove \n if a \ is present before him if (lexer->buf_size > 1 && buf[lexer->buf_size - 2] == '\\') buf[lexer->buf_size - 2] = 0; //show incomplet recognition prompt @@ -279,13 +310,14 @@ static int lexer_eatline(s_lexer *lexer) //retrieve a new line if (!(buf2 = getline(lexer->stream))) { lexer->eof = 1; - return 0; + token_set(&lexer->current, TOK_EOF, "EOF"); + return 1; } lexer->buf = strmerge(2, buf, buf2); lexer->buf_size = strlen(lexer->buf); free(buf); free(buf2); - return 1; + return 0; } static int lexer_cut(s_lexer *lexer) @@ -295,25 +327,25 @@ static int lexer_cut(s_lexer *lexer) size_t *buf_pos = &lexer->buf_pos, token_start, token_pos; int end_found = 0; char backed = 0, quoted = 0; - const s_quote *quote; + const s_quote *quote = NULL; // Rationale: Search begin of token - //eat separators (" ",\t, \v) + // eat separators (" ",\t, \v) while (buf[*buf_pos] && is_sep(buf[*buf_pos])) ++*buf_pos; - //eat comment + // eat comment if (buf[*buf_pos] == '#') while (buf[*buf_pos] && buf[*buf_pos] != '\n') ++*buf_pos; - //check if first chars is an operator - if (is_operator(buf + *buf_pos, buf_pos, &lexer->token)) + // check if first chars is an operator + if (is_operator(buf + *buf_pos, buf_pos, &lexer->current)) return 1; token_start = token_pos = *buf_pos; // Rationale: Search end of token for (; buf[token_pos]; ++token_pos) { // backslah newline => eatline - if ((backed || quoted) && buf[token_pos] == '\n' && lexer_eatline(lexer)) - return 0; //new line added, you can try again + if ((backed || quoted) && buf[token_pos] == '\n' && buf[token_pos + 1] == '\0') + return lexer_eatline(lexer); // backed, go to next char else if (backed) backed = 0; // check end of quoting @@ -332,7 +364,7 @@ static int lexer_cut(s_lexer *lexer) } lexer->buf_pos = token_pos; //update real lexer position buffer tokstr = strndup(buf + token_start, token_pos - token_start); - token_set(&lexer->token, ((buf[token_pos] == '>' || buf[token_pos] == '<') + token_set(&lexer->current, ((buf[token_pos] == '>' || buf[token_pos] == '<') && isdigitstr(tokstr)) ? TOK_IONUMBER : TOK_WORD, tokstr); return 1; } @@ -364,6 +396,7 @@ static int is_quote_start(const char *buf, size_t *buf_pos, const s_quote **quot static int is_quote_stop(const char *buf, size_t *buf_pos, const s_quote *quote) { + assert(quote); if (!strncmp(buf + *buf_pos, quote->stop, quote->lenstop)) { *buf_pos += quote->lenstop - 1; return 1; diff --git a/src/parser/parser.c b/src/parser/parser.c index cb9d5f1..eaaa493 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -5,9 +5,10 @@ ** Login ** ** Started on Wed Aug 2 00:56:07 2006 Seblu -** Last update Mon Oct 16 16:35:13 2006 seblu +** Last update Wed Oct 18 19:21:32 2006 seblu */ + #include #include #include @@ -26,10 +27,6 @@ ** ============ */ -enum { - FD_MAX = 32765 -}; - static s_ast_node *regnode(s_parser *parser, s_ast_node *node); /*! @@ -121,7 +118,8 @@ static const s_token keyword_table[] = {TOK_WORD, "case", 4}, {TOK_WORD, "esac", 4}, {TOK_WORD, "while", 5}, - {TOK_WORD, "until", 5} + {TOK_WORD, "until", 5}, + {TOK_WORD, "function", 8} }; s_parser *parser_init(int fd) @@ -152,13 +150,16 @@ static s_ast_node *regnode(s_parser *parser, s_ast_node *node) static void parse_error(s_parser *parser, s_token t) { - fprintf(stderr, "%s: syntax error near unexpected token `%s'\n", - shell->name, t.str); + if (t.id == TOK_EOF) + fprintf(stderr, "%s: syntax error: unexpected end of file\n", shell->name); + else + fprintf(stderr, "%s: syntax error near unexpected token `%s'\n", + shell->name, t.str); parser->error = 1; shell->status = ERROR_PARSE; -/* if (parser->regnodes) */ -/* for (register int i = 0; parser->regnodes[i]; ++i) */ -/* ast_destruct(parser->regnodes[i]); */ + if (parser->regnodes) + for (register int i = 0; parser->regnodes[i]; ++i) + ast_destruct_node(parser->regnodes[i]); lexer_flush(parser->lexer); longjmp(parser->stack, 1); } @@ -168,9 +169,10 @@ s_ast_node *parse(s_parser *parser) parser->regpos = 0; parser->error = 0; // prevent of too big register ast size - if (parser->regsize >= 200) + if (parser->regsize >= REGISTER_REDUCE_SIZE) secrealloc(parser->regnodes, parser->regnodes, - (parser->regsize = 50) * sizeof (s_ast_node)); + (parser->regsize = REGISTER_DEFAULT_SIZE) * sizeof (s_ast_node)); + //return from parse_error (return !0) if (setjmp(parser->stack)) return NULL; show_prompt(PROMPT_PS1); @@ -178,10 +180,10 @@ s_ast_node *parse(s_parser *parser) //test lexer mode for (;;) { s_token tok = lexer_gettoken(parser->lexer); - if (tok.id == TOK_EOF) - exit(69); printf("Returned token: %d [%s]\n", tok.id, (*tok.str == '\n') ? "\\n" : tok.str); + if (tok.id == TOK_EOF) + exit(69); if (tok.id == TOK_NEWLINE) show_prompt(PROMPT_PS1); } @@ -290,7 +292,6 @@ static s_ast_node *parse_pipeline_command(s_parser *parser) return lhs; } -//problem of choice between simple and funcdec static s_ast_node *parse_command(s_parser *parser) { s_token token; @@ -302,13 +303,15 @@ static s_ast_node *parse_command(s_parser *parser) !strcmp(token.str, "if") || !strcmp(token.str, "until") || !strcmp(token.str, "{") || !strcmp(token.str, "case")))) return parse_shellcommand(parser); - // probleme de choix avec function pour l'instant seulement si function! - else if (token.id == TOK_WORD && !strcmp(token.str, "function")) + else if ((token.id == TOK_WORD && !strcmp(token.str, "function")) || + (token.id == TOK_WORD && + lexer_lookahead2(parser->lexer).id == TOK_LPAREN)) return parse_funcdec(parser); else if (token.id >= TOK_DLESSDASH && token.id <= TOK_WORD) return parse_simplecommand(parser); else parse_error(parser, token); + assert(0); return NULL; } @@ -341,7 +344,7 @@ static int parse_element(s_parser *parser, { s_token token; int found = 0; - int first = 1; + int first = 1; debugmsg("parse_element"); for (;;) { @@ -350,10 +353,14 @@ static int parse_element(s_parser *parser, parse_redirection(parser, red); ++found; } - else if (token.id == TOK_WORD && (!first || !is_keyword(token))) { + else if (token.id == TOK_WORD && first && !is_keyword(token)) { + first = 0; + //TODO: gestion des alias ast_cmd_add_argv(cmd, lexer_gettoken(parser->lexer).str); ++found; } + else if (token.id == TOK_WORD && !first) + ast_cmd_add_argv(cmd, lexer_gettoken(parser->lexer).str); else break; } return found; @@ -420,7 +427,6 @@ static s_ast_node *parse_shellcommand(s_parser *parser) return NULL; } -//IN PROGRESS static s_ast_node *parse_funcdec(s_parser *parser) { s_token tok; @@ -437,11 +443,9 @@ static s_ast_node *parse_funcdec(s_parser *parser) if (tok.id != TOK_WORD) parse_error(parser, tok); funcname = tok.str; - if ((tok = lexer_gettoken(parser->lexer)).id != TOK_WORD && - !strcmp(tok.str, "(")) + if (lexer_gettoken(parser->lexer).id != TOK_LPAREN) parse_error(parser, tok); - if ((tok = lexer_gettoken(parser->lexer)).id != TOK_WORD && - !strcmp(tok.str, ")")) + if (lexer_gettoken(parser->lexer).id != TOK_RPAREN) parse_error(parser, tok); eat_newline(); body = parse_shellcommand(parser); @@ -487,6 +491,7 @@ static void parse_redirection(s_parser *parser, s_ast_node **reds) case TOK_GREATAND: redtype = R_GREATAND; if (fd == -1) fd = 1; break; default: parse_error(parser, token); + redtype = 0; //to avoid warning about redtype may be unitialized } //retrieve redirection word token = lexer_gettoken(parser->lexer); @@ -510,6 +515,8 @@ static s_ast_node *parse_compound_list(s_parser *parser) tok = lexer_lookahead(parser->lexer); if (tok.id == TOK_SEP || tok.id == TOK_SEPAND || tok.id == TOK_NEWLINE) { lexer_gettoken(parser->lexer); + if (tok.id == TOK_NEWLINE) + show_prompt(PROMPT_PS2); eat_newline(); //check for and_or tok2 = lexer_lookahead(parser->lexer); @@ -572,7 +579,7 @@ static s_ast_node *parse_rulefor(s_parser *parser) while ((tok = lexer_lookahead(parser->lexer)).id == TOK_WORD); //check for ';' or '\n' if ((tok = lexer_gettoken(parser->lexer)).id != TOK_SEP && - tok.id != TOK_NEWLINE) + tok.id != TOK_NEWLINE) parse_error(parser, tok); //eat newline eat_newline(); @@ -726,8 +733,9 @@ static s_ast_node *parse_rulecase(s_parser *parser) free(tok.str); //eat newline eat_newline(); + //parse case body tok = lexer_lookahead(parser->lexer); - if ((tok.id == TOK_WORD && !strcmp(tok.str, "esac")) || + if ((tok.id == TOK_WORD && strcmp(tok.str, "esac")) || tok.id == TOK_LPAREN) { casenode = regnode(parser, ast_case_create(varname)); parse_caseclause(parser, casenode); @@ -744,13 +752,19 @@ static void parse_caseclause(s_parser *parser, s_ast_node *casenode) { s_token tok; - parse_caseitem(parser, casenode); - //check for token 'case' - tok = lexer_lookahead(parser->lexer); - if (tok.id != TOK_DSEMI) - return; - lexer_gettoken(parser->lexer); - tok = lexer_gettoken(parser->lexer); + debugmsg("parse_caseclause"); + do { + parse_caseitem(parser, casenode); + tok = lexer_lookahead(parser->lexer); + if (tok.id == TOK_DSEMI) { + lexer_gettoken(parser->lexer); + eat_newline(); + tok = lexer_lookahead(parser->lexer); + } + if (tok.id == TOK_WORD && !strcmp(tok.str, "esac")) + return; + } + while (1); } static void parse_caseitem(s_parser *parser, s_ast_node *casenode) @@ -759,6 +773,7 @@ static void parse_caseitem(s_parser *parser, s_ast_node *casenode) char **pattern = NULL; s_ast_node *exec = NULL; + debugmsg("parse_caseitem"); tok = lexer_gettoken(parser->lexer); //check for a '(' before pattern list if (tok.id == TOK_LPAREN) @@ -773,6 +788,9 @@ static void parse_caseitem(s_parser *parser, s_ast_node *casenode) parse_error(parser, tok); pattern = strvectoradd(pattern, tok.str); } + //check for ')' + if ((tok = lexer_gettoken(parser->lexer)).id != TOK_RPAREN) + parse_error(parser, tok); //eat newline eat_newline(); if ((tok = lexer_lookahead(parser->lexer)).id != TOK_DSEMI && diff --git a/src/parser/parser.h b/src/parser/parser.h index 41e2f3a..d0d7477 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Wed Aug 2 00:49:50 2006 Seblu -** Last update Mon Oct 16 15:33:04 2006 seblu +** Last update Wed Oct 18 18:28:06 2006 seblu */ #ifndef PARSER_H_ @@ -20,8 +20,11 @@ # define DEBUG_LEXER 0 enum { - TOKEN_COUNT = 22, + TOKEN_COUNT = 23, KEYWORD_COUNT = 15, + FD_MAX = 32765, + REGISTER_REDUCE_SIZE = 200, + REGISTER_DEFAULT_SIZE = 50, }; typedef enum tokenid @@ -59,7 +62,8 @@ typedef struct token typedef struct lexer { - s_token token; + s_token current; //working token + s_token previous; FILE *fs; char eof; char *buf; @@ -121,6 +125,7 @@ s_lexer *lexer_init(int fd); ** Flush current information of position in the line, ** size of the line, and free line buffer. This is call ** by the parser after an error. +** Flush don't reset eof flag ! ** ** @param lexer lexer to flush */ @@ -146,6 +151,17 @@ s_token lexer_gettoken(s_lexer *lexer); */ s_token lexer_lookahead(s_lexer *lexer); +/*! +** Return the next next token without destruction of it. +** @warning The token string MUST NOT be freed ! +** This is a possibility will come from LL1 lexer. +** +** @param lexer lexer structure +** +** @return the look ahead token +*/ +s_token lexer_lookahead2(s_lexer *lexer); + /*! ** Parse input as a here-document (describe is XSI) ** diff --git a/src/shell/prompt.c b/src/shell/prompt.c index ce1926b..34dec8b 100644 --- a/src/shell/prompt.c +++ b/src/shell/prompt.c @@ -5,7 +5,7 @@ ** Login ** ** Started on Sun Jul 30 02:27:59 2006 Seblu -** Last update Tue Aug 29 00:47:41 2006 Seblu +** Last update Wed Oct 18 21:08:51 2006 seblu */ #include @@ -38,22 +38,20 @@ const char *get_prompt(e_prompt pty) //todo gestion des variables ! void show_prompt(e_prompt pty) { - char *prompt; - if (!isinteractive()) return; + fflush(stderr); switch (pty) { + default: case PROMPT_PS1: - prompt = "42sh "; + fprintf(stderr, "%s$ ", shell->name); break; case PROMPT_PS2: - prompt = "> "; + fprintf(stderr, "> "); break; case PROMPT_PS4: - prompt = "+"; + fprintf(stderr, "+ "); break; } fflush(stderr); - fprintf(stderr, "%s", prompt); - fflush(stderr); } diff --git a/src/shell/shell.h b/src/shell/shell.h index 9d1f4ad..079c00a 100644 --- a/src/shell/shell.h +++ b/src/shell/shell.h @@ -5,7 +5,7 @@ ** Login ** ** Started on Sun Jul 16 20:03:53 2006 Seblu -** Last update Tue Aug 29 00:51:36 2006 Seblu +** Last update Tue Oct 17 09:38:57 2006 seblu */ #ifndef SHELL_H_ diff --git a/test/parse/bad/compoundlist_1.sh b/test/parse/bad/compoundlist_1.sh new file mode 100644 index 0000000..7e217f9 --- /dev/null +++ b/test/parse/bad/compoundlist_1.sh @@ -0,0 +1 @@ +{ toto; do; } diff --git a/test/parse/bad/eof.sh b/test/parse/bad/eof.sh new file mode 100644 index 0000000..a327fb3 --- /dev/null +++ b/test/parse/bad/eof.sh @@ -0,0 +1,3 @@ +echo "toto +titi +tata diff --git a/test/parse/bad/freetext.sh b/test/parse/bad/freetext.sh new file mode 100644 index 0000000..5e2eef5 --- /dev/null +++ b/test/parse/bad/freetext.sh @@ -0,0 +1,7 @@ + +coucou +c'est moi +EOF +je suis grand +OF + diff --git a/test/parse/bad/if_1.sh b/test/parse/bad/if_1.sh new file mode 100644 index 0000000..9641b43 --- /dev/null +++ b/test/parse/bad/if_1.sh @@ -0,0 +1,11 @@ +if { true; false; true & false; true && false; false; } then + false +elif { true; false; true & false; true && false; false; } then + true; +else + if { true; false; true & false; true && false; false; } then + true; + fi +elif { true; false; true & false; true && false; false; } then + true; +fi diff --git a/test/parse/bad/reserved_1.sh b/test/parse/bad/reserved_1.sh new file mode 100644 index 0000000..2627403 --- /dev/null +++ b/test/parse/bad/reserved_1.sh @@ -0,0 +1 @@ +true; fi diff --git a/test/parse/bad/reserved_2.sh b/test/parse/bad/reserved_2.sh new file mode 100644 index 0000000..8e75d0f --- /dev/null +++ b/test/parse/bad/reserved_2.sh @@ -0,0 +1 @@ +{ function toto; } diff --git a/test/parse/good/big_1.sh b/test/parse/good/big_1.sh new file mode 100644 index 0000000..0ae86dc --- /dev/null +++ b/test/parse/good/big_1.sh @@ -0,0 +1,63 @@ +toto=bite tata=chate >chiche 2pipi 4>popo >>pupu +{ toto; ! titi; toto && titi; } +{ true; ! false; { false; }; } +function toto() +{ + echo "je m'appel toto" +} +cat << EOF; echo toto; cat << OF + +coucou +c'est moi +EOF +je suis grand +OF + + +if true; then + false +elif false; then + false; +else + true; +fi + +if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + false; + fi + fi + fi + fi + fi + fi + fi + fi +else + true; +fi + +if { true toto; false; true & false; true && false; false; } then + false +elif { true; false; true & false; true && false; false; } then + true; +else + if { true; false; true & false; true && false; false; } then + true; + fi +fi +if [[ -f /etc/DIR_COLORS ]] ; then + match_lhs=$(/dev/null ; then + match_lhs=$(dircolors --print-database) +else + match_lhs="" +fi#!/bin/sh +for i in toto tata titi; do echo $i; done diff --git a/test/parse/good/big_command.sh b/test/parse/good/big_command.sh new file mode 100644 index 0000000..7feb8b2 --- /dev/null +++ b/test/parse/good/big_command.sh @@ -0,0 +1 @@ +toto=bite tata=chate >chiche 2pipi 4>popo >>pupu diff --git a/test/parse/good/brace_1.sh b/test/parse/good/brace_1.sh new file mode 100644 index 0000000..9008709 --- /dev/null +++ b/test/parse/good/brace_1.sh @@ -0,0 +1 @@ +{ toto; ! titi; toto && titi; } diff --git a/test/parse/good/brace_2.sh b/test/parse/good/brace_2.sh new file mode 100644 index 0000000..62cd067 --- /dev/null +++ b/test/parse/good/brace_2.sh @@ -0,0 +1 @@ +{ true; ! false; { false; }; } diff --git a/test/parse/good/case_1.sh b/test/parse/good/case_1.sh new file mode 100644 index 0000000..c5a509b --- /dev/null +++ b/test/parse/good/case_1.sh @@ -0,0 +1,14 @@ +case toto in + tata) + cmd >> toto | sex |bite + ;; + titi) + cmd2 &>/sex `ls -la < /sex` + ;; + toto) + cmd4 >/sex + ;; +esac diff --git a/test/parse/good/empty.sh b/test/parse/good/empty.sh new file mode 100644 index 0000000..e69de29 diff --git a/test/parse/good/funcdec.sh b/test/parse/good/funcdec.sh new file mode 100644 index 0000000..789d975 --- /dev/null +++ b/test/parse/good/funcdec.sh @@ -0,0 +1,4 @@ +function toto() +{ + echo "je m'appel toto" +} diff --git a/test/parse/good/heredocs.sh b/test/parse/good/heredocs.sh new file mode 100644 index 0000000..ea90425 --- /dev/null +++ b/test/parse/good/heredocs.sh @@ -0,0 +1,8 @@ +cat << EOF; echo toto; cat << OF + +coucou +c'est moi +EOF +je suis grand +OF + diff --git a/test/parse/good/if_1.sh b/test/parse/good/if_1.sh new file mode 100644 index 0000000..fcddb7f --- /dev/null +++ b/test/parse/good/if_1.sh @@ -0,0 +1,7 @@ +if true; then + false +elif false; then + false; +else + true; +fi diff --git a/test/parse/good/if_2.sh b/test/parse/good/if_2.sh new file mode 100644 index 0000000..76d5a0f --- /dev/null +++ b/test/parse/good/if_2.sh @@ -0,0 +1,21 @@ +if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + if true; then + false; + fi + fi + fi + fi + fi + fi + fi + fi +else + true; +fi diff --git a/test/parse/good/if_3.sh b/test/parse/good/if_3.sh new file mode 100644 index 0000000..cb72390 --- /dev/null +++ b/test/parse/good/if_3.sh @@ -0,0 +1,9 @@ +if { true toto; false; true & false; true && false; false; } then + false +elif { true; false; true & false; true && false; false; } then + true; +else + if { true; false; true & false; true && false; false; } then + true; + fi +fi diff --git a/test/parse/good/if_4.sh b/test/parse/good/if_4.sh new file mode 100644 index 0000000..791e197 --- /dev/null +++ b/test/parse/good/if_4.sh @@ -0,0 +1,7 @@ +if [[ -f /etc/DIR_COLORS ]] ; then + match_lhs=$(/dev/null ; then + match_lhs=$(dircolors --print-database) +else + match_lhs="" +fi \ No newline at end of file diff --git a/test/parse/good/sheebang.sh b/test/parse/good/sheebang.sh new file mode 100644 index 0000000..66d6228 --- /dev/null +++ b/test/parse/good/sheebang.sh @@ -0,0 +1 @@ +#!/bin/42sh diff --git a/test/parse/good/simple_for.sh b/test/parse/good/simple_for.sh new file mode 100644 index 0000000..6917793 --- /dev/null +++ b/test/parse/good/simple_for.sh @@ -0,0 +1 @@ +for i in toto tata titi; do echo $i; done diff --git a/test/parse/moulette.sh b/test/parse/moulette.sh new file mode 100755 index 0000000..a45db75 --- /dev/null +++ b/test/parse/moulette.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +my42sh="../../src/42sh" + +# check good syntax +for file in good/*; do + $my42sh < "$file" &>/dev/null + echo ">>>>>>Return: $?" +done + +# check bad syntax +for file in bad/*; do + $my42sh < "$file" &>/dev/null + echo ">>>>>>Return: $?" +done diff --git a/tools/last-ast.sh b/tools/last-ast.sh index 849b433..94d01ec 100755 --- a/tools/last-ast.sh +++ b/tools/last-ast.sh @@ -32,4 +32,4 @@ ln -sf ${last%*.dot}.png ast.png echo "${lyellow}Showing ${lblue}${last%*.dot}.png${lyellow}...$norm" xview=`which xview` test -x "$xview" || { echo "${lred}xview not found !$norm"; exit 2; } -"$xview" ast.png +"$xview" ast.png & -- GitLab