From e2413da90146d0e4de09fc5bfbf44842f6922381 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Fri, 11 Jun 2010 13:59:07 +0530 Subject: [PATCH 1/7] multiline support for strings --- script/yylex.l | 114 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 23 deletions(-) diff --git a/script/yylex.l b/script/yylex.l index 7d4ea9e4e..658bcfdf8 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -58,6 +58,7 @@ #define YY_INPUT(buf,res,max) do { res = 0; } while (0) /* forward declarations */ +static int resplit (const char *input, yyscan_t yyscanner); static void grub_lexer_yyfree (void *, yyscan_t yyscanner); static void* grub_lexer_yyalloc (yy_size_t, yyscan_t yyscanner); static void* grub_lexer_yyrealloc (void*, yy_size_t, yyscan_t yyscanner); @@ -120,14 +121,19 @@ NAME [[:alpha:]_][[:alnum:][:digit:]_]* ESC \\. VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} -DQSTR \"([^\\\"]|{ESC})*\" -SQSTR \'[^\']*\' +DQSTR \"([^\"]|{ESC})*\" +SQSTR \'([^\'])*\' WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ +DQSTR2 {WORD}?\"({ESC}|[^\"])*\n +SQSTR2 {WORD}?\'({ESC}|[^\'])*\n + %x SPLIT %x DQUOTE %x SQUOTE %x VAR +%x DQMULTILINE +%x SQMULTILINE %% @@ -173,26 +179,55 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ {NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; } {WORD} { RECORD; - /* resplit yytext */ - grub_dprintf ("lexer", "word: [%s]\n", yytext); - yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); - if (yy_scan_string (yytext, yyscanner)) - { - yyextra->lexerstate->merge_start = 1; - yy_push_state (SPLIT, yyscanner); - } - else - { - grub_script_yyerror (yyextra, 0); - yypop_buffer_state (yyscanner); - return GRUB_PARSER_TOKEN_WORD; - } + yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); + if (resplit (yytext, yyscanner)) + { + yypop_buffer_state (yyscanner); + return GRUB_PARSER_TOKEN_WORD; + } + } +{DQSTR2} { + yy_push_state (DQMULTILINE, yyscanner); + grub_script_lexer_ref (yyextra->lexerstate); + yymore (); + } +{ + \"{WORD}? { + RECORD; + grub_script_lexer_deref (yyextra->lexerstate); + yy_pop_state (yyscanner); + yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); + if (resplit (yytext, yyscanner)) + { + yypop_buffer_state (yyscanner); + return GRUB_PARSER_TOKEN_WORD; + } + } + {ESC} { yymore(); } + [^\"] { yymore(); } +} + +{SQSTR2} { + yy_push_state (SQMULTILINE, yyscanner); + grub_script_lexer_ref (yyextra->lexerstate); + yymore (); } -.|\n { - grub_script_yyerror (yyextra, "unrecognized token"); - return GRUB_PARSER_TOKEN_BAD; +{ + \'{WORD}? { + RECORD; + grub_script_lexer_deref (yyextra->lexerstate); + yy_pop_state (yyscanner); + yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); + if (resplit (yytext, yyscanner)) + { + yypop_buffer_state (yyscanner); + return GRUB_PARSER_TOKEN_WORD; + } } + {ESC} { yymore(); } + [^\'] { yymore(); } +} /* Split word into multiple args */ @@ -270,6 +305,7 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ (.|\n) { COPY (yytext, yyleng); } } +. { /* ignore */ } <> { yypop_buffer_state (yyscanner); if (! grub_script_lexer_yywrap (yyextra)) @@ -278,9 +314,29 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ return GRUB_PARSER_TOKEN_EOF; } } - %% +#if 0 +int +yywrap (yyscan_t yyscanner) +{ + char *line = 0; + struct grub_lexer_param *lexerstate = yyget_extra(yyscanner)->lexerstate; + + grub_printf ("yywrap\n"); + if (lexerstate->getline) + { + lexerstate->getline (&line, 1); + if (! line) + return 1; + + yy_scan_string (line, yyscanner); + return 0; + } + return 1; +} +#endif + static void grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused))) { @@ -300,8 +356,6 @@ grub_lexer_yyrealloc (void *ptr, yy_size_t size, return grub_realloc (ptr, size); } -#define MAX(a,b) ((a) < (b) ? (b) : (a)) - static void copy_string (struct grub_parser_param *parser, const char *str, unsigned hint) { int size; @@ -311,7 +365,7 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi len = hint ? hint : grub_strlen (str); if (parser->lexerstate->used + len >= parser->lexerstate->size) { - size = MAX (len, parser->lexerstate->size) * 2; + size = grub_max (len, parser->lexerstate->size) * 2; ptr = grub_realloc (parser->lexerstate->text, size); if (!ptr) { @@ -325,3 +379,17 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi grub_strcpy (parser->lexerstate->text + parser->lexerstate->used - 1, str); parser->lexerstate->used += len; } + +static int +resplit (const char *text, yyscan_t yyscanner) +{ + /* resplit text */ + if (yy_scan_string (text, yyscanner)) + { + yyget_extra (yyscanner)->lexerstate->merge_start = 1; + yy_push_state (SPLIT, yyscanner); + return 0; + } + grub_script_yyerror (yyget_extra (yyscanner), 0); + return 1; +} From b06f83e3babd32fe94c9a6ca54153cd6f0e51ebb Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sat, 12 Jun 2010 11:06:02 +0530 Subject: [PATCH 2/7] a better fix --- include/grub/script_sh.h | 8 ++- script/lexer.c | 126 ++++++++++++++++++--------------------- script/yylex.l | 118 ++++++++++++++---------------------- 3 files changed, 110 insertions(+), 142 deletions(-) diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index b55b6a806..447b3a375 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -195,6 +195,12 @@ struct grub_lexer_param /* Type of text. */ grub_script_arg_type_t type; + /* Flag to indicate resplit in progres. */ + unsigned resplit; + + /* Text that is unput. */ + char *prefix; + /* Flex scanner. */ void *yyscanner; @@ -284,7 +290,7 @@ void grub_script_lexer_ref (struct grub_lexer_param *); void grub_script_lexer_deref (struct grub_lexer_param *); void grub_script_lexer_record_start (struct grub_parser_param *); char *grub_script_lexer_record_stop (struct grub_parser_param *); -int grub_script_lexer_yywrap (struct grub_parser_param *); +int grub_script_lexer_yywrap (struct grub_parser_param *, const char *input); void grub_script_lexer_record (struct grub_parser_param *, char *); /* Functions to track allocated memory. */ diff --git a/script/lexer.c b/script/lexer.c index 42a570348..63b74e2e0 100644 --- a/script/lexer.c +++ b/script/lexer.c @@ -98,8 +98,6 @@ grub_script_lexer_record_stop (struct grub_parser_param *parser) return result; } -#define MAX(a,b) ((a) < (b) ? (b) : (a)) - /* Record STR if input recording is enabled. */ void grub_script_lexer_record (struct grub_parser_param *parser, char *str) @@ -115,7 +113,7 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str) if (lexer->recordpos + len + 1 > lexer->recordlen) { old = lexer->recording; - lexer->recordlen = MAX (len, lexer->recordlen) * 2; + lexer->recordlen = grub_max (len, lexer->recordlen) * 2; lexer->recording = grub_realloc (lexer->recording, lexer->recordlen); if (!lexer->recording) { @@ -131,76 +129,85 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str) lexer->recordpos += len; } -/* Append '\n' to SRC, before '\0' */ -static char * -append_newline (const char *src) -{ - char *line; - grub_size_t len; - - len = grub_strlen (src); - line = grub_malloc (len + 2); - if (!line) - return 0; - - grub_strcpy (line, src); - - line[len] = '\n'; - line[len + 1] = '\0'; - return line; -} - /* Read next line of input if necessary, and set yyscanner buffers. */ int -grub_script_lexer_yywrap (struct grub_parser_param *parserstate) +grub_script_lexer_yywrap (struct grub_parser_param *parserstate, + const char *input) { int len; - char *line; - char *line2; + char *p = 0; + char *line = 0; YY_BUFFER_STATE buffer; struct grub_lexer_param *lexerstate = parserstate->lexerstate; - if (!lexerstate->refs) - return 0; + if (! lexerstate->refs && ! lexerstate->prefix && ! input) + return 1; - if (!lexerstate->getline) + if (! lexerstate->getline && ! input) { grub_script_yyerror (parserstate, "unexpected end of file"); - return 0; + return 1; } line = 0; - buffer = 0; - lexerstate->getline (&line, 1); - if (!line) + if (! input) + lexerstate->getline (&line, 1); + else + line = grub_strdup (input); + if (! line) { - grub_script_yyerror (parserstate, 0); /* XXX this could be for ^C case? */ - return 0; + grub_script_yyerror (parserstate, 0); + return 1; } len = grub_strlen (line); - if (line[len - 1] == '\n') + if (lexerstate->prefix) { - buffer = yy_scan_string (line, lexerstate->yyscanner); - } - else - { - line2 = append_newline (line); - if (line2) + int plen = grub_strlen (lexerstate->prefix); + + p = grub_malloc (len + plen + 2); + if (! p) { - buffer = yy_scan_string (line2, lexerstate->yyscanner); - grub_free (line2); + grub_free (line); + return 1; } + grub_strcpy (p, lexerstate->prefix); + lexerstate->prefix = 0; + + if (! line[0]) + { + line = "\n"; + len = 1; + } + grub_strcpy (p + plen, line); + + line = p; + len = len + plen; } + if (line[len - 1] != '\n') + { + char *p; + p = grub_realloc (line, len + 2); + if (! p) + { + grub_free (line); + return 1; + } + line = p; + line[len++] = '\n'; + line[len] = '\0'; + } + + buffer = yy_scan_string (line, lexerstate->yyscanner); grub_free (line); - if (!buffer) + + if (! buffer) { grub_script_yyerror (parserstate, 0); - return 0; + return 1; } - - return 1; + return 0; } struct grub_lexer_param * @@ -231,35 +238,18 @@ grub_script_lexer_init (struct grub_parser_param *parser, char *script, grub_free (lexerstate); return 0; } + yyset_extra (parser, lexerstate->yyscanner); + parser->lexerstate = lexerstate; - buffer = 0; - script = script ? : "\n"; - len = grub_strlen (script); - - if (script[len - 1] == '\n') - { - buffer = yy_scan_string (script, lexerstate->yyscanner); - } - else - { - script2 = append_newline (script); - if (script2) - { - buffer = yy_scan_string (script2, lexerstate->yyscanner); - grub_free (script2); - } - } - - if (!buffer) + if (grub_script_lexer_yywrap (parser, script ?: "\n")) { + parser->lexerstate = 0; yylex_destroy (lexerstate->yyscanner); grub_free (lexerstate->yyscanner); - grub_free (lexerstate->text); grub_free (lexerstate); return 0; } - yyset_extra (parser, lexerstate->yyscanner); return lexerstate; } diff --git a/script/yylex.l b/script/yylex.l index 658bcfdf8..025810da3 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -58,7 +58,9 @@ #define YY_INPUT(buf,res,max) do { res = 0; } while (0) /* forward declarations */ -static int resplit (const char *input, yyscan_t yyscanner); +static int grub_lexer_unput (const char *input, yyscan_t yyscanner); +static int grub_lexer_resplit (const char *input, yyscan_t yyscanner); + static void grub_lexer_yyfree (void *, yyscan_t yyscanner); static void* grub_lexer_yyalloc (yy_size_t, yyscan_t yyscanner); static void* grub_lexer_yyrealloc (void*, yy_size_t, yyscan_t yyscanner); @@ -100,10 +102,9 @@ typedef size_t yy_size_t; %option never-interactive %option noyyfree noyyalloc noyyrealloc -%option nounistd nostdinit nodefault noyylineno noyywrap +%option nounistd nostdinit nodefault noyylineno /* Reduce lexer size, by not defining these. */ -%option noyy_top_state %option noinput nounput %option noyyget_in noyyset_in %option noyyget_out noyyset_out @@ -120,20 +121,19 @@ DIGITS [[:digit:]]+ NAME [[:alpha:]_][[:alnum:][:digit:]_]* ESC \\. +SQCHR [^\'] +DQCHR {ESC}|[^\"] +DQSTR \"{DQCHR}*\" +SQSTR \'{SQCHR}*\' VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} -DQSTR \"([^\"]|{ESC})*\" -SQSTR \'([^\'])*\' WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ -DQSTR2 {WORD}?\"({ESC}|[^\"])*\n -SQSTR2 {WORD}?\'({ESC}|[^\'])*\n +MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)) %x SPLIT %x DQUOTE %x SQUOTE %x VAR -%x DQMULTILINE -%x SQMULTILINE %% @@ -179,55 +179,22 @@ SQSTR2 {WORD}?\'({ESC}|[^\'])*\n {NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; } {WORD} { RECORD; + yyextra->lexerstate->resplit = 1; yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); - if (resplit (yytext, yyscanner)) + if (grub_lexer_resplit (yytext, yyscanner)) { yypop_buffer_state (yyscanner); return GRUB_PARSER_TOKEN_WORD; } } -{DQSTR2} { - yy_push_state (DQMULTILINE, yyscanner); - grub_script_lexer_ref (yyextra->lexerstate); - yymore (); +{MULTILINE} { + if (grub_lexer_unput (yytext, yyscanner)) + return GRUB_PARSER_TOKEN_BAD; + } +. { + grub_script_yyerror (yyextra, yytext); + return GRUB_PARSER_TOKEN_BAD; } -{ - \"{WORD}? { - RECORD; - grub_script_lexer_deref (yyextra->lexerstate); - yy_pop_state (yyscanner); - yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); - if (resplit (yytext, yyscanner)) - { - yypop_buffer_state (yyscanner); - return GRUB_PARSER_TOKEN_WORD; - } - } - {ESC} { yymore(); } - [^\"] { yymore(); } -} - -{SQSTR2} { - yy_push_state (SQMULTILINE, yyscanner); - grub_script_lexer_ref (yyextra->lexerstate); - yymore (); - } - -{ - \'{WORD}? { - RECORD; - grub_script_lexer_deref (yyextra->lexerstate); - yy_pop_state (yyscanner); - yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); - if (resplit (yytext, yyscanner)) - { - yypop_buffer_state (yyscanner); - return GRUB_PARSER_TOKEN_WORD; - } - } - {ESC} { yymore(); } - [^\'] { yymore(); } -} /* Split word into multiple args */ @@ -250,6 +217,7 @@ SQSTR2 {WORD}?\'({ESC}|[^\'])*\n <> { yy_pop_state (yyscanner); yypop_buffer_state (yyscanner); + yyextra->lexerstate->resplit = 0; yyextra->lexerstate->merge_end = 1; ARG (GRUB_SCRIPT_ARG_TYPE_TEXT); } @@ -305,37 +273,21 @@ SQSTR2 {WORD}?\'({ESC}|[^\'])*\n (.|\n) { COPY (yytext, yyleng); } } -. { /* ignore */ } <> { yypop_buffer_state (yyscanner); - if (! grub_script_lexer_yywrap (yyextra)) - { - yyextra->lexerstate->eof = 1; - return GRUB_PARSER_TOKEN_EOF; - } + yyextra->lexerstate->eof = 1; + return GRUB_PARSER_TOKEN_EOF; } %% -#if 0 int yywrap (yyscan_t yyscanner) { - char *line = 0; - struct grub_lexer_param *lexerstate = yyget_extra(yyscanner)->lexerstate; + if (yyget_extra (yyscanner)->lexerstate->resplit) + return 1; - grub_printf ("yywrap\n"); - if (lexerstate->getline) - { - lexerstate->getline (&line, 1); - if (! line) - return 1; - - yy_scan_string (line, yyscanner); - return 0; - } - return 1; + return grub_script_lexer_yywrap (yyget_extra (yyscanner), 0); } -#endif static void grub_lexer_yyfree (void *ptr, yyscan_t yyscanner __attribute__ ((unused))) @@ -381,7 +333,7 @@ static void copy_string (struct grub_parser_param *parser, const char *str, unsi } static int -resplit (const char *text, yyscan_t yyscanner) +grub_lexer_resplit (const char *text, yyscan_t yyscanner) { /* resplit text */ if (yy_scan_string (text, yyscanner)) @@ -393,3 +345,23 @@ resplit (const char *text, yyscan_t yyscanner) grub_script_yyerror (yyget_extra (yyscanner), 0); return 1; } + +static int +grub_lexer_unput (const char *text, yyscan_t yyscanner) +{ + struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate; + + if (lexerstate->prefix) + { + grub_free (lexerstate->prefix); + lexerstate->prefix = 0; + } + + lexerstate->prefix = grub_strdup (text); + if (! lexerstate->prefix) + { + grub_script_yyerror (yyget_extra (yyscanner), "out of memory"); + return 1; + } + return 0; +} From 94606d3845d316b9619699b32a0685d57213c1f4 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sat, 12 Jun 2010 11:12:38 +0530 Subject: [PATCH 3/7] some minor fixes --- script/yylex.l | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/script/yylex.l b/script/yylex.l index 025810da3..c5c5cc4e3 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -105,6 +105,7 @@ typedef size_t yy_size_t; %option nounistd nostdinit nodefault noyylineno /* Reduce lexer size, by not defining these. */ +%option noyy_top_state %option noinput nounput %option noyyget_in noyyset_in %option noyyget_out noyyset_out @@ -179,13 +180,13 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)) {NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; } {WORD} { RECORD; - yyextra->lexerstate->resplit = 1; yypush_buffer_state (YY_CURRENT_BUFFER, yyscanner); if (grub_lexer_resplit (yytext, yyscanner)) { yypop_buffer_state (yyscanner); return GRUB_PARSER_TOKEN_WORD; } + yyextra->lexerstate->resplit = 1; } {MULTILINE} { if (grub_lexer_unput (yytext, yyscanner)) @@ -352,10 +353,7 @@ grub_lexer_unput (const char *text, yyscan_t yyscanner) struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate; if (lexerstate->prefix) - { - grub_free (lexerstate->prefix); - lexerstate->prefix = 0; - } + grub_free (lexerstate->prefix); lexerstate->prefix = grub_strdup (text); if (! lexerstate->prefix) From 4c4a352a9819552d81f0cb58a31fb0b6b0206231 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sat, 12 Jun 2010 11:15:53 +0530 Subject: [PATCH 4/7] small fix, large gain (in size) --- script/yylex.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/yylex.l b/script/yylex.l index c5c5cc4e3..2e770c49f 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -123,7 +123,7 @@ NAME [[:alpha:]_][[:alnum:][:digit:]_]* ESC \\. SQCHR [^\'] -DQCHR {ESC}|[^\"] +DQCHR {ESC}|[^\\\"] DQSTR \"{DQCHR}*\" SQSTR \'{SQCHR}*\' VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} From 2f169df5a48358b07cff6a788b39210818b14a58 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sat, 12 Jun 2010 11:25:44 +0530 Subject: [PATCH 5/7] updated echo1 test with multiline strings --- tests/grub_script_echo1.in | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/grub_script_echo1.in b/tests/grub_script_echo1.in index 048907a76..056ea73ad 100644 --- a/tests/grub_script_echo1.in +++ b/tests/grub_script_echo1.in @@ -30,3 +30,33 @@ e"$foo"${bar}o hello world foo=echo $foo 1234 + +echo "one +" +echo "one +\"" +echo "one +two" + +echo one"two +"three +echo one"two +\""three +echo one"two +\"three\" +four" + + +echo 'one +' +echo 'one +\' +echo 'one +two' +echo one'two +' +echo one'two +\' +echo one'two +\'three + From 0500dfd1b46eb465c2ddbb68651d38d109f29fcc Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sat, 12 Jun 2010 12:02:06 +0530 Subject: [PATCH 6/7] cleanup & a fix --- script/lexer.c | 45 +++++++++++++++++++------------------- tests/grub_script_echo1.in | 4 ++++ 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/script/lexer.c b/script/lexer.c index 63b74e2e0..208ad0bf6 100644 --- a/script/lexer.c +++ b/script/lexer.c @@ -154,18 +154,37 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, lexerstate->getline (&line, 1); else line = grub_strdup (input); + + /* Ensure '\n' at the end. */ + if (line && line[0] == '\0') + { + grub_free (line); + line = grub_strdup ("\n"); + } + + if (line && (len = grub_strlen(line)) && line[len - 1] != '\n') + { + p = grub_realloc (line, len + 2); + if (p) + { + p[len++] = '\n'; + p[len] = '\0'; + } + line = p; + } + if (! line) { - grub_script_yyerror (parserstate, 0); + grub_script_yyerror (parserstate, "out of memory"); return 1; } - len = grub_strlen (line); + /* Prepend any left over unput-text. */ if (lexerstate->prefix) { int plen = grub_strlen (lexerstate->prefix); - p = grub_malloc (len + plen + 2); + p = grub_malloc (len + plen + 1); if (! p) { grub_free (line); @@ -174,31 +193,13 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, grub_strcpy (p, lexerstate->prefix); lexerstate->prefix = 0; - if (! line[0]) - { - line = "\n"; - len = 1; - } grub_strcpy (p + plen, line); + grub_free (line); line = p; len = len + plen; } - if (line[len - 1] != '\n') - { - char *p; - p = grub_realloc (line, len + 2); - if (! p) - { - grub_free (line); - return 1; - } - line = p; - line[len++] = '\n'; - line[len] = '\0'; - } - buffer = yy_scan_string (line, lexerstate->yyscanner); grub_free (line); diff --git a/tests/grub_script_echo1.in b/tests/grub_script_echo1.in index 056ea73ad..13b7364f4 100644 --- a/tests/grub_script_echo1.in +++ b/tests/grub_script_echo1.in @@ -60,3 +60,7 @@ echo one'two echo one'two \'three +# echo "one +# +# two" + From 7b466fbb9e3cba84dd616e52bb5fe812711242a3 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sat, 12 Jun 2010 12:23:49 +0530 Subject: [PATCH 7/7] logical linebreaks support --- script/yylex.l | 14 ++++++++------ tests/grub_script_echo1.in | 8 ++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/script/yylex.l b/script/yylex.l index 2e770c49f..c580b1ed3 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -121,7 +121,7 @@ CHAR [^{}|&$;<> \t\n\'\"\\] DIGITS [[:digit:]]+ NAME [[:alpha:]_][[:alnum:][:digit:]_]* -ESC \\. +ESC \\(.|\n) SQCHR [^\'] DQCHR {ESC}|[^\\\"] DQSTR \"{DQCHR}*\" @@ -129,7 +129,7 @@ SQSTR \'{SQCHR}*\' VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ -MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)) +MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n)) %x SPLIT %x DQUOTE @@ -177,6 +177,11 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)) "function" { RECORD; return GRUB_PARSER_TOKEN_FUNCTION; } "menuentry" { RECORD; return GRUB_PARSER_TOKEN_MENUENTRY; } +{MULTILINE} { + if (grub_lexer_unput (yytext, yyscanner)) + return GRUB_PARSER_TOKEN_BAD; + } + {NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; } {WORD} { RECORD; @@ -188,10 +193,6 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)) } yyextra->lexerstate->resplit = 1; } -{MULTILINE} { - if (grub_lexer_unput (yytext, yyscanner)) - return GRUB_PARSER_TOKEN_BAD; - } . { grub_script_yyerror (yyextra, yytext); return GRUB_PARSER_TOKEN_BAD; @@ -201,6 +202,7 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)) { \\. { COPY (yytext + 1, yyleng - 1); } + \\\n { /* ignore */ } \" { yy_push_state (DQUOTE, yyscanner); ARG (GRUB_SCRIPT_ARG_TYPE_TEXT); diff --git a/tests/grub_script_echo1.in b/tests/grub_script_echo1.in index 13b7364f4..2a90fc65f 100644 --- a/tests/grub_script_echo1.in +++ b/tests/grub_script_echo1.in @@ -60,6 +60,14 @@ echo one'two echo one'two \'three +# echo "one\ +# two" +# echo 'one\ +# two' +# echo foo\ +# bar +# \ +# echo foo # echo "one # # two"