diff options
author | Jim Meyering <jim@meyering.net> | 2004-03-23 17:33:25 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2004-03-23 17:33:25 +0000 |
commit | 42401183af3f2d950ef528754106c973ceb8dffd (patch) | |
tree | bc35d04dd6a31d72d64bc00851e24254d2f13fec | |
parent | 546413e85adb50c850fcb63bd98d30d7c420e540 (diff) | |
download | coreutils-42401183af3f2d950ef528754106c973ceb8dffd.tar.xz |
Sync from gnulib.
-rw-r--r-- | lib/getopt.c | 481 | ||||
-rw-r--r-- | lib/getopt.h | 33 | ||||
-rw-r--r-- | lib/getopt1.c | 42 |
3 files changed, 307 insertions, 249 deletions
diff --git a/lib/getopt.c b/lib/getopt.c index 6dcdbebf5..8f017f87b 100644 --- a/lib/getopt.c +++ b/lib/getopt.c @@ -2,11 +2,8 @@ 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, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, - Inc. - + 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. This program is free software; you can redistribute it and/or modify @@ -72,10 +69,9 @@ #ifdef _LIBC # include <libintl.h> #else -/* This is for other GNU distributions with internationalized messages. */ # include "gettext.h" +# define _(msgid) gettext (msgid) #endif -#define _(msgid) gettext (msgid) #if defined _LIBC && defined USE_IN_LIBIO # include <wchar.h> @@ -100,6 +96,7 @@ they can distinguish the relative order of options and other arguments. */ #include "getopt.h" +#include "getopt_int.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, @@ -124,21 +121,6 @@ char *optarg; /* 1003.2 says this must be 1 before any call. */ int optind = 1; -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -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. */ @@ -150,44 +132,12 @@ 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. +static struct _getopt_data getopt_data; - 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 enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; -#ifndef __GNU_LIBRARY__ +#ifndef __GNU_LIBRARY__ /* Avoid depending on library functions or files whose names are inconsistent. */ @@ -198,15 +148,6 @@ extern char *getenv (); #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 @@ -220,14 +161,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]; \ @@ -250,11 +188,11 @@ static int nonoption_flags_len; the new indices of the non-options in ARGV after they are moved. */ static void -exchange (char **argv) +exchange (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. @@ -266,19 +204,19 @@ exchange (char **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; } } @@ -324,70 +262,71 @@ exchange (char **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. */ static const char * -_getopt_initialize (int argc, char *const *argv, const char *optstring) +_getopt_initialize (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; @@ -450,25 +389,25 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring) long-named options. */ int -_getopt_internal (int argc, char *const *argv, - const char *optstring, const struct option *longopts, - int *longind, int long_only) +_getopt_internal_r (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. @@ -476,40 +415,41 @@ _getopt_internal (int argc, char *const *argv, 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. @@ -517,28 +457,29 @@ _getopt_internal (int argc, char *const *argv, 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; } @@ -547,17 +488,17 @@ _getopt_internal (int argc, char *const *argv, 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. */ @@ -576,9 +517,9 @@ _getopt_internal (int argc, char *const *argv, This distinction seems to be the most useful approach. */ if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only - && (argv[optind][2] || !strchr (optstring, argv[optind][1]))))) + && (argv[d->optind][1] == '-' + || (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))))) { char *nameend; const struct option *p; @@ -588,15 +529,15 @@ _getopt_internal (int argc, char *const *argv, 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. */ @@ -627,37 +568,44 @@ _getopt_internal (int argc, char *const *argv, 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); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #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) @@ -667,7 +615,7 @@ _getopt_internal (int argc, char *const *argv, int n; #endif - if (argv[optind - 1][1] == '-') + if (argv[d->optind - 1][1] == '-') { /* --option */ #if defined _LIBC && defined USE_IN_LIBIO @@ -686,38 +634,48 @@ _getopt_internal (int argc, char *const *argv, #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 } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #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) @@ -727,27 +685,36 @@ _getopt_internal (int argc, char *const *argv, 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); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #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) @@ -762,8 +729,8 @@ _getopt_internal (int argc, char *const *argv, 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] == '-' - || strchr (optstring, *nextchar) == NULL) + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) { if (print_errors) { @@ -772,15 +739,15 @@ _getopt_internal (int argc, char *const *argv, 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 @@ -788,28 +755,36 @@ _getopt_internal (int argc, char *const *argv, /* +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 } #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #endif } - nextchar = (char *) ""; - optind++; - optopt = 0; + d->__nextchar = (char *) ""; + d->optind++; + d->optopt = 0; return '?'; } } @@ -817,12 +792,12 @@ _getopt_internal (int argc, char *const *argv, /* Look at and handle the next short option-character. */ { - char c = *nextchar++; + char c = *d->__nextchar++; char *temp = strchr (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 == ':') { @@ -833,7 +808,7 @@ _getopt_internal (int argc, char *const *argv, 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 @@ -856,16 +831,24 @@ _getopt_internal (int argc, char *const *argv, #if defined _LIBC && defined USE_IN_LIBIO if (n >= 0) { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #endif } - optopt = c; + d->optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ @@ -880,14 +863,14 @@ _getopt_internal (int argc, char *const *argv, 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) { @@ -899,11 +882,19 @@ _getopt_internal (int argc, char *const *argv, _("%s: option requires an argument -- %c\n"), argv[0], c) >= 0) { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #else @@ -911,7 +902,7 @@ _getopt_internal (int argc, char *const *argv, argv[0], c); #endif } - optopt = c; + d->optopt = c; if (optstring[0] == ':') c = ':'; else @@ -919,22 +910,23 @@ _getopt_internal (int argc, char *const *argv, 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; @@ -960,22 +952,30 @@ _getopt_internal (int argc, char *const *argv, 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); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #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) @@ -986,7 +986,7 @@ _getopt_internal (int argc, char *const *argv, /* 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) @@ -998,11 +998,20 @@ _getopt_internal (int argc, char *const *argv, %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name) >= 0) { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #else @@ -1012,14 +1021,14 @@ _getopt_internal (int argc, char *const *argv, #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) @@ -1029,26 +1038,35 @@ _getopt_internal (int argc, char *const *argv, 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); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #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) @@ -1058,7 +1076,7 @@ _getopt_internal (int argc, char *const *argv, } return pfound->val; } - nextchar = NULL; + d->__nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') @@ -1066,26 +1084,26 @@ _getopt_internal (int argc, char *const *argv, 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) { @@ -1097,11 +1115,19 @@ _getopt_internal (int argc, char *const *argv, %s: option requires an argument -- %c\n"), argv[0], c) >= 0) { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + if (_IO_fwide (stderr, 0) > 0) __fwprintf (stderr, L"%s", buf); else fputs (buf, stderr); + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + free (buf); } #else @@ -1110,7 +1136,7 @@ _getopt_internal (int argc, char *const *argv, argv[0], c); #endif } - optopt = c; + d->optopt = c; if (optstring[0] == ':') c = ':'; else @@ -1119,8 +1145,8 @@ _getopt_internal (int argc, char *const *argv, 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; @@ -1128,6 +1154,25 @@ _getopt_internal (int argc, char *const *argv, } int +_getopt_internal (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; + + result = _getopt_internal_r (argc, argv, optstring, longopts, + longind, long_only, &getopt_data); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +int getopt (int argc, char *const *argv, const char *optstring) { return _getopt_internal (argc, argv, optstring, diff --git a/lib/getopt.h b/lib/getopt.h index 5e15191e6..c61768c69 100644 --- a/lib/getopt.h +++ b/lib/getopt.h @@ -1,8 +1,6 @@ /* Declarations for getopt. - - Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, - 1999, 2001, 2003 Free Software Foundation, Inc. - + Copyright (C) 1989-1994,1996-1999,2001,2003,2004 + Free Software Foundation, Inc. This file is part of the GNU C Library. This program is free software; you can redistribute it and/or modify @@ -36,6 +34,17 @@ # include <ctype.h> #endif +#ifndef __THROW +# ifndef __GNUC_PREREQ +# define __GNUC_PREREQ(maj, min) (0) +# endif +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + #ifdef __cplusplus extern "C" { #endif @@ -80,7 +89,7 @@ extern int optopt; The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. + optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but @@ -139,7 +148,8 @@ struct option /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ -extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __THROW; #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ @@ -147,16 +157,13 @@ extern int getopt (); #ifndef __need_getopt extern int getopt_long (int ___argc, char *const *___argv, const char *__shortopts, - const struct option *__longopts, int *__longind); + const struct option *__longopts, int *__longind) + __THROW; extern int getopt_long_only (int ___argc, char *const *___argv, const char *__shortopts, - const struct option *__longopts, int *__longind); + 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 #ifdef __cplusplus diff --git a/lib/getopt1.c b/lib/getopt1.c index 3288c7261..7671eba37 100644 --- a/lib/getopt1.c +++ b/lib/getopt1.c @@ -1,8 +1,6 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. - - Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, - 1997, 1998, 2003 Free Software Foundation, Inc. - + 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. This program is free software; you can redistribute it and/or modify @@ -28,6 +26,7 @@ #else # include "getopt.h" #endif +#include "getopt_int.h" #include <stdio.h> @@ -61,34 +60,41 @@ #endif int -getopt_long (int argc, - char *const *argv, - const char *options, - const struct option *long_options, - int *opt_index) +getopt_long (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } +int +_getopt_long_r (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 instead. */ int -getopt_long_only (int argc, - char *const *argv, - const char *options, - const struct option *long_options, - int *opt_index) +getopt_long_only (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) { 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 (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. */ |