# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: address@hidden # target_branch: ../cmdlist/ # testament_sha1: fce09d768b00aad9c9ecd97dec45e31041b6cc9c # timestamp: 2010-07-22 22:50:07 +0530 # base_revision_id: address@hidden # q6dgo7psbg1vzkkd # # Begin patch === modified file 'commands/acpi.c' --- commands/acpi.c 2010-07-20 12:42:32 +0000 +++ commands/acpi.c 2010-07-22 17:09:42 +0000 @@ -458,10 +458,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/cat.c' --- commands/cat.c 2010-07-02 17:35:07 +0000 +++ commands/cat.c 2010-07-12 11:59:44 +0000 @@ -33,9 +33,9 @@ }; static grub_err_t -grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int dos = 0; grub_file_t file; char buf[GRUB_DISK_SECTOR_SIZE]; === 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-07-21 23:35:49 +0000 @@ -21,20 +21,31 @@ #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 *script) { 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; - - ext = cmd->data; + grub_extcmd_t ext = cmd->data; + + context.state = 0; + context.extcmd = ext; + context.script = script; + + if (! ext->options) + { + ret = (ext->func) (&context, argc, args); + return ret; + } + parser = (struct grub_arg_option *) ext->options; while (parser && (parser++)->doc) maxargs++; @@ -44,8 +55,8 @@ if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc)) { - ext->state = state; - ret = (ext->func) (ext, new_argc, new_args); + context.state = state; + ret = (ext->func) (&context, new_argc, new_args); grub_free (new_args); } else @@ -56,11 +67,18 @@ 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, - const char *description, - const struct grub_arg_option *parser) +grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, + unsigned flags, const char *summary, + const char *description, + const struct grub_arg_option *parser, + int prio) { grub_extcmd_t ext; grub_command_t cmd; @@ -69,8 +87,8 @@ if (! ext) return 0; - cmd = grub_register_command_prio (name, grub_extcmd_dispatcher, - summary, description, 1); + cmd = grub_register_command_prio (name, grub_extcmd_dispatch, + summary, description, prio); if (! cmd) { grub_free (ext); @@ -88,6 +106,16 @@ return ext; } +grub_extcmd_t +grub_register_extcmd (const char *name, grub_extcmd_func_t func, + unsigned flags, const char *summary, + const char *description, + const struct grub_arg_option *parser) +{ + return grub_register_extcmd_prio (name, func, flags, + summary, description, parser, 1); +} + void grub_unregister_extcmd (grub_extcmd_t ext) { === 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-07-10 00:40:41 +0000 +++ commands/help.c 2010-07-12 11:59:44 +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-03-15 10:49:27 +0000 +++ commands/ls.c 2010-07-12 11:59:44 +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-31 18:40:42 +0000 +++ commands/setpci.c 2010-06-10 16:17:25 +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-07-20 21:14:26 +0000 +++ disk/loopback.c 2010-07-22 17:09:42 +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; grub_err_t ret; === modified file 'hello/hello.c' --- hello/hello.c 2010-01-03 18:50:51 +0000 +++ hello/hello.c 2010-07-18 15:30:58 +0000 @@ -27,7 +27,7 @@ #include static grub_err_t -grub_cmd_hello (struct grub_extcmd *cmd __attribute__ ((unused)), +grub_cmd_hello (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { === modified file 'include/grub/command.h' --- include/grub/command.h 2010-03-26 18:32:21 +0000 +++ include/grub/command.h 2010-06-13 04:28:24 +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-07-20 22:17:30 +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 parameter, if any. */ + struct grub_script *script; }; -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, @@ -50,6 +62,18 @@ const char *description, const struct grub_arg_option *parser); +grub_extcmd_t grub_register_extcmd_prio (const char *name, + grub_extcmd_func_t func, + unsigned flags, + const char *summary, + const char *description, + const struct grub_arg_option *parser, + int prio); + 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 *script); + #endif /* ! GRUB_EXTCMD_HEADER */ === modified file 'include/grub/script_sh.h' --- include/grub/script_sh.h 2010-06-12 11:02:06 +0000 +++ include/grub/script_sh.h 2010-07-21 23:33:49 +0000 @@ -39,8 +39,13 @@ struct grub_script { + unsigned refcnt; struct grub_script_mem *mem; struct grub_script_cmd *cmd; + + /* Other grub_script's from block arguments. */ + struct grub_script *siblings; + struct grub_script *children; }; typedef enum @@ -49,7 +54,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 +65,9 @@ char *str; + /* Parsed block argument. */ + struct grub_script *script; + /* Next argument part. */ struct grub_script_arg *next; }; @@ -68,6 +77,7 @@ { unsigned argc; char **args; + struct grub_script *script; }; /* A complete argument. It consists of a list of one or more `struct @@ -216,12 +226,17 @@ /* The memory that was used while parsing and scanning. */ struct grub_script_mem *memused; + /* The block argument scripts. */ + struct grub_script *scripts; + /* The result of the parser. */ struct grub_script_cmd *parsed; struct grub_lexer_param *lexerstate; }; +void grub_script_mem_free (struct grub_script_mem *mem); + void grub_script_argv_free (struct grub_script_argv *argv); int grub_script_argv_next (struct grub_script_argv *argv); int grub_script_argv_append (struct grub_script_argv *argv, const char *s); @@ -283,8 +298,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 *); @@ -355,4 +370,24 @@ 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) +{ + if (script) + script->refcnt++; + return script; +} + +static inline void +grub_script_put (struct grub_script *script) +{ + if (! script) + return; + + if (script->refcnt == 0) + grub_script_free (script); + else + script->refcnt--; +} + #endif /* ! GRUB_NORMAL_PARSER_HEADER */ === 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 'normal/dyncmd.c' --- normal/dyncmd.c 2010-04-09 19:07:24 +0000 +++ normal/dyncmd.c 2010-07-20 22:17:30 +0000 @@ -23,16 +23,21 @@ #include #include #include +#include +#include #include static grub_err_t -grub_dyncmd_dispatcher (struct grub_command *cmd, +grub_dyncmd_dispatcher (struct grub_extcmd_context *ctxt, int argc, char **args) { - char *modname = cmd->data; + char *modname; grub_dl_t mod; grub_err_t ret; + grub_extcmd_t extcmd = ctxt->extcmd; + grub_command_t cmd = extcmd->cmd; + modname = extcmd->data; mod = grub_dl_load (modname); if (mod) { @@ -42,11 +47,17 @@ grub_dl_ref (mod); name = (char *) cmd->name; - grub_unregister_command (cmd); + grub_unregister_extcmd (extcmd); cmd = grub_command_find (name); if (cmd) - ret = (cmd->func) (cmd, argc, args); + { + if (cmd->flags & GRUB_COMMAND_FLAG_BLOCKS && + cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) + ret = grub_extcmd_dispatcher (cmd, argc, args, ctxt->script); + else + ret = (cmd->func) (cmd, argc, args); + } else ret = grub_errno; @@ -81,13 +92,14 @@ for (ptr = grub_command_list; ptr; ptr = next) { next = ptr->next; - if (ptr->func == grub_dyncmd_dispatcher) + if (ptr->flags & GRUB_COMMAND_FLAG_DYNCMD) { if (last) last->next = ptr->next; else grub_command_list = ptr->next; grub_free (ptr); + grub_free (ptr->data); /* extcmd struct */ } else last = ptr; @@ -96,7 +108,7 @@ for (;; grub_free (buf)) { char *p, *name, *modname; - grub_command_t cmd; + grub_extcmd_t cmd; int prio = 0; buf = grub_file_getline (file); @@ -139,16 +151,19 @@ continue; } - cmd = grub_register_command_prio (name, - grub_dyncmd_dispatcher, - 0, N_("not loaded"), prio); + cmd = grub_register_extcmd_prio (name, + grub_dyncmd_dispatcher, + GRUB_COMMAND_FLAG_BLOCKS + | GRUB_COMMAND_FLAG_EXTCMD + | GRUB_COMMAND_FLAG_DYNCMD, + 0, N_("not loaded"), 0, + prio); if (! cmd) { grub_free (name); grub_free (modname); continue; } - cmd->flags |= GRUB_COMMAND_FLAG_DYNCMD; cmd->data = modname; /* Update the active flag. */ === modified file 'script/argv.c' --- script/argv.c 2010-05-21 10:04:36 +0000 +++ script/argv.c 2010-07-21 23:19:05 +0000 @@ -18,6 +18,7 @@ */ #include +#include #include static unsigned @@ -51,9 +52,12 @@ grub_free (argv->args); } + if (argv->script) + grub_script_put (argv->script); argv->argc = 0; argv->args = 0; + argv->script = 0; } /* Prepare for next argc. */ @@ -62,7 +66,7 @@ { char **p = argv->args; - 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 *))); === modified file 'script/execute.c' --- script/execute.c 2010-05-21 10:13:24 +0000 +++ script/execute.c 2010-07-21 23:19:05 +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,14 @@ grub_free (values); break; + case GRUB_SCRIPT_ARG_TYPE_BLOCK: + if (grub_script_argv_append (&result, "{") || + grub_script_argv_append (&result, arg->str) || + grub_script_argv_append (&result, "}")) + goto fail; + result.script = grub_script_get (arg->script); + break; + case GRUB_SCRIPT_ARG_TYPE_TEXT: if (grub_strlen (arg->str) && grub_script_argv_append (&result, arg->str)) @@ -269,7 +278,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 +322,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.script); + 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 +389,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 +431,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/main.c' --- script/main.c 2010-03-26 23:19:42 +0000 +++ script/main.c 2010-07-21 23:19:05 +0000 @@ -34,7 +34,7 @@ grub_script_execute (parsed_script); /* The parsed script was executed, throw it away. */ - grub_script_free (parsed_script); + grub_script_put (parsed_script); } return grub_errno; === modified file 'script/parser.y' --- script/parser.y 2010-07-11 15:44:18 +0000 +++ script/parser.y 2010-07-22 17:20:04 +0000 @@ -20,6 +20,7 @@ %{ #include #include +#include #define YYFREE grub_free #define YYMALLOC grub_malloc @@ -34,6 +35,11 @@ struct grub_script_arglist *arglist; struct grub_script_arg *arg; char *string; + struct { + unsigned offset; + struct grub_script_mem *memory; + struct grub_script *scripts; + }; } %token GRUB_PARSER_TOKEN_BAD @@ -74,6 +80,7 @@ %token GRUB_PARSER_TOKEN_NAME "name" %token GRUB_PARSER_TOKEN_WORD "word" +%type block block0 %type word argument arguments0 arguments1 %type script_init script @@ -146,6 +153,74 @@ | word { $$ = $1; } ; +/* + Block parameter is passed to commands in two forms: as unparsed + string and as pre-parsed grub_script object. Passing as grub_script + object makes memory management difficult, because: + + (1) Command may want to keep a reference to grub_script objects for + later use, so script framework may not free the grub_script + object after command completes. + + (2) Command may get called multiple times with same grub_script + object under loops, so we should not let command implementation + to free the grub_script object. + + To solve above problems, we rely on reference counting for + grub_script objects. Commands that want to keep the grub_script + object must take a reference to it. + + Other complexity comes with arbitrary nesting of grub_script + objects: a grub_script object may have commands with several block + parameters, and each block parameter may further contain multiple + block parameters nested. We use temporary variable, state->scripts + to collect nested child scripts (that are linked by siblings and + children members), and will build grub_scripts tree from bottom. + */ +block: "{" + { + grub_script_lexer_ref (state->lexerstate); + $$ = grub_script_lexer_record_start (state); + $$ = grub_script_mem_record (state); + + /* save currently known scripts. */ + $$ = state->scripts; + state->scripts = 0; + } + commands1 delimiters0 "}" + { + char *p; + struct grub_script_mem *memory; + struct grub_script *s = $2; + + memory = grub_script_mem_record_stop (state, $2); + if ((p = grub_script_lexer_record_stop (state, $2))) + *grub_strrchr (p, '}') = '\0'; + + $$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p); + if (! $$ || ! ($$->script = grub_script_create ($3, memory))) + grub_script_mem_free (memory); + + else { + /* attach nested scripts to $$->script as children */ + $$->script->children = state->scripts; + + /* restore old scripts; append $$->script to siblings. */ + state->scripts = $2 ?: $$->script; + if (s) { + while (s->siblings) + s = s->siblings; + s->siblings = $$->script; + } + } + + grub_script_lexer_deref (state->lexerstate); + } +; +block0: /* Empty */ { $$ = 0; } + | block { $$ = $1; } +; + arguments0: /* Empty */ { $$ = 0; } | arguments1 { $$ = $1; } ; @@ -161,12 +236,17 @@ } ; -grubcmd: word arguments0 +grubcmd: word arguments0 block0 { - if ($1 && $2) { - $1->next = $2; - $1->argcount += $2->argcount; - $2->argcount = 0; + struct grub_script_arglist *x = $2; + + if ($3) + x = grub_script_add_arglist (state, $2, $3); + + if ($1 && x) { + $1->next = x; + $1->argcount += x->argcount; + x->argcount = 0; } $$ = grub_script_create_cmdline (state, $1); } @@ -191,10 +271,13 @@ } ; -function: "function" "name" +function: "function" "name" { grub_script_lexer_ref (state->lexerstate); state->func_mem = grub_script_mem_record (state); + + $$ = state->scripts; + state->scripts = 0; } delimiters0 "{" commands1 delimiters1 "}" { @@ -202,9 +285,14 @@ state->func_mem = grub_script_mem_record_stop (state, state->func_mem); script = grub_script_create ($6, state->func_mem); - if (script) - grub_script_function_create ($2, script); + if (! script) + grub_script_mem_free (state->func_mem); + else { + script->children = state->scripts; + grub_script_function_create ($2, script); + } + state->scripts = $3; grub_script_lexer_deref (state->lexerstate); } ; @@ -215,14 +303,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-07-22 15:43:45 +0000 @@ -54,7 +54,7 @@ } /* Free all memory described by MEM. */ -static void +void grub_script_mem_free (struct grub_script_mem *mem) { struct grub_script_mem *memfree; @@ -94,9 +94,21 @@ void grub_script_free (struct grub_script *script) { - if (!script) + struct grub_script *s; + struct grub_script *t; + + if (! script) return; - grub_script_mem_free (script->mem); + + if (script->mem) + grub_script_mem_free (script->mem); + + s = script->children; + while (s) { + t = s->siblings; + grub_script_put (s); + s = t; + } grub_free (script); } @@ -119,6 +131,8 @@ return arg; argpart->type = type; + argpart->script = 0; + len = grub_strlen (str) + 1; argpart->str = grub_script_malloc (state, len); if (!argpart->str) @@ -335,16 +349,14 @@ struct grub_script *parsed; parsed = grub_malloc (sizeof (*parsed)); - if (!parsed) - { - grub_script_mem_free (mem); - grub_free (cmd); - - return 0; - } + if (! parsed) + return 0; parsed->mem = mem; parsed->cmd = cmd; + parsed->refcnt = 0; + parsed->siblings = 0; + parsed->children = 0; return parsed; } @@ -359,7 +371,7 @@ struct grub_lexer_param *lexstate; struct grub_parser_param *parsestate; - parsed = grub_malloc (sizeof (*parsed)); + parsed = grub_script_create (0, 0); if (!parsed) return 0; @@ -393,6 +405,7 @@ parsed->mem = grub_script_mem_record_stop (parsestate, membackup); parsed->cmd = parsestate->parsed; + parsed->children = parsestate->scripts; grub_script_lexer_fini (lexstate); grub_free (parsestate); === modified file 'term/gfxterm.c' --- term/gfxterm.c 2010-07-07 13:12:16 +0000 +++ term/gfxterm.c 2010-07-12 11:59:44 +0000 @@ -1111,11 +1111,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-07-02 17:35:07 +0000 +++ term/serial.c 2010-07-12 11:59:44 +0000 @@ -236,11 +236,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-03-26 18:32:21 +0000 +++ tests/lib/functional_test.c 2010-06-13 04:28:24 +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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 Ngdh/7Mp/nIEpH/8XckU4UJB3TTLqA==