From 70aa91cc187065c920bb3205e65339a1897a6cfc Mon Sep 17 00:00:00 2001 From: James Youngman Date: Thu, 26 May 2011 01:45:13 +0100 Subject: [PATCH] getopt: for ambiguous options, enumerate the possibilities. * lib/getopt.c (_getopt_internal_r): Merge glibc change printing the ambiguous options when an ambiguous prefix is given. This was http://sourceware.org/bugzilla/show_bug.cgi?id=7101. The merged glibc change was http://sourceware.org/git/?p=glibc.git;a=commit;h=bd25564e1e98910ed69043ed6a6f884ce60e5780. --- ChangeLog | 9 +++++++ lib/getopt.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index e3c4d221a..70293f767 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-15 James Youngman + + getopt: for ambiguous options, enumerate the possibilities. + * lib/getopt.c (_getopt_internal_r): Merge glibc change printing + the ambiguous options when an ambiguous prefix is given. This was + http://sourceware.org/bugzilla/show_bug.cgi?id=7101. The merged + glibc change was + http://sourceware.org/git/?p=glibc.git;a=commit;h=bd25564e1e98910ed69043ed6a6f884ce60e5780. + 2011-05-25 Eric Blake getcwd: work around mingw bug diff --git a/lib/getopt.c b/lib/getopt.c index c8b301363..ee96d972d 100644 --- a/lib/getopt.c +++ b/lib/getopt.c @@ -479,8 +479,14 @@ _getopt_internal_r (int argc, char **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; + } *ambig_list = NULL; int exact = 0; int ambig = 0; int indfound = -1; @@ -488,14 +494,14 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, 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; @@ -513,35 +519,71 @@ _getopt_internal_r (int argc, char **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; + { + /* Second or later nonexact match found. */ + struct option_list *newp = malloc (sizeof (*newp)); + newp->p = p; + newp->next = ambig_list; + ambig_list = newp; + } } - if (ambig && !exact) + if (ambig_list != NULL && !exact) { if (print_errors) { + struct option_list first; + first.p = pfound; + first.next = ambig_list; + ambig_list = &first; + #if defined _LIBC && defined USE_IN_LIBIO - char *buf; + char *buf = NULL; + size_t buflen = 0; - if (__asprintf (&buf, _("%s: option '%s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) + FILE *fp = open_memstream (&buf, &buflen); + if (fp != NULL) { - _IO_flockfile (stderr); + fprintf (fp, + _("%s: option '%s' is ambiguous; possibilities:"), + argv[0], argv[d->optind]); - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + do + { + fprintf (fp, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); - __fxprintf (NULL, "%s", buf); + fputc_unlocked ('\n', fp); - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); + if (__builtin_expect (fclose (fp) != EOF, 1)) + { + _IO_flockfile (stderr); - free (buf); + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + 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 + { + fprintf (stderr, " '--%s'", ambig_list->p->name); + ambig_list = ambig_list->next; + } + while (ambig_list != NULL); + + fputc ('\n', stderr); #endif } d->__nextchar += strlen (d->__nextchar); @@ -550,6 +592,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, return '?'; } + while (ambig_list != NULL) + { + struct option_list *pn = ambig_list->next; + free (ambig_list); + ambig_list = pn; + } + if (pfound != NULL) { option_index = indfound; -- 2.11.0