This patch fixes the following bugs:

1. Token parser

echo aa"bb"cc
old: aa"bb"
new:  aa"bb"cc

set BB=1
echo aa$BB
old: aa 1
new: aa1

set BB=1
echo ${BB}aa
old: 1 aa
new: 1aa

set AA=1
set BB=$AA
echo $BB
old: empty
new: 1

AA is not defined
echo $AA
old: trash
new: empty

2. function

function aa {
echo $AA
}
old: infinite loop
new: ok

function bb {
  echo Hello
}
old: Unknown command `echo'
new: ok

BTW, the echo module needs to be enabled manually in conf/common.rmk.

-- 
Bean
-- 
Bean
        * kern/parser.c (state_transitions): Exit GRUB_PARSER_STATE_VARNAME
        state when "/" is encountered.

        * normal/execute.c (grub_script_argument_to_string): Output empty
        string when variable does not exist.

        * normal/execute.c (grub_script_execute_cmdline): Reset error
        number.

        * normal/lexer.c (grub_script_yylex2): Return arg structure when
        mixed text is detected.

        * normal/parser.y : token GRUB_PARSER_TOKEN_VAR returns arg
        instead of text.


Index: normal/execute.c
===================================================================
RCS file: /sources/grub/grub2/normal/execute.c,v
retrieving revision 1.4
diff -u -r1.4 execute.c
--- normal/execute.c    28 May 2006 21:58:34 -0000      1.4
+++ normal/execute.c    25 Jun 2007 11:43:57 -0000
@@ -50,7 +50,8 @@
       if (argi->type == 1)
        {
          val = grub_env_get (argi->str);
-         size += grub_strlen (val);
+         if (val)
+           size += grub_strlen (val);
        }
       else
        size += grub_strlen (argi->str);
@@ -68,7 +69,8 @@
       if (argi->type == 1)
        {
          val = grub_env_get (argi->str);
-         grub_strcat (chararg, val);
+         if (val)
+           grub_strcat (chararg, val);
        }
       else
        grub_strcat (chararg, argi->str);
@@ -100,6 +102,9 @@
   grubcmd = grub_command_find (cmdline->cmdname);
   if (! grubcmd)
     {
+      /* Reset error number */
+      grub_errno = 0;
+
       /* It's not a GRUB command, try all functions.  */
       func = grub_script_function_find (cmdline->cmdname);
       if (! func)
Index: normal/lexer.c
===================================================================
RCS file: /sources/grub/grub2/normal/lexer.c,v
retrieving revision 1.6
diff -u -r1.6 lexer.c
--- normal/lexer.c      4 Jun 2006 15:56:55 -0000       1.6
+++ normal/lexer.c      25 Jun 2007 11:43:58 -0000
@@ -161,6 +161,8 @@
   char *buffer;
   char *bp;
   struct grub_lexer_param *state = parsestate->lexerstate;
+  struct grub_script_arg *arg = 0;
+  int done = 0;
 
   if (state->done)
     return 0;
@@ -196,13 +198,14 @@
        }
     }
 
+back:
   newstate = grub_parser_cmdline_state (state->state, *state->script, &use);
 
   /* Check if it is a text.  */
   if (check_textstate (newstate))
     {
       /* In case the string is not quoted, this can be a one char
-        length symbol.  */
+         length symbol.  */
       if (newstate == GRUB_PARSER_STATE_TEXT)
        {
          switch (*state->script)
@@ -213,7 +216,7 @@
                  newstate = grub_parser_cmdline_state (state->state,
                                                        *state->script, &use);
                  if (! (state->state == GRUB_PARSER_STATE_TEXT
-                        && *state->script == ' '))
+                         && *state->script == ' '))
                    {
                      grub_dprintf ("scripting", "token=` '\n");
                      return ' ';
@@ -260,8 +263,6 @@
          if (newstate == GRUB_PARSER_STATE_TEXT
              && state->state != GRUB_PARSER_STATE_ESC)
            {
-             int breakout = 0;
-
              switch (use)
                {
                case ' ':
@@ -269,13 +270,13 @@
                case '}':
                case ';':
                case '\n':
-                 breakout = 1;
+                 done = 1;
                }
-             if (breakout)
+             if (done)
                break;
-             *(bp++) = use;
            }
-         else if (use)
+
+         if (use)
            *(bp++) = use;
 
          state->state = newstate;
@@ -285,27 +286,39 @@
       /* A string of text was read in.  */
       *bp = '\0';
       grub_dprintf ("scripting", "token=`%s'\n", buffer);
-      yylval->string = buffer;
 
-      /* Detect some special tokens.  */
-      if (! grub_strcmp (buffer, "while"))
-       return GRUB_PARSER_TOKEN_WHILE;
-      else if (! grub_strcmp (buffer, "if"))
-       return GRUB_PARSER_TOKEN_IF;
-      else if (! grub_strcmp (buffer, "function"))
-       return GRUB_PARSER_TOKEN_FUNCTION;
-      else if (! grub_strcmp (buffer, "menuentry"))
-       return GRUB_PARSER_TOKEN_MENUENTRY;
-      else if (! grub_strcmp (buffer, "@"))
-       return GRUB_PARSER_TOKEN_MENUENTRY;
-      else if (! grub_strcmp (buffer, "else"))
-       return GRUB_PARSER_TOKEN_ELSE;
-      else if (! grub_strcmp (buffer, "then"))
-       return GRUB_PARSER_TOKEN_THEN;
-      else if (! grub_strcmp (buffer, "fi"))
-       return GRUB_PARSER_TOKEN_FI;
-      else
-       return GRUB_PARSER_TOKEN_NAME;
+      if (!*state->script)
+       done = 1;
+
+      if ((done) && (!arg))
+       {
+         yylval->string = buffer;
+
+         /* Detect some special tokens.  */
+         if (! grub_strcmp (buffer, "while"))
+           return GRUB_PARSER_TOKEN_WHILE;
+         else if (! grub_strcmp (buffer, "if"))
+           return GRUB_PARSER_TOKEN_IF;
+         else if (! grub_strcmp (buffer, "function"))
+           return GRUB_PARSER_TOKEN_FUNCTION;
+         else if (! grub_strcmp (buffer, "menuentry"))
+           return GRUB_PARSER_TOKEN_MENUENTRY;
+         else if (! grub_strcmp (buffer, "@"))
+           return GRUB_PARSER_TOKEN_MENUENTRY;
+         else if (! grub_strcmp (buffer, "else"))
+           return GRUB_PARSER_TOKEN_ELSE;
+         else if (! grub_strcmp (buffer, "then"))
+           return GRUB_PARSER_TOKEN_THEN;
+         else if (! grub_strcmp (buffer, "fi"))
+           return GRUB_PARSER_TOKEN_FI;
+         else
+           return GRUB_PARSER_TOKEN_NAME;
+       }
+
+      if (bp != buffer)
+       arg =
+         grub_script_arg_add (parsestate, arg, GRUB_SCRIPT_ARG_TYPE_STR,
+                              buffer);
     }
   else if (newstate == GRUB_PARSER_STATE_VAR
           || newstate == GRUB_PARSER_STATE_QVAR)
@@ -341,19 +354,33 @@
        }
 
       *bp = '\0';
-      state->state = newstate;
-      yylval->string = buffer;
-      grub_dprintf ("scripting", "vartoken=`%s'\n", buffer);
+      if (newstate == GRUB_PARSER_STATE_VARNAME)
+        state->state = GRUB_PARSER_STATE_TEXT;
 
-      return GRUB_PARSER_TOKEN_VAR;
+      if (bp != buffer)
+       arg = grub_script_arg_add (parsestate, arg, GRUB_SCRIPT_ARG_TYPE_VAR,
+                                  buffer);
     }
   else
     {
       /* There is either text or a variable name.  In the case you
-        arrive here there is a serious problem with the lexer.  */
+         arrive here there is a serious problem with the lexer.  */
       grub_error (GRUB_ERR_BAD_ARGUMENT, "Internal error\n");
       return 0;
     }
+
+  if ((done) || (!*state->script))
+    {
+      if (arg)
+       {
+         yylval->arg = arg;
+         return GRUB_PARSER_TOKEN_VAR;
+       }
+      else
+       return ' ';
+    }
+
+  goto back;
 }
 
 void
Index: normal/parser.y
===================================================================
RCS file: /sources/grub/grub2/normal/parser.y,v
retrieving revision 1.6
diff -u -r1.6 parser.y
--- normal/parser.y     4 Jun 2006 15:56:55 -0000       1.6
+++ normal/parser.y     25 Jun 2007 11:43:58 -0000
@@ -46,9 +46,9 @@
 %token GRUB_PARSER_TOKEN_VAR
 %type <cmd> script grubcmd command commands commandblock menuentry if
 %type <arglist> arguments;
-%type <arg> argument;
+%type <arg> argument GRUB_PARSER_TOKEN_VAR;
 %type <string> "if" "while" "function" "else" "then" "fi"
-%type <string> text GRUB_PARSER_TOKEN_NAME GRUB_PARSER_TOKEN_VAR
+%type <string> text GRUB_PARSER_TOKEN_NAME
 
 %pure-parser
 %lex-param { struct grub_parser_param *state };
@@ -86,7 +86,7 @@
    for example: `foo${bar}baz'.  */
 argument:      GRUB_PARSER_TOKEN_VAR
                  {
-                   $$ = grub_script_arg_add (state, 0, 
GRUB_SCRIPT_ARG_TYPE_VAR, $1);
+                   $$ = $1;
                  }
                | text
                  {
Index: kern/parser.c
===================================================================
RCS file: /sources/grub/grub2/kern/parser.c,v
retrieving revision 1.2
diff -u -r1.2 parser.c
--- kern/parser.c       23 Nov 2005 03:36:24 -0000      1.2
+++ kern/parser.c       25 Jun 2007 11:43:58 -0000
@@ -44,6 +44,7 @@
   { GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME2, '{', 0},
   { GRUB_PARSER_STATE_VAR, GRUB_PARSER_STATE_VARNAME, 0, 1},
   { GRUB_PARSER_STATE_VARNAME, GRUB_PARSER_STATE_TEXT, ' ', 1},
+  { GRUB_PARSER_STATE_VARNAME, GRUB_PARSER_STATE_TEXT, '/', 1},
   { GRUB_PARSER_STATE_VARNAME2, GRUB_PARSER_STATE_TEXT, '}', 0},
 
   { GRUB_PARSER_STATE_QVAR, GRUB_PARSER_STATE_QVARNAME2, '{', 0},
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to