lexer-rewrite rebase commit
This commit is contained in:
parent
bf86e59a76
commit
547e494f1b
25 changed files with 1214 additions and 652 deletions
218
script/execute.c
218
script/execute.c
|
@ -1,7 +1,7 @@
|
|||
/* execute.c -- Execute a GRUB script. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2005,2007,2008,2009,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
|
||||
|
@ -35,49 +35,146 @@ grub_script_execute_cmd (struct grub_script_cmd *cmd)
|
|||
return cmd->exec (cmd);
|
||||
}
|
||||
|
||||
/* Parse ARG and return the textual representation. Add strings are
|
||||
concatenated and all values of the variables are filled in. */
|
||||
char *
|
||||
grub_script_execute_argument_to_string (struct grub_script_arg *arg)
|
||||
#define ROUND_UPTO(sz,up) (((sz) + (up) - 1) / (up) * (up))
|
||||
|
||||
/* Expand arguments in ARGLIST into multiple arguments. */
|
||||
char **
|
||||
grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist)
|
||||
{
|
||||
int size = 0;
|
||||
char *val;
|
||||
char *chararg;
|
||||
struct grub_script_arg *argi;
|
||||
int i;
|
||||
int oom;
|
||||
int argc;
|
||||
int empty;
|
||||
char *ptr;
|
||||
char **argv;
|
||||
char *value;
|
||||
struct grub_script_arg *arg;
|
||||
|
||||
/* First determine the size of the argument. */
|
||||
for (argi = arg; argi; argi = argi->next)
|
||||
auto void push (char *str);
|
||||
void push (char *str)
|
||||
{
|
||||
char **p;
|
||||
|
||||
if (oom)
|
||||
return;
|
||||
|
||||
p = grub_realloc (argv, ROUND_UPTO (sizeof(char*) * (argc + 1), 32));
|
||||
if (!p)
|
||||
oom = 1;
|
||||
else
|
||||
{
|
||||
p[argc++] = str;
|
||||
argv = p;
|
||||
}
|
||||
}
|
||||
|
||||
auto char* append (const char *str, grub_size_t nchar);
|
||||
char* append (const char *str, grub_size_t nchar)
|
||||
{
|
||||
int len;
|
||||
int old;
|
||||
char *p;
|
||||
|
||||
if (oom || !str)
|
||||
return 0;
|
||||
|
||||
len = nchar ?: grub_strlen (str);
|
||||
old = argv[argc - 1] ? grub_strlen (argv[argc - 1]) : 0;
|
||||
p = grub_realloc (argv[argc - 1], ROUND_UPTO(old + len + 1, 32));
|
||||
|
||||
if (p)
|
||||
{
|
||||
grub_strncpy (p + old, str, len);
|
||||
p[old + len] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
oom = 1;
|
||||
grub_free (argv[argc - 1]);
|
||||
}
|
||||
argv[argc - 1] = p;
|
||||
return argv[argc - 1];
|
||||
}
|
||||
|
||||
/* Move *STR to the begining of next word, but return current word. */
|
||||
auto char* move_to_next (char **str);
|
||||
char* move_to_next (char **str)
|
||||
{
|
||||
char *end;
|
||||
char *start;
|
||||
|
||||
if (oom || !str || !*str)
|
||||
return 0;
|
||||
|
||||
start = *str;
|
||||
while (*start && grub_isspace (*start)) start++;
|
||||
if (*start == '\0')
|
||||
return 0;
|
||||
|
||||
end = start + 1;
|
||||
while (*end && !grub_isspace (*end)) end++;
|
||||
|
||||
*str = end;
|
||||
return start;
|
||||
}
|
||||
|
||||
oom = 0;
|
||||
argv = 0;
|
||||
argc = 0;
|
||||
push (0);
|
||||
for (; arglist; arglist = arglist->next)
|
||||
{
|
||||
if (argi->type == 1)
|
||||
empty = 1;
|
||||
arg = arglist->arg;
|
||||
while (arg)
|
||||
{
|
||||
val = grub_env_get (argi->str);
|
||||
if (val)
|
||||
size += grub_strlen (val);
|
||||
switch (arg->type)
|
||||
{
|
||||
case GRUB_SCRIPT_ARG_TYPE_VAR:
|
||||
value = grub_env_get (arg->str);
|
||||
while (*value && (ptr = move_to_next(&value)))
|
||||
{
|
||||
empty = 0;
|
||||
append (ptr, value - ptr);
|
||||
if (*value) push(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case GRUB_SCRIPT_ARG_TYPE_TEXT:
|
||||
if (grub_strlen (arg->str) > 0)
|
||||
{
|
||||
empty = 0;
|
||||
append (arg->str, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case GRUB_SCRIPT_ARG_TYPE_DQSTR:
|
||||
case GRUB_SCRIPT_ARG_TYPE_SQSTR:
|
||||
empty = 0;
|
||||
append (arg->str, 0);
|
||||
break;
|
||||
|
||||
case GRUB_SCRIPT_ARG_TYPE_DQVAR:
|
||||
empty = 0;
|
||||
append (grub_env_get (arg->str), 0);
|
||||
break;
|
||||
}
|
||||
arg = arg->next;
|
||||
}
|
||||
else
|
||||
size += grub_strlen (argi->str);
|
||||
if (!empty)
|
||||
push (0);
|
||||
}
|
||||
push (0); /* Ensure argv[argc] == 0. */
|
||||
|
||||
if (oom)
|
||||
{
|
||||
for (i = 0; i < argc; i++)
|
||||
grub_free (argv[i]);
|
||||
grub_free (argv);
|
||||
argv = 0;
|
||||
}
|
||||
|
||||
/* Create the argument. */
|
||||
chararg = grub_malloc (size + 1);
|
||||
if (! chararg)
|
||||
return 0;
|
||||
|
||||
*chararg = '\0';
|
||||
/* First determine the size of the argument. */
|
||||
for (argi = arg; argi; argi = argi->next)
|
||||
{
|
||||
if (argi->type == 1)
|
||||
{
|
||||
val = grub_env_get (argi->str);
|
||||
if (val)
|
||||
grub_strcat (chararg, val);
|
||||
}
|
||||
else
|
||||
grub_strcat (chararg, argi->str);
|
||||
}
|
||||
|
||||
return chararg;
|
||||
return argv;
|
||||
}
|
||||
|
||||
/* Execute a single command line. */
|
||||
|
@ -85,7 +182,6 @@ grub_err_t
|
|||
grub_script_execute_cmdline (struct grub_script_cmd *cmd)
|
||||
{
|
||||
struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd;
|
||||
struct grub_script_arglist *arglist;
|
||||
char **args = 0;
|
||||
int i = 0;
|
||||
grub_command_t grubcmd;
|
||||
|
@ -96,7 +192,11 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
|
|||
char *cmdname;
|
||||
|
||||
/* Lookup the command. */
|
||||
cmdname = grub_script_execute_argument_to_string (cmdline->arglist->arg);
|
||||
args = grub_script_execute_arglist_to_argv (cmdline->arglist);
|
||||
if (!args)
|
||||
return grub_errno;
|
||||
|
||||
cmdname = args[0];
|
||||
grubcmd = grub_command_find (cmdname);
|
||||
if (! grubcmd)
|
||||
{
|
||||
|
@ -129,27 +229,15 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
grub_free (cmdname);
|
||||
|
||||
if (cmdline->arglist->next)
|
||||
{
|
||||
argcount = cmdline->arglist->argcount - 1;
|
||||
|
||||
/* Create argv from the arguments. */
|
||||
args = grub_malloc (sizeof (char *) * argcount);
|
||||
for (arglist = cmdline->arglist->next; arglist; arglist = arglist->next)
|
||||
{
|
||||
char *str;
|
||||
str = grub_script_execute_argument_to_string (arglist->arg);
|
||||
args[i++] = str;
|
||||
}
|
||||
}
|
||||
/* Count argv size. */
|
||||
for (argcount = 0; args[argcount]; argcount++);
|
||||
|
||||
/* Execute the GRUB command or function. */
|
||||
if (grubcmd)
|
||||
ret = (grubcmd->func) (grubcmd, argcount, args);
|
||||
ret = (grubcmd->func) (grubcmd, argcount - 1, args + 1);
|
||||
else
|
||||
ret = grub_script_function_call (func, argcount, args);
|
||||
ret = grub_script_function_call (func, argcount - 1, args + 1);
|
||||
|
||||
/* Free arguments. */
|
||||
for (i = 0; i < argcount; i++)
|
||||
|
@ -202,7 +290,6 @@ grub_err_t
|
|||
grub_script_execute_menuentry (struct grub_script_cmd *cmd)
|
||||
{
|
||||
struct grub_script_cmd_menuentry *cmd_menuentry;
|
||||
struct grub_script_arglist *arglist;
|
||||
char **args = 0;
|
||||
int argcount = 0;
|
||||
int i = 0;
|
||||
|
@ -211,22 +298,11 @@ grub_script_execute_menuentry (struct grub_script_cmd *cmd)
|
|||
|
||||
if (cmd_menuentry->arglist)
|
||||
{
|
||||
argcount = cmd_menuentry->arglist->argcount;
|
||||
args = grub_script_execute_arglist_to_argv (cmd_menuentry->arglist);
|
||||
if (!args)
|
||||
return grub_errno;
|
||||
|
||||
/* Create argv from the arguments. */
|
||||
args = grub_malloc (sizeof (char *) * argcount);
|
||||
|
||||
if (! args)
|
||||
{
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
for (arglist = cmd_menuentry->arglist; arglist; arglist = arglist->next)
|
||||
{
|
||||
char *str;
|
||||
str = grub_script_execute_argument_to_string (arglist->arg);
|
||||
args[i++] = str;
|
||||
}
|
||||
for (argcount = 0; args[argcount]; argcount++);
|
||||
}
|
||||
|
||||
grub_normal_add_menu_entry (argcount, (const char **) args,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue