1
/* arg.c - argument parser */
3
* GRUB -- GRand Unified Bootloader
4
* Copyright (C) 2003,2004,2005,2007,2008 Free Software Foundation, Inc.
6
* GRUB is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* GRUB is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20
#include <grub/misc.h>
23
#include <grub/term.h>
24
#include <grub/extcmd.h>
25
#include <grub/i18n.h>
27
/* Built-in parser for default options. */
28
#define SHORT_ARG_HELP -100
29
#define SHORT_ARG_USAGE -101
31
static const struct grub_arg_option help_options[] =
33
{"help", SHORT_ARG_HELP, 0,
34
N_("Display this help and exit."), 0, ARG_TYPE_NONE},
35
{"usage", SHORT_ARG_USAGE, 0,
36
N_("Display the usage of this command and exit."), 0, ARG_TYPE_NONE},
40
static struct grub_arg_option *
41
find_short (const struct grub_arg_option *options, char c)
43
struct grub_arg_option *found = 0;
44
auto struct grub_arg_option *fnd_short (const struct grub_arg_option *opt);
46
struct grub_arg_option *fnd_short (const struct grub_arg_option *opt)
50
if (opt->shortarg == c)
51
return (struct grub_arg_option *) opt;
58
found = fnd_short (options);
65
found = (struct grub_arg_option *) help_options;
69
found = (struct grub_arg_option *) (help_options + 1);
80
static struct grub_arg_option *
81
find_long (const struct grub_arg_option *options, const char *s, int len)
83
struct grub_arg_option *found = 0;
84
auto struct grub_arg_option *fnd_long (const struct grub_arg_option *opt);
86
struct grub_arg_option *fnd_long (const struct grub_arg_option *opt)
90
if (opt->longarg && ! grub_strncmp (opt->longarg, s, len) &&
91
opt->longarg[len] == '\0')
92
return (struct grub_arg_option *) opt;
99
found = fnd_long (options);
102
found = fnd_long (help_options);
108
show_usage (grub_extcmd_t cmd)
110
grub_printf ("%s %s %s\n", _("Usage:"), cmd->cmd->name, _(cmd->cmd->summary));
114
grub_arg_show_help (grub_extcmd_t cmd)
116
auto void showargs (const struct grub_arg_option *opt);
120
auto void showargs (const struct grub_arg_option *opt)
122
for (; opt->doc; opt++)
126
if (opt->shortarg && grub_isgraph (opt->shortarg))
127
grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' ');
128
else if (opt->shortarg == SHORT_ARG_HELP && ! h_is_used)
129
grub_printf ("-h, ");
130
else if (opt->shortarg == SHORT_ARG_USAGE && ! u_is_used)
131
grub_printf ("-u, ");
137
grub_printf ("--%s", opt->longarg);
138
spacing -= grub_strlen (opt->longarg) + 2;
142
grub_printf ("=%s", opt->arg);
143
spacing -= grub_strlen (opt->arg) + 1;
147
const char *doc = _(opt->doc);
150
while (spacing-- > 0)
153
while (*doc && *doc != '\n')
154
grub_putchar (*doc++);
163
switch (opt->shortarg)
180
grub_printf ("%s\n\n", _(cmd->cmd->description));
182
showargs (cmd->options);
183
showargs (help_options);
185
grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
191
parse_option (grub_extcmd_t cmd, int key, char *arg, struct grub_arg_list *usr)
196
grub_arg_show_help (cmd);
199
case SHORT_ARG_USAGE:
207
const struct grub_arg_option *opt = cmd->options;
211
if (opt->shortarg && key == opt->shortarg)
224
usr[found].arg = arg;
232
grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
233
struct grub_arg_list *usr, char ***args, int *argnum)
240
auto grub_err_t add_arg (char *s);
242
grub_err_t add_arg (char *s)
244
argl = grub_realloc (argl, (++num) * sizeof (char *));
252
for (curarg = 0; curarg < argc; curarg++)
254
char *arg = argv[curarg];
255
struct grub_arg_option *opt;
258
/* No option is used. */
259
if (arg[0] != '-' || grub_strlen (arg) == 1)
261
if (add_arg (arg) != 0)
267
/* One or more short options. */
270
char *curshort = arg + 1;
274
opt = find_short (cmd->options, *curshort);
277
grub_error (GRUB_ERR_BAD_ARGUMENT,
278
"unknown argument `-%c'", *curshort);
284
/* Parse all arguments here except the last one because
285
it can have an argument value. */
288
if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)
293
if (opt->type != ARG_TYPE_NONE)
295
if (curarg + 1 < argc)
297
char *nextarg = argv[curarg + 1];
298
if (!(opt->flags & GRUB_ARG_OPTION_OPTIONAL)
299
|| (grub_strlen (nextarg) < 2 || nextarg[0] != '-'))
300
option = argv[++curarg];
308
else /* The argument starts with "--". */
310
/* If the argument "--" is used just pass the other
312
if (grub_strlen (arg) == 2)
314
for (curarg++; curarg < argc; curarg++)
315
if (add_arg (argv[curarg]) != 0)
320
option = grub_strchr (arg, '=');
322
arglen = option - arg - 2;
325
arglen = grub_strlen (arg) - 2;
327
opt = find_long (cmd->options, arg + 2, arglen);
330
grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown argument `%s'", arg);
335
if (! (opt->type == ARG_TYPE_NONE
336
|| (! option && (opt->flags & GRUB_ARG_OPTION_OPTIONAL))))
340
grub_error (GRUB_ERR_BAD_ARGUMENT,
341
"missing mandatory option for `%s'", opt->longarg);
348
/* This will never happen. */
351
case ARG_TYPE_STRING:
352
/* No need to do anything. */
359
grub_strtoull (option, &tail, 0);
360
if (tail == 0 || tail == option || *tail != '\0' || grub_errno)
362
grub_error (GRUB_ERR_BAD_ARGUMENT,
363
"the argument `%s' requires an integer",
371
case ARG_TYPE_DEVICE:
374
case ARG_TYPE_PATHNAME:
375
/* XXX: Not implemented. */
378
if (parse_option (cmd, opt->shortarg, option, usr) || grub_errno)
385
grub_error (GRUB_ERR_BAD_ARGUMENT,
386
"a value was assigned to the argument `%s' while it "
387
"doesn't require an argument", arg);
391
if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)