From 3a20130e7a667e89c369346d122a7f900f65990b Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sun, 15 Aug 2010 12:02:33 +0530 Subject: [PATCH] setparams command to set positional parameters --- conf/tests.rmk | 4 +++ include/grub/script_sh.h | 4 +++ script/argv.c | 17 ++++++++++ script/execute.c | 61 +++++++++++++++++++++++++++++++--- script/main.c | 8 +++++ tests/grub_script_setparams.in | 59 ++++++++++++++++++++++++++++++++ util/grub-script-check.c | 8 +++++ 7 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 tests/grub_script_setparams.in diff --git a/conf/tests.rmk b/conf/tests.rmk index c14fe0fda..0d41a711b 100644 --- a/conf/tests.rmk +++ b/conf/tests.rmk @@ -83,6 +83,9 @@ grub_script_continue_SOURCES = tests/grub_script_continue.in check_SCRIPTS += grub_script_shift grub_script_shift_SOURCES = tests/grub_script_shift.in +check_SCRIPTS += grub_script_setparams +grub_script_setparams_SOURCES = tests/grub_script_setparams.in + # List of tests to execute on "make check" # SCRIPTED_TESTS = example_scripted_test # SCRIPTED_TESTS += example_grub_script_test @@ -103,6 +106,7 @@ SCRIPTED_TESTS += grub_script_functions SCRIPTED_TESTS += grub_script_break SCRIPTED_TESTS += grub_script_continue SCRIPTED_TESTS += grub_script_shift +SCRIPTED_TESTS += grub_script_setparams # dependencies between tests and testing-tools $(SCRIPTED_TESTS): grub-shell grub-shell-tester diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index 77e807360..e0ed5c005 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -227,6 +227,7 @@ void grub_script_init (void); void grub_script_fini (void); void grub_script_argv_free (struct grub_script_argv *argv); +int grub_script_argv_make (struct grub_script_argv *argv, int argc, char **args); int grub_script_argv_next (struct grub_script_argv *argv); int grub_script_argv_append (struct grub_script_argv *argv, const char *s); int grub_script_argv_split_append (struct grub_script_argv *argv, char *s); @@ -321,6 +322,9 @@ grub_err_t grub_script_break (grub_command_t cmd, int argc, char *argv[]); /* SHIFT command for GRUB script. */ grub_err_t grub_script_shift (grub_command_t cmd, int argc, char *argv[]); +/* SETPARAMS command for GRUB script functions. */ +grub_err_t grub_script_setparams (grub_command_t cmd, int argc, char *argv[]); + /* This variable points to the parsed command. This is used to communicate with the bison code. */ extern struct grub_script_cmd *grub_script_parsed; diff --git a/script/argv.c b/script/argv.c index b69ee39c5..c642ea9c5 100644 --- a/script/argv.c +++ b/script/argv.c @@ -57,6 +57,23 @@ grub_script_argv_free (struct grub_script_argv *argv) argv->args = 0; } +/* Make argv from argc, args pair. */ +int +grub_script_argv_make (struct grub_script_argv *argv, int argc, char **args) +{ + int i; + struct grub_script_argv r = { 0, 0}; + + for (i = 0; i < argc; i++) + if (grub_script_argv_next (&r) || grub_script_argv_append (&r, args[i])) + { + grub_script_argv_free (&r); + return 1; + } + *argv = r; + return 0; +} + /* Prepare for next argc. */ int grub_script_argv_next (struct grub_script_argv *argv) diff --git a/script/execute.c b/script/execute.c index 26a46b12b..b911163f7 100644 --- a/script/execute.c +++ b/script/execute.c @@ -34,13 +34,35 @@ static unsigned long is_continue; static unsigned long active_loops; static unsigned long active_breaks; +#define GRUB_SCRIPT_SCOPE_MALLOCED 1 +#define GRUB_SCRIPT_SCOPE_ARGS_MALLOCED 2 + /* Scope for grub script functions. */ struct grub_script_scope { + unsigned flags; + unsigned shifts; struct grub_script_argv argv; }; static struct grub_script_scope *scope = 0; +static void +replace_scope (struct grub_script_scope *new_scope) +{ + if (scope) + { + scope->argv.argc += scope->shifts; + scope->argv.args -= scope->shifts; + + if (scope->flags & GRUB_SCRIPT_SCOPE_ARGS_MALLOCED) + grub_script_argv_free (&scope->argv); + + if (scope->flags & GRUB_SCRIPT_SCOPE_MALLOCED) + grub_free (scope); + } + scope = new_scope; +} + grub_err_t grub_script_break (grub_command_t cmd, int argc, char *argv[]) { @@ -85,11 +107,41 @@ grub_script_shift (grub_command_t cmd __attribute__((unused)), if (n > scope->argv.argc) return GRUB_ERR_BAD_ARGUMENT; + scope->shifts += n; scope->argv.argc -= n; scope->argv.args += n; return GRUB_ERR_NONE; } +grub_err_t +grub_script_setparams (grub_command_t cmd __attribute__((unused)), + int argc, char **args) +{ + struct grub_script_scope *new_scope; + struct grub_script_argv argv = { 0, 0 }; + + if (! scope) + return GRUB_ERR_INVALID_COMMAND; + + new_scope = grub_malloc (sizeof (*new_scope)); + if (! new_scope) + return grub_errno; + + if (grub_script_argv_make (&argv, argc, args)) + { + grub_free (new_scope); + return grub_errno; + } + + new_scope->shifts = 0; + new_scope->argv = argv; + new_scope->flags = GRUB_SCRIPT_SCOPE_MALLOCED | + GRUB_SCRIPT_SCOPE_ARGS_MALLOCED; + + replace_scope (new_scope); + return GRUB_ERR_NONE; +} + static int grub_env_special (const char *name) { @@ -104,6 +156,7 @@ grub_env_special (const char *name) static char ** grub_script_env_get (const char *name, grub_script_arg_type_t type) { + unsigned i; struct grub_script_argv result = { 0, 0 }; if (grub_script_argv_next (&result)) @@ -138,8 +191,6 @@ grub_script_env_get (const char *name, grub_script_arg_type_t type) } else if (grub_strcmp (name, "*") == 0) { - unsigned i; - for (i = 0; i < scope->argv.argc; i++) if (type == GRUB_SCRIPT_ARG_TYPE_VAR) { @@ -160,8 +211,6 @@ grub_script_env_get (const char *name, grub_script_arg_type_t type) } else if (grub_strcmp (name, "@") == 0) { - unsigned i; - for (i = 0; i < scope->argv.argc; i++) { if (i != 0 && grub_script_argv_next (&result)) @@ -302,6 +351,8 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args) struct grub_script_scope new_scope; active_loops = 0; + new_scope.flags = 0; + new_scope.shifts = 0; new_scope.argv.argc = argc; new_scope.argv.args = args; @@ -311,7 +362,7 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args) ret = grub_script_execute (func->func); active_loops = loops; - scope = old_scope; + replace_scope (old_scope); /* free any scopes by setparams */ return ret; } diff --git a/script/main.c b/script/main.c index ff714d060..a16a65c13 100644 --- a/script/main.c +++ b/script/main.c @@ -44,6 +44,7 @@ grub_normal_parse_line (char *line, grub_reader_getline_t getline) static grub_command_t cmd_break; static grub_command_t cmd_continue; static grub_command_t cmd_shift; +static grub_command_t cmd_setparams; void grub_script_init (void) @@ -54,6 +55,9 @@ grub_script_init (void) N_("[n]"), N_("Continue loops")); cmd_shift = grub_register_command ("shift", grub_script_shift, N_("[n]"), N_("Shift positional parameters.")); + cmd_setparams = grub_register_command ("setparams", grub_script_setparams, + N_("[VALUE]..."), + N_("Set positional parameters.")); } void @@ -70,4 +74,8 @@ grub_script_fini (void) if (cmd_shift) grub_unregister_command (cmd_shift); cmd_shift = 0; + + if (cmd_setparams) + grub_unregister_command (cmd_setparams); + cmd_setparams = 0; } diff --git a/tests/grub_script_setparams.in b/tests/grub_script_setparams.in new file mode 100644 index 000000000..82d316813 --- /dev/null +++ b/tests/grub_script_setparams.in @@ -0,0 +1,59 @@ +#! @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 . + +if test x$grubshell = xyes; then cmd=setparams; else cmd=set; fi + +function f1 { + echo $# + echo "$#" + + echo $@ + echo "$@" + + echo $* + echo "$*" + + echo $1 $2 + for v in "$@"; do echo $v; done + shift + echo $1 $2 + for v in "$@"; do echo $v; done + + $cmd 1 2 3 4 + + echo $# + echo "$#" + + echo $@ + echo "$@" + + echo $* + echo "$*" + + echo $1 $2 + for v in "$@"; do echo $v; done + shift + echo $1 $2 + for v in "$@"; do echo $v; done +} +# f1 +# f1 a +f1 a b +f1 a b c +f1 a b c d +f1 a b c d e diff --git a/util/grub-script-check.c b/util/grub-script-check.c index 4ca85c4bd..375d064d4 100644 --- a/util/grub-script-check.c +++ b/util/grub-script-check.c @@ -73,6 +73,14 @@ grub_script_shift (grub_command_t cmd __attribute__((unused)), return 0; } +grub_err_t +grub_script_setparams (grub_command_t cmd __attribute__((unused)), + int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + return 0; +} + char * grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused))) {