# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: address@hidden # target_branch: ../cmdlist/ # testament_sha1: a0095da64c8113f14d0fc50e451aedb4f7b94f0e # timestamp: 2010-06-10 12:26:11 +0530 # base_revision_id: address@hidden # qr58e8hf6tmt6xkm # # Begin patch === modified file 'commands/acpi.c' --- commands/acpi.c 2010-01-05 21:04:15 +0000 +++ commands/acpi.c 2010-06-10 06:42:03 +0000 @@ -456,10 +456,9 @@ } static grub_err_t -grub_cmd_acpi (struct grub_extcmd *cmd, - int argc, char **args) +grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; struct grub_acpi_rsdp_v10 *rsdp; struct efiemu_acpi_table *cur, *t; grub_err_t err; === modified file 'commands/echo.c' --- commands/echo.c 2010-01-03 18:24:22 +0000 +++ commands/echo.c 2010-06-10 06:42:03 +0000 @@ -30,9 +30,9 @@ }; static grub_err_t -grub_cmd_echo (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int newline = 1; int i; === modified file 'commands/extcmd.c' --- commands/extcmd.c 2009-07-16 22:14:09 +0000 +++ commands/extcmd.c 2010-06-10 06:42:03 +0000 @@ -21,15 +21,17 @@ #include #include #include +#include -static grub_err_t -grub_extcmd_dispatcher (struct grub_command *cmd, - int argc, char **args) +grub_err_t +grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, + struct grub_script **scripts) { 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; @@ -44,8 +46,11 @@ if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc)) { - ext->state = state; - ret = (ext->func) (ext, new_argc, new_args); + context.extcmd = ext; + context.state = state; + context.script_params = scripts; + + ret = (ext->func) (&context, new_argc, new_args); grub_free (new_args); } else @@ -56,6 +61,12 @@ return ret; } +static grub_err_t +grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args) +{ + return grub_extcmd_dispatcher (cmd, argc, args, 0); +} + grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, unsigned flags, const char *summary, @@ -69,7 +80,7 @@ if (! ext) return 0; - cmd = grub_register_command_prio (name, grub_extcmd_dispatcher, + cmd = grub_register_command_prio (name, grub_extcmd_dispatch, summary, description, 1); if (! cmd) { === modified file 'commands/hashsum.c' --- commands/hashsum.c 2010-05-01 18:28:07 +0000 +++ commands/hashsum.c 2010-06-10 06:42:03 +0000 @@ -165,10 +165,10 @@ } static grub_err_t -grub_cmd_hashsum (struct grub_extcmd *cmd, +grub_cmd_hashsum (struct grub_extcmd_context *ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; const char *hashname = NULL; const char *prefix = NULL; const gcry_md_spec_t *hash; @@ -177,7 +177,7 @@ unsigned unread = 0; for (i = 0; i < ARRAY_SIZE (aliases); i++) - if (grub_strcmp (cmd->cmd->name, aliases[i].name) == 0) + if (grub_strcmp (ctxt->extcmd->cmd->name, aliases[i].name) == 0) hashname = aliases[i].hashname; if (state[0].set) hashname = state[0].arg; === modified file 'commands/hdparm.c' --- commands/hdparm.c 2010-01-03 18:24:22 +0000 +++ commands/hdparm.c 2010-06-10 06:42:03 +0000 @@ -270,9 +270,9 @@ } static grub_err_t -grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? +grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; /* Check command line. */ if (argc != 1) === modified file 'commands/help.c' --- commands/help.c 2010-05-01 19:31:45 +0000 +++ commands/help.c 2010-06-10 06:42:03 +0000 @@ -27,7 +27,7 @@ #include static grub_err_t -grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, +grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, char **args) { int cnt = 0; === modified file 'commands/hexdump.c' --- commands/hexdump.c 2010-01-03 22:05:07 +0000 +++ commands/hexdump.c 2010-06-10 06:42:03 +0000 @@ -34,9 +34,9 @@ }; static grub_err_t -grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; char buf[GRUB_DISK_SECTOR_SIZE * 4]; grub_ssize_t size, length; grub_disk_addr_t skip; === modified file 'commands/i386/cpuid.c' --- commands/i386/cpuid.c 2010-01-03 18:24:22 +0000 +++ commands/i386/cpuid.c 2010-06-10 06:42:03 +0000 @@ -43,7 +43,7 @@ unsigned char grub_cpuid_has_longmode = 0; static grub_err_t -grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)), +grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { === modified file 'commands/i386/pc/drivemap.c' --- commands/i386/pc/drivemap.c 2010-05-01 18:28:07 +0000 +++ commands/i386/pc/drivemap.c 2010-06-10 06:42:03 +0000 @@ -196,13 +196,13 @@ } static grub_err_t -grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args) +grub_cmd_drivemap (struct grub_extcmd_context *ctxt, int argc, char **args) { - if (cmd->state[OPTIDX_LIST].set) + if (ctxt->state[OPTIDX_LIST].set) { return list_mappings (); } - else if (cmd->state[OPTIDX_RESET].set) + else if (ctxt->state[OPTIDX_RESET].set) { /* Reset: just delete all mappings, freeing their memory. */ drivemap_node_t *curnode = map_head; @@ -216,7 +216,7 @@ map_head = 0; return GRUB_ERR_NONE; } - else if (!cmd->state[OPTIDX_SWAP].set && argc == 0) + else if (!ctxt->state[OPTIDX_SWAP].set && argc == 0) { /* No arguments */ return list_mappings (); @@ -248,11 +248,11 @@ } /* Set the mapping for the disk (overwrites any existing mapping). */ grub_dprintf ("drivemap", "%s %s (%02x) = %s (%02x)\n", - cmd->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping", + ctxt->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping", args[1], mapto, args[0], mapfrom); err = drivemap_set (mapto, mapfrom); /* If -s, perform the reverse mapping too (only if the first was OK). */ - if (cmd->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE) + if (ctxt->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE) err = drivemap_set (mapfrom, mapto); return err; } === modified file 'commands/i386/pc/halt.c' --- commands/i386/pc/halt.c 2010-01-03 22:05:07 +0000 +++ commands/i386/pc/halt.c 2010-06-10 06:42:03 +0000 @@ -29,12 +29,12 @@ }; static grub_err_t -grub_cmd_halt (grub_extcmd_t cmd, +grub_cmd_halt (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int no_apm = 0; if (state[0].set) no_apm = 1; === modified file 'commands/iorw.c' --- commands/iorw.c 2010-05-01 18:28:07 +0000 +++ commands/iorw.c 2010-06-10 06:42:03 +0000 @@ -36,7 +36,7 @@ static grub_err_t -grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; @@ -46,7 +46,7 @@ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); addr = grub_strtoul (argv[0], 0, 0); - switch (cmd->cmd->name[sizeof ("in") - 1]) + switch (ctxt->extcmd->cmd->name[sizeof ("in") - 1]) { case 'l': value = grub_inl (addr); @@ -61,10 +61,10 @@ break; } - if (cmd->state[0].set) + if (ctxt->state[0].set) { grub_snprintf (buf, sizeof (buf), "%x", value); - grub_env_set (cmd->state[0].arg, buf); + grub_env_set (ctxt->state[0].arg, buf); } else grub_printf ("0x%x\n", value); === modified file 'commands/keystatus.c' --- commands/keystatus.c 2010-01-05 15:27:41 +0000 +++ commands/keystatus.c 2010-06-10 06:42:03 +0000 @@ -34,11 +34,11 @@ #define grub_cur_term_input grub_term_get_current_input () static grub_err_t -grub_cmd_keystatus (grub_extcmd_t cmd, +grub_cmd_keystatus (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int expect_mods = 0; int mods; === modified file 'commands/loadenv.c' --- commands/loadenv.c 2010-02-06 17:43:37 +0000 +++ commands/loadenv.c 2010-06-10 06:42:03 +0000 @@ -111,11 +111,11 @@ } static grub_err_t -grub_cmd_load_env (grub_extcmd_t cmd, +grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; @@ -143,11 +143,11 @@ } static grub_err_t -grub_cmd_list_env (grub_extcmd_t cmd, +grub_cmd_list_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; @@ -280,9 +280,9 @@ } static grub_err_t -grub_cmd_save_env (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; struct blocklist *head = 0; === modified file 'commands/ls.c' --- commands/ls.c 2010-02-06 19:52:11 +0000 +++ commands/ls.c 2010-06-10 06:42:03 +0000 @@ -248,9 +248,9 @@ } static grub_err_t -grub_cmd_ls (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; if (argc == 0) grub_ls_list_devices (state[0].set); === modified file 'commands/lspci.c' --- commands/lspci.c 2010-01-20 19:40:30 +0000 +++ commands/lspci.c 2010-06-10 06:42:03 +0000 @@ -211,11 +211,11 @@ } static grub_err_t -grub_cmd_lspci (grub_extcmd_t cmd, +grub_cmd_lspci (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - iospace = cmd->state[0].set; + iospace = ctxt->state[0].set; grub_pci_iterate (grub_lspci_iter); return GRUB_ERR_NONE; } === modified file 'commands/memrw.c' --- commands/memrw.c 2010-01-20 06:36:17 +0000 +++ commands/memrw.c 2010-06-10 06:42:03 +0000 @@ -35,7 +35,7 @@ static grub_err_t -grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; @@ -45,7 +45,7 @@ return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments"); addr = grub_strtoul (argv[0], 0, 0); - switch (cmd->cmd->name[sizeof ("read_") - 1]) + switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1]) { case 'd': value = *((volatile grub_uint32_t *) addr); @@ -60,10 +60,10 @@ break; } - if (cmd->state[0].set) + if (ctxt->state[0].set) { grub_snprintf (buf, sizeof (buf), "%x", value); - grub_env_set (cmd->state[0].arg, buf); + grub_env_set (ctxt->state[0].arg, buf); } else grub_printf ("0x%x\n", value); === modified file 'commands/probe.c' --- commands/probe.c 2010-01-03 18:24:22 +0000 +++ commands/probe.c 2010-06-10 06:42:03 +0000 @@ -45,9 +45,9 @@ }; static grub_err_t -grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_device_t dev; grub_fs_t fs; char *ptr; === modified file 'commands/search_wrap.c' --- commands/search_wrap.c 2009-12-25 22:06:52 +0000 +++ commands/search_wrap.c 2010-06-10 06:42:03 +0000 @@ -50,9 +50,9 @@ }; static grub_err_t -grub_cmd_search (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; const char *var = 0; if (argc == 0) === modified file 'commands/setpci.c' --- commands/setpci.c 2010-05-01 18:28:07 +0000 +++ commands/setpci.c 2010-06-10 06:42:03 +0000 @@ -155,7 +155,7 @@ } static grub_err_t -grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) { const char *ptr; unsigned i; @@ -163,14 +163,14 @@ pciid_check_value = 0; pciid_check_mask = 0; - if (cmd->state[0].set) + if (ctxt->state[0].set) { - ptr = cmd->state[0].arg; + ptr = ctxt->state[0].arg; pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff); if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = GRUB_ERR_NONE; - ptr = cmd->state[0].arg; + ptr = ctxt->state[0].arg; } else pciid_check_mask |= 0xffff; @@ -191,11 +191,11 @@ check_bus = check_device = check_function = 0; - if (cmd->state[1].set) + if (ctxt->state[1].set) { const char *optr; - ptr = cmd->state[1].arg; + ptr = ctxt->state[1].arg; optr = ptr; bus = grub_strtoul (ptr, (char **) &ptr, 16); if (grub_errno == GRUB_ERR_BAD_NUMBER) @@ -229,8 +229,8 @@ } } - if (cmd->state[2].set) - varname = cmd->state[2].arg; + if (ctxt->state[2].set) + varname = ctxt->state[2].arg; else varname = NULL; === modified file 'commands/sleep.c' --- commands/sleep.c 2010-02-07 02:06:33 +0000 +++ commands/sleep.c 2010-06-10 06:42:03 +0000 @@ -60,9 +60,9 @@ } static grub_err_t -grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int n; if (argc != 1) === modified file 'disk/loopback.c' --- disk/loopback.c 2010-02-07 02:06:33 +0000 +++ disk/loopback.c 2010-06-10 06:42:03 +0000 @@ -71,9 +71,9 @@ /* The command to add and remove loopback devices. */ static grub_err_t -grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; struct grub_loopback *newdev; === modified file 'hello/hello.c' --- hello/hello.c 2010-01-03 18:50:51 +0000 +++ hello/hello.c 2010-06-10 06:56:07 +0000 @@ -26,12 +26,36 @@ #include #include +static struct grub_script *script; + static grub_err_t -grub_cmd_hello (struct grub_extcmd *cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) +grub_cmd_hello (grub_extcmd_context_t ctxt, + int argc, char **args __attribute__ ((unused))) { - grub_printf ("Hello World\n"); + if (argc == 0 && script == 0) + grub_printf ("Hello World\n"); + + else if (argc == 0) + grub_script_execute (script); + + else + { + if (! ctxt->script_params || ! ctxt->script_params[0]) + return 1; + + if (script) + grub_script_free (script); + + script = grub_malloc (sizeof (*script)); + if (! script) + return 1; + + script->cmd = ctxt->script_params[0]->cmd; + script->mem = ctxt->script_params[0]->mem; + ctxt->script_params[0]->cmd = 0; + ctxt->script_params[0]->mem = 0; + } + return 0; } @@ -39,11 +63,15 @@ GRUB_MOD_INIT(hello) { - cmd = grub_register_extcmd ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH, - 0, N_("Say \"Hello World\"."), 0); + cmd = grub_register_extcmd ("hello", grub_cmd_hello, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS, + N_("[BLOCK]"), N_("Say \"Hello World\"."), 0); } GRUB_MOD_FINI(hello) { + if (script) + grub_script_free (script); + grub_unregister_extcmd (cmd); } === modified file 'include/grub/command.h' --- include/grub/command.h 2009-05-04 20:06:05 +0000 +++ include/grub/command.h 2010-06-10 06:42:03 +0000 @@ -37,6 +37,8 @@ #define GRUB_COMMAND_FLAG_EXTCMD 0x10 /* This is an dynamic command. */ #define GRUB_COMMAND_FLAG_DYNCMD 0x20 +/* This command accepts block arguments. */ +#define GRUB_COMMAND_FLAG_BLOCKS 0x40 struct grub_command; === modified file 'include/grub/extcmd.h' --- include/grub/extcmd.h 2009-03-21 08:39:59 +0000 +++ include/grub/extcmd.h 2010-06-10 06:42:03 +0000 @@ -21,10 +21,12 @@ #include #include +#include struct grub_extcmd; +struct grub_extcmd_context; -typedef grub_err_t (*grub_extcmd_func_t) (struct grub_extcmd *cmd, +typedef grub_err_t (*grub_extcmd_func_t) (struct grub_extcmd_context *ctxt, int argc, char **args); /* The argcmd description. */ @@ -38,10 +40,20 @@ const struct grub_arg_option *options; void *data; +}; +typedef struct grub_extcmd *grub_extcmd_t; + +/* Command context for each instance of execution. */ +struct grub_extcmd_context +{ + struct grub_extcmd *extcmd; struct grub_arg_list *state; + + /* Script parameters, if any. */ + struct grub_script **script_params; }; -typedef struct grub_extcmd *grub_extcmd_t; +typedef struct grub_extcmd_context *grub_extcmd_context_t; grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, @@ -52,4 +64,8 @@ void grub_unregister_extcmd (grub_extcmd_t cmd); +grub_err_t +grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, + struct grub_script **scripts); + #endif /* ! GRUB_EXTCMD_HEADER */ === modified file 'include/grub/script_sh.h' --- include/grub/script_sh.h 2010-05-19 04:55:41 +0000 +++ include/grub/script_sh.h 2010-06-10 06:42:03 +0000 @@ -49,7 +49,8 @@ GRUB_SCRIPT_ARG_TYPE_TEXT, GRUB_SCRIPT_ARG_TYPE_DQVAR, GRUB_SCRIPT_ARG_TYPE_DQSTR, - GRUB_SCRIPT_ARG_TYPE_SQSTR + GRUB_SCRIPT_ARG_TYPE_SQSTR, + GRUB_SCRIPT_ARG_TYPE_BLOCK } grub_script_arg_type_t; /* A part of an argument. */ @@ -59,6 +60,9 @@ char *str; + /* Parsed block argument. */ + struct grub_script block; + /* Next argument part. */ struct grub_script_arg *next; }; @@ -68,6 +72,7 @@ { unsigned argc; char **args; + struct grub_script **scripts; }; /* A complete argument. It consists of a list of one or more `struct @@ -226,6 +231,8 @@ int grub_script_argv_next (struct grub_script_argv *argv); int grub_script_argv_append (struct grub_script_argv *argv, const char *s); int grub_script_argv_split_append (struct grub_script_argv *argv, char *s); +int grub_script_argv_script_append (struct grub_script_argv *argv, + struct grub_script *s); struct grub_script_arglist * grub_script_create_arglist (struct grub_parser_param *state); @@ -283,8 +290,8 @@ void grub_script_lexer_fini (struct grub_lexer_param *); void grub_script_lexer_ref (struct grub_lexer_param *); void grub_script_lexer_deref (struct grub_lexer_param *); -void grub_script_lexer_record_start (struct grub_parser_param *); -char *grub_script_lexer_record_stop (struct grub_parser_param *); +unsigned grub_script_lexer_record_start (struct grub_parser_param *); +char *grub_script_lexer_record_stop (struct grub_parser_param *, unsigned); int grub_script_lexer_yywrap (struct grub_parser_param *); void grub_script_lexer_record (struct grub_parser_param *, char *); === modified file 'loader/i386/bsd.c' --- loader/i386/bsd.c 2010-03-26 14:44:13 +0000 +++ loader/i386/bsd.c 2010-06-10 06:42:03 +0000 @@ -946,10 +946,10 @@ } static grub_err_t -grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[]) +grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) { kernel_type = KERNEL_TYPE_FREEBSD; - bootflags = grub_bsd_parse_flags (cmd->state, freebsd_flags); + bootflags = grub_bsd_parse_flags (ctxt->state, freebsd_flags); if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) { @@ -1009,16 +1009,16 @@ } static grub_err_t -grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[]) +grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) { grub_uint32_t bootdev; kernel_type = KERNEL_TYPE_OPENBSD; - bootflags = grub_bsd_parse_flags (cmd->state, openbsd_flags); + bootflags = grub_bsd_parse_flags (ctxt->state, openbsd_flags); - if (cmd->state[OPENBSD_ROOT_ARG].set) + if (ctxt->state[OPENBSD_ROOT_ARG].set) { - const char *arg = cmd->state[OPENBSD_ROOT_ARG].arg; + const char *arg = ctxt->state[OPENBSD_ROOT_ARG].arg; int unit, part; if (*(arg++) != 'w' || *(arg++) != 'd') return grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -1049,16 +1049,16 @@ } static grub_err_t -grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[]) +grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) { kernel_type = KERNEL_TYPE_NETBSD; - bootflags = grub_bsd_parse_flags (cmd->state, netbsd_flags); + bootflags = grub_bsd_parse_flags (ctxt->state, netbsd_flags); if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) { grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1); - if (cmd->state[NETBSD_ROOT_ARG].set) - netbsd_root = grub_strdup (cmd->state[NETBSD_ROOT_ARG].arg); + if (ctxt->state[NETBSD_ROOT_ARG].set) + netbsd_root = grub_strdup (ctxt->state[NETBSD_ROOT_ARG].arg); } return grub_errno; === modified file 'loader/xnu.c' --- loader/xnu.c 2010-02-07 03:23:44 +0000 +++ loader/xnu.c 2010-06-10 06:42:03 +0000 @@ -1368,15 +1368,15 @@ }; static grub_err_t -grub_cmd_xnu_splash (grub_extcmd_t cmd, +grub_cmd_xnu_splash (grub_extcmd_context_t ctxt, int argc, char *args[]) { grub_err_t err; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); - if (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && - grub_strcmp (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, + if (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && + grub_strcmp (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, "stretch") == 0) grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_STRETCH; else === modified file 'script/argv.c' --- script/argv.c 2010-05-21 10:04:36 +0000 +++ script/argv.c 2010-06-10 06:42:03 +0000 @@ -52,8 +52,17 @@ grub_free (argv->args); } + if (argv->scripts) + { + for (i = 0; i < argv->argc; i++) + grub_script_free (argv->scripts[i]); + + grub_free (argv->scripts); + } + argv->argc = 0; argv->args = 0; + argv->scripts = 0; } /* Prepare for next argc. */ @@ -61,20 +70,33 @@ grub_script_argv_next (struct grub_script_argv *argv) { char **p = argv->args; + struct grub_script **q = argv->scripts; - if (argv->args && argv->args[argv->argc - 1] == 0) + if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0) return 0; p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *))); if (! p) return 1; + q = grub_realloc (q, round_up_exp ((argv->argc + 2) * sizeof (struct grub_script *))); + if (! q) + { + grub_free (p); + return 1; + } + argv->argc++; argv->args = p; + argv->scripts = q; if (argv->argc == 1) - argv->args[0] = 0; + { + argv->args[0] = 0; + argv->scripts[0] = 0; + } argv->args[argv->argc] = 0; + argv->scripts[argv->argc] = 0; return 0; } @@ -100,6 +122,25 @@ return 0; } +/* Append grub_script `s' as the last argument. */ +int +grub_script_argv_script_append (struct grub_script_argv *argv, + struct grub_script *script) +{ + struct grub_script *s; + + s = grub_malloc (sizeof (*s)); + if (! s) + return 1; + + if (argv->scripts[argv->argc - 1]) + grub_script_free (argv->scripts[argv->argc - 1]); + + *s = *script; + argv->scripts[argv->argc - 1] = s; + return 0; +} + /* Split `s' and append words as multiple arguments. */ int grub_script_argv_split_append (struct grub_script_argv *argv, char *s) === modified file 'script/execute.c' --- script/execute.c 2010-05-21 10:13:24 +0000 +++ script/execute.c 2010-06-10 06:42:03 +0000 @@ -25,6 +25,7 @@ #include #include #include +#include /* Max digits for a char is 3 (0xFF is 255), similarly for an int it is sizeof (int) * 3, and one extra for a possible -ve sign. */ @@ -51,7 +52,7 @@ static char ** grub_script_env_get (const char *name, grub_script_arg_type_t type) { - struct grub_script_argv result = { 0, 0 }; + struct grub_script_argv result = { 0, 0, 0 }; if (grub_script_argv_next (&result)) goto fail; @@ -169,7 +170,7 @@ int i; char **values = 0; struct grub_script_arg *arg = 0; - struct grub_script_argv result = { 0, 0 }; + struct grub_script_argv result = { 0, 0, 0 }; for (; arglist && arglist->arg; arglist = arglist->next) { @@ -195,6 +196,12 @@ grub_free (values); break; + case GRUB_SCRIPT_ARG_TYPE_BLOCK: + if (grub_script_argv_append (&result, arg->str) || + grub_script_argv_script_append (&result, &arg->block)) + goto fail; + break; + case GRUB_SCRIPT_ARG_TYPE_TEXT: if (grub_strlen (arg->str) && grub_script_argv_append (&result, arg->str)) @@ -269,7 +276,7 @@ grub_script_function_t func = 0; char errnobuf[18]; char *cmdname; - struct grub_script_argv argv = { 0, 0 }; + struct grub_script_argv argv = { 0, 0, 0 }; /* Lookup the command. */ if (grub_script_arglist_to_argv (cmdline->arglist, &argv)) @@ -313,7 +320,14 @@ /* Execute the GRUB command or function. */ if (grubcmd) - ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1); + { + if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) && + (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD)) + ret = grub_extcmd_dispatcher (grubcmd, argv.argc - 1, argv.args + 1, + argv.scripts + 1); + else + ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1); + } else ret = grub_script_function_call (func, argv.argc - 1, argv.args + 1); @@ -373,7 +387,7 @@ { unsigned i; grub_err_t result; - struct grub_script_argv argv = { 0, 0 }; + struct grub_script_argv argv = { 0, 0, 0 }; struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd; if (grub_script_arglist_to_argv (cmdfor->words, &argv)) @@ -415,7 +429,7 @@ grub_script_execute_menuentry (struct grub_script_cmd *cmd) { struct grub_script_cmd_menuentry *cmd_menuentry; - struct grub_script_argv argv = { 0, 0 }; + struct grub_script_argv argv = { 0, 0, 0 }; cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd; === modified file 'script/lexer.c' --- script/lexer.c 2010-02-11 13:19:57 +0000 +++ script/lexer.c 2010-04-29 12:40:22 +0000 @@ -38,68 +38,57 @@ } /* Start recording all characters passing through the lexer. */ -void +unsigned grub_script_lexer_record_start (struct grub_parser_param *parser) { struct grub_lexer_param *lexer = parser->lexerstate; - lexer->record = 1; + lexer->record++; + if (lexer->recording) + return lexer->recordpos; + lexer->recordpos = 0; - if (lexer->recording) /* reuse last record */ - return; - lexer->recordlen = GRUB_LEXER_INITIAL_RECORD_SIZE; lexer->recording = grub_malloc (lexer->recordlen); if (!lexer->recording) { grub_script_yyerror (parser, 0); - lexer->record = 0; lexer->recordlen = 0; } + return lexer->recordpos; } char * -grub_script_lexer_record_stop (struct grub_parser_param *parser) +grub_script_lexer_record_stop (struct grub_parser_param *parser, unsigned offset) { - char *ptr; + int count; char *result; struct grub_lexer_param *lexer = parser->lexerstate; - auto char *compact (char *start, char *end); - char *compact (char *start, char *end) - { - /* Delete '{' and '}' characters and whitespaces. */ - while (*start && grub_isspace (*start)) start++; - if (*start == '{') start++; - while (*start && grub_isspace (*start)) start++; - - while (*end && grub_isspace (*end)) end--; - if (*end == '}') end--; - while (*end && grub_isspace (*end)) end--; - end[1] = '\0'; - - return start; + if (!lexer->record) + return 0; + + lexer->record--; + if (!lexer->recording) + return 0; + + count = lexer->recordpos - offset; + result = grub_script_malloc (parser, count + 1); + if (result) { + grub_strncpy (result, lexer->recording + offset, count); + result[count] = '\0'; } - if (!lexer->record || !lexer->recording) - return 0; - - /* XXX This is not necessary in BASH. */ - - ptr = compact (lexer->recording, lexer->recording + lexer->recordpos - 1); - lexer->record = 0; - lexer->recordpos = 0; - - /* This memory would be freed by, grub_script_free. */ - result = grub_script_malloc (parser, grub_strlen (ptr) + 1); - if (result) - grub_strcpy (result, ptr); - + if (lexer->record == 0) + { + grub_free (lexer->recording); + lexer->recording = 0; + lexer->recordlen = 0; + lexer->recordpos = 0; + } return result; } -#define MAX(a,b) ((a) < (b) ? (b) : (a)) - /* Record STR if input recording is enabled. */ void grub_script_lexer_record (struct grub_parser_param *parser, char *str) @@ -108,21 +97,20 @@ char *old; struct grub_lexer_param *lexer = parser->lexerstate; - if (!lexer->record) + if (!lexer->record || !lexer->recording) return; len = grub_strlen (str); if (lexer->recordpos + len + 1 > lexer->recordlen) { old = lexer->recording; - lexer->recordlen = MAX (len, lexer->recordlen) * 2; + lexer->recordlen = grub_max (len, lexer->recordlen) * 2; lexer->recording = grub_realloc (lexer->recording, lexer->recordlen); if (!lexer->recording) { grub_free (old); - lexer->record = 0; lexer->recordpos = 0; - lexer->recordlen /= 2; + lexer->recordlen = 0; grub_script_yyerror (parser, 0); return; } === modified file 'script/parser.y' --- script/parser.y 2010-05-05 08:35:06 +0000 +++ script/parser.y 2010-06-10 06:42:03 +0000 @@ -33,6 +33,10 @@ struct grub_script_arglist *arglist; struct grub_script_arg *arg; char *string; + struct { + unsigned offset; + struct grub_script_mem *memory; + }; } %token GRUB_PARSER_TOKEN_BAD @@ -73,7 +77,7 @@ %token GRUB_PARSER_TOKEN_NAME "name" %token GRUB_PARSER_TOKEN_WORD "word" -%type word argument arguments0 arguments1 +%type word argument block parameters0 parameters1 arguments0 arguments1 %type script_init script %type grubcmd ifclause ifcmd forcmd whilecmd untilcmd @@ -144,6 +148,33 @@ | word { $$ = $1; } ; +block: "{" + { + grub_script_lexer_ref (state->lexerstate); + $$ = grub_script_lexer_record_start (state); + $$ = grub_script_mem_record (state); + } + commands1 delimiters0 "}" + { + char *p; + struct grub_script_arg *arg; + struct grub_script_mem *memory; + + memory = grub_script_mem_record_stop (state, $2); + if ((p = grub_script_lexer_record_stop (state, $2))) + *grub_strrchr (p, '}') = '\0'; + + if ((arg = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p))) + { + arg->block.cmd = $3; + arg->block.mem = memory; + } + + $$ = grub_script_add_arglist (state, 0, arg); + grub_script_lexer_deref (state->lexerstate); + } +; + arguments0: /* Empty */ { $$ = 0; } | arguments1 { $$ = $1; } ; @@ -159,7 +190,32 @@ } ; -grubcmd: word arguments0 +parameters1: argument parameters0 + { + if ($1 && $2) + { + $1->next = $2; + $1->argcount += $2->argcount; + $2->argcount = 0; + } + $$ = $1; + } + | block parameters0 + { + if ($1 && $2) + { + $1->next = $2; + $1->argcount += $2->argcount; + $2->argcount = 0; + } + $$ = $1; + } +; +parameters0: /* Empty */ { $$ = 0; } + | parameters1 { $$ = $1; } +; + +grubcmd: word parameters0 { if ($1 && $2) { $1->next = $2; @@ -213,14 +269,16 @@ } arguments1 { - grub_script_lexer_record_start (state); + $$ = grub_script_lexer_record_start (state); } delimiters0 "{" commands1 delimiters1 "}" { - char *menu_entry; - menu_entry = grub_script_lexer_record_stop (state); + 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, menu_entry, 0); + $$ = grub_script_create_cmdmenu (state, $3, def, 0); } ; === modified file 'script/script.c' --- script/script.c 2010-05-05 08:35:06 +0000 +++ script/script.c 2010-06-10 06:42:03 +0000 @@ -96,7 +96,10 @@ { if (!script) return; - grub_script_mem_free (script->mem); + + if (script->mem) + grub_script_mem_free (script->mem); + grub_free (script); } @@ -119,6 +122,9 @@ return arg; argpart->type = type; + argpart->block.mem = 0; + argpart->block.cmd = 0; + len = grub_strlen (str) + 1; argpart->str = grub_script_malloc (state, len); if (!argpart->str) === modified file 'term/gfxterm.c' --- term/gfxterm.c 2010-05-01 18:28:07 +0000 +++ term/gfxterm.c 2010-06-10 06:42:03 +0000 @@ -1091,11 +1091,10 @@ }; static grub_err_t -grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)), - int argc, - char **args) +grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, + int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; /* Check that we have video adapter active. */ if (grub_video_get_info(NULL) != GRUB_ERR_NONE) === modified file 'term/serial.c' --- term/serial.c 2010-05-01 18:28:07 +0000 +++ term/serial.c 2010-06-10 06:42:03 +0000 @@ -497,11 +497,11 @@ static grub_err_t -grub_cmd_serial (grub_extcmd_t cmd, +grub_cmd_serial (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; struct serial_port backup_settings = serial_settings; grub_err_t hwiniterr; === modified file 'tests/lib/functional_test.c' --- tests/lib/functional_test.c 2010-01-17 17:29:57 +0000 +++ tests/lib/functional_test.c 2010-06-10 06:42:03 +0000 @@ -22,7 +22,7 @@ #include static grub_err_t -grub_functional_test (struct grub_extcmd *cmd __attribute__ ((unused)), +grub_functional_test (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { # Begin bundle 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