From 8b23fe4e540a299e4f5934a571ebc1c865f1e98c Mon Sep 17 00:00:00 2001 From: Miles Bader Date: Thu, 15 Feb 1996 22:42:58 +0000 Subject: (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. --- libshouldbeinlibc/argp-parse.c | 69 ++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 29 deletions(-) (limited to 'libshouldbeinlibc/argp-parse.c') 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)) { -- cgit v1.2.3