=== modified file 'conf/tests.rmk' --- conf/tests.rmk 2009-12-19 12:48:11 +0000 +++ conf/tests.rmk 2009-12-24 21:04:32 +0000 @@ -45,3 +45,9 @@ check_SCRIPTS += grub_script_functions1 grub_script_functions1_SOURCES = tests/grub_script_functions1.in + +check_SCRIPTS += grub_script_for1 +grub_script_for1_SOURCES = tests/grub_script_for1.in + +check_SCRIPTS += grub_script_vars1 +grub_script_vars1_SOURCES = tests/grub_script_vars1.in === modified file 'include/grub/script_sh.h' --- include/grub/script_sh.h 2009-12-20 07:00:31 +0000 +++ include/grub/script_sh.h 2009-12-24 20:34:07 +0000 @@ -103,6 +103,21 @@ struct grub_script_cmd *exec_on_false; }; +/* A for statement. */ +struct grub_script_cmdfor +{ + struct grub_script_cmd cmd; + + /* The name used as looping variable. */ + struct grub_script_arg *name; + + /* The words loop iterates over. */ + struct grub_script_arglist *words; + + /* The command list executed in each loop. */ + struct grub_script_cmd *list; +}; + /* A menu entry generate statement. */ struct grub_script_cmd_menuentry { @@ -209,6 +224,12 @@ struct grub_script_cmd *exec_on_false); struct grub_script_cmd * +grub_script_create_cmdfor (struct grub_parser_param *state, + struct grub_script_arg *name, + struct grub_script_arglist *words, + struct grub_script_cmd *list); + +struct grub_script_cmd * grub_script_create_cmdmenu (struct grub_parser_param *state, struct grub_script_arglist *arglist, char *sourcecode, @@ -256,6 +277,7 @@ grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd); +grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd); /* Execute any GRUB pre-parsed command or script. */ === modified file 'script/execute.c' --- script/execute.c 2009-12-13 12:35:20 +0000 +++ script/execute.c 2009-12-24 21:17:09 +0000 @@ -197,6 +197,57 @@ return grub_script_execute_cmd (cmdif->exec_on_false); } +/* Execute a for statement. */ +grub_err_t +grub_script_execute_cmdfor (struct grub_script_cmd *cmd) +{ + char *str; + char *end; + char *start; + int last; + int result; + struct grub_script_arglist *word; + struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd; + + result = 0; + word = cmdfor->words; + while (word) + { + str = grub_script_execute_argument_to_string (word->arg); + if (!str) + return 1; + + last = 0; + start = str; + while (!last && *start) + { + /* Skip whitespaces. */ + while (*start && grub_isspace (*start)) + start++; + + if (*start == '\0') + break; + + end = start + 1; + while (*end && !grub_isspace (*end)) + end++; + if (*end == '\0') + last = 1; + else + *end = '\0'; + + grub_env_set (cmdfor->name->str, start); + result = grub_script_execute_cmd (cmdfor->list); + start = end + 1; + } + + grub_free (str); + word = word->next; + } + + return result; +} + /* Execute the menu entry generate statement. */ grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd) === modified file 'script/parser.y' --- script/parser.y 2009-12-20 07:00:31 +0000 +++ script/parser.y 2009-12-24 20:32:31 +0000 @@ -76,7 +76,7 @@ %token GRUB_PARSER_TOKEN_WORD "word" %type word argument arguments0 arguments1 -%type script_init script grubcmd ifcmd command +%type script_init script grubcmd ifcmd forcmd command %type commands1 menuentry statement %pure-parser @@ -181,6 +181,7 @@ /* A single command. */ command: grubcmd { $$ = $1; } | ifcmd { $$ = $1; } + | forcmd { $$ = $1; } ; /* A list of commands. */ @@ -249,3 +250,14 @@ grub_script_lexer_deref (state->lexerstate); } ; + +forcmd: "for" "name" + { + grub_script_lexer_ref (state->lexerstate); + } + "in" arguments0 delimiters1 "do" commands1 delimiters1 "done" + { + $$ = grub_script_create_cmdfor (state, $2, $5, $8); + grub_script_lexer_deref (state->lexerstate); + } +; === modified file 'script/script.c' --- script/script.c 2009-12-20 07:30:02 +0000 +++ script/script.c 2009-12-24 20:07:58 +0000 @@ -206,6 +206,30 @@ return (struct grub_script_cmd *) cmd; } +/* Create a command that functions as a for statement. */ +struct grub_script_cmd * +grub_script_create_cmdfor (struct grub_parser_param *state, + struct grub_script_arg *name, + struct grub_script_arglist *words, + struct grub_script_cmd *list) +{ + struct grub_script_cmdfor *cmd; + + grub_dprintf ("scripting", "cmdfor\n"); + + cmd = grub_script_malloc (state, sizeof (*cmd)); + if (! cmd) + return 0; + + cmd->cmd.exec = grub_script_execute_cmdfor; + cmd->cmd.next = 0; + cmd->name = name; + cmd->words = words; + cmd->list = list; + + return (struct grub_script_cmd *) cmd; +} + /* Create a command that adds a menu entry to the menu. Title is an argument that is parsed to generate a string that can be used as the title. The sourcecode for this entry is passed in SOURCECODE. === added file 'tests/grub_script_for1.in' --- tests/grub_script_for1.in 1970-01-01 00:00:00 +0000 +++ tests/grub_script_for1.in 2009-12-24 21:22:17 +0000 @@ -0,0 +1,27 @@ +#! @builddir@/grub-shell-tester + +for x in one two 'three 3' "four 4" five six-6; do echo $x; done + +for x in one two 'three 3' "four 4" five six-6 +do + echo $x +done + +foo="1 2" +for x in ab${foo}cd; do echo $x; done +for x in "ab${foo}cd"; do echo $x; done + +a="one two three" +y=foo +echo $y +for y in $a; do + echo $y +done +echo $y + + +b="one two three" +for z in $b; do + echo $z +done +echo $z === added file 'tests/grub_script_vars1.in' --- tests/grub_script_vars1.in 1970-01-01 00:00:00 +0000 +++ tests/grub_script_vars1.in 2009-12-24 21:02:22 +0000 @@ -0,0 +1,10 @@ +#! @builddir@/grub-shell-tester + +var=foo +echo $var +echo "$var" +echo ${var} +echo "${var}" + + + === modified file 'util/grub-script-check.c' --- util/grub-script-check.c 2009-12-20 06:08:06 +0000 +++ util/grub-script-check.c 2009-12-24 20:38:30 +0000 @@ -78,6 +78,12 @@ } grub_err_t +grub_script_execute_cmdfor (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd) { struct grub_script_cmd_menuentry *menu;