]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
function parameters support
authorBVK Chaitanya <bvk.groups@gmail.com>
Wed, 5 May 2010 09:17:50 +0000 (14:47 +0530)
committerBVK Chaitanya <bvk.groups@gmail.com>
Wed, 5 May 2010 09:17:50 +0000 (14:47 +0530)
conf/tests.rmk
include/grub/script_sh.h
script/execute.c
script/function.c
script/yylex.l
tests/grub_script_functions.in [new file with mode: 0644]

index 9af2f8f866716539fb25f5bc76ec888a81a67db4..9144e552845b3a517dc7ff959b226bbfcc722e58 100644 (file)
@@ -71,6 +71,9 @@ grub_script_dollar_SOURCES = tests/grub_script_dollar.in
 check_SCRIPTS += grub_script_comments
 grub_script_comments_SOURCES = tests/grub_script_comments.in
 
+check_SCRIPTS += grub_script_functions
+grub_script_functions_SOURCES = tests/grub_script_functions.in
+
 # List of tests to execute on "make check"
 # SCRIPTED_TESTS    = example_scripted_test
 # SCRIPTED_TESTS   += example_grub_script_test
@@ -87,6 +90,7 @@ SCRIPTED_TESTS += grub_script_blanklines
 SCRIPTED_TESTS += grub_script_final_semicolon
 SCRIPTED_TESTS += grub_script_dollar
 SCRIPTED_TESTS += grub_script_comments
+SCRIPTED_TESTS += grub_script_functions
 
 # dependencies between tests and testing-tools
 $(SCRIPTED_TESTS): grub-shell grub-shell-tester
index 53f4f13bb30232081316731bda28faccbd1bda36..730aa30050e85670d054d70cbcfa559e58f09109 100644 (file)
@@ -73,6 +73,15 @@ struct grub_script_arglist
   int argcount;
 };
 
+/* Scope for grub script constructs.  */
+struct grub_script_scope
+{
+  struct grub_script_scope *next;
+
+  char **args;
+  unsigned int argc;
+};
+
 /* A single command line.  */
 struct grub_script_cmdline
 {
@@ -329,8 +338,8 @@ grub_script_function_t grub_script_function_create (struct grub_script_arg *func
 void grub_script_function_remove (const char *name);
 grub_script_function_t grub_script_function_find (char *functionname);
 int grub_script_function_iterate (int (*iterate) (grub_script_function_t));
-int grub_script_function_call (grub_script_function_t func,
-                              int argc, char **args);
+grub_err_t grub_script_function_call (grub_script_function_t func,
+                                     int argc, char **args);
 
 char **
 grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count);
index e10558b4d55b2ebac71221d2e3373bf9e44f82f1..571b6785bfc13de1c49f4555463b515bb8f95eca 100644 (file)
    is sizeof (int) * 3, and one extra for a possible -ve sign.  */
 #define ERRNO_DIGITS_MAX  (sizeof (int) * 3 + 1)
 
+static struct grub_script_scope *scope = 0;
+
+static char *
+grub_script_env_get (const char *name)
+{
+  char *p = 0;
+  unsigned long num = 0;
+
+  if (! scope)
+    return grub_env_get (name);
+
+  if (grub_isdigit (name[0]))
+    {
+      num = grub_strtoul (name, &p, 10);
+      if (p && *p == '\0')
+       {
+         if (num == 0)
+           return 0; /* XXX no file name, for now.  */
+
+         return (num > scope->argc ? 0 : scope->args[num - 1]);
+       }
+      else
+       {
+         grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variabe name substitution");
+         return 0;
+       }
+    }
+  else if (grub_strcmp (name, "#") == 0)
+    {
+      static char buf[32]; /* Rewritten everytime.  */
+      grub_snprintf (buf, sizeof (buf), "%u", scope->argc);
+      return buf;
+    }
+  else
+    return grub_env_get (name);
+}
+
+static grub_err_t
+grub_script_env_set (const char *name, const char *val)
+{
+  if (grub_isdigit (name[0]) || grub_strcmp (name, "#") == 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variable name");
+
+  return grub_env_set (name, val);
+}
+
 static grub_err_t
 grub_script_execute_cmd (struct grub_script_cmd *cmd)
 {
@@ -143,7 +189,7 @@ grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *c
          switch (arg->type)
            {
            case GRUB_SCRIPT_ARG_TYPE_VAR:
-             value = grub_env_get (arg->str);
+             value = grub_script_env_get (arg->str);
              while (value && *value && (ptr = move_to_next(&value)))
                {
                  empty = 0;
@@ -168,7 +214,7 @@ grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *c
 
            case GRUB_SCRIPT_ARG_TYPE_DQVAR:
              empty = 0;
-             append (grub_env_get (arg->str), 0);
+             append (grub_script_env_get (arg->str), 0);
              break;
            }
          arg = arg->next;
@@ -191,6 +237,23 @@ grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *c
   return argv;
 }
 
+/* Execute a function call.  */
+grub_err_t
+grub_script_function_call (grub_script_function_t func, int argc, char **args)
+{
+  grub_err_t ret = 0;
+  struct grub_script_scope new_scope;
+
+  new_scope.argc = argc;
+  new_scope.args = args;
+  grub_list_push (GRUB_AS_LIST_P (&scope), GRUB_AS_LIST (&new_scope));
+
+  ret = grub_script_execute (func->func);
+
+  grub_list_pop (GRUB_AS_LIST_P (&scope));
+  return ret;
+}
+
 /* Execute a single command line.  */
 grub_err_t
 grub_script_execute_cmdline (struct grub_script_cmd *cmd)
@@ -232,12 +295,12 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
              /* Create two strings and set the variable.  */
              *eq = '\0';
              eq++;
-             grub_env_set (assign, eq);
+             grub_script_env_set (assign, eq);
            }
          grub_free (assign);
 
          grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno);
-         grub_env_set ("?", errnobuf);
+         grub_script_env_set ("?", errnobuf);
 
          grub_print_error ();
 
@@ -291,7 +354,7 @@ grub_script_execute_cmdif (struct grub_script_cmd *cmd)
   /* Check if the commands results in a true or a false.  The value is
      read from the env variable `?'.  */
   grub_script_execute_cmd (cmdif->exec_to_evaluate);
-  result = grub_env_get ("?");
+  result = grub_script_env_get ("?");
 
   grub_errno = GRUB_ERR_NONE;
 
@@ -320,7 +383,7 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
   result = 0;
   for (i = 0; i < argcount; i++)
     {
-      grub_env_set (cmdfor->name->str, args[i]);
+      grub_script_env_set (cmdfor->name->str, args[i]);
       result = grub_script_execute_cmd (cmdfor->list);
       grub_free (args[i]);
     }
index ded470c4ee1650132db920ded1e8768e782afedc..82c753bcd83b3d3db591586cd2926cddd4378534 100644 (file)
@@ -115,12 +115,3 @@ grub_script_function_iterate (int (*iterate) (grub_script_function_t))
 
   return 0;
 }
-
-int
-grub_script_function_call (grub_script_function_t func,
-                          int argc __attribute__((unused)),
-                          char **args __attribute__((unused)))
-{
-  /* XXX: Arguments are not supported yet.  */
-  return grub_script_execute (func->func);
-}
index 7d4ea9e4e3027683a716c003cff42393b841b1f4..f563ac30d02d80517858e314810c8469c34efd51 100644 (file)
@@ -119,7 +119,8 @@ DIGITS          [[:digit:]]+
 NAME            [[:alpha:]_][[:alnum:][:digit:]_]*
 
 ESC             \\.
-VARIABLE        ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\}
+SPECIAL        \?|\#
+VARIABLE        ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|${SPECIAL}|$\{{SPECIAL}\}
 DQSTR           \"([^\\\"]|{ESC})*\"
 SQSTR           \'[^\']*\'
 WORD            ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
@@ -221,7 +222,7 @@ WORD            ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
 }
 
 <VAR>{
-  \?            |
+  {SPECIAL}     |
   {DIGITS}      |
   {NAME}        {
                   COPY (yytext, yyleng);
@@ -231,7 +232,7 @@ WORD            ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+
                   else
                     ARG (GRUB_SCRIPT_ARG_TYPE_DQVAR);
                 }
-  \{\?\}        |
+  \{{SPECIAL}\} |
   \{{DIGITS}\}  |
   \{{NAME}\}    {
                   yytext[yyleng - 1] = '\0';
diff --git a/tests/grub_script_functions.in b/tests/grub_script_functions.in
new file mode 100644 (file)
index 0000000..41af874
--- /dev/null
@@ -0,0 +1,63 @@
+#! @builddir@/grub-shell-tester
+
+# Run GRUB script in a Qemu instance
+# Copyright (C) 2010  Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+
+echo parameter count
+function fcount {
+  echo "$#"
+}
+
+fcount
+fcount a
+fcount a b
+
+echo parameter count, with nesting
+function ffcount {
+  echo "$#"
+  fcount
+  fcount a
+  fcount a b
+}
+
+ffcount
+ffcount 1
+ffcount 1 2
+
+echo parameters
+function fparam {
+  echo 1 $1
+  echo 2 $2
+  echo 3 $3
+}
+
+fparam
+fparam a
+fparam a b
+
+echo parameters, with nesting
+function ffparam {
+  echo 1 $1
+  echo 2 $2
+  echo 3 $3
+  fparam
+  fparam a
+  fparam a b
+}
+
+ffparam
+ffparam 1
+ffparam 1 2