summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1996-02-15 22:42:58 +0000
committerMiles Bader <miles@gnu.org>1996-02-15 22:42:58 +0000
commit8b23fe4e540a299e4f5934a571ebc1c865f1e98c (patch)
tree579193f3df44442ea3d6b1ab513a49bc1dd03507
parentbe53543f2c9fbd54cec004261366df19434e83c1 (diff)
(argp_parse): Correctly deal with errors from getopt, and allow the user to
use '?' as a short option. (KEY_ERR): New macro. (argp_default_options, argp_default_parser): Use -? as the short option for --help.
-rw-r--r--libshouldbeinlibc/argp-parse.c69
1 files changed, 40 insertions, 29 deletions
diff --git a/libshouldbeinlibc/argp-parse.c b/libshouldbeinlibc/argp-parse.c
index b9c04b8f..315d6dbc 100644
--- a/libshouldbeinlibc/argp-parse.c
+++ b/libshouldbeinlibc/argp-parse.c
@@ -28,10 +28,10 @@
#include "argp.h"
-/* What getopt returns after the end of the options. */
-#define KEY_END (-1)
-/* What getopt returns for a non-option argument. */
-#define KEY_ARG 1
+/* Getopt return values. */
+#define KEY_END (-1) /* The end of the options. */
+#define KEY_ARG 1 /* A non-option argument. */
+#define KEY_ERR '?' /* An error parsing the options. */
/* The meta-argument used to prevent any further arguments being interpreted
as options. */
@@ -46,12 +46,11 @@
/* ---------------------------------------------------------------- */
-#define OPT_HELP -1
#define OPT_PROGNAME -2
static const struct argp_option argp_default_options[] =
{
- {"help", OPT_HELP, 0, 0, "Give this help list", -1},
+ {"help", '?', 0, 0, "Give this help list", -1},
{"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, "Set the program name"},
{0, 0}
};
@@ -62,7 +61,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
unsigned usage_flags = ARGP_HELP_STD_HELP;
switch (key)
{
- case OPT_HELP:
+ case '?':
if (state->flags & ARGP_NO_EXIT)
usage_flags &= ~ARGP_HELP_EXIT;
argp_help (state->argp, stdout, usage_flags);
@@ -419,10 +418,13 @@ argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
/* Give getopt a chance to parse this. */
{
optind = state.next; /* Put it back in OPTIND for getopt. */
+ optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */
opt = getopt_long (state.argc, state.argv, short_opts, long_opts, 0);
state.next = optind; /* And see what getopt did. */
+
if (opt == KEY_END)
- /* Getopt says there are no more options, so stop using getopt. */
+ /* Getopt says there are no more options, so stop using
+ getopt; we'll continue if necessary on our own. */
{
try_getopt = 0;
if (state.next > 1
@@ -433,6 +435,14 @@ argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
here, whatever happens. */
state.quoted = state.next;
}
+ else if (opt == KEY_ERR && optopt != KEY_END)
+ /* KEY_ERR can have the same value as a valid user short
+ option, but in the case of a real error, getopt sets OPTOPT
+ to the offending character, which can never be KEY_END. */
+ {
+ err = EINVAL;
+ break;
+ }
}
else
opt = KEY_END;
@@ -453,29 +463,30 @@ argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
mutex_unlock (&getopt_lock);
- if (state.next == state.argc)
- /* We successfully parsed all arguments! Call all the parsers again,
- just a few more times... */
- {
- for (group = groups; group < egroup && (!err || err == EINVAL); group++)
- if (group->args_processed == 0 && group->parser)
- err = (*group->parser)(ARGP_KEY_NO_ARGS, 0, &state);
- for (group = groups; group < egroup && (!err || err == EINVAL); group++)
- if (group->parser)
- err = (*group->parser)(ARGP_KEY_END, 0, &state);
- if (err == EINVAL)
- /* EINVAL here just means that ARGP_KEY_END wasn't understood. */
- err = 0;
- }
+ if (err == EINVAL && arg_einval)
+ /* Suppress errors generated by unparsed arguments. */
+ err = 0;
- if (end_index)
- {
- if (err == EINVAL && arg_einval)
- /* As long as there's some way for the user to deal with the
- remaining arguments, don't complain. */
- err = 0;
+ if (!err)
+ if (state.next == state.argc)
+ /* We successfully parsed all arguments! Call all the parsers again,
+ just a few more times... */
+ {
+ for (group = groups; group < egroup && (!err || err ==EINVAL); group++)
+ if (group->args_processed == 0 && group->parser)
+ err = (*group->parser)(ARGP_KEY_NO_ARGS, 0, &state);
+ for (group = groups; group < egroup && (!err || err ==EINVAL); group++)
+ if (group->parser)
+ err = (*group->parser)(ARGP_KEY_END, 0, &state);
+ if (err == EINVAL)
+ err = 0; /* Some parser didn't understand. */
+ }
+ else if (end_index)
+ /* Return any remaining arguments to the user. */
*end_index = state.next;
- }
+ else
+ /* No way to return the remaining arguments, they must be bogus. */
+ err = EINVAL;
if (err && !(state.flags & ARGP_NO_HELP))
{