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;
150
grub_printf ("%s\n", _(opt->doc));
152
switch (opt->shortarg)
169
grub_printf ("%s\n\n", _(cmd->cmd->description));
171
showargs (cmd->options);
172
showargs (help_options);
174
grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
180
parse_option (grub_extcmd_t cmd, int key, char *arg, struct grub_arg_list *usr)
185
grub_arg_show_help (cmd);
188
case SHORT_ARG_USAGE:
196
const struct grub_arg_option *opt = cmd->options;
200
if (opt->shortarg && key == opt->shortarg)
213
usr[found].arg = arg;
221
grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv,
222
struct grub_arg_list *usr, char ***args, int *argnum)
229
auto grub_err_t add_arg (char *s);
231
grub_err_t add_arg (char *s)
233
argl = grub_realloc (argl, (++num) * sizeof (char *));
241
for (curarg = 0; curarg < argc; curarg++)
243
char *arg = argv[curarg];
244
struct grub_arg_option *opt;
247
/* No option is used. */
248
if (arg[0] != '-' || grub_strlen (arg) == 1)
250
if (add_arg (arg) != 0)
256
/* One or more short options. */
259
char *curshort = arg + 1;
263
opt = find_short (cmd->options, *curshort);
266
grub_error (GRUB_ERR_BAD_ARGUMENT,
267
"unknown argument `-%c'", *curshort);
273
/* Parse all arguments here except the last one because
274
it can have an argument value. */
277
if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)
282
if (opt->type != ARG_TYPE_NONE)
284
if (curarg + 1 < argc)
286
char *nextarg = argv[curarg + 1];
287
if (!(opt->flags & GRUB_ARG_OPTION_OPTIONAL)
288
|| (grub_strlen (nextarg) < 2 || nextarg[0] != '-'))
289
option = argv[++curarg];
297
else /* The argument starts with "--". */
299
/* If the argument "--" is used just pass the other
301
if (grub_strlen (arg) == 2)
303
for (curarg++; curarg < argc; curarg++)
304
if (add_arg (argv[curarg]) != 0)
309
option = grub_strchr (arg, '=');
311
arglen = option - arg - 2;
314
arglen = grub_strlen (arg) - 2;
316
opt = find_long (cmd->options, arg + 2, arglen);
319
grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown argument `%s'", arg);
324
if (! (opt->type == ARG_TYPE_NONE
325
|| (! option && (opt->flags & GRUB_ARG_OPTION_OPTIONAL))))
329
grub_error (GRUB_ERR_BAD_ARGUMENT,
330
"missing mandatory option for `%s'", opt->longarg);
337
/* This will never happen. */
340
case ARG_TYPE_STRING:
341
/* No need to do anything. */
348
grub_strtoull (option, &tail, 0);
349
if (tail == 0 || tail == option || *tail != '\0' || grub_errno)
351
grub_error (GRUB_ERR_BAD_ARGUMENT,
352
"the argument `%s' requires an integer",
360
case ARG_TYPE_DEVICE:
363
case ARG_TYPE_PATHNAME:
364
/* XXX: Not implemented. */
367
if (parse_option (cmd, opt->shortarg, option, usr) || grub_errno)
374
grub_error (GRUB_ERR_BAD_ARGUMENT,
375
"a value was assigned to the argument `%s' while it "
376
"doesn't require an argument", arg);
380
if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)