is sizeof (int) * 3, and one extra for a possible -ve sign. */
#define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1)
+ /* Scope for grub script functions. */
+ struct grub_script_scope
+ {
+ struct grub_script_argv argv;
+ };
static struct grub_script_scope *scope = 0;
- if (*p != '\0')
+grub_err_t
+grub_script_cmd_shift (grub_command_t cmd __attribute__((unused)),
+ int argc, char *argv[])
+{
+ char *p = 0;
+ unsigned long n = 0;
+
+ if (! scope)
+ return GRUB_ERR_NONE;
+
++ if (scope->argv.argc == 0)
++ return GRUB_ERR_NONE;
++
+ if (argc == 0)
+ n = 1;
++
+ else if (argc > 1)
+ return GRUB_ERR_BAD_ARGUMENT;
++
+ else
+ {
+ n = grub_strtoul (argv[0], &p, 10);
- scope->shift = (unsigned int)(n > scope->argc ? 0 : n);
++ if (*p != '\0' || n > scope->argv.argc)
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
- static char *
- grub_script_env_get (const char *name)
++ scope->argv.argc -= n;
++ scope->argv.args += n;
+ return GRUB_ERR_NONE;
+}
+
+ static int
+ grub_env_special (const char *name)
{
- char *p = 0;
- unsigned long num = 0;
+ if (grub_isdigit (name[0]) ||
+ grub_strcmp (name, "#") == 0 ||
+ grub_strcmp (name, "*") == 0 ||
+ grub_strcmp (name, "@") == 0)
+ return 1;
+ return 0;
+ }
- if (! scope)
- return grub_env_get (name);
+ static char **
+ grub_script_env_get (const char *name, grub_script_arg_type_t type)
+ {
+ int errors = 0;
+ struct grub_script_argv result = { 0, 0 };
+
+ errors += grub_script_argv_next (&result);
+ if (! grub_env_special (name))
+ {
+ char *v = grub_env_get (name);
+ if (v && v[0])
+ {
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ errors += grub_script_argv_split_append (&result, v);
+ else
+ errors += grub_script_argv_append (&result, v);
+ }
+ }
+ else if (! scope)
+ errors += grub_script_argv_append (&result, 0);
- if (grub_isdigit (name[0]))
+ else if (grub_strcmp (name, "#") == 0)
{
- num = grub_strtoul (name, &p, 10);
- if (p && *p == '\0')
+ char buffer[ERRNO_DIGITS_MAX + 1];
+ grub_snprintf (buffer, sizeof (buffer), "%u", scope->argv.argc);
+ errors += grub_script_argv_append (&result, buffer);
+ }
+ else if (grub_strcmp (name, "*") == 0)
+ {
- int i;
++ unsigned i;
+
+ for (i = 0; ! errors && i < scope->argv.argc; i++)
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ {
+ if (i != 0)
+ errors += grub_script_argv_next (&result);
+ errors += grub_script_argv_split_append (&result,
+ scope->argv.args[i]);
+ }
+ else
+ {
+ if (i != 0)
+ errors += grub_script_argv_append (&result, " ");
+ errors += grub_script_argv_append (&result,
+ scope->argv.args[i]);
+ }
+ }
+ else if (grub_strcmp (name, "@") == 0)
+ {
- int i;
++ unsigned i;
+
+ for (i = 0; ! errors && i < scope->argv.argc; i++)
{
- if (num == 0)
- return 0; /* XXX no file name, for now. */
+ if (i != 0)
+ errors += grub_script_argv_next (&result);
- if (num > scope->argc - scope->shift)
- return 0;
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ errors += grub_script_argv_split_append (&result,
+ scope->argv.args[i]);
else
- return scope->args[num - 1 + scope->shift];
+ errors += grub_script_argv_append (&result,
+ scope->argv.args[i]);
}
- else
+ }
+ else
+ {
+ unsigned long num = grub_strtoul (name, 0, 10);
+ if (num == 0)
+ ; /* XXX no file name, for now. */
+
+ else if (num <= scope->argv.argc)
{
- grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variabe name substitution");
- return 0;
+ if (type == GRUB_SCRIPT_ARG_TYPE_VAR)
+ errors += grub_script_argv_split_append (&result,
+ scope->argv.args[num - 1]);
+ else
+ errors += grub_script_argv_append (&result,
+ scope->argv.args[num - 1]);
}
}
- else if (grub_strcmp (name, "#") == 0)
+
+ if (errors)
{
- static char buf[32]; /* Rewritten everytime. */
- grub_snprintf (buf, sizeof (buf), "%u", scope->argc - scope->shift);
- return buf;
+ grub_script_argv_free (&result);
+ return 0;
}
- else
- return grub_env_get (name);
+
+ return result.args;
}
static grub_err_t
grub_err_t
grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
{
-- int i;
++ unsigned i;
int result;
- char **args;
- int argcount;
+ struct grub_script_argv argv;
struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd;
- args = grub_script_execute_arglist_to_argv (cmdfor->words, &argcount);
- if (!args)
+ if (grub_script_arglist_to_argv (cmdfor->words, &argv))
return grub_errno;
result = 0;