"return" command for GRUB script functions.

* tests/grub_script_return.in: New test.
	* Makefile.util.def: Rules for new test.

	* grub-core/script/execute.c (grub_script_return): New function.
	* grub-core/script/main.c: Register/unregister return commaond.
	* include/grub/script_sh.h (grub_script_return): New prototype.
This commit is contained in:
BVK Chaitanya 2010-09-04 20:53:09 +05:30
commit dacd0cf07a
6 changed files with 212 additions and 9 deletions

View file

@ -1,3 +1,14 @@
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
"return" command for GRUB script functions.
* tests/grub_script_return.in: New test.
* Makefile.util.def: Rules for new test.
* grub-core/script/execute.c (grub_script_return): New function.
* grub-core/script/main.c: Register/unregister return commaond.
* include/grub/script_sh.h (grub_script_return): New prototype.
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
"setparams" command to update positional parameters.

View file

@ -513,6 +513,12 @@ script = {
common = tests/grub_script_setparams.in;
};
script = {
testcase;
name = grub_script_return;
common = tests/grub_script_return.in;
};
program = {
testcase;
name = example_unit_test;

View file

@ -34,6 +34,7 @@
static unsigned long is_continue;
static unsigned long active_loops;
static unsigned long active_breaks;
static unsigned long function_return;
#define GRUB_SCRIPT_SCOPE_MALLOCED 1
#define GRUB_SCRIPT_SCOPE_ARGS_MALLOCED 2
@ -143,6 +144,30 @@ grub_script_setparams (grub_command_t cmd __attribute__((unused)),
return GRUB_ERR_NONE;
}
grub_err_t
grub_script_return (grub_command_t cmd __attribute__((unused)),
int argc, char *argv[])
{
char *p;
unsigned long n;
if (! scope || argc > 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in function scope");
if (argc == 0)
{
function_return = 1;
return grub_strtoul (grub_env_get ("?"), NULL, 10);
}
n = grub_strtoul (argv[0], &p, 10);
if (*p != '\0')
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad argument");
function_return = 1;
return n ? grub_error (GRUB_ERR_TEST_FAILURE, "false") : GRUB_ERR_NONE;
}
static int
grub_env_special (const char *name)
{
@ -370,6 +395,7 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
ret = grub_script_execute (func->func);
function_return = 0;
active_loops = loops;
replace_scope (old_scope); /* free any scopes by setparams */
return ret;
@ -462,8 +488,16 @@ grub_script_execute_cmdlist (struct grub_script_cmd *list)
struct grub_script_cmd *cmd;
/* Loop over every command and execute it. */
for (cmd = list->next; cmd && ! active_breaks; cmd = cmd->next)
ret = grub_script_execute_cmd (cmd);
for (cmd = list->next; cmd; cmd = cmd->next)
{
if (active_breaks)
break;
ret = grub_script_execute_cmd (cmd);
if (function_return)
break;
}
return ret;
}
@ -472,14 +506,17 @@ grub_script_execute_cmdlist (struct grub_script_cmd *list)
grub_err_t
grub_script_execute_cmdif (struct grub_script_cmd *cmd)
{
struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd;
int ret;
char *result;
struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) 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 ("?");
ret = grub_script_execute_cmd (cmdif->exec_to_evaluate);
if (function_return)
return ret;
result = grub_env_get ("?");
grub_errno = GRUB_ERR_NONE;
/* Execute the `if' or the `else' part depending on the value of
@ -513,6 +550,8 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
{
grub_script_env_set (cmdfor->name->str, argv.args[i]);
result = grub_script_execute_cmd (cmdfor->list);
if (function_return)
break;
}
}
@ -528,18 +567,21 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
grub_err_t
grub_script_execute_cmdwhile (struct grub_script_cmd *cmd)
{
int cond;
int result;
struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd;
active_loops++;
result = 0;
do {
cond = grub_script_execute_cmd (cmdwhile->cond);
if (cmdwhile->until ? !cond : cond)
result = grub_script_execute_cmd (cmdwhile->cond);
if (function_return)
break;
if (cmdwhile->until ? !result : result)
break;
result = grub_script_execute_cmd (cmdwhile->list);
if (function_return)
break;
if (active_breaks == 1 && is_continue)
active_breaks = 0;

View file

@ -45,6 +45,7 @@ static grub_command_t cmd_break;
static grub_command_t cmd_continue;
static grub_command_t cmd_shift;
static grub_command_t cmd_setparams;
static grub_command_t cmd_return;
void
grub_script_init (void)
@ -58,6 +59,8 @@ grub_script_init (void)
cmd_setparams = grub_register_command ("setparams", grub_script_setparams,
N_("[VALUE]..."),
N_("Set positional parameters."));
cmd_return = grub_register_command ("return", grub_script_return,
N_("[n]"), N_("Return from a function."));
}
void
@ -78,4 +81,8 @@ grub_script_fini (void)
if (cmd_setparams)
grub_unregister_command (cmd_setparams);
cmd_setparams = 0;
if (cmd_return)
grub_unregister_command (cmd_return);
cmd_return = 0;
}

View file

@ -346,6 +346,9 @@ 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[]);
/* RETURN command for functions. */
grub_err_t grub_script_return (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;

134
tests/grub_script_return.in Normal file
View file

@ -0,0 +1,134 @@
#! @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/>.
function f1 {
return
echo one
}
f1
function f2 {
true
return
echo one
}
if f2; then echo true; else echo false; fi
function f3 {
false
return
echo one
}
if f3; then echo true; else echo false; fi
function f4 {
true
return 1;
echo one
}
if f4; then echo true; else echo false; fi
function f5 {
false
return 0;
echo one
}
if f5; then echo true; else echo false; fi
function f6 {
echo one
if true; then
echo two
return 0
else
echo three
return 1
fi
echo four
}
if f6; then echo true; else echo false; fi
function f7 {
if return 1; then
echo one
else
echo no
fi
}
if f7; then echo true; else echo false; fi
function f8 {
echo one
for v in 1 2 3 4 5; do
echo $v
if test $v = 3; then return 1; fi
done
echo two
}
if f8; then echo true; else echo false; fi
function f9 {
x=1
echo one
until test x = 11111111; do
echo $x
x="1$x"
if test $x = 1111; then return 0; fi
done
echo two
}
if f9; then echo true; else echo false; fi
function f10 {
echo one
while return 0; do
echo two
done
echo three
}
if f10; then echo true; else echo false; fi
function f11 {
f1
f2
f3
f4
f5
f6
f7
f8
f9
f10
}
if f11; then echo true; else echo false; fi
function f12 {
echo one
f11
return 1
echo two
}
if f12; then echo true; else echo false; fi
function f13 {
echo one
f12
echo two
return 0
}
if f13; then echo true; else echo false; fi