From: BVK Chaitanya Date: Wed, 12 May 2010 12:05:07 +0000 (+0530) Subject: pull-in func-params branch X-Git-Tag: 1.99~665^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=45ab4f486fee433f30fa9ae31f4ff7f555972500;p=thirdparty%2Fgrub.git pull-in func-params branch --- 45ab4f486fee433f30fa9ae31f4ff7f555972500 diff --cc include/grub/script_sh.h index 8610348f6,5455fc763..2b4c4e2f2 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@@ -64,6 -63,13 +64,13 @@@ struct grub_script_ar struct grub_script_arg *next; }; + /* An argument vector. */ + struct grub_script_argv + { - int argc; ++ unsigned argc; + char **args; + }; + /* A complete argument. It consists of a list of one or more `struct grub_script_arg's. */ struct grub_script_arglist diff --cc script/execute.c index d3f8e9b25,2040be13c..d83f51914 --- a/script/execute.c +++ b/script/execute.c @@@ -30,69 -30,112 +30,143 @@@ is sizeof (int) * 3, and one extra for a possible -ve sign. */ #define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1) + /* Scope for grub script functions. */ + struct grub_script_scope + { + struct grub_script_argv argv; + }; static struct grub_script_scope *scope = 0; +grub_err_t +grub_script_cmd_shift (grub_command_t cmd __attribute__((unused)), + int argc, char *argv[]) +{ + char *p = 0; + unsigned long n = 0; + + if (! scope) + return GRUB_ERR_NONE; + ++ if (scope->argv.argc == 0) ++ return GRUB_ERR_NONE; ++ + if (argc == 0) + n = 1; ++ + else if (argc > 1) + return GRUB_ERR_BAD_ARGUMENT; ++ + else + { + n = grub_strtoul (argv[0], &p, 10); - if (*p != '\0') ++ if (*p != '\0' || n > scope->argv.argc) + return GRUB_ERR_BAD_ARGUMENT; + } + - scope->shift = (unsigned int)(n > scope->argc ? 0 : n); ++ scope->argv.argc -= n; ++ scope->argv.args += n; + return GRUB_ERR_NONE; +} + - static char * - grub_script_env_get (const char *name) + static int + grub_env_special (const char *name) { - char *p = 0; - unsigned long num = 0; + if (grub_isdigit (name[0]) || + grub_strcmp (name, "#") == 0 || + grub_strcmp (name, "*") == 0 || + grub_strcmp (name, "@") == 0) + return 1; + return 0; + } - if (! scope) - return grub_env_get (name); + static char ** + grub_script_env_get (const char *name, grub_script_arg_type_t type) + { + int errors = 0; + struct grub_script_argv result = { 0, 0 }; + + errors += grub_script_argv_next (&result); + if (! grub_env_special (name)) + { + char *v = grub_env_get (name); + if (v && v[0]) + { + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + errors += grub_script_argv_split_append (&result, v); + else + errors += grub_script_argv_append (&result, v); + } + } + else if (! scope) + errors += grub_script_argv_append (&result, 0); - if (grub_isdigit (name[0])) + else if (grub_strcmp (name, "#") == 0) { - num = grub_strtoul (name, &p, 10); - if (p && *p == '\0') + char buffer[ERRNO_DIGITS_MAX + 1]; + grub_snprintf (buffer, sizeof (buffer), "%u", scope->argv.argc); + errors += grub_script_argv_append (&result, buffer); + } + else if (grub_strcmp (name, "*") == 0) + { - int i; ++ unsigned i; + + for (i = 0; ! errors && i < scope->argv.argc; i++) + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (i != 0) + errors += grub_script_argv_next (&result); + errors += grub_script_argv_split_append (&result, + scope->argv.args[i]); + } + else + { + if (i != 0) + errors += grub_script_argv_append (&result, " "); + errors += grub_script_argv_append (&result, + scope->argv.args[i]); + } + } + else if (grub_strcmp (name, "@") == 0) + { - int i; ++ unsigned i; + + for (i = 0; ! errors && i < scope->argv.argc; i++) { - if (num == 0) - return 0; /* XXX no file name, for now. */ + if (i != 0) + errors += grub_script_argv_next (&result); - if (num > scope->argc - scope->shift) - return 0; + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + errors += grub_script_argv_split_append (&result, + scope->argv.args[i]); else - return scope->args[num - 1 + scope->shift]; + errors += grub_script_argv_append (&result, + scope->argv.args[i]); } - else + } + else + { + unsigned long num = grub_strtoul (name, 0, 10); + if (num == 0) + ; /* XXX no file name, for now. */ + + else if (num <= scope->argv.argc) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variabe name substitution"); - return 0; + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + errors += grub_script_argv_split_append (&result, + scope->argv.args[num - 1]); + else + errors += grub_script_argv_append (&result, + scope->argv.args[num - 1]); } } - else if (grub_strcmp (name, "#") == 0) + + if (errors) { - static char buf[32]; /* Rewritten everytime. */ - grub_snprintf (buf, sizeof (buf), "%u", scope->argc - scope->shift); - return buf; + grub_script_argv_free (&result); + return 0; } - else - return grub_env_get (name); + + return result.args; } static grub_err_t @@@ -399,14 -353,12 +384,12 @@@ grub_script_execute_cmdif (struct grub_ grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd) { -- int i; ++ unsigned i; int result; - char **args; - int argcount; + struct grub_script_argv argv; struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd; - args = grub_script_execute_arglist_to_argv (cmdfor->words, &argcount); - if (!args) + if (grub_script_arglist_to_argv (cmdfor->words, &argv)) return grub_errno; result = 0; diff --cc tests/grub_script_shift.in index 542e72974,000000000..c7c94ab18 mode 100644,000000..100644 --- a/tests/grub_script_shift.in +++ b/tests/grub_script_shift.in @@@ -1,69 -1,0 +1,69 @@@ +#! @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 . + +function f1 { + echo f1 $# $1 $2 $3 + shift + echo f1 $# $1 $2 $3 +} + - function f2 { - echo f2 $# $1 $2 $3 - shift 1 - echo f2 $# $1 $2 $3 - } - - function f3 { - echo f3 $# $1 $2 $3 - shift 3 - echo f3 $# $1 $2 $3 - } - - function f4 { - echo f4 $# $1 $2 $3 - shift 100 - echo f4 $# $1 $2 $3 - } - +f1 +f1 a +f1 a b +f1 a b c +f1 a b c d +f1 a b c d e + ++function f2 { ++ echo f2 $# $1 $2 $3 ++ shift 1 ++ echo f2 $# $1 $2 $3 ++} ++ +f2 +f2 a +f2 a b +f2 a b c +f2 a b c d +f2 a b c d e + ++function f3 { ++ echo f3 $# $1 $2 $3 ++ shift 3 ++ echo f3 $# $1 $2 $3 ++} ++ +f3 +f3 a +f3 a b +f3 a b c +f3 a b c d +f3 a b c d e + ++function f4 { ++ echo f4 $# $1 $2 $3 ++ shift 100 ++ echo f4 $# $1 $2 $3 ++} ++ +f4 +f4 a +f4 a b +f4 a b c +f4 a b c d +f4 a b c d e