2004-03-03 Marcus Brinkmann * posix/getopt.h (_getopt_internal): Prototype moved to ... * include/getopt.h (_getopt_internal): ... here. Remove libc_hidden_proto for getopt_long and getopt_long_only. (struct _getopt_data): New structure. (_GETOPT_DATA_INITIALIZER): New macro. (_getopt_internal_r): New declaration. (__getopt_long_r, __getopt_long_only_r): New prototypes. * posix/getopt.c [_LIBC]: Include , not "getopt.h". (nextchar, ordering, posixly_correct, first_nonopt, last_nonopt): Static variables removed. (nonoption_flags_max_len, nonoption_flags_len) [_LIBC && USE_NONOPTION_FLAGS]: Static variables removed. (getopt_data): New static variable. (SWAP_FLAGS): Use d->__nonoption_flags_len instead nonoption_flags_len. (exchange): Add new argument D of type struct getopt_data *. Replace optind with d->optind, optarg with d->optarg, opterr with d->opterr, optopt with d->optopt, nextchar with d->__nextchar, first_nonopt with d->__first_nonopt, last_nonopt with d->__last_nonopt, d->ordering with d->__ordering, d->posixly_correct with d->__posixly_correct (which is now an int instead a string, so fix users), nonoption_flags_len with d->__nonoption_flags_len, nonoption_flags_max_len with d->__nonoption_flags_max_len. (_getopt_initialize): Likewise. (_getopt_internal): Rename to ... (_getopt_internal_r): ... this. Also add new argument D of type struct getopt_data * and use of members of D rather than global or static variables as described for exchange() above. Add new argument to invocations of _getopt_initialize and exchange. (_getopt_internal): Reimplement in terms of _getopt_internal_r. * posix/getopt1.c: Remove libc_hidden_def for getopt_long and getopt_long_only. (__getopt_long_r, __getopt_long_only_r): New functions. * argp/argp-parse.c [_LIBC]: Do not include . [!_LIBC && HAVE_CTHREADS_H]: Do not include . [!_LIBC] (_argp_hang): Make static. (getopt_lock, LOCK_GETOPT, UNLOCK_GETOPT): Remove. (_argp_unlock_xxx): Remove. (parser_init): Do not use LOCK_GETOPT. (parser_finalize): Do not use UNLOCK_GETOPT. (struct parser): New member OPT_DATA. (parser_init): Initialize parser->opt_data. Use parser->opt_data.opterr instead of opterr. (parser_parse_opt): Use parser->opt_data.optarg instead optarg. (parser_parse_next): Likewise. Use parser->opt_data.optind instead optind. Use parser->opt_data.optopt instead of optopt. Call __getopt_long_only_r and __getopt_long_r instead of getopt_long_only and getopt_long, and pass the extra argument. diff -rup libc-old/argp/argp-parse.c libc/argp/argp-parse.c --- libc-old/argp/argp-parse.c 2004-03-08 01:38:12.000000000 +0100 +++ libc/argp/argp-parse.c 2004-03-08 01:38:47.000000000 +0100 @@ -1,5 +1,5 @@ /* Hierarchial argument parsing, layered over getopt - Copyright (C) 1995-2000, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Miles Bader . @@ -62,14 +62,6 @@ char *alloca (); # define N_(msgid) (msgid) #endif -#if _LIBC - 0 -#include -#else -#ifdef HAVE_CTHREADS_H -#include -#endif -#endif /* _LIBC */ - #include "argp.h" #include "argp-namefrob.h" @@ -97,14 +89,8 @@ char *alloca (); /* 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. - - 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; + it to 0 yourself. */ +static volatile int _argp_hang; #define OPT_PROGNAME -2 #define OPT_USAGE -3 @@ -223,42 +209,7 @@ find_long_option (struct option *long_op 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 particular argp structure from the tree of such descending from the top @@ -320,6 +271,8 @@ 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; @@ -554,6 +507,7 @@ parser_init (struct parser *parser, cons parser->child_inputs = parser->storage + GLEN; parser->long_opts = parser->storage + GLEN + CLEN; parser->short_opts = parser->storage + GLEN + CLEN + LLEN; + parser->opt_data = (struct _getopt_data) _GETOPT_DATA_INITIALIZER; memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); parser_convert (parser, argp, flags); @@ -597,19 +551,16 @@ parser_init (struct parser *parser, cons 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++; } 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. */ @@ -630,8 +581,6 @@ parser_finalize (struct parser *parser, { struct group *group; - UNLOCK_GETOPT; - if (err == EBADKEY && arg_ebadkey) /* Suppress errors generated by unparsed arguments. */ err = 0; @@ -793,7 +742,8 @@ parser_parse_opt (struct parser *parser, for (group = parser->groups; group < parser->egroup; group++) if (group->short_end > short_index) { - err = group_parse (group, &parser->state, opt, optarg); + err = group_parse (group, &parser->state, opt, + parser->opt_data.optarg); break; } } @@ -802,7 +752,8 @@ parser_parse_opt (struct parser *parser, 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 @@ -848,15 +799,20 @@ parser_parse_next (struct parser *parser 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 @@ -872,7 +828,7 @@ parser_parse_next (struct parser *parser here, whatever happens. */ parser->state.quoted = parser->state.next; } - else if (opt == KEY_ERR && optopt != KEY_END) + 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. */ @@ -898,15 +854,15 @@ parser_parse_next (struct parser *parser /* A non-option arg; simulate what getopt might have done. */ { opt = KEY_ARG; - optarg = parser->state.argv[parser->state.next++]; + 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); diff -rup libc-old/include/getopt.h libc/include/getopt.h --- libc-old/include/getopt.h 2004-03-08 01:38:12.000000000 +0100 +++ libc/include/getopt.h 2004-03-08 01:40:33.000000000 +0100 @@ -5,12 +5,113 @@ # ifdef _GETOPT_H -libc_hidden_proto (getopt_long) -libc_hidden_proto (getopt_long_only) - /* Now define the internal interfaces. */ extern void __getopt_clean_environment (char **__env); +extern int _getopt_internal (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); + +/* Reentrant versions which can handle parsing multiple argument + vectors at the same time. */ + +/* Data type for reentrant functions. */ +struct _getopt_data +{ + /* These have exactly the same meaning as the corresponding global + variables, except that they are used for the reentrant + versions of getopt. */ + int optind; + int opterr; + int optopt; + char *optarg; + + /* Internal members. */ + + /* True if the internal members have been initialized. */ + int __initialized; + + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + char *__nextchar; + + /* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we + scan, so that eventually all the non-options are at the end. + This allows options to be given in any order, even with programs + that were not written to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. Using `-' as the first character of the + list of option characters selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + + enum + { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER + } __ordering; + + /* If the POSIXLY_CORRECT environment variable is set. */ + int __posixly_correct; + + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first + of them; `last_nonopt' is the index after the last of them. */ + + int __first_nonopt; + int __last_nonopt; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + int __nonoption_flags_max_len; + int __nonoption_flags_len; +# endif +}; + +/* The initializer is necessary to set OPTIND and OPTERR to their + default values and to clear the initialization flag. */ +#define _GETOPT_DATA_INITIALIZER { 1, 1 } + +extern int _getopt_internal_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, struct _getopt_data *__data); + +extern int __getopt_long_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + struct _getopt_data *__data); +extern int __getopt_long_only_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, + int *__longind, + struct _getopt_data *__data); + # endif #endif diff -rup libc-old/posix/Versions libc/posix/Versions --- libc-old/posix/Versions 2004-03-06 21:10:17.000000000 +0100 +++ libc/posix/Versions 2004-03-08 02:47:28.000000000 +0100 @@ -125,7 +125,5 @@ libc { __libc_wait; __libc_waitpid; __libc_pause; __libc_nanosleep; __libc_fork; __libc_pread; __libc_pread64; __libc_pwrite; __libc_pwrite64; __waitid; __pselect; - # used by argp - __getopt_long_r; __getopt_long_only_r; } } diff -rup libc-old/posix/getopt.c libc/posix/getopt.c --- libc-old/posix/getopt.c 2004-03-08 01:38:12.000000000 +0100 +++ libc/posix/getopt.c 2004-03-08 03:05:00.000000000 +0100 @@ -2,7 +2,7 @@ NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! - Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003 + Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -109,7 +109,11 @@ GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ -#include "getopt.h" +#ifdef _LIBC +# include +#else +# include "getopt.h" +#endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, @@ -140,15 +144,6 @@ int optind = 1; int __getopt_initialized attribute_hidden; -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - /* Callers store zero here to inhibit the error message for unrecognized options. */ @@ -160,42 +155,10 @@ int opterr = 1; int optopt = '?'; -/* Describe how to deal with options that follow non-option ARGV-elements. +/* Keep a global copy of all internal members of getopt_data. */ - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ +static struct _getopt_data __getopt_data; -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries @@ -247,15 +210,6 @@ extern int strlen (const char *); #endif /* not __GNU_LIBRARY__ */ -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - #ifdef _LIBC /* Stored original parameters. XXX This is no good solution. We should rather copy the args so @@ -269,14 +223,11 @@ extern char **__libc_argv; # ifdef USE_NONOPTION_FLAGS /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; # endif # ifdef USE_NONOPTION_FLAGS # define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ + if (d->__nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ @@ -299,16 +250,17 @@ static int nonoption_flags_len; the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ -static void exchange (char **); +static void exchange (char **, struct _getopt_data *); #endif static void -exchange (argv) +exchange (argv, d) char **argv; + struct _getopt_data *d; { - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. @@ -320,19 +272,19 @@ exchange (argv) /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) + if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; + d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; + d->__nonoption_flags_max_len), + '\0', top + 1 - d->__nonoption_flags_max_len); + d->__nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } @@ -378,76 +330,78 @@ exchange (argv) /* Update records for the slots the non-options now occupy. */ - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); +static const char *_getopt_initialize (int, char *const *, const char *, + struct _getopt_data *); #endif static const char * -_getopt_initialize (argc, argv, optstring) +_getopt_initialize (argc, argv, optstring, d) int argc; char *const *argv; const char *optstring; + struct _getopt_data *d; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ - first_nonopt = last_nonopt = optind; + d->__first_nonopt = d->__last_nonopt = d->optind; - nextchar = NULL; + d->__nextchar = NULL; - posixly_correct = getenv ("POSIXLY_CORRECT"); + d->__posixly_correct = !!getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { - ordering = RETURN_IN_ORDER; + d->__ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { - ordering = REQUIRE_ORDER; + d->__ordering = REQUIRE_ORDER; ++optstring; } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; else - ordering = PERMUTE; + d->__ordering = PERMUTE; #if defined _LIBC && defined USE_NONOPTION_FLAGS - if (posixly_correct == NULL + if (!d->__posixly_correct && argc == __libc_argc && argv == __libc_argv) { - if (nonoption_flags_max_len == 0) + if (d->__nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; + d->__nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; + int len = d->__nonoption_flags_max_len = strlen (orig_str); + if (d->__nonoption_flags_max_len < argc) + d->__nonoption_flags_max_len = argc; __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); + (char *) malloc (d->__nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; + d->__nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); + '\0', d->__nonoption_flags_max_len - len); } } - nonoption_flags_len = nonoption_flags_max_len; + d->__nonoption_flags_len = d->__nonoption_flags_max_len; } else - nonoption_flags_len = 0; + d->__nonoption_flags_len = 0; #endif return optstring; @@ -510,29 +464,30 @@ _getopt_initialize (argc, argv, optstrin long-named options. */ int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) +_getopt_internal_r (argc, argv, optstring, longopts, longind, long_only, d) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; + struct _getopt_data *d; { - int print_errors = opterr; + int print_errors = d->opterr; if (optstring[0] == ':') print_errors = 0; if (argc < 1) return -1; - optarg = NULL; + d->optarg = NULL; - if (optind == 0 || !__getopt_initialized) + if (d->optind == 0 || !d->__initialized) { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; + if (d->optind == 0) + d->optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring, d); + d->__initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. @@ -540,40 +495,41 @@ _getopt_internal (argc, argv, optstring, from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ + || (d->optind < d->__nonoption_flags_len \ + && __getopt_nonoption_flags[d->optind] == '1')) #else -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') #endif - if (nextchar == NULL || *nextchar == '\0') + if (d->__nextchar == NULL || *d->__nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; - if (ordering == PERMUTE) + if (d->__ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; } /* The special ARGV-element `--' means premature end of options. @@ -581,28 +537,29 @@ _getopt_internal (argc, argv, optstring, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ - if (optind != argc && !strcmp (argv[optind], "--")) + if (d->optind != argc && !strcmp (argv[d->optind], "--")) { - optind++; + d->optind++; - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; - optind = argc; + d->optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ - if (optind == argc) + if (d->optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; return -1; } @@ -611,17 +568,17 @@ _getopt_internal (argc, argv, optstring, if (NONOPTION_P) { - if (ordering == REQUIRE_ORDER) + if (d->__ordering == REQUIRE_ORDER) return -1; - optarg = argv[optind++]; + d->optarg = argv[d->optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); + d->__nextchar = (argv[d->optind] + 1 + + (longopts != NULL && argv[d->optind][1] == '-')); } /* Decode the current option-ARGV-element. */ @@ -640,8 +597,9 @@ _getopt_internal (argc, argv, optstring, This distinction seems to be the most useful approach. */ if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + && (argv[d->optind][1] == '-' + || (long_only && (argv[d->optind][2] + || !my_index (optstring, argv[d->optind][1]))))) { char *nameend; const struct option *p; @@ -651,15 +609,15 @@ _getopt_internal (argc, argv, optstring, int indfound = -1; int option_index; - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) { - if ((unsigned int) (nameend - nextchar) + if ((unsigned int) (nameend - d->__nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ @@ -690,7 +648,7 @@ _getopt_internal (argc, argv, optstring, char *buf; if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]) >= 0) + argv[0], argv[d->optind]) >= 0) { _IO_flockfile (stderr); @@ -709,25 +667,25 @@ _getopt_internal (argc, argv, optstring, } #else fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); + argv[0], argv[d->optind]); #endif } - nextchar += strlen (nextchar); - optind++; - optopt = 0; + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; - optind++; + d->optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) - optarg = nameend + 1; + d->optarg = nameend + 1; else { if (print_errors) @@ -737,7 +695,7 @@ _getopt_internal (argc, argv, optstring, int n; #endif - if (argv[optind - 1][1] == '-') + if (argv[d->optind - 1][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO @@ -756,12 +714,13 @@ _getopt_internal (argc, argv, optstring, #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("\ %s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], + argv[0], argv[d->optind - 1][0], pfound->name); #else fprintf (stderr, _("\ %s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); + argv[0], argv[d->optind - 1][0], + pfound->name); #endif } @@ -787,16 +746,16 @@ _getopt_internal (argc, argv, optstring, #endif } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); - optopt = pfound->val; + d->optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { - if (optind < argc) - optarg = argv[optind++]; + if (d->optind < argc) + d->optarg = argv[d->optind++]; else { if (print_errors) @@ -806,7 +765,7 @@ _getopt_internal (argc, argv, optstring, if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]) >= 0) + argv[0], argv[d->optind - 1]) >= 0) { _IO_flockfile (stderr); @@ -827,15 +786,15 @@ _getopt_internal (argc, argv, optstring, #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); + argv[0], argv[d->optind - 1]); #endif } - nextchar += strlen (nextchar); - optopt = pfound->val; + d->__nextchar += strlen (d->__nextchar); + d->optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) @@ -850,8 +809,8 @@ _getopt_internal (argc, argv, optstring, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) + if (!long_only || argv[d->optind][1] == '-' + || my_index (optstring, *d->__nextchar) == NULL) { if (print_errors) { @@ -860,15 +819,15 @@ _getopt_internal (argc, argv, optstring, int n; #endif - if (argv[optind][1] == '-') + if (argv[d->optind][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); + argv[0], d->__nextchar); #else fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); + argv[0], d->__nextchar); #endif } else @@ -876,10 +835,10 @@ _getopt_internal (argc, argv, optstring, /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); + argv[0], argv[d->optind][0], d->__nextchar); #else fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); + argv[0], argv[d->optind][0], d->__nextchar); #endif } @@ -903,9 +862,9 @@ _getopt_internal (argc, argv, optstring, } #endif } - nextchar = (char *) ""; - optind++; - optopt = 0; + d->__nextchar = (char *) ""; + d->optind++; + d->optopt = 0; return '?'; } } @@ -913,12 +872,12 @@ _getopt_internal (argc, argv, optstring, /* Look at and handle the next short option-character. */ { - char c = *nextchar++; + char c = *d->__nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; + if (*d->__nextchar == '\0') + ++d->optind; if (temp == NULL || c == ':') { @@ -929,7 +888,7 @@ _getopt_internal (argc, argv, optstring, int n; #endif - if (posixly_correct) + if (d->__posixly_correct) { /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO @@ -969,7 +928,7 @@ _getopt_internal (argc, argv, optstring, } #endif } - optopt = c; + d->optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ @@ -984,14 +943,14 @@ _getopt_internal (argc, argv, optstring, int option_index; /* This is an option that requires an argument. */ - if (*nextchar != '\0') + if (*d->__nextchar != '\0') { - optarg = nextchar; + d->optarg = d->__nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ - optind++; + d->optind++; } - else if (optind == argc) + else if (d->optind == argc) { if (print_errors) { @@ -1023,7 +982,7 @@ _getopt_internal (argc, argv, optstring, argv[0], c); #endif } - optopt = c; + d->optopt = c; if (optstring[0] == ':') c = ':'; else @@ -1031,22 +990,23 @@ _getopt_internal (argc, argv, optstring, return c; } else - /* We already incremented `optind' once; + /* We already incremented `d->optind' once; increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; + d->optarg = argv[d->optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; + nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) + if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; @@ -1072,7 +1032,7 @@ _getopt_internal (argc, argv, optstring, char *buf; if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]) >= 0) + argv[0], argv[d->optind]) >= 0) { _IO_flockfile (stderr); @@ -1091,11 +1051,11 @@ _getopt_internal (argc, argv, optstring, } #else fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); + argv[0], argv[d->optind]); #endif } - nextchar += strlen (nextchar); - optind++; + d->__nextchar += strlen (d->__nextchar); + d->optind++; return '?'; } if (pfound != NULL) @@ -1106,7 +1066,7 @@ _getopt_internal (argc, argv, optstring, /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) - optarg = nameend + 1; + d->optarg = nameend + 1; else { if (print_errors) @@ -1141,14 +1101,14 @@ _getopt_internal (argc, argv, optstring, #endif } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); return '?'; } } else if (pfound->has_arg == 1) { - if (optind < argc) - optarg = argv[optind++]; + if (d->optind < argc) + d->optarg = argv[d->optind++]; else { if (print_errors) @@ -1158,7 +1118,7 @@ _getopt_internal (argc, argv, optstring, if (__asprintf (&buf, _("\ %s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]) >= 0) + argv[0], argv[d->optind - 1]) >= 0) { _IO_flockfile (stderr); @@ -1179,14 +1139,14 @@ _getopt_internal (argc, argv, optstring, #else fprintf (stderr, _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); + argv[0], argv[d->optind - 1]); #endif } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); return optstring[0] == ':' ? ':' : '?'; } } - nextchar += strlen (nextchar); + d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) @@ -1196,7 +1156,7 @@ _getopt_internal (argc, argv, optstring, } return pfound->val; } - nextchar = NULL; + d->__nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') @@ -1204,26 +1164,26 @@ _getopt_internal (argc, argv, optstring, if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') + if (*d->__nextchar != '\0') { - optarg = nextchar; - optind++; + d->optarg = d->__nextchar; + d->optind++; } else - optarg = NULL; - nextchar = NULL; + d->optarg = NULL; + d->__nextchar = NULL; } else { /* This is an option that requires an argument. */ - if (*nextchar != '\0') + if (*d->__nextchar != '\0') { - optarg = nextchar; + d->optarg = d->__nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ - optind++; + d->optind++; } - else if (optind == argc) + else if (d->optind == argc) { if (print_errors) { @@ -1256,7 +1216,7 @@ _getopt_internal (argc, argv, optstring, argv[0], c); #endif } - optopt = c; + d->optopt = c; if (optstring[0] == ':') c = ':'; else @@ -1265,8 +1225,8 @@ _getopt_internal (argc, argv, optstring, else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; } } return c; @@ -1274,6 +1234,35 @@ _getopt_internal (argc, argv, optstring, } int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int result; + + __getopt_data.optind = optind; + __getopt_data.opterr = opterr; + __getopt_data.optarg = optarg; + __getopt_data.optopt = optopt; + __getopt_data.__initialized = __getopt_initialized; + + result = _getopt_internal_r (argc, argv, optstring, longopts, + longind, long_only, &__getopt_data); + + optind = __getopt_data.optind; + opterr = __getopt_data.opterr; + optarg = __getopt_data.optarg; + optopt = __getopt_data.optopt; + __getopt_initialized = __getopt_data.__initialized; + + return result; +} + +int getopt (argc, argv, optstring) int argc; char *const *argv; diff -rup libc-old/posix/getopt.h libc/posix/getopt.h --- libc-old/posix/getopt.h 2004-03-08 01:38:12.000000000 +0100 +++ libc/posix/getopt.h 2004-03-08 01:40:38.000000000 +0100 @@ -170,11 +170,6 @@ extern int getopt_long_only (int ___argc const struct option *__longopts, int *__longind) __THROW; -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int ___argc, char *const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only); # endif #else /* not __STDC__ */ extern int getopt (); @@ -182,7 +177,6 @@ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); -extern int _getopt_internal (); # endif #endif /* __STDC__ */ diff -rup libc-old/posix/getopt1.c libc/posix/getopt1.c --- libc-old/posix/getopt1.c 2004-03-08 01:38:12.000000000 +0100 +++ libc/posix/getopt1.c 2004-03-08 01:38:47.000000000 +0100 @@ -1,5 +1,5 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -78,6 +78,19 @@ getopt_long (argc, argv, options, long_o return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } +int +__getopt_long_r (argc, argv, options, long_options, opt_index, d) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; + struct _getopt_data *d; +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 0, d); +} + /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option @@ -94,10 +107,18 @@ getopt_long_only (argc, argv, options, l return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } -# ifdef _LIBC -libc_hidden_def (getopt_long) -libc_hidden_def (getopt_long_only) -# endif +int +__getopt_long_only_r (argc, argv, options, long_options, opt_index, d) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; + struct _getopt_data *d; +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 1, d); +} #endif /* Not ELIDE_CODE. */