]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
a better fix
authorBVK Chaitanya <bvk.groups@gmail.com>
Sat, 12 Jun 2010 05:36:02 +0000 (11:06 +0530)
committerBVK Chaitanya <bvk.groups@gmail.com>
Sat, 12 Jun 2010 05:36:02 +0000 (11:06 +0530)
include/grub/script_sh.h
script/lexer.c
script/yylex.l

index b55b6a806bdf338c41ec67df6b3b62975dc98051..447b3a375da99cbe51abfea8dab979ec5f86a9db 100644 (file)
@@ -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.  */
index 42a570348081544f196e1015aeae843a5e38c34f..63b74e2e01e433ea30d3777154d2414d2db8299e 100644 (file)
@@ -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);
+      int plen = grub_strlen (lexerstate->prefix);
+
+      p = grub_malloc (len + plen + 2);
+      if (! p)
+       {
+         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;
     }
-  else
+
+  if (line[len - 1] != '\n')
     {
-      line2 = append_newline (line);
-      if (line2)
+      char *p;
+      p = grub_realloc (line, len + 2);
+      if (! p)
        {
-         buffer = yy_scan_string (line2, lexerstate->yyscanner);
-         grub_free (line2);
+         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;
 }
index 658bcfdf8289c550aa2e455b2a99d7c440667a24..025810da37290ccdef5f9952759f6f1b2d492a51 100644 (file)
@@ -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))
-                   {
-                     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))
+                 if (grub_lexer_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 ();
-                }
-
-<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;
-                   }
+{MULTILINE}     {
+                  if (grub_lexer_unput (yytext, yyscanner))
+                   return GRUB_PARSER_TOKEN_BAD;
+               }
+.               {
+                  grub_script_yyerror (yyextra, yytext);
+                 return GRUB_PARSER_TOKEN_BAD;
                 }
-  {ESC}         { yymore(); }
-  [^\']         { yymore(); }
-}
 
  /* Split word into multiple args */
 
@@ -250,6 +217,7 @@ SQSTR2          {WORD}?\'({ESC}|[^\'])*\n
   <<EOF>>       {
                   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 */ }
 <<EOF>>         {
                   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;
+}