# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: address@hidden
# target_branch: ../block-arg/
# testament_sha1: 040742457d78f9f38292c55ac81b39a4102fd020
# timestamp: 2010-07-22 23:22:42 +0530
# base_revision_id: address@hidden
# 7a5njysjimymabii
#
# Begin patch
=== modified file 'commands/extcmd.c'
--- commands/extcmd.c 2010-07-21 23:35:49 +0000
+++ commands/extcmd.c 2010-07-22 17:52:36 +0000
@@ -29,10 +29,8 @@
{
int new_argc;
char **new_args;
- struct grub_arg_option *parser;
struct grub_arg_list *state;
struct grub_extcmd_context context;
- int maxargs = 0;
grub_err_t ret;
grub_extcmd_t ext = cmd->data;
@@ -46,25 +44,18 @@
return ret;
}
- parser = (struct grub_arg_option *) ext->options;
- while (parser && (parser++)->doc)
- maxargs++;
-
- /* Set up the option state. */
- state = grub_zalloc (sizeof (struct grub_arg_list) * maxargs);
-
+ state = grub_arg_list_alloc (ext, argc, args);
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
{
context.state = state;
ret = (ext->func) (&context, new_argc, new_args);
grub_free (new_args);
+ grub_free (state);
+ return ret;
}
- else
- ret = grub_errno;
grub_free (state);
-
- return ret;
+ return grub_errno;
}
static grub_err_t
=== added file 'commands/menuentry.c'
--- commands/menuentry.c 1970-01-01 00:00:00 +0000
+++ commands/menuentry.c 2010-07-22 15:45:14 +0000
@@ -0,0 +1,213 @@
+/* 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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},
+ {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 *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_strdup (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))
+ goto fail;
+ }
+
+ 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 grub_err_t
+grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+ char ch;
+ char *src;
+ unsigned len;
+ grub_err_t r;
+
+ if (! argc || ! ctxt->script)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ src = args[argc - 1];
+ args[argc - 1] = NULL;
+
+ len = grub_strlen(src);
+ ch = src[len - 1];
+ src[len - 1] = '\0';
+
+ r = append_menu_entry (argc - 1, (const char **) args,
+ ctxt->state[0].args, ctxt->state[1].arg,
+ ctxt->state[2].arg, src + 1);
+
+ src[len - 1] = ch;
+ args[argc - 1] = src;
+ return r;
+}
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT(menuentry)
+{
+ cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
+ GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS,
+ N_("BLOCK"), N_("Define a menuentry."), options);
+}
+
+GRUB_MOD_FINI(menuentry)
+{
+ grub_unregister_extcmd (cmd);
+}
=== modified file 'conf/common.rmk'
--- conf/common.rmk 2010-07-22 17:07:10 +0000
+++ conf/common.rmk 2010-07-22 17:48:28 +0000
@@ -830,6 +830,12 @@
boot_mod_CFLAGS = $(COMMON_CFLAGS)
boot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For menuentry.mod.
+pkglib_MODULES += menuentry.mod
+menuentry_mod_SOURCES = commands/menuentry.c
+menuentry_mod_CFLAGS = $(COMMON_CFLAGS)
+menuentry_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
bin_UTILITIES += grub-mkpasswd-pbkdf2
grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/emu/misc.c kern/emu/mm.c kern/err.c
grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1
=== modified file 'include/grub/lib/arg.h'
--- include/grub/lib/arg.h 2009-03-21 08:39:59 +0000
+++ include/grub/lib/arg.h 2010-07-22 13:31:40 +0000
@@ -38,6 +38,8 @@
/* Flags for the option field op grub_arg_option. */
#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
{
@@ -59,7 +61,10 @@
struct grub_arg_list
{
int set;
- char *arg;
+ union {
+ char *arg;
+ char **args;
+ };
};
struct grub_extcmd;
@@ -68,5 +73,7 @@
struct grub_arg_list *usr, char ***args, int *argnum);
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 */
=== modified file 'include/grub/menu.h'
--- include/grub/menu.h 2009-12-29 22:01:12 +0000
+++ include/grub/menu.h 2010-07-22 15:45:14 +0000
@@ -47,6 +47,10 @@
/* The sourcecode of the menu entry, used by the editor. */
const char *sourcecode;
+ /* Parameters to be passed to menu definition. */
+ int argc;
+ char **args;
+
int hotkey;
/* The next element. */
=== modified file 'include/grub/normal.h'
--- include/grub/normal.h 2010-05-05 14:28:52 +0000
+++ include/grub/normal.h 2010-07-22 13:31:40 +0000
@@ -54,8 +54,6 @@
void grub_menu_init_page (int nested, int edit,
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);
void grub_cmdline_run (int nested);
=== modified file 'include/grub/script_sh.h'
--- include/grub/script_sh.h 2010-07-21 23:33:49 +0000
+++ include/grub/script_sh.h 2010-07-22 15:45:14 +0000
@@ -144,21 +144,6 @@
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. */
struct grub_lexer_param
{
@@ -272,12 +257,6 @@
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 *
grub_script_append_cmd (struct grub_parser_param *state,
struct grub_script_cmd *list,
struct grub_script_cmd *last);
@@ -321,10 +300,10 @@
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_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. */
grub_err_t grub_script_execute (struct grub_script *script);
+grub_err_t grub_script_execute_sourcecode (const char *source, int argc, char **args);
/* This variable points to the parsed command. This is used to
communicate with the bison code. */
@@ -367,9 +346,6 @@
char **
grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count);
-grub_err_t
-grub_normal_parse_line (char *line, grub_reader_getline_t getline);
-
static inline struct grub_script *
grub_script_get (struct grub_script *script)
{
@@ -390,4 +366,7 @@
script->refcnt--;
}
+grub_err_t
+grub_normal_parse_line (char *line, grub_reader_getline_t getline);
+
#endif /* ! GRUB_NORMAL_PARSER_HEADER */
=== modified file 'lib/arg.c'
--- lib/arg.c 2010-03-15 10:49:27 +0000
+++ lib/arg.c 2010-07-22 13:31:40 +0000
@@ -207,8 +207,16 @@
if (found == -1)
return -1;
- usr[found].set = 1;
- usr[found].arg = arg;
+ 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].arg = arg;
+ }
}
}
@@ -228,10 +236,15 @@
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)
- return grub_errno;
+ {
+ grub_free (p);
+ return grub_errno;
+ }
argl[num - 1] = s;
+ argl[num] = NULL;
return 0;
}
@@ -308,8 +321,11 @@
if (option) {
arglen = option - arg - 2;
option++;
- } else
+ } else {
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);
if (! opt)
@@ -388,3 +404,43 @@
fail:
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;
+}
=== modified file 'normal/main.c'
--- normal/main.c 2010-07-02 17:35:07 +0000
+++ normal/main.c 2010-07-22 13:31:40 +0000
@@ -141,209 +141,6 @@
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
read_config_file (const char *config)
{
=== modified file 'normal/menu.c'
--- normal/menu.c 2010-07-02 17:35:07 +0000
+++ normal/menu.c 2010-07-22 15:45:14 +0000
@@ -142,44 +142,6 @@
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. */
void
grub_menu_execute_entry(grub_menu_entry_t entry)
@@ -197,8 +159,7 @@
}
grub_env_set ("chosen", entry->title);
-
- grub_menu_execute_entry_real (entry);
+ grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args);
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */
=== modified file 'script/execute.c'
--- script/execute.c 2010-07-21 23:19:05 +0000
+++ script/execute.c 2010-07-22 15:45:14 +0000
@@ -268,6 +268,62 @@
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. */
grub_err_t
grub_script_execute_cmdline (struct grub_script_cmd *cmd)
@@ -426,31 +482,6 @@
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)
=== modified file 'script/parser.y'
--- script/parser.y 2010-07-22 17:20:04 +0000
+++ script/parser.y 2010-07-22 17:48:28 +0000
@@ -76,7 +76,6 @@
%token GRUB_PARSER_TOKEN_WHILE "while"
%token GRUB_PARSER_TOKEN_TIME "time"
%token GRUB_PARSER_TOKEN_FUNCTION "function"
-%token GRUB_PARSER_TOKEN_MENUENTRY "menuentry"
%token GRUB_PARSER_TOKEN_NAME "name"
%token GRUB_PARSER_TOKEN_WORD "word"
@@ -85,7 +84,7 @@
%type script_init script
%type grubcmd ifclause ifcmd forcmd whilecmd untilcmd
-%type command commands1 menuentry statement
+%type command commands1 statement
%pure-parser
%lex-param { struct grub_parser_param *state };
@@ -131,7 +130,6 @@
statement: command { $$ = $1; }
| function { $$ = 0; }
- | menuentry { $$ = $1; }
;
argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); }
@@ -149,7 +147,6 @@
| "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; }
;
@@ -297,25 +294,6 @@
}
;
-menuentry: "menuentry"
- {
- grub_script_lexer_ref (state->lexerstate);
- }
- arguments1
- {
- $$ = grub_script_lexer_record_start (state);
- }
- delimiters0 "{" commands1 delimiters1 "}"
- {
- char *def;
- def = grub_script_lexer_record_stop (state, $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);
=== modified file 'script/script.c'
--- script/script.c 2010-07-22 15:43:45 +0000
+++ script/script.c 2010-07-22 17:48:28 +0000
@@ -281,30 +281,6 @@
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. */
=== modified file 'script/yylex.l'
--- script/yylex.l 2010-06-09 06:04:01 +0000
+++ script/yylex.l 2010-06-10 12:45:38 +0000
@@ -169,7 +169,6 @@
"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; }
{NAME} { RECORD; return GRUB_PARSER_TOKEN_NAME; }
{WORD} {
=== modified file 'util/grub-script-check.c'
--- util/grub-script-check.c 2010-07-22 17:07:10 +0000
+++ util/grub-script-check.c 2010-07-22 17:48:28 +0000
@@ -94,12 +94,6 @@
}
grub_err_t
-grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused)))
-{
- return 0;
-}
-
-grub_err_t
grub_script_execute (struct grub_script *script)
{
if (script == 0 || script->cmd == 0)
# Begin bundle
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