X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fargp-parse.c;h=489d6de91c2a858b341136b60bc0dada82602e9f;hb=5191b3546cfb6c163228c23f214e325ddf60d46f;hp=cb8f9e1ad29b4d9d51b192a88a2b27a803490eb3;hpb=35b6e3c3bdaf7541e7a03d985c80c464e49d2182;p=gnulib.git diff --git a/lib/argp-parse.c b/lib/argp-parse.c index cb8f9e1ad..489d6de91 100644 --- a/lib/argp-parse.c +++ b/lib/argp-parse.c @@ -1,66 +1,54 @@ -/* Hierarchial argument parsing, layered over getopt - Copyright (C) 1995-2000, 2002 Free Software Foundation, Inc. +/* Hierarchical argument parsing, layered over getopt + Copyright (C) 1995-2000, 2002-2004, 2009-2013 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #ifdef HAVE_CONFIG_H -#include +# include #endif +#include +#include +#include #include #include #include #include #include +#include -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -# if defined HAVE_LIBINTL_H || defined _LIBC -# include -# ifdef _LIBC -# undef dgettext -# define dgettext(domain, msgid) \ - INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) -# endif -# else -# define dgettext(domain, msgid) (msgid) -# define gettext(msgid) (msgid) -# endif -#endif -#ifndef N_ -# define N_(msgid) (msgid) -#endif - -#if _LIBC - 0 -#include +#ifdef _LIBC +# include +# undef dgettext +# define dgettext(domain, msgid) \ + INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) #else -#ifdef HAVE_CTHREADS_H -#include +# include "gettext.h" #endif -#endif /* _LIBC */ +#define N_(msgid) msgid #include "argp.h" #include "argp-namefrob.h" +#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d)) + /* 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. */ +#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. */ @@ -81,27 +69,21 @@ /* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep for one second intervals, decrementing _ARGP_HANG until it's zero. Thus you can force the program to continue by attaching a debugger and setting - it to 0 yourself. + it to 0 yourself. */ +static volatile int _argp_hang; - XXX This variable used to be exported. But there seems to be no - need, at least not inside libc. */ -#ifdef _LIBC -static -#endif -volatile int _argp_hang; - -#define OPT_PROGNAME -2 -#define OPT_USAGE -3 -#define OPT_HANG -4 +#define OPT_PROGNAME -2 +#define OPT_USAGE -3 +#define OPT_HANG -4 static const struct argp_option argp_default_options[] = { - {"help", '?', 0, 0, N_("Give this help list"), -1}, - {"usage", OPT_USAGE, 0, 0, N_("Give a short usage message")}, - {"program-name",OPT_PROGNAME,"NAME", OPTION_HIDDEN, N_("Set the program name")}, - {"HANG", OPT_HANG, "SECS", OPTION_ARG_OPTIONAL | OPTION_HIDDEN, - N_("Hang for SECS seconds (default 3600)")}, - {0, 0} + {"help", '?', 0, 0, N_("give this help list"), -1}, + {"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0}, + {"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0}, + {"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN, + N_("hang for SECS seconds (default 3600)"), 0}, + {NULL, 0, 0, 0, NULL, 0} }; static error_t @@ -114,35 +96,35 @@ argp_default_parser (int key, char *arg, struct argp_state *state) break; case OPT_USAGE: __argp_state_help (state, state->out_stream, - ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); + ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); break; - case OPT_PROGNAME: /* Set the program name. */ + case OPT_PROGNAME: /* Set the program name. */ +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME program_invocation_name = arg; - +#endif /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka - __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined - to be that, so we have to be a bit careful here.] */ - arg = strrchr (arg, '/'); - if (arg) - program_invocation_short_name = arg + 1; - else - program_invocation_short_name = program_invocation_name; + __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined + to be that, so we have to be a bit careful here.] */ /* Update what we use for messages. */ - state->name = program_invocation_short_name; + state->name = __argp_base_name (arg); + +#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + program_invocation_short_name = state->name; +#endif if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) - == ARGP_PARSE_ARGV0) - /* Update what getopt uses too. */ - state->argv[0] = program_invocation_name; + == ARGP_PARSE_ARGV0) + /* Update what getopt uses too. */ + state->argv[0] = arg; break; case OPT_HANG: _argp_hang = atoi (arg ? arg : "3600"); while (_argp_hang-- > 0) - __sleep (1); + __sleep (1); break; default: @@ -157,8 +139,8 @@ static const struct argp argp_default_argp = static const struct argp_option argp_version_options[] = { - {"version", 'V', 0, 0, N_("Print program version"), -1}, - {0, 0} + {"version", 'V', 0, 0, N_("print program version"), -1}, + {NULL, 0, 0, 0, NULL, 0} }; static error_t @@ -168,14 +150,15 @@ argp_version_parser (int key, char *arg, struct argp_state *state) { case 'V': if (argp_program_version_hook) - (*argp_program_version_hook) (state->out_stream, state); + (*argp_program_version_hook) (state->out_stream, state); else if (argp_program_version) - fprintf (state->out_stream, "%s\n", argp_program_version); + fprintf (state->out_stream, "%s\n", argp_program_version); else - __argp_error (state, dgettext (state->root_argp->argp_domain, - "(PROGRAM ERROR) No version known!?")); + __argp_error (state, "%s", + dgettext (state->root_argp->argp_domain, + "(PROGRAM ERROR) No version known!?")); if (! (state->flags & ARGP_NO_EXIT)) - exit (0); + exit (0); break; default: return EBADKEY; @@ -203,44 +186,9 @@ find_long_option (struct option *long_options, const char *name) else return -1; } - -/* If we can, we regulate access to getopt, which is non-reentrant, with a - mutex. Since the case we're trying to guard against is two different - threads interfering, and it's possible that someone might want to call - argp_parse recursively (they're careful), we use a recursive lock if - possible. */ - -#if _LIBC - 0 - -__libc_lock_define_initialized_recursive (static, getopt_lock) -#define LOCK_GETOPT __libc_lock_lock_recursive (getopt_lock) -#define UNLOCK_GETOPT __libc_lock_unlock_recursive (getopt_lock) - -#else /* !_LIBC */ -#ifdef HAVE_CTHREADS_H -static struct mutex getopt_lock = MUTEX_INITIALIZER; -#define LOCK_GETOPT mutex_lock (&getopt_lock) -#define UNLOCK_GETOPT mutex_unlock (&getopt_lock) - -#else /* !HAVE_CTHREADS_H */ - -#define LOCK_GETOPT (void)0 -#define UNLOCK_GETOPT (void)0 - -#endif /* HAVE_CTHREADS_H */ -#endif /* _LIBC */ - -/* This hack to allow programs that know what's going on to call argp - recursively. If someday argp is changed not to use the non-reentrant - getopt interface, we can get rid of this shit. XXX */ -void -_argp_unlock_xxx (void) -{ - UNLOCK_GETOPT; -} -/* The state of a `group' during parsing. Each group corresponds to a +/* The state of a "group" during parsing. Each group corresponds to a particular argp structure from the tree of such descending from the top level argp passed to argp_parse. */ struct group @@ -256,12 +204,12 @@ struct group particular short options is from. */ char *short_end; - /* The number of non-option args sucessfully handled by this parser. */ + /* The number of non-option args successfully handled by this parser. */ unsigned args_processed; /* This group's parser's parent's group. */ struct group *parent; - unsigned parent_index; /* And the our position in the parent. */ + unsigned parent_index; /* And the our position in the parent. */ /* These fields are swapped into and out of the state structure when calling this group's parser. */ @@ -300,12 +248,14 @@ struct parser /* LONG_OPTS is the array of getop long option structures for the union of all the groups of options. */ struct option *long_opts; + /* OPT_DATA is the getopt data used for the re-entrant getopt. */ + struct _getopt_data opt_data; /* States of the various parsing groups. */ struct group *groups; /* The end of the GROUPS array. */ struct group *egroup; - /* An vector containing storage for the CHILD_INPUTS field in all groups. */ + /* A vector containing storage for the CHILD_INPUTS field in all groups. */ void **child_inputs; /* True if we think using getopt is still useful; if false, then @@ -337,8 +287,8 @@ struct parser_convert_state next unused group entry. CVT holds state used during the conversion. */ static struct group * convert_options (const struct argp *argp, - struct group *parent, unsigned parent_index, - struct group *group, struct parser_convert_state *cvt) + struct group *parent, unsigned parent_index, + struct group *group, struct parser_convert_state *cvt) { /* REAL is the most recent non-alias value of OPT. */ const struct argp_option *real = argp->options; @@ -349,55 +299,55 @@ convert_options (const struct argp *argp, const struct argp_option *opt; if (real) - for (opt = real; !__option_is_end (opt); opt++) - { - if (! (opt->flags & OPTION_ALIAS)) - /* OPT isn't an alias, so we can use values from it. */ - real = opt; - - if (! (real->flags & OPTION_DOC)) - /* A real option (not just documentation). */ - { - if (__option_is_short (opt)) - /* OPT can be used as a short option. */ - { - *cvt->short_end++ = opt->key; - if (real->arg) - { - *cvt->short_end++ = ':'; - if (real->flags & OPTION_ARG_OPTIONAL) - *cvt->short_end++ = ':'; - } - *cvt->short_end = '\0'; /* keep 0 terminated */ - } - - if (opt->name - && find_long_option (cvt->parser->long_opts, opt->name) < 0) - /* OPT can be used as a long option. */ - { - cvt->long_end->name = opt->name; - cvt->long_end->has_arg = - (real->arg - ? (real->flags & OPTION_ARG_OPTIONAL - ? optional_argument - : required_argument) - : no_argument); - cvt->long_end->flag = 0; - /* we add a disambiguating code to all the user's - values (which is removed before we actually call - the function to parse the value); this means that - the user loses use of the high 8 bits in all his - values (the sign of the lower bits is preserved - however)... */ - cvt->long_end->val = - ((opt->key | real->key) & USER_MASK) - + (((group - cvt->parser->groups) + 1) << USER_BITS); - - /* Keep the LONG_OPTS list terminated. */ - (++cvt->long_end)->name = NULL; - } - } - } + for (opt = real; !__option_is_end (opt); opt++) + { + if (! (opt->flags & OPTION_ALIAS)) + /* OPT isn't an alias, so we can use values from it. */ + real = opt; + + if (! (real->flags & OPTION_DOC)) + /* A real option (not just documentation). */ + { + if (__option_is_short (opt)) + /* OPT can be used as a short option. */ + { + *cvt->short_end++ = opt->key; + if (real->arg) + { + *cvt->short_end++ = ':'; + if (real->flags & OPTION_ARG_OPTIONAL) + *cvt->short_end++ = ':'; + } + *cvt->short_end = '\0'; /* keep 0 terminated */ + } + + if (opt->name + && find_long_option (cvt->parser->long_opts, opt->name) < 0) + /* OPT can be used as a long option. */ + { + cvt->long_end->name = opt->name; + cvt->long_end->has_arg = + (real->arg + ? (real->flags & OPTION_ARG_OPTIONAL + ? optional_argument + : required_argument) + : no_argument); + cvt->long_end->flag = 0; + /* we add a disambiguating code to all the user's + values (which is removed before we actually call + the function to parse the value); this means that + the user loses use of the high 8 bits in all his + values (the sign of the lower bits is preserved + however)... */ + cvt->long_end->val = + ((opt->key ? opt->key : real->key) & USER_MASK) + + (((group - cvt->parser->groups) + 1) << USER_BITS); + + /* Keep the LONG_OPTS list terminated. */ + (++cvt->long_end)->name = NULL; + } + } + } group->parser = argp->parser; group->argp = argp; @@ -410,15 +360,15 @@ convert_options (const struct argp *argp, group->child_inputs = 0; if (children) - /* Assign GROUP's CHILD_INPUTS field some space from + /* Assign GROUP's CHILD_INPUTS field some space from CVT->child_inputs_end.*/ - { - unsigned num_children = 0; - while (children[num_children].argp) - num_children++; - group->child_inputs = cvt->child_inputs_end; - cvt->child_inputs_end += num_children; - } + { + unsigned num_children = 0; + while (children[num_children].argp) + num_children++; + group->child_inputs = cvt->child_inputs_end; + cvt->child_inputs_end += num_children; + } parent = group++; } @@ -429,14 +379,14 @@ convert_options (const struct argp *argp, { unsigned index = 0; while (children->argp) - group = - convert_options (children++->argp, parent, index++, group, cvt); + group = + convert_options (children++->argp, parent, index++, group, cvt); } return group; } -/* Find the merged set of getopt options, with keys appropiately prefixed. */ +/* Find the merged set of getopt options, with keys appropriately prefixed. */ static void parser_convert (struct parser *parser, const struct argp *argp, int flags) { @@ -466,10 +416,10 @@ parser_convert (struct parser *parser, const struct argp *argp, int flags) /* Lengths of various parser fields which we will allocated. */ struct parser_sizes { - size_t short_len; /* Getopt short options string. */ - size_t long_len; /* Getopt long options vector. */ - size_t num_groups; /* Group structures we allocate. */ - size_t num_child_inputs; /* Child input slots. */ + size_t short_len; /* Getopt short options string. */ + size_t long_len; /* Getopt long options vector. */ + size_t num_groups; /* Group structures we allocate. */ + size_t num_child_inputs; /* Child input slots. */ }; /* For ARGP, increments the NUM_GROUPS field in SZS by the total number of @@ -486,31 +436,37 @@ calc_sizes (const struct argp *argp, struct parser_sizes *szs) { szs->num_groups++; if (opt) - { - int num_opts = 0; - while (!__option_is_end (opt++)) - num_opts++; - szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */ - szs->long_len += num_opts; - } + { + int num_opts = 0; + while (!__option_is_end (opt++)) + num_opts++; + szs->short_len += num_opts * 3; /* opt + up to 2 ':'s */ + szs->long_len += num_opts; + } } if (child) while (child->argp) { - calc_sizes ((child++)->argp, szs); - szs->num_child_inputs++; + calc_sizes ((child++)->argp, szs); + szs->num_child_inputs++; } } /* Initializes PARSER to parse ARGP in a manner described by FLAGS. */ static error_t parser_init (struct parser *parser, const struct argp *argp, - int argc, char **argv, int flags, void *input) + int argc, char **argv, int flags, void *input) { error_t err = 0; struct group *group; struct parser_sizes szs; + struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER; + char *storage; + size_t glen, gsum; + size_t clen, csum; + size_t llen, lsum; + size_t slen, ssum; szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; szs.long_len = 0; @@ -521,21 +477,33 @@ parser_init (struct parser *parser, const struct argp *argp, calc_sizes (argp, &szs); /* Lengths of the various bits of storage used by PARSER. */ -#define GLEN (szs.num_groups + 1) * sizeof (struct group) -#define CLEN (szs.num_child_inputs * sizeof (void *)) -#define LLEN ((szs.long_len + 1) * sizeof (struct option)) -#define SLEN (szs.short_len + 1) - - parser->storage = malloc (GLEN + CLEN + LLEN + SLEN); + glen = (szs.num_groups + 1) * sizeof (struct group); + clen = szs.num_child_inputs * sizeof (void *); + llen = (szs.long_len + 1) * sizeof (struct option); + slen = szs.short_len + 1; + + /* Sums of previous lengths, properly aligned. There's no need to + align gsum, since struct group is aligned at least as strictly as + void * (since it contains a void * member). And there's no need + to align lsum, since struct option is aligned at least as + strictly as char. */ + gsum = glen; + csum = alignto (gsum + clen, alignof (struct option)); + lsum = csum + llen; + ssum = lsum + slen; + + parser->storage = malloc (ssum); if (! parser->storage) return ENOMEM; + storage = parser->storage; parser->groups = parser->storage; - parser->child_inputs = parser->storage + GLEN; - parser->long_opts = parser->storage + GLEN + CLEN; - parser->short_opts = parser->storage + GLEN + CLEN + LLEN; + parser->child_inputs = (void **) (storage + gsum); + parser->long_opts = (struct option *) (storage + csum); + parser->short_opts = storage + lsum; + parser->opt_data = opt_data; - memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); + memset (parser->child_inputs, 0, clen); parser_convert (parser, argp, flags); memset (&parser->state, 0, sizeof (struct argp_state)); @@ -545,7 +513,7 @@ parser_init (struct parser *parser, const struct argp *argp, parser->state.flags = flags; parser->state.err_stream = stderr; parser->state.out_stream = stdout; - parser->state.next = 0; /* Tell getopt to initialize. */ + parser->state.next = 0; /* Tell getopt to initialize. */ parser->state.pstate = parser; parser->try_getopt = 1; @@ -559,46 +527,40 @@ parser_init (struct parser *parser, const struct argp *argp, group++) { if (group->parent) - /* If a child parser, get the initial input value from the parent. */ - group->input = group->parent->child_inputs[group->parent_index]; + /* If a child parser, get the initial input value from the parent. */ + group->input = group->parent->child_inputs[group->parent_index]; if (!group->parser - && group->argp->children && group->argp->children->argp) - /* For the special case where no parsing function is supplied for an - argp, propagate its input to its first child, if any (this just - makes very simple wrapper argps more convenient). */ - group->child_inputs[0] = group->input; + && group->argp->children && group->argp->children->argp) + /* For the special case where no parsing function is supplied for an + argp, propagate its input to its first child, if any (this just + makes very simple wrapper argps more convenient). */ + group->child_inputs[0] = group->input; err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0); } if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ + err = 0; /* Some parser didn't understand. */ if (err) return err; - /* Getopt is (currently) non-reentrant. */ - LOCK_GETOPT; - if (parser->state.flags & ARGP_NO_ERRS) { - opterr = 0; + parser->opt_data.opterr = 0; if (parser->state.flags & ARGP_PARSE_ARGV0) - /* getopt always skips ARGV[0], so we have to fake it out. As long - as OPTERR is 0, then it shouldn't actually try to access it. */ - parser->state.argv--, parser->state.argc++; + /* getopt always skips ARGV[0], so we have to fake it out. As long + as OPTERR is 0, then it shouldn't actually try to access it. */ + parser->state.argv--, parser->state.argc++; } else - opterr = 1; /* Print error messages. */ + parser->opt_data.opterr = 1; /* Print error messages. */ if (parser->state.argv == argv && argv[0]) /* There's an argv[0]; use it for messages. */ - { - char *short_name = strrchr (argv[0], '/'); - parser->state.name = short_name ? short_name + 1 : argv[0]; - } + parser->state.name = __argp_base_name (argv[0]); else - parser->state.name = program_invocation_short_name; + parser->state.name = __argp_short_program_name (); return 0; } @@ -606,12 +568,10 @@ parser_init (struct parser *parser, const struct argp *argp, /* Free any storage consumed by PARSER (but not PARSER itself). */ static error_t parser_finalize (struct parser *parser, - error_t err, int arg_ebadkey, int *end_index) + error_t err, int arg_ebadkey, int *end_index) { struct group *group; - UNLOCK_GETOPT; - if (err == EBADKEY && arg_ebadkey) /* Suppress errors generated by unparsed arguments. */ err = 0; @@ -619,40 +579,40 @@ parser_finalize (struct parser *parser, if (! err) { if (parser->state.next == parser->state.argc) - /* We successfully parsed all arguments! Call all the parsers again, - just a few more times... */ - { - for (group = parser->groups; - group < parser->egroup && (!err || err==EBADKEY); - group++) - if (group->args_processed == 0) - err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); - for (group = parser->egroup - 1; - group >= parser->groups && (!err || err==EBADKEY); - group--) - err = group_parse (group, &parser->state, ARGP_KEY_END, 0); - - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - - /* Tell the user that all arguments are parsed. */ - if (end_index) - *end_index = parser->state.next; - } + /* We successfully parsed all arguments! Call all the parsers again, + just a few more times... */ + { + for (group = parser->groups; + group < parser->egroup && (!err || err==EBADKEY); + group++) + if (group->args_processed == 0) + err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); + for (group = parser->egroup - 1; + group >= parser->groups && (!err || err==EBADKEY); + group--) + err = group_parse (group, &parser->state, ARGP_KEY_END, 0); + + if (err == EBADKEY) + err = 0; /* Some parser didn't understand. */ + + /* Tell the user that all arguments are parsed. */ + if (end_index) + *end_index = parser->state.next; + } else if (end_index) - /* Return any remaining arguments to the user. */ - *end_index = parser->state.next; + /* Return any remaining arguments to the user. */ + *end_index = parser->state.next; else - /* No way to return the remaining arguments, they must be bogus. */ - { - if (!(parser->state.flags & ARGP_NO_ERRS) - && parser->state.err_stream) - fprintf (parser->state.err_stream, - dgettext (parser->argp->argp_domain, - "%s: Too many arguments\n"), - parser->state.name); - err = EBADKEY; - } + /* No way to return the remaining arguments, they must be bogus. */ + { + if (!(parser->state.flags & ARGP_NO_ERRS) + && parser->state.err_stream) + fprintf (parser->state.err_stream, + dgettext (parser->argp->argp_domain, + "%s: Too many arguments\n"), + parser->state.name); + err = EBADKEY; + } } /* Okay, we're all done, with either an error or success; call the parsers @@ -662,27 +622,27 @@ parser_finalize (struct parser *parser, { /* Maybe print an error message. */ if (err == EBADKEY) - /* An appropriate message describing what the error was should have - been printed earlier. */ - __argp_state_help (&parser->state, parser->state.err_stream, - ARGP_HELP_STD_ERR); + /* An appropriate message describing what the error was should have + been printed earlier. */ + __argp_state_help (&parser->state, parser->state.err_stream, + ARGP_HELP_STD_ERR); /* Since we didn't exit, give each parser an error indication. */ for (group = parser->groups; group < parser->egroup; group++) - group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); + group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); } else /* Notify parsers of success, and propagate back values from parsers. */ { /* We pass over the groups in reverse order so that child groups are - given a chance to do there processing before passing back a value to - the parent. */ + given a chance to do there processing before passing back a value to + the parent. */ for (group = parser->egroup - 1 - ; group >= parser->groups && (!err || err == EBADKEY) - ; group--) - err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); + ; group >= parser->groups && (!err || err == EBADKEY) + ; group--) + err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ + err = 0; /* Some parser didn't understand. */ } /* Call parsers once more, to do any final cleanup. Errors are ignored. */ @@ -710,42 +670,42 @@ parser_parse_arg (struct parser *parser, char *val) int index = --parser->state.next; error_t err = EBADKEY; struct group *group; - int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */ + int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */ /* Try to parse the argument in each parser. */ for (group = parser->groups ; group < parser->egroup && err == EBADKEY ; group++) { - parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ + parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ key = ARGP_KEY_ARG; err = group_parse (group, &parser->state, key, val); if (err == EBADKEY) - /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ - { - parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ - key = ARGP_KEY_ARGS; - err = group_parse (group, &parser->state, key, 0); - } + /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ + { + parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ + key = ARGP_KEY_ARGS; + err = group_parse (group, &parser->state, key, 0); + } } if (! err) { if (key == ARGP_KEY_ARGS) - /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't - changed by the user, *all* arguments should be considered - consumed. */ - parser->state.next = parser->state.argc; + /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't + changed by the user, *all* arguments should be considered + consumed. */ + parser->state.next = parser->state.argc; if (parser->state.next > index) - /* Remember that we successfully processed a non-option - argument -- but only if the user hasn't gotten tricky and set - the clock back. */ - (--group)->args_processed += (parser->state.next - index); + /* Remember that we successfully processed a non-option + argument -- but only if the user hasn't gotten tricky and set + the clock back. */ + (--group)->args_processed += (parser->state.next - index); else - /* The user wants to reparse some args, give getopt another try. */ - parser->try_getopt = 1; + /* The user wants to reparse some args, give getopt another try. */ + parser->try_getopt = 1; } return err; @@ -770,19 +730,21 @@ parser_parse_opt (struct parser *parser, int opt, char *val) char *short_index = strchr (parser->short_opts, opt); if (short_index) - for (group = parser->groups; group < parser->egroup; group++) - if (group->short_end > short_index) - { - err = group_parse (group, &parser->state, opt, optarg); - break; - } + for (group = parser->groups; group < parser->egroup; group++) + if (group->short_end > short_index) + { + err = group_parse (group, &parser->state, opt, + parser->opt_data.optarg); + break; + } } else /* A long option. We use shifts instead of masking for extracting the user value in order to preserve the sign. */ err = group_parse (&parser->groups[group_key - 1], &parser->state, - (opt << GROUP_BITS) >> GROUP_BITS, optarg); + (opt << GROUP_BITS) >> GROUP_BITS, + parser->opt_data.optarg); if (err == EBADKEY) /* At least currently, an option not recognized is an error in the @@ -790,19 +752,19 @@ parser_parse_opt (struct parser *parser, int opt, char *val) with each option. */ { static const char bad_key_err[] = - N_("(PROGRAM ERROR) Option should have been recognized!?"); + N_("(PROGRAM ERROR) Option should have been recognized!?"); if (group_key == 0) - __argp_error (&parser->state, "-%c: %s", opt, - dgettext (parser->argp->argp_domain, bad_key_err)); + __argp_error (&parser->state, "-%c: %s", opt, + dgettext (parser->argp->argp_domain, bad_key_err)); else - { - struct option *long_opt = parser->long_opts; - while (long_opt->val != opt && long_opt->name) - long_opt++; - __argp_error (&parser->state, "--%s: %s", - long_opt->name ? long_opt->name : "???", - dgettext (parser->argp->argp_domain, bad_key_err)); - } + { + struct option *long_opt = parser->long_opts; + while (long_opt->val != opt && long_opt->name) + long_opt++; + __argp_error (&parser->state, "--%s: %s", + long_opt->name ? long_opt->name : "???", + dgettext (parser->argp->argp_domain, bad_key_err)); + } } return err; @@ -820,7 +782,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) if (parser->state.quoted && parser->state.next < parser->state.quoted) /* The next argument pointer has been moved to before the quoted - region, so pretend we never saw the quoting `--', and give getopt + region, so pretend we never saw the quoting "--", and give getopt another chance. If the user hasn't removed it, getopt will just process it again. */ parser->state.quoted = 0; @@ -828,38 +790,43 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) if (parser->try_getopt && !parser->state.quoted) /* Give getopt a chance to parse this. */ { - optind = parser->state.next; /* Put it back in OPTIND for getopt. */ - optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ + /* Put it back in OPTIND for getopt. */ + parser->opt_data.optind = parser->state.next; + /* Distinguish KEY_ERR from a real option. */ + parser->opt_data.optopt = KEY_END; if (parser->state.flags & ARGP_LONG_ONLY) - opt = getopt_long_only (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); + opt = _getopt_long_only_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); else - opt = getopt_long (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0); - parser->state.next = optind; /* And see what getopt did. */ + opt = _getopt_long_r (parser->state.argc, parser->state.argv, + parser->short_opts, parser->long_opts, 0, + &parser->opt_data); + /* And see what getopt did. */ + parser->state.next = parser->opt_data.optind; if (opt == KEY_END) - /* Getopt says there are no more options, so stop using - getopt; we'll continue if necessary on our own. */ - { - parser->try_getopt = 0; - if (parser->state.next > 1 - && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) - == 0) - /* Not only is this the end of the options, but it's a - `quoted' region, which may have args that *look* like - options, so we definitely shouldn't try to use getopt past - here, whatever happens. */ - parser->state.quoted = parser->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. */ - { - *arg_ebadkey = 0; - return EBADKEY; - } + /* Getopt says there are no more options, so stop using + getopt; we'll continue if necessary on our own. */ + { + parser->try_getopt = 0; + if (parser->state.next > 1 + && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) + == 0) + /* Not only is this the end of the options, but it's a + "quoted" region, which may have args that *look* like + options, so we definitely shouldn't try to use getopt past + here, whatever happens. */ + parser->state.quoted = parser->state.next; + } + else if (opt == KEY_ERR && parser->opt_data.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. */ + { + *arg_ebadkey = 0; + return EBADKEY; + } } else opt = KEY_END; @@ -868,25 +835,25 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) { /* We're past what getopt considers the options. */ if (parser->state.next >= parser->state.argc - || (parser->state.flags & ARGP_NO_ARGS)) - /* Indicate that we're done. */ - { - *arg_ebadkey = 1; - return EBADKEY; - } + || (parser->state.flags & ARGP_NO_ARGS)) + /* Indicate that we're done. */ + { + *arg_ebadkey = 1; + return EBADKEY; + } else - /* A non-option arg; simulate what getopt might have done. */ - { - opt = KEY_ARG; - optarg = parser->state.argv[parser->state.next++]; - } + /* A non-option arg; simulate what getopt might have done. */ + { + opt = KEY_ARG; + parser->opt_data.optarg = parser->state.argv[parser->state.next++]; + } } if (opt == KEY_ARG) /* A non-option argument; try each parser in turn. */ - err = parser_parse_arg (parser, optarg); + err = parser_parse_arg (parser, parser->opt_data.optarg); else - err = parser_parse_opt (parser, opt, optarg); + err = parser_parse_opt (parser, opt, parser->opt_data.optarg); if (err == EBADKEY) *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); @@ -901,7 +868,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey) returned a non-zero value, it is returned; otherwise 0 is returned. */ error_t __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, - int *end_index, void *input) + int *end_index, void *input) { error_t err; struct parser parser; @@ -910,6 +877,20 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, to be parsed (which in some cases isn't actually an error). */ int arg_ebadkey = 0; +#ifndef _LIBC + if (!(flags & ARGP_PARSE_ARGV0)) + { +#if HAVE_DECL_PROGRAM_INVOCATION_NAME + if (!program_invocation_name) + program_invocation_name = argv[0]; +#endif +#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME + if (!program_invocation_short_name) + program_invocation_short_name = __argp_base_name (argv[0]); +#endif + } +#endif + if (! (flags & ARGP_NO_HELP)) /* Add our own options. */ { @@ -917,17 +898,17 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, struct argp *top_argp = alloca (sizeof (struct argp)); /* TOP_ARGP has no options, it just serves to group the user & default - argps. */ + argps. */ memset (top_argp, 0, sizeof (*top_argp)); top_argp->children = child; memset (child, 0, 4 * sizeof (struct argp_child)); if (argp) - (child++)->argp = argp; + (child++)->argp = argp; (child++)->argp = &argp_default_argp; if (argp_program_version || argp_program_version_hook) - (child++)->argp = &argp_version_argp; + (child++)->argp = &argp_version_argp; child->argp = 0; argp = top_argp; @@ -940,7 +921,7 @@ __argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, /* Parse! */ { while (! err) - err = parser_parse_next (&parser, &arg_ebadkey); + err = parser_parse_next (&parser, &arg_ebadkey); err = parser_finalize (&parser, err, arg_ebadkey, end_index); } @@ -961,8 +942,8 @@ __argp_input (const struct argp *argp, const struct argp_state *state) struct parser *parser = state->pstate; for (group = parser->groups; group < parser->egroup; group++) - if (group->argp == argp) - return group->input; + if (group->argp == argp) + return group->input; } return 0;