Support for options to appear multiple times on cmdline.

* include/grub/lib/arg.h (grub_arg_list_alloc): New prototype.
	* grub-core/commands/extcmd.c: Support for repeatable option.
	* grub-core/lib/arg.c (grub_arg_list_alloc): New function for
	repeatable option support.

	Refactor menuentry into a regular command.

	* grub-core/commands/menuentry.c: New file, menuentry command
	implementation.
	* grub-core/Makefile.core.def: Rule update for normal.mod.
	* grub-core/normal/main.c: Moved menuentry creation to
	grub-core/commands/menuentry.c.
	* grub-core/normal/menu.c (grub_menu_execute_entry): Removed.
	(grub_menu_execute_entry_real): Removed.
	* grub-core/script/execute.c (grub_script_execute_sourcecode): New
	function.
	(grub_script_execute_menuentry): Removed.
	* grub-core/script/parser.y (menuentry): Removed.
	* grub-core/script/script.c (grub_script_create_cmdmenu): Removed.
	* grub-core/script/yylex.l (menuentry): Removed.
	* include/grub/menu.h (grub_menu_init): New prototype.
	(grub_menu_fini): New prototype.
	* include/grub/normal.h (grub_normal_add_menu_entry): Removed.
	* include/grub/script_sh.h (grub_script_cmd_menuentry): Removed.
	(grub_script_execute_sourcecode): New prototype.
This commit is contained in:
BVK Chaitanya 2010-09-04 21:43:54 +05:30
commit ed8c6dec96
15 changed files with 464 additions and 366 deletions

View file

@ -1,3 +1,33 @@
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
Support for options to appear multiple times on cmdline.
* include/grub/lib/arg.h (grub_arg_list_alloc): New prototype.
* grub-core/commands/extcmd.c: Support for repeatable option.
* grub-core/lib/arg.c (grub_arg_list_alloc): New function for
repeatable option support.
Refactor menuentry into a regular command.
* grub-core/commands/menuentry.c: New file, menuentry command
implementation.
* grub-core/Makefile.core.def: Rule update for normal.mod.
* grub-core/normal/main.c: Moved menuentry creation to
grub-core/commands/menuentry.c.
* grub-core/normal/menu.c (grub_menu_execute_entry): Removed.
(grub_menu_execute_entry_real): Removed.
* grub-core/script/execute.c (grub_script_execute_sourcecode): New
function.
(grub_script_execute_menuentry): Removed.
* grub-core/script/parser.y (menuentry): Removed.
* grub-core/script/script.c (grub_script_create_cmdmenu): Removed.
* grub-core/script/yylex.l (menuentry): Removed.
* include/grub/menu.h (grub_menu_init): New prototype.
(grub_menu_fini): New prototype.
* include/grub/normal.h (grub_normal_add_menu_entry): Removed.
* include/grub/script_sh.h (grub_script_cmd_menuentry): Removed.
(grub_script_execute_sourcecode): New prototype.
2010-09-04 BVK Chaitanya <bvk.groups@gmail.com> 2010-09-04 BVK Chaitanya <bvk.groups@gmail.com>
"return" command for GRUB script functions. "return" command for GRUB script functions.

View file

@ -1164,6 +1164,8 @@ module = {
common = script/lexer.c; common = script/lexer.c;
common = script/argv.c; common = script/argv.c;
common = commands/menuentry.c;
common = unidata.c; common = unidata.c;
common_nodist = grub_script.tab.c; common_nodist = grub_script.tab.c;
common_nodist = grub_script.yy.c; common_nodist = grub_script.yy.c;

View file

@ -29,10 +29,8 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
{ {
int new_argc; int new_argc;
char **new_args; char **new_args;
struct grub_arg_option *parser;
struct grub_arg_list *state; struct grub_arg_list *state;
struct grub_extcmd_context context; struct grub_extcmd_context context;
int maxargs = 0;
grub_err_t ret; grub_err_t ret;
grub_extcmd_t ext = cmd->data; grub_extcmd_t ext = cmd->data;
@ -46,25 +44,18 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
return ret; return ret;
} }
parser = (struct grub_arg_option *) ext->options; state = grub_arg_list_alloc (ext, argc, args);
while (parser && (parser++)->doc)
maxargs++;
/* Set up the option state. */
state = grub_zalloc (sizeof (struct grub_arg_list) * maxargs);
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc)) if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
{ {
context.state = state; context.state = state;
ret = (ext->func) (&context, new_argc, new_args); ret = (ext->func) (&context, new_argc, new_args);
grub_free (new_args); grub_free (new_args);
grub_free (state);
return ret;
} }
else
ret = grub_errno;
grub_free (state); grub_free (state);
return grub_errno;
return ret;
} }
static grub_err_t static grub_err_t

View file

@ -0,0 +1,285 @@
/* menuentry.c - menuentry command */
/*
* GRUB -- GRand Unified Bootloader
* 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/>.
*/
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/normal.h>
static const struct grub_arg_option options[] =
{
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
N_("Menu entry type."), "STRING", ARG_TYPE_STRING},
{"users", 2, 0,
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING},
{"hotkey", 3, 0,
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
{"source", 4, 0,
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
static struct
{
char *name;
int key;
} hotkey_aliases[] =
{
{"backspace", '\b'},
{"tab", '\t'},
{"delete", GRUB_TERM_DC}
};
/* Add a menu entry to the current menu context (as given by the environment
variable data slot `menu'). As the configuration file is read, the script
parser calls this when a menu entry is to be created. */
static grub_err_t
append_menu_entry (int argc, const char **args, char **classes,
const char *users, const char *hotkey,
const char *prefix, const char *sourcecode)
{
unsigned i;
int menu_hotkey = 0;
char **menu_args = NULL;
char *menu_users = NULL;
char *menu_title = NULL;
char *menu_sourcecode = NULL;
struct grub_menu_entry_class *menu_classes = NULL;
grub_menu_t menu;
grub_menu_entry_t *last;
menu = grub_env_get_menu ();
if (! menu)
return grub_error (GRUB_ERR_MENU, "no menu context");
last = &menu->entry_list;
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
if (! menu_sourcecode)
return grub_errno;
if (classes)
{
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class) * i);
if (! menu_classes)
goto fail;
for (i = 0; classes[i]; i++)
{
menu_classes[i].name = grub_strdup (classes[i]);
if (! menu_classes[i].name)
goto fail;
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
}
}
if (users)
{
menu_users = grub_strdup (users);
if (! menu_users)
goto fail;
}
if (hotkey)
{
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
{
menu_hotkey = hotkey_aliases[i].key;
break;
}
if (i == ARRAY_SIZE (hotkey_aliases))
menu_hotkey = hotkey[0];
}
if (! argc)
{
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
goto fail;
}
menu_title = grub_strdup (args[0]);
if (! menu_title)
goto fail;
/* Save argc, args to pass as parameters to block arg later. */
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
if (! menu_args)
goto fail;
for (i = 0; args[i]; i++)
{
menu_args[i] = grub_strdup (args[i]);
if (! menu_args[i])
goto fail;
}
menu_args[argc] = NULL;
/* Add the menu entry at the end of the list. */
while (*last)
last = &(*last)->next;
*last = grub_zalloc (sizeof (**last));
if (! *last)
goto fail;
(*last)->title = menu_title;
(*last)->hotkey = menu_hotkey;
(*last)->classes = menu_classes;
if (menu_users)
(*last)->restricted = 1;
(*last)->users = menu_users;
(*last)->argc = argc;
(*last)->args = menu_args;
(*last)->sourcecode = menu_sourcecode;
menu->size++;
return GRUB_ERR_NONE;
fail:
grub_free (menu_sourcecode);
for (i = 0; menu_classes && menu_classes[i].name; i++)
grub_free (menu_classes[i].name);
grub_free (menu_classes);
for (i = 0; menu_args && menu_args[i]; i++)
grub_free (menu_args[i]);
grub_free (menu_args);
grub_free (menu_users);
grub_free (menu_title);
return grub_errno;
}
static char *
setparams_prefix (int argc, char **args)
{
int i;
int j;
char *p;
char *result;
grub_size_t len = 10;
static const char *escape_characters = "\"\\";
auto char *strescpy (char *, const char *, const char *);
char * strescpy (char *d, const char *s, const char *escapes)
{
while (*s)
{
if (grub_strchr (escapes, *s))
*d++ = '\\';
*d++ = *s++;
}
*d = '\0';
return d;
}
/* Count resulting string length */
for (i = 0; i < argc; i++)
{
len += 3; /* 3 = 1 space + 2 quotes */
p = args[i];
while (*p)
len += grub_strchr (escape_characters, *p++) ? 2 : 1;
}
result = grub_malloc (len + 2);
if (! result)
return 0;
grub_strcpy (result, "setparams");
i = 9;
for (j = 0; j < argc; j++)
{
result[i++] = ' ';
result[i++] = '"';
i = strescpy (result + i, args[j], escape_characters) - result;
result[i++] = '"';
}
result[i++] = '\n';
result[i] = '\0';
return result;
}
static grub_err_t
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
{
char ch;
char *src;
char *prefix;
unsigned len;
grub_err_t r;
if (! argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
if (ctxt->state[3].set && ctxt->script)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
if (! ctxt->state[3].set && ! ctxt->script)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
if (! ctxt->script)
return append_menu_entry (argc, (const char **) args,
ctxt->state[0].args, ctxt->state[1].arg,
ctxt->state[2].arg, 0, ctxt->state[3].arg);
src = args[argc - 1];
args[argc - 1] = NULL;
len = grub_strlen(src);
ch = src[len - 1];
src[len - 1] = '\0';
prefix = setparams_prefix (argc - 1, args);
if (! prefix)
return grub_errno;
r = append_menu_entry (argc - 1, (const char **) args,
ctxt->state[0].args, ctxt->state[1].arg,
ctxt->state[2].arg, prefix, src + 1);
src[len - 1] = ch;
args[argc - 1] = src;
grub_free (prefix);
return r;
}
static grub_extcmd_t cmd;
void
grub_menu_init (void)
{
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS,
N_("BLOCK"), N_("Define a menuentry."), options);
}
void
grub_menu_fini (void)
{
grub_unregister_extcmd (cmd);
}

View file

@ -209,10 +209,18 @@ parse_option (grub_extcmd_t cmd, int key, char *arg, struct grub_arg_list *usr)
if (found == -1) if (found == -1)
return -1; return -1;
if (opt->flags & GRUB_ARG_OPTION_REPEATABLE)
{
usr[found].args[usr[found].set++] = arg;
usr[found].args[usr[found].set] = NULL;
}
else
{
usr[found].set = 1; usr[found].set = 1;
usr[found].arg = arg; usr[found].arg = arg;
} }
} }
}
return 0; return 0;
} }
@ -230,10 +238,15 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
grub_err_t add_arg (char *s) grub_err_t add_arg (char *s)
{ {
argl = grub_realloc (argl, (++num) * sizeof (char *)); char **p = argl;
argl = grub_realloc (argl, (++num + 1) * sizeof (char *));
if (! argl) if (! argl)
{
grub_free (p);
return grub_errno; return grub_errno;
}
argl[num - 1] = s; argl[num - 1] = s;
argl[num] = NULL;
return 0; return 0;
} }
@ -310,8 +323,11 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
if (option) { if (option) {
arglen = option - arg - 2; arglen = option - arg - 2;
option++; option++;
} else } else {
arglen = grub_strlen (arg) - 2; arglen = grub_strlen (arg) - 2;
if (argv[curarg + 1])
option = argv[curarg + 1][0] == '-' ? 0 : argv[++curarg];
}
opt = find_long (cmd->options, arg + 2, arglen); opt = find_long (cmd->options, arg + 2, arglen);
if (! opt) if (! opt)
@ -390,3 +406,43 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
fail: fail:
return complete; return complete;
} }
struct grub_arg_list*
grub_arg_list_alloc(grub_extcmd_t extcmd, int argc,
char **argv __attribute__((unused)))
{
int i;
char **args;
unsigned argcnt;
struct grub_arg_list *list;
const struct grub_arg_option *options;
options = extcmd->options;
if (! options)
return 0;
argcnt = 0;
for (i = 0; options[i].doc; i++)
{
if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE)
argcnt += (argc + 1) / 2 + 1; /* max possible for any option */
}
list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt);
if (! list)
return 0;
args = (char**) (list + i);
for (i = 0; options[i].doc; i++)
{
list[i].set = 0;
list[i].arg = 0;
if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE)
{
list[i].args = args;
args += argc / 2 + 1;
}
}
return list;
}

View file

@ -141,209 +141,6 @@ free_menu (grub_menu_t menu)
grub_env_unset_menu (); grub_env_unset_menu ();
} }
static void
free_menu_entry_classes (struct grub_menu_entry_class *head)
{
/* Free all the classes. */
while (head)
{
struct grub_menu_entry_class *next;
grub_free (head->name);
next = head->next;
grub_free (head);
head = next;
}
}
static struct
{
char *name;
int key;
} hotkey_aliases[] =
{
{"backspace", '\b'},
{"tab", '\t'},
{"delete", GRUB_TERM_DC}
};
/* Add a menu entry to the current menu context (as given by the environment
variable data slot `menu'). As the configuration file is read, the script
parser calls this when a menu entry is to be created. */
grub_err_t
grub_normal_add_menu_entry (int argc, const char **args,
const char *sourcecode)
{
const char *menutitle = 0;
const char *menusourcecode;
grub_menu_t menu;
grub_menu_entry_t *last;
int failed = 0;
int i;
struct grub_menu_entry_class *classes_head; /* Dummy head node for list. */
struct grub_menu_entry_class *classes_tail;
char *users = NULL;
int hotkey = 0;
/* Allocate dummy head node for class list. */
classes_head = grub_zalloc (sizeof (struct grub_menu_entry_class));
if (! classes_head)
return grub_errno;
classes_tail = classes_head;
menu = grub_env_get_menu ();
if (! menu)
return grub_error (GRUB_ERR_MENU, "no menu context");
last = &menu->entry_list;
menusourcecode = grub_strdup (sourcecode);
if (! menusourcecode)
return grub_errno;
/* Parse menu arguments. */
for (i = 0; i < argc; i++)
{
/* Capture arguments. */
if (grub_strncmp ("--", args[i], 2) == 0 && i + 1 < argc)
{
const char *arg = &args[i][2];
/* Handle menu class. */
if (grub_strcmp(arg, "class") == 0)
{
char *class_name;
struct grub_menu_entry_class *new_class;
i++;
class_name = grub_strdup (args[i]);
if (! class_name)
{
failed = 1;
break;
}
/* Create a new class and add it at the tail of the list. */
new_class = grub_zalloc (sizeof (struct grub_menu_entry_class));
if (! new_class)
{
grub_free (class_name);
failed = 1;
break;
}
/* Fill in the new class node. */
new_class->name = class_name;
/* Link the tail to it, and make it the new tail. */
classes_tail->next = new_class;
classes_tail = new_class;
continue;
}
else if (grub_strcmp(arg, "users") == 0)
{
i++;
users = grub_strdup (args[i]);
if (! users)
{
failed = 1;
break;
}
continue;
}
else if (grub_strcmp(arg, "hotkey") == 0)
{
unsigned j;
i++;
if (args[i][1] == 0)
{
hotkey = args[i][0];
continue;
}
for (j = 0; j < ARRAY_SIZE (hotkey_aliases); j++)
if (grub_strcmp (args[i], hotkey_aliases[j].name) == 0)
{
hotkey = hotkey_aliases[j].key;
break;
}
if (j < ARRAY_SIZE (hotkey_aliases))
continue;
failed = 1;
grub_error (GRUB_ERR_MENU,
"Invalid hotkey: '%s'.", args[i]);
break;
}
else
{
/* Handle invalid argument. */
failed = 1;
grub_error (GRUB_ERR_MENU,
"invalid argument for menuentry: %s", args[i]);
break;
}
}
/* Capture title. */
if (! menutitle)
{
menutitle = grub_strdup (args[i]);
}
else
{
failed = 1;
grub_error (GRUB_ERR_MENU,
"too many titles for menuentry: %s", args[i]);
break;
}
}
/* Validate arguments. */
if ((! failed) && (! menutitle))
{
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
failed = 1;
}
/* If argument parsing failed, free any allocated resources. */
if (failed)
{
free_menu_entry_classes (classes_head);
grub_free ((void *) menutitle);
grub_free ((void *) menusourcecode);
/* Here we assume that grub_error has been used to specify failure details. */
return grub_errno;
}
/* Add the menu entry at the end of the list. */
while (*last)
last = &(*last)->next;
*last = grub_zalloc (sizeof (**last));
if (! *last)
{
free_menu_entry_classes (classes_head);
grub_free ((void *) menutitle);
grub_free ((void *) menusourcecode);
return grub_errno;
}
(*last)->title = menutitle;
(*last)->hotkey = hotkey;
(*last)->classes = classes_head;
if (users)
(*last)->restricted = 1;
(*last)->users = users;
(*last)->sourcecode = menusourcecode;
menu->size++;
return GRUB_ERR_NONE;
}
static grub_menu_t static grub_menu_t
read_config_file (const char *config) read_config_file (const char *config)
{ {
@ -679,6 +476,7 @@ GRUB_MOD_INIT(normal)
{ {
grub_context_init (); grub_context_init ();
grub_script_init (); grub_script_init ();
grub_menu_init ();
grub_xputs_saved = grub_xputs; grub_xputs_saved = grub_xputs;
grub_xputs = grub_xputs_normal; grub_xputs = grub_xputs_normal;
@ -718,6 +516,7 @@ GRUB_MOD_FINI(normal)
{ {
grub_context_fini (); grub_context_fini ();
grub_script_fini (); grub_script_fini ();
grub_menu_fini ();
grub_xputs = grub_xputs_saved; grub_xputs = grub_xputs_saved;

View file

@ -153,44 +153,6 @@ get_and_remove_first_entry_number (const char *name)
return entry; return entry;
} }
static void
grub_menu_execute_entry_real (grub_menu_entry_t entry)
{
const char *source;
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;
}
source = entry->sourcecode;
while (source)
{
char *line;
getline (&line, 0);
grub_normal_parse_line (line, getline);
grub_free (line);
}
}
/* Run a menu entry. */ /* Run a menu entry. */
void void
grub_menu_execute_entry(grub_menu_entry_t entry) grub_menu_execute_entry(grub_menu_entry_t entry)
@ -208,8 +170,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry)
} }
grub_env_set ("chosen", entry->title); grub_env_set ("chosen", entry->title);
grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args);
grub_menu_execute_entry_real (entry);
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */ /* Implicit execution of boot, only if something is loaded. */

View file

@ -401,6 +401,62 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
return ret; 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;
}
/* Execute a single command line. */ /* Execute a single command line. */
grub_err_t grub_err_t
grub_script_execute_cmdline (struct grub_script_cmd *cmd) grub_script_execute_cmdline (struct grub_script_cmd *cmd)
@ -598,31 +654,6 @@ grub_script_execute_cmdwhile (struct grub_script_cmd *cmd)
return result; 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. */ /* Execute any GRUB pre-parsed command or script. */
grub_err_t grub_err_t
grub_script_execute (struct grub_script *script) grub_script_execute (struct grub_script *script)

View file

@ -76,7 +76,6 @@
%token <arg> GRUB_PARSER_TOKEN_WHILE "while" %token <arg> GRUB_PARSER_TOKEN_WHILE "while"
%token <arg> GRUB_PARSER_TOKEN_TIME "time" %token <arg> GRUB_PARSER_TOKEN_TIME "time"
%token <arg> GRUB_PARSER_TOKEN_FUNCTION "function" %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_NAME "name"
%token <arg> GRUB_PARSER_TOKEN_WORD "word" %token <arg> GRUB_PARSER_TOKEN_WORD "word"
@ -85,7 +84,7 @@
%type <cmd> script_init script %type <cmd> script_init script
%type <cmd> grubcmd ifclause ifcmd forcmd whilecmd untilcmd %type <cmd> grubcmd ifclause ifcmd forcmd whilecmd untilcmd
%type <cmd> command commands1 menuentry statement %type <cmd> command commands1 statement
%pure-parser %pure-parser
%lex-param { struct grub_parser_param *state }; %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; } statement: command { $$ = $1; }
| function { $$ = 0; } | function { $$ = 0; }
| menuentry { $$ = $1; }
; ;
argument : "case" { $$ = grub_script_add_arglist (state, 0, $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); } | "until" { $$ = grub_script_add_arglist (state, 0, $1); }
| "while" { $$ = grub_script_add_arglist (state, 0, $1); } | "while" { $$ = grub_script_add_arglist (state, 0, $1); }
| "function" { $$ = 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; } | word { $$ = $1; }
; ;
@ -243,8 +240,7 @@ grubcmd: word arguments0 block0
if ($3) if ($3)
x = grub_script_add_arglist (state, $2, $3); x = grub_script_add_arglist (state, $2, $3);
if ($1 && x) if ($1 && x) {
{
$1->next = x; $1->next = x;
$1->argcount += x->argcount; $1->argcount += x->argcount;
x->argcount = 0; x->argcount = 0;
@ -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" ifcmd: "if"
{ {
grub_script_lexer_ref (state->lexerstate); grub_script_lexer_ref (state->lexerstate);

View file

@ -281,30 +281,6 @@ grub_script_create_cmdwhile (struct grub_parser_param *state,
return (struct grub_script_cmd *) cmd; 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 /* 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 be added at the end of LIST's list. If LIST is zero, a new list
will be created. */ will be created. */

View file

@ -176,7 +176,6 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n))
"until" { RECORD; return GRUB_PARSER_TOKEN_UNTIL; } "until" { RECORD; return GRUB_PARSER_TOKEN_UNTIL; }
"while" { RECORD; return GRUB_PARSER_TOKEN_WHILE; } "while" { RECORD; return GRUB_PARSER_TOKEN_WHILE; }
"function" { RECORD; return GRUB_PARSER_TOKEN_FUNCTION; } "function" { RECORD; return GRUB_PARSER_TOKEN_FUNCTION; }
"menuentry" { RECORD; return GRUB_PARSER_TOKEN_MENUENTRY; }
{MULTILINE} { {MULTILINE} {
if (grub_lexer_unput (yytext, yyscanner)) if (grub_lexer_unput (yytext, yyscanner))

View file

@ -38,6 +38,8 @@ typedef enum grub_arg_type grub_arg_type_t;
/* Flags for the option field op grub_arg_option. */ /* Flags for the option field op grub_arg_option. */
#define GRUB_ARG_OPTION_OPTIONAL (1 << 1) #define GRUB_ARG_OPTION_OPTIONAL (1 << 1)
/* Flags for an option that can appear multiple times. */
#define GRUB_ARG_OPTION_REPEATABLE (1 << 2)
enum grub_key_type enum grub_key_type
{ {
@ -59,7 +61,10 @@ struct grub_arg_option
struct grub_arg_list struct grub_arg_list
{ {
int set; int set;
union {
char *arg; char *arg;
char **args;
};
}; };
struct grub_extcmd; struct grub_extcmd;
@ -68,5 +73,7 @@ int grub_arg_parse (struct grub_extcmd *cmd, int argc, char **argv,
struct grub_arg_list *usr, char ***args, int *argnum); struct grub_arg_list *usr, char ***args, int *argnum);
void grub_arg_show_help (struct grub_extcmd *cmd); void grub_arg_show_help (struct grub_extcmd *cmd);
struct grub_arg_list* grub_arg_list_alloc (struct grub_extcmd *cmd,
int argc, char *argv[]);
#endif /* ! GRUB_ARG_HEADER */ #endif /* ! GRUB_ARG_HEADER */

View file

@ -47,6 +47,10 @@ struct grub_menu_entry
/* The sourcecode of the menu entry, used by the editor. */ /* The sourcecode of the menu entry, used by the editor. */
const char *sourcecode; const char *sourcecode;
/* Parameters to be passed to menu definition. */
int argc;
char **args;
int hotkey; int hotkey;
/* The next element. */ /* The next element. */
@ -96,4 +100,7 @@ void grub_menu_execute_with_fallback (grub_menu_t menu,
void grub_menu_entry_run (grub_menu_entry_t entry); void grub_menu_entry_run (grub_menu_entry_t entry);
int grub_menu_get_default_entry_index (grub_menu_t menu); int grub_menu_get_default_entry_index (grub_menu_t menu);
void grub_menu_init (void);
void grub_menu_fini (void);
#endif /* GRUB_MENU_HEADER */ #endif /* GRUB_MENU_HEADER */

View file

@ -54,8 +54,6 @@ void grub_normal_execute (const char *config, int nested, int batch);
void grub_menu_init_page (int nested, int edit, void grub_menu_init_page (int nested, int edit,
struct grub_term_output *term); struct grub_term_output *term);
void grub_normal_init_page (struct grub_term_output *term); void grub_normal_init_page (struct grub_term_output *term);
grub_err_t grub_normal_add_menu_entry (int argc, const char **args,
const char *sourcecode);
char *grub_file_getline (grub_file_t file); char *grub_file_getline (grub_file_t file);
void grub_cmdline_run (int nested); void grub_cmdline_run (int nested);

View file

@ -145,21 +145,6 @@ struct grub_script_cmdwhile
int until; int until;
}; };
/* A menu entry generate statement. */
struct grub_script_cmd_menuentry
{
struct grub_script_cmd cmd;
/* The arguments for this menu entry. */
struct grub_script_arglist *arglist;
/* The sourcecode the entry will be generated from. */
const char *sourcecode;
/* Options. XXX: Not used yet. */
int options;
};
/* State of the lexer as passed to the lexer. */ /* State of the lexer as passed to the lexer. */
struct grub_lexer_param struct grub_lexer_param
{ {
@ -282,12 +267,6 @@ grub_script_create_cmdwhile (struct grub_parser_param *state,
struct grub_script_cmd *list, struct grub_script_cmd *list,
int is_an_until_loop); int is_an_until_loop);
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 * struct grub_script_cmd *
grub_script_append_cmd (struct grub_parser_param *state, grub_script_append_cmd (struct grub_parser_param *state,
struct grub_script_cmd *list, struct grub_script_cmd *list,
@ -332,10 +311,10 @@ 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_cmdif (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdfor (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); grub_err_t grub_script_execute_cmdwhile (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd);
/* Execute any GRUB pre-parsed command or script. */ /* Execute any GRUB pre-parsed command or script. */
grub_err_t grub_script_execute (struct grub_script *script); grub_err_t grub_script_execute (struct grub_script *script);
grub_err_t grub_script_execute_sourcecode (const char *source, int argc, char **args);
/* Break command for loops. */ /* Break command for loops. */
grub_err_t grub_script_break (grub_command_t cmd, int argc, char *argv[]); grub_err_t grub_script_break (grub_command_t cmd, int argc, char *argv[]);