Hi,

Attached patch adds for-loop support to GRUB script.  It is based on
r/grub/people/bvk/grub-script branch.  Please review it and let me
know your comments.

Unfortunately, there is a bug in GRUB script string arguments
expansion, which is causing grub_script_for1.in test case to fail.  I
will fix it separately as it requires changes in other parts of GRUB
script code.



thanks,
-- 
bvk.chaitanya
=== 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 <arg> GRUB_PARSER_TOKEN_WORD      "word"
 
 %type <arglist> word argument arguments0 arguments1
-%type <cmd> script_init script grubcmd ifcmd command
+%type <cmd> script_init script grubcmd ifcmd forcmd command
 %type <cmd> 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;

_______________________________________________
Grub-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to