merge with mainline

This commit is contained in:
BVK Chaitanya 2010-09-04 22:34:32 +05:30
commit ee14ec9935
27 changed files with 1004 additions and 396 deletions

View file

@ -34,10 +34,16 @@
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
/* 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;
@ -45,6 +51,23 @@ static struct grub_script_scope *scope = 0;
/* Wildcard translator for GRUB script. */
struct grub_script_wildcard_translator *grub_wildcard_translator;
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[])
{
@ -89,11 +112,65 @@ 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, 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;
}
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)
{
@ -108,6 +185,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, 0 };
if (grub_script_argv_next (&result))
@ -142,8 +220,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)
{
@ -164,8 +240,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))
@ -391,6 +465,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;
@ -399,7 +475,64 @@ 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;
}
/* Execute a source script. */
grub_err_t
grub_script_execute_sourcecode (const char *source, int argc, char **args)
{
grub_err_t ret = 0;
struct grub_script *parsed_script;
struct grub_script_scope new_scope;
struct grub_script_scope *old_scope;
auto grub_err_t getline (char **line, int cont);
grub_err_t getline (char **line, int cont __attribute__ ((unused)))
{
const char *p;
if (! source)
{
*line = 0;
return 0;
}
p = grub_strchr (source, '\n');
if (p)
*line = grub_strndup (source, p - source);
else
*line = grub_strdup (source);
source = p ? p + 1 : 0;
return 0;
}
new_scope.argv.argc = argc;
new_scope.argv.args = args;
old_scope = scope;
scope = &new_scope;
while (source)
{
char *line;
getline (&line, 0);
parsed_script = grub_script_parse (line, getline);
if (! parsed_script)
{
ret = grub_errno;
break;
}
ret = grub_script_execute (parsed_script);
grub_free (line);
}
scope = old_scope;
return ret;
}
@ -491,8 +624,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;
}
@ -501,14 +642,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
@ -542,6 +686,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;
}
}
@ -557,18 +703,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;
@ -585,30 +734,6 @@ grub_script_execute_cmdwhile (struct grub_script_cmd *cmd)
return result;
}
/* Execute the menu entry generate statement. */
grub_err_t
grub_script_execute_menuentry (struct grub_script_cmd *cmd)
{
struct grub_script_cmd_menuentry *cmd_menuentry;
struct grub_script_argv argv = { 0, 0, 0 };
cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd;
if (cmd_menuentry->arglist)
{
if (grub_script_arglist_to_argv (cmd_menuentry->arglist, &argv))
return grub_errno;
}
grub_normal_add_menu_entry (argv.argc, (const char **) argv.args,
cmd_menuentry->sourcecode);
grub_script_argv_free (&argv);
return grub_errno;
}
/* Execute any GRUB pre-parsed command or script. */
grub_err_t
grub_script_execute (struct grub_script *script)