]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
multiline support for strings
authorBVK Chaitanya <bvk.groups@gmail.com>
Fri, 11 Jun 2010 08:29:07 +0000 (13:59 +0530)
committerBVK Chaitanya <bvk.groups@gmail.com>
Fri, 11 Jun 2010 08:29:07 +0000 (13:59 +0530)
script/yylex.l

index 7d4ea9e4e3027683a716c003cff42393b841b1f4..658bcfdf8289c550aa2e455b2a99d7c440667a24 100644 (file)
@@ -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,27 +179,56 @@ 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 ();
+                }
+<DQMULTILINE>{
+  \"{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(); }
+}
 
-.|\n            {
-                  grub_script_yyerror (yyextra, "unrecognized token");
-                  return GRUB_PARSER_TOKEN_BAD;
+{SQSTR2}        {
+                 yy_push_state (SQMULTILINE, yyscanner);
+                 grub_script_lexer_ref (yyextra->lexerstate);
+                 yymore ();
                 }
 
+<SQMULTILINE>{
+  \'{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 */
 
 <SPLIT>{
@@ -270,6 +305,7 @@ WORD            ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
   (.|\n)        { COPY (yytext, yyleng); }
 }
 
+.               { /* ignore */ }
 <<EOF>>         {
                   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;
+}