grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] bug fix for scripting (update 2)


From: Marco Gerards
Subject: Re: [PATCH] bug fix for scripting (update 2)
Date: Sun, 22 Jul 2007 14:57:31 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux)

Bean <address@hidden> writes:

> 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

The header of the changelog entry is missing.

>       * 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.

Can you leave this part out of the patch for now?  See the text below.

>       * 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);

ok

>       }
>        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);

ok

>       }
>        else
>       grub_strcat (chararg, argi->str);
> @@ -100,6 +102,9 @@
>    grubcmd = grub_command_find (cmdline->cmdname);
>    if (! grubcmd)
>      {
> +      /* Reset error number */
> +      grub_errno = 0;
> +

Please use GRUB_ERR_NONE.  I know this isn't done consistently, but
this is what I prefer.

Why is this change needed and whih problem does it fix?

>        /* 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 == ' '))

Why do you change indention here?

>                   {
>                     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);

You are still doing parsing in the lexer.  I don't like that...  If
you make a separate patch that excludes this, be can apply that first
before we work on this specific problem.  I don't want to hold back
applying the fixes for these other bugs because of this.

>      }
>    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
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel

--
Marco





reply via email to

[Prev in Thread] Current Thread [Next in Thread]