# 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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