merge with mainline
This commit is contained in:
commit
ee14ec9935
27 changed files with 1004 additions and 396 deletions
|
@ -59,6 +59,23 @@ grub_script_argv_free (struct grub_script_argv *argv)
|
|||
argv->script = 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, 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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -205,8 +205,6 @@ struct grub_lexer_param *
|
|||
grub_script_lexer_init (struct grub_parser_param *parser, char *script,
|
||||
grub_reader_getline_t getline)
|
||||
{
|
||||
int len;
|
||||
YY_BUFFER_STATE buffer;
|
||||
struct grub_lexer_param *lexerstate;
|
||||
|
||||
lexerstate = grub_zalloc (sizeof (*lexerstate));
|
||||
|
|
|
@ -44,6 +44,8 @@ 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;
|
||||
static grub_command_t cmd_return;
|
||||
|
||||
void
|
||||
grub_script_init (void)
|
||||
|
@ -54,6 +56,11 @@ 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."));
|
||||
cmd_return = grub_register_command ("return", grub_script_return,
|
||||
N_("[n]"), N_("Return from a function."));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -70,4 +77,12 @@ 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;
|
||||
|
||||
if (cmd_return)
|
||||
grub_unregister_command (cmd_return);
|
||||
cmd_return = 0;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@
|
|||
%token <arg> GRUB_PARSER_TOKEN_WHILE "while"
|
||||
%token <arg> GRUB_PARSER_TOKEN_TIME "time"
|
||||
%token <arg> GRUB_PARSER_TOKEN_FUNCTION "function"
|
||||
%token <arg> GRUB_PARSER_TOKEN_MENUENTRY "menuentry"
|
||||
%token <arg> GRUB_PARSER_TOKEN_NAME "name"
|
||||
%token <arg> GRUB_PARSER_TOKEN_WORD "word"
|
||||
|
||||
|
@ -85,7 +84,7 @@
|
|||
|
||||
%type <cmd> script_init script
|
||||
%type <cmd> grubcmd ifclause ifcmd forcmd whilecmd untilcmd
|
||||
%type <cmd> command commands1 menuentry statement
|
||||
%type <cmd> command commands1 statement
|
||||
|
||||
%pure-parser
|
||||
%lex-param { struct grub_parser_param *state };
|
||||
|
@ -131,7 +130,6 @@ word: GRUB_PARSER_TOKEN_NAME { $$ = grub_script_add_arglist (state, 0, $1); }
|
|||
|
||||
statement: command { $$ = $1; }
|
||||
| function { $$ = 0; }
|
||||
| menuentry { $$ = $1; }
|
||||
;
|
||||
|
||||
argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); }
|
||||
|
@ -149,7 +147,6 @@ argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); }
|
|||
| "until" { $$ = grub_script_add_arglist (state, 0, $1); }
|
||||
| "while" { $$ = grub_script_add_arglist (state, 0, $1); }
|
||||
| "function" { $$ = grub_script_add_arglist (state, 0, $1); }
|
||||
| "menuentry" { $$ = grub_script_add_arglist (state, 0, $1); }
|
||||
| word { $$ = $1; }
|
||||
;
|
||||
|
||||
|
@ -243,12 +240,11 @@ grubcmd: word arguments0 block0
|
|||
if ($3)
|
||||
x = grub_script_add_arglist (state, $2, $3);
|
||||
|
||||
if ($1 && x)
|
||||
{
|
||||
$1->next = x;
|
||||
$1->argcount += x->argcount;
|
||||
x->argcount = 0;
|
||||
}
|
||||
if ($1 && x) {
|
||||
$1->next = x;
|
||||
$1->argcount += x->argcount;
|
||||
x->argcount = 0;
|
||||
}
|
||||
$$ = grub_script_create_cmdline (state, $1);
|
||||
}
|
||||
;
|
||||
|
@ -298,25 +294,6 @@ function: "function" "name"
|
|||
}
|
||||
;
|
||||
|
||||
menuentry: "menuentry"
|
||||
{
|
||||
grub_script_lexer_ref (state->lexerstate);
|
||||
}
|
||||
arguments1
|
||||
{
|
||||
$<offset>$ = grub_script_lexer_record_start (state);
|
||||
}
|
||||
delimiters0 "{" commands1 delimiters1 "}"
|
||||
{
|
||||
char *def;
|
||||
def = grub_script_lexer_record_stop (state, $<offset>4);
|
||||
*grub_strrchr(def, '}') = '\0';
|
||||
|
||||
grub_script_lexer_deref (state->lexerstate);
|
||||
$$ = grub_script_create_cmdmenu (state, $3, def, 0);
|
||||
}
|
||||
;
|
||||
|
||||
ifcmd: "if"
|
||||
{
|
||||
grub_script_lexer_ref (state->lexerstate);
|
||||
|
|
|
@ -281,30 +281,6 @@ grub_script_create_cmdwhile (struct grub_parser_param *state,
|
|||
return (struct grub_script_cmd *) cmd;
|
||||
}
|
||||
|
||||
/* Create a command that adds a menu entry to the menu. Title is an
|
||||
argument that is parsed to generate a string that can be used as
|
||||
the title. The sourcecode for this entry is passed in SOURCECODE.
|
||||
The options for this entry are passed in OPTIONS. */
|
||||
struct grub_script_cmd *
|
||||
grub_script_create_cmdmenu (struct grub_parser_param *state,
|
||||
struct grub_script_arglist *arglist,
|
||||
char *sourcecode, int options)
|
||||
{
|
||||
struct grub_script_cmd_menuentry *cmd;
|
||||
|
||||
cmd = grub_script_malloc (state, sizeof (*cmd));
|
||||
if (!cmd)
|
||||
return 0;
|
||||
|
||||
cmd->cmd.exec = grub_script_execute_menuentry;
|
||||
cmd->cmd.next = 0;
|
||||
cmd->sourcecode = sourcecode;
|
||||
cmd->arglist = arglist;
|
||||
cmd->options = options;
|
||||
|
||||
return (struct grub_script_cmd *) cmd;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
|
|
@ -176,7 +176,6 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n))
|
|||
"until" { RECORD; return GRUB_PARSER_TOKEN_UNTIL; }
|
||||
"while" { RECORD; return GRUB_PARSER_TOKEN_WHILE; }
|
||||
"function" { RECORD; return GRUB_PARSER_TOKEN_FUNCTION; }
|
||||
"menuentry" { RECORD; return GRUB_PARSER_TOKEN_MENUENTRY; }
|
||||
|
||||
{MULTILINE} {
|
||||
if (grub_lexer_unput (yytext, yyscanner))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue