1
/* arg.c - argument parser */
3
* GRUB -- GRand Unified Bootloader
4
* Copyright (C) 2003,2004,2005 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 2 of the License, or
9
* (at your option) any later version.
11
* This program 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, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
#include <grub/misc.h>
25
#include <grub/normal.h>
26
#include <grub/term.h>
28
/* Built-in parser for default options. */
29
#define SHORT_ARG_HELP -100
30
#define SHORT_ARG_USAGE -101
32
static const struct grub_arg_option help_options[] =
34
{"help", SHORT_ARG_HELP, 0,
35
"display this help and exit", 0, ARG_TYPE_NONE},
36
{"usage", SHORT_ARG_USAGE, 0,
37
"display the usage of this command and exit", 0, ARG_TYPE_NONE},
41
static struct grub_arg_option *
42
find_short (const struct grub_arg_option *options, char c)
44
struct grub_arg_option *found = 0;
45
auto struct grub_arg_option *fnd_short (const struct grub_arg_option *opt);
47
struct grub_arg_option *fnd_short (const struct grub_arg_option *opt)
51
if (opt->shortarg == c)
52
return (struct grub_arg_option *) opt;
59
found = fnd_short (options);
66
found = (struct grub_arg_option *) help_options;
70
found = (struct grub_arg_option *) (help_options + 1);
82
find_long_option (char *s)
84
char *argpos = grub_strchr (s, '=');
94
static struct grub_arg_option *
95
find_long (const struct grub_arg_option *options, char *s)
97
struct grub_arg_option *found = 0;
98
auto struct grub_arg_option *fnd_long (const struct grub_arg_option *opt);
100
struct grub_arg_option *fnd_long (const struct grub_arg_option *opt)
104
if (opt->longarg && ! grub_strcmp (opt->longarg, s))
105
return (struct grub_arg_option *) opt;
112
found = fnd_long (options);
115
found = fnd_long (help_options);
121
show_usage (grub_command_t cmd)
123
grub_printf ("Usage: %s\n", cmd->summary);
127
grub_arg_show_help (grub_command_t cmd)
129
auto void showargs (const struct grub_arg_option *opt);
133
auto void showargs (const struct grub_arg_option *opt)
135
for (; opt->doc; opt++)
139
if (opt->shortarg && grub_isgraph (opt->shortarg))
140
grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' ');
141
else if (opt->shortarg == SHORT_ARG_HELP && ! h_is_used)
142
grub_printf ("-h, ");
143
else if (opt->shortarg == SHORT_ARG_USAGE && ! u_is_used)
144
grub_printf ("-u, ");
150
grub_printf ("--%s", opt->longarg);
151
spacing -= grub_strlen (opt->longarg);
155
grub_printf ("=%s", opt->arg);
156
spacing -= grub_strlen (opt->arg) + 1;
160
while (spacing-- > 0)
163
grub_printf ("%s\n", opt->doc);
165
switch (opt->shortarg)
182
grub_printf ("%s\n\n", cmd->description);
184
showargs (cmd->options);
185
showargs (help_options);
187
grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
193
parse_option (grub_command_t cmd, int key, char *arg, struct grub_arg_list *usr)
198
grub_arg_show_help (cmd);
201
case SHORT_ARG_USAGE:
209
const struct grub_arg_option *opt = cmd->options;
213
if (opt->shortarg && key == opt->shortarg)
226
usr[found].arg = arg;
234
grub_arg_parse (grub_command_t cmd, int argc, char **argv,
235
struct grub_arg_list *usr, char ***args, int *argnum)
242
auto grub_err_t add_arg (char *s);
244
grub_err_t add_arg (char *s)
246
argl = grub_realloc (argl, (++num) * sizeof (char *));
254
for (curarg = 0; curarg < argc; curarg++)
256
char *arg = argv[curarg];
257
struct grub_arg_option *opt;
260
/* No option is used. */
261
if (arg[0] != '-' || grub_strlen (arg) == 1)
263
if (add_arg (arg) != 0)
269
/* One or more short options. */
272
char *curshort = arg + 1;
276
opt = find_short (cmd->options, *curshort);
279
grub_error (GRUB_ERR_BAD_ARGUMENT,
280
"Unknown argument `-%c'\n", *curshort);
286
/* Parse all arguments here except the last one because
287
it can have an argument value. */
290
if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)
295
if (opt->type != ARG_TYPE_NONE)
297
if (curarg + 1 < argc)
299
char *nextarg = argv[curarg + 1];
300
if (!(opt->flags & GRUB_ARG_OPTION_OPTIONAL)
301
|| (grub_strlen (nextarg) < 2 || nextarg[0] != '-'))
302
option = argv[++curarg];
310
else /* The argument starts with "--". */
312
/* If the argument "--" is used just pass the other
314
if (grub_strlen (arg) == 2)
316
for (curarg++; curarg < argc; curarg++)
317
if (add_arg (arg) != 0)
322
longarg = (char *) grub_strdup (arg);
326
option = find_long_option (longarg);
329
opt = find_long (cmd->options, arg + 2);
332
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown argument `%s'\n", arg);
337
if (! (opt->type == ARG_TYPE_NONE
338
|| (! option && (opt->flags & GRUB_ARG_OPTION_OPTIONAL))))
342
grub_error (GRUB_ERR_BAD_ARGUMENT,
343
"Missing mandatory option for `%s'\n", opt->longarg);
350
/* This will never happen. */
353
case ARG_TYPE_STRING:
354
/* No need to do anything. */
361
grub_strtoul (option, &tail, 0);
362
if (tail == 0 || tail == option || *tail != '\0' || grub_errno)
364
grub_error (GRUB_ERR_BAD_ARGUMENT,
365
"The argument `%s' requires an integer.",
373
case ARG_TYPE_DEVICE:
376
case ARG_TYPE_PATHNAME:
377
/* XXX: Not implemented. */
380
if (parse_option (cmd, opt->shortarg, option, usr) || grub_errno)
387
grub_error (GRUB_ERR_BAD_ARGUMENT,
388
"A value was assigned to the argument `%s' while it "
389
"doesn't require an argument\n", arg);
393
if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno)