# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: address@hidden # target_branch: ../mainline/ # testament_sha1: 2fefe3c7a1fd759379827e43db3f0ea5433e011e # timestamp: 2010-05-05 14:05:34 +0530 # base_revision_id: address@hidden # # Begin patch === modified file 'conf/tests.rmk' --- conf/tests.rmk 2010-04-30 08:20:41 +0000 +++ conf/tests.rmk 2010-05-05 08:21:46 +0000 @@ -71,6 +71,9 @@ 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_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 === modified file 'include/grub/script_sh.h' --- include/grub/script_sh.h 2010-03-26 15:43:06 +0000 +++ include/grub/script_sh.h 2010-05-05 08:21:46 +0000 @@ -73,6 +73,15 @@ 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 { @@ -82,15 +91,6 @@ struct grub_script_arglist *arglist; }; -/* A block of commands, this can be used to group commands. */ -struct grub_script_cmdblock -{ - struct grub_script_cmd cmd; - - /* A chain of commands. */ - struct grub_script_cmd *cmdlist; -}; - /* An if statement. */ struct grub_script_cmdif { @@ -234,8 +234,6 @@ struct grub_script_cmd * grub_script_create_cmdline (struct grub_parser_param *state, struct grub_script_arglist *arglist); -struct grub_script_cmd * -grub_script_create_cmdblock (struct grub_parser_param *state); struct grub_script_cmd * grub_script_create_cmdif (struct grub_parser_param *state, @@ -262,9 +260,9 @@ int options); struct grub_script_cmd * -grub_script_add_cmd (struct grub_parser_param *state, - struct grub_script_cmdblock *cmdblock, - struct grub_script_cmd *cmd); +grub_script_append_cmd (struct grub_parser_param *state, + struct grub_script_cmd *list, + struct grub_script_cmd *last); struct grub_script_arg * grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg *arg, @@ -301,7 +299,7 @@ /* Commands to execute, don't use these directly. */ 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_cmdlist (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_cmdwhile (struct grub_script_cmd *cmd); @@ -340,8 +338,8 @@ 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); === modified file 'script/execute.c' --- script/execute.c 2010-03-26 15:43:06 +0000 +++ script/execute.c 2010-05-05 08:21:46 +0000 @@ -30,6 +30,52 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 (); @@ -262,20 +325,20 @@ grub_print_error (); grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret); - grub_env_set ("?", errnobuf); + grub_script_env_set ("?", errnobuf); return ret; } /* Execute a block of one or more commands. */ grub_err_t -grub_script_execute_cmdblock (struct grub_script_cmd *cmd) +grub_script_execute_cmdlist (struct grub_script_cmd *list) { int ret = 0; - struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) cmd; + struct grub_script_cmd *cmd; /* Loop over every command and execute it. */ - for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next) + for (cmd = list->next; cmd; cmd = cmd->next) ret = grub_script_execute_cmd (cmd); return ret; @@ -291,7 +354,7 @@ /* 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 @@ 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]); } === modified file 'script/function.c' --- script/function.c 2010-01-22 13:37:27 +0000 +++ script/function.c 2010-05-05 08:21:46 +0000 @@ -115,12 +115,3 @@ 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); -} === modified file 'script/parser.y' --- script/parser.y 2010-04-09 17:02:58 +0000 +++ script/parser.y 2010-05-05 08:21:46 +0000 @@ -96,9 +96,7 @@ } | script statement delimiter newlines0 { - struct grub_script_cmdblock *cmdblock; - cmdblock = (struct grub_script_cmdblock *) $1; - $$ = grub_script_add_cmd (state, cmdblock, $2); + $$ = grub_script_append_cmd (state, $1, $2); } | error { @@ -183,17 +181,15 @@ /* A list of commands. */ commands1: newlines0 command { - $$ = grub_script_add_cmd (state, 0, $2); + $$ = grub_script_append_cmd (state, 0, $2); } | commands1 delimiters1 command { - struct grub_script_cmdblock *cmdblock; - cmdblock = (struct grub_script_cmdblock *) $1; - $$ = grub_script_add_cmd (state, cmdblock, $3); + $$ = grub_script_append_cmd (state, $1, $3); } ; -function: "function" "name" +function: "function" "name" { grub_script_lexer_ref (state->lexerstate); state->func_mem = grub_script_mem_record (state); === modified file 'script/script.c' --- script/script.c 2010-01-23 05:49:26 +0000 +++ script/script.c 2010-05-05 08:21:46 +0000 @@ -291,46 +291,40 @@ return (struct grub_script_cmd *) cmd; } -/* Create a block of commands. CMD contains the command that should - be added at the end of CMDBLOCK's list. If CMDBLOCK is zero, a new - cmdblock will be created. */ +/* Create a chain of commands. LAST contains the command that should + be added at the end of LIST's list. If LIST is zero, a new list + will be created. */ struct grub_script_cmd * -grub_script_add_cmd (struct grub_parser_param *state, - struct grub_script_cmdblock *cmdblock, - struct grub_script_cmd *cmd) +grub_script_append_cmd (struct grub_parser_param *state, + struct grub_script_cmd *list, + struct grub_script_cmd *last) { struct grub_script_cmd *ptr; - grub_dprintf ("scripting", "cmdblock\n"); - - if (!cmd) - return (struct grub_script_cmd *) cmdblock; - - if (!cmdblock) + grub_dprintf ("scripting", "append command\n"); + + if (! last) + return list; + + if (! list) { - cmdblock = grub_script_malloc (state, sizeof (*cmdblock)); - if (!cmdblock) + list = grub_script_malloc (state, sizeof (*list)); + if (! list) return 0; - cmdblock->cmd.exec = grub_script_execute_cmdblock; - cmdblock->cmd.next = 0; - cmdblock->cmdlist = cmd; - cmd->next = 0; + list->exec = grub_script_execute_cmdlist; + list->next = last; } else { - if (!cmdblock->cmdlist) - cmdblock->cmdlist = cmd; - else - { - ptr = cmdblock->cmdlist; - while (ptr->next) - ptr = ptr->next; - ptr->next = cmd; - } + ptr = list; + while (ptr->next) + ptr = ptr->next; + + ptr->next = last; } - return (struct grub_script_cmd *) cmdblock; + return list; } === modified file 'script/yylex.l' --- script/yylex.l 2010-04-30 08:20:41 +0000 +++ script/yylex.l 2010-05-05 08:21:46 +0000 @@ -119,7 +119,8 @@ 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 @@ } { - \? | + {SPECIAL} | {DIGITS} | {NAME} { COPY (yytext, yyleng); @@ -231,7 +232,7 @@ else ARG (GRUB_SCRIPT_ARG_TYPE_DQVAR); } - \{\?\} | + \{{SPECIAL}\} | \{{DIGITS}\} | \{{NAME}\} { yytext[yyleng - 1] = '\0'; === added file 'tests/grub_script_functions.in' --- tests/grub_script_functions.in 1970-01-01 00:00:00 +0000 +++ tests/grub_script_functions.in 2010-05-05 08:21:46 +0000 @@ -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 . + +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 === modified file 'util/grub-script-check.c' --- util/grub-script-check.c 2010-04-10 13:48:24 +0000 +++ util/grub-script-check.c 2010-05-05 08:21:46 +0000 @@ -70,7 +70,7 @@ } grub_err_t -grub_script_execute_cmdblock (struct grub_script_cmd *cmd __attribute__ ((unused))) +grub_script_execute_cmdlist (struct grub_script_cmd *cmd __attribute__ ((unused))) { return 0; } # Begin bundle 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