diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index 17b1c5a5a..e1bf6f22e 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -49,7 +49,8 @@ typedef enum GRUB_SCRIPT_ARG_TYPE_TEXT, GRUB_SCRIPT_ARG_TYPE_DQVAR, GRUB_SCRIPT_ARG_TYPE_DQSTR, - GRUB_SCRIPT_ARG_TYPE_SQSTR + GRUB_SCRIPT_ARG_TYPE_SQSTR, + GRUB_SCRIPT_ARG_TYPE_BLOCK } grub_script_arg_type_t; /* A part of an argument. */ @@ -59,6 +60,9 @@ struct grub_script_arg char *str; + /* Parsed block argument. */ + struct grub_script_cmd *block; + /* Next argument part. */ struct grub_script_arg *next; }; diff --git a/script/execute.c b/script/execute.c index 40f161267..31fce554c 100644 --- a/script/execute.c +++ b/script/execute.c @@ -152,6 +152,7 @@ grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *c } break; + case GRUB_SCRIPT_ARG_TYPE_BLOCK: case GRUB_SCRIPT_ARG_TYPE_TEXT: if (grub_strlen (arg->str) > 0) { diff --git a/script/parser.y b/script/parser.y index e5de35cf4..9d256a153 100644 --- a/script/parser.y +++ b/script/parser.y @@ -74,7 +74,7 @@ %token GRUB_PARSER_TOKEN_NAME "name" %token GRUB_PARSER_TOKEN_WORD "word" -%type word argument arguments0 arguments1 +%type word argument block parameters0 parameters1 arguments0 arguments1 %type script_init script %type grubcmd ifclause ifcmd forcmd whilecmd untilcmd @@ -147,6 +147,27 @@ argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); } | word { $$ = $1; } ; +block: "{" + { + grub_script_lexer_ref (state->lexerstate); + $$ = grub_script_lexer_record_start (state); + } + commands1 delimiters0 "}" + { + char *p; + struct grub_script_arg *arg; + + grub_script_lexer_deref (state->lexerstate); + if (p = grub_script_lexer_record_stop (state, $2)) + *grub_strrchr (p, '}') = '\0'; + + if (arg = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p)) + arg->block = $3; + + $$ = grub_script_add_arglist (state, 0, arg); + } +; + arguments0: /* Empty */ { $$ = 0; } | arguments1 { $$ = $1; } ; @@ -162,7 +183,32 @@ arguments1: argument arguments0 } ; -grubcmd: word arguments0 +parameters1: argument parameters0 + { + if ($1 && $2) + { + $1->next = $2; + $1->argcount += $2->argcount; + $2->argcount = 0; + } + $$ = $1; + } + | block parameters0 + { + if ($1 && $2) + { + $1->next = $2; + $1->argcount += $2->argcount; + $2->argcount = 0; + } + $$ = $1; + } +; +parameters0: /* Empty */ { $$ = 0; } + | parameters1 { $$ = $1; } +; + +grubcmd: word parameters0 { if ($1 && $2) { $1->next = $2; diff --git a/script/yylex.l b/script/yylex.l index 29aa5c2e3..585f818cb 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -114,7 +114,7 @@ typedef size_t yy_size_t; BLANK [ \t] COMMENT ^[ \t]*#.*$ -CHAR [^|&$;<> \t\n\'\"\\] +CHAR [^{}|&$;<> \t\n\'\"\\] DIGITS [[:digit:]]+ NAME [[:alpha:]_][[:alnum:][:digit:]_]*