* 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 script grubcmd command commands commandblock menuentry if %type arguments; -%type argument; +%type argument GRUB_PARSER_TOKEN_VAR; %type "if" "while" "function" "else" "then" "fi" -%type text GRUB_PARSER_TOKEN_NAME GRUB_PARSER_TOKEN_VAR +%type 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},