diff --git a/ChangeLog b/ChangeLog index 4c1046655..a155853d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2010-09-04 BVK Chaitanya + + 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 "return" command for GRUB script functions. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index e27152706..df67ae948 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1164,6 +1164,8 @@ module = { common = script/lexer.c; common = script/argv.c; + common = commands/menuentry.c; + common = unidata.c; common_nodist = grub_script.tab.c; common_nodist = grub_script.yy.c; @@ -1384,4 +1386,4 @@ module = { module = { name = test_blockarg; common = tests/test_blockarg.c; -}; \ No newline at end of file +}; diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c index ecf2d4133..44a4b6cfd 100644 --- a/grub-core/commands/extcmd.c +++ b/grub-core/commands/extcmd.c @@ -29,10 +29,8 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, { 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 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, 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 diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c new file mode 100644 index 000000000..fc1ae71c7 --- /dev/null +++ b/grub-core/commands/menuentry.c @@ -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 . + */ + +#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}, + {"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); +} diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index a9b8a520e..f3352520b 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -209,8 +209,16 @@ parse_option (grub_extcmd_t cmd, int key, char *arg, struct grub_arg_list *usr) 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; + } } } @@ -230,10 +238,15 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, 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; } @@ -310,8 +323,11 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, 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) @@ -390,3 +406,43 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, 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; +} diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index cddb15216..6a008f577 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -141,209 +141,6 @@ free_menu (grub_menu_t 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 read_config_file (const char *config) { @@ -679,6 +476,7 @@ GRUB_MOD_INIT(normal) { grub_context_init (); grub_script_init (); + grub_menu_init (); grub_xputs_saved = grub_xputs; grub_xputs = grub_xputs_normal; @@ -718,6 +516,7 @@ GRUB_MOD_FINI(normal) { grub_context_fini (); grub_script_fini (); + grub_menu_fini (); grub_xputs = grub_xputs_saved; diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index cc84ce38c..6827a893f 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -153,44 +153,6 @@ get_and_remove_first_entry_number (const char *name) 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) @@ -208,8 +170,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry) } 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. */ diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index 88057d44e..f35e9ce76 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -401,6 +401,62 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args) 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) @@ -598,31 +654,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) diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y index 3faaf4736..88c7fe9e3 100644 --- a/grub-core/script/parser.y +++ b/grub-core/script/parser.y @@ -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 @@ 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 - { - $$ = 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); diff --git a/grub-core/script/script.c b/grub-core/script/script.c index 76d5aa518..ad3018357 100644 --- a/grub-core/script/script.c +++ b/grub-core/script/script.c @@ -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. */ diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index 45728dfb4..d4cad8097 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -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)) diff --git a/include/grub/lib/arg.h b/include/grub/lib/arg.h index e6af60cf9..3bab27781 100644 --- a/include/grub/lib/arg.h +++ b/include/grub/lib/arg.h @@ -38,6 +38,8 @@ typedef enum grub_arg_type grub_arg_type_t; /* 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_option struct grub_arg_list { int set; - char *arg; + union { + char *arg; + char **args; + }; }; 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); 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 */ diff --git a/include/grub/menu.h b/include/grub/menu.h index e5e5fb110..608253863 100644 --- a/include/grub/menu.h +++ b/include/grub/menu.h @@ -47,6 +47,10 @@ struct grub_menu_entry /* 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. */ @@ -96,4 +100,7 @@ void grub_menu_execute_with_fallback (grub_menu_t menu, void grub_menu_entry_run (grub_menu_entry_t entry); 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 */ diff --git a/include/grub/normal.h b/include/grub/normal.h index 2a0298bc6..51ab46b12 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -54,8 +54,6 @@ void grub_normal_execute (const char *config, int nested, int batch); 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); diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index 848e55411..de6e3a47f 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -145,21 +145,6 @@ struct grub_script_cmdwhile 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 { @@ -282,12 +267,6 @@ grub_script_create_cmdwhile (struct grub_parser_param *state, struct grub_script_cmd *list, 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, @@ -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_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); /* Break command for loops. */ grub_err_t grub_script_break (grub_command_t cmd, int argc, char *argv[]);