diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2012-03-16 15:25:40 +0200 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2012-03-16 15:25:40 +0200 |
commit | a19298ed002eb20d91c37fd5067de18466211f83 (patch) | |
tree | 054a08cd961bff2b6a5e01973f194e1e6b6a236f /getopt.c | |
parent | 58b5aa30bc83d715b1d0708e686eed50ccf11f15 (diff) | |
download | egawk-a19298ed002eb20d91c37fd5067de18466211f83.tar.gz egawk-a19298ed002eb20d91c37fd5067de18466211f83.tar.bz2 egawk-a19298ed002eb20d91c37fd5067de18466211f83.zip |
Sync from GLIBC.
Diffstat (limited to 'getopt.c')
-rw-r--r-- | getopt.c | 118 |
1 files changed, 85 insertions, 33 deletions
@@ -2,7 +2,7 @@ NOTE: getopt is 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-1996,1998-2004,2008,2009,2010 + Copyright (C) 1987-1996,1998-2004,2008,2009,2010,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -17,9 +17,8 @@ Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA. */ + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. Ditto for AIX 3.2 and <stdlib.h>. */ @@ -74,7 +73,7 @@ # define _(msgid) gettext (msgid) #endif -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC # include <wchar.h> #endif @@ -526,23 +525,29 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, || !strchr (optstring, argv[d->optind][1]))))) { char *nameend; + unsigned int namelen; const struct option *p; const struct option *pfound = NULL; + struct option_list + { + const struct option *p; + struct option_list *next; + int needs_free; + } *ambig_list = NULL; int exact = 0; - int ambig = 0; int indfound = -1; int option_index; for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; + namelen = nameend - d->__nextchar; /* 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, d->__nextchar, nameend - d->__nextchar)) + if (!strncmp (p->name, d->__nextchar, namelen)) { - if ((unsigned int) (nameend - d->__nextchar) - == (unsigned int) strlen (p->name)) + if (namelen == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; @@ -560,19 +565,46 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) + { /* Second or later nonexact match found. */ - ambig = 1; + struct option_list *newp = malloc (sizeof (*newp)); + newp->p = p; + newp->needs_free = 1; + newp->next = ambig_list; + ambig_list = newp; + } } - if (ambig && !exact) + if (ambig_list != NULL && !exact) { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; + struct option_list first; + first.p = pfound; + first.next = ambig_list; + ambig_list = &first; - if (__asprintf (&buf, _("%s: option '%s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) +#if defined _LIBC + char *buf = NULL; + size_t buflen = 0; + + FILE *fp = open_memstream (&buf, &buflen); + if (fp != NULL) + { + fprintf (fp, + _("%s: option '%s' is ambiguous; possibilities:"), + argv[0], argv[d->optind]); + + do + { + fprintf (fp, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); + + fputc_unlocked ('\n', fp); + + if (__builtin_expect (fclose (fp) != EOF, 1)) { _IO_flockfile (stderr); @@ -586,9 +618,24 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, free (buf); } + } #else - fprintf (stderr, _("%s: option '%s' is ambiguous\n"), + fprintf (stderr, + _("%s: option '%s' is ambiguous; possibilities:"), argv[0], argv[d->optind]); + do + { + struct option_list *tmp_next; + + fprintf (stderr, " '--%s'", ambig_list->p->name); + tmp_next = ambig_list->next; + if (ambig_list->needs_free) + free(ambig_list); + ambig_list = tmp_next; + } + while (ambig_list != NULL); + + fputc ('\n', stderr); #endif } d->__nextchar += strlen (d->__nextchar); @@ -611,7 +658,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; int n; #endif @@ -619,7 +666,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, if (argv[d->optind - 1][1] == '-') { /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC n = __asprintf (&buf, _("\ %s: option '--%s' doesn't allow an argument\n"), argv[0], pfound->name); @@ -632,7 +679,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, else { /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC n = __asprintf (&buf, _("\ %s: option '%c%s' doesn't allow an argument\n"), argv[0], argv[d->optind - 1][0], @@ -645,7 +692,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, #endif } -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC if (n >= 0) { _IO_flockfile (stderr); @@ -678,7 +725,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; if (__asprintf (&buf, _("\ @@ -729,7 +776,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; int n; #endif @@ -737,7 +784,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, if (argv[d->optind][1] == '-') { /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC n = __asprintf (&buf, _("%s: unrecognized option '--%s'\n"), argv[0], d->__nextchar); #else @@ -748,7 +795,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, else { /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC n = __asprintf (&buf, _("%s: unrecognized option '%c%s'\n"), argv[0], argv[d->optind][0], d->__nextchar); #else @@ -757,7 +804,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, #endif } -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC if (n >= 0) { _IO_flockfile (stderr); @@ -795,19 +842,19 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; int n; #endif -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC n = __asprintf (&buf, _("%s: invalid option -- '%c'\n"), argv[0], c); #else fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); #endif -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC if (n >= 0) { _IO_flockfile (stderr); @@ -830,6 +877,9 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { + if (longopts == NULL) + goto no_longs; + char *nameend; const struct option *p; const struct option *pfound = NULL; @@ -850,7 +900,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; if (__asprintf (&buf, @@ -924,7 +974,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), @@ -964,7 +1014,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; if (__asprintf (&buf, _("\ @@ -1003,7 +1053,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; if (__asprintf (&buf, _("\ @@ -1045,6 +1095,8 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, } return pfound->val; } + + no_longs: d->__nextchar = NULL; return 'W'; /* Let the application handle it. */ } @@ -1076,7 +1128,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring, { if (print_errors) { -#if defined _LIBC && defined USE_IN_LIBIO +#if defined _LIBC char *buf; if (__asprintf (&buf, _("\ |