summaryrefslogtreecommitdiff
path: root/getopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'getopt.c')
-rw-r--r--getopt.c161
1 files changed, 111 insertions, 50 deletions
diff --git a/getopt.c b/getopt.c
index 6521f48e..4de0b9a0 100644
--- a/getopt.c
+++ b/getopt.c
@@ -2,8 +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
- Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,9 +16,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>. */
@@ -49,14 +47,23 @@
# endif
#endif
+/* !@#$%^&*() !!!!!!!! */
+#ifdef GAWK
+#undef ELIDE_CODE
+#endif
+
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
+#if defined (__GNU_LIBRARY__) || defined (__CYGWIN__) || defined(__DJGPP__) || defined(__APPLE__) || defined(__MINGW32__) || defined(__sun) /* Illumos */
+/* Don't include stdlib.h for
+ * non-GNU C libraries
+ * non-Cygwin
+ * non-DJGPP
+ * non-MinGW
+ * because some of them contain conflicting prototypes for getopt. */
# include <stdlib.h>
# include <unistd.h>
#endif /* GNU C library. */
@@ -74,7 +81,7 @@
# define _(msgid) gettext (msgid)
#endif
-#if defined _LIBC && defined USE_IN_LIBIO
+#if defined _LIBC
# include <wchar.h>
#endif
@@ -229,7 +236,7 @@ exchange (char **argv, struct _getopt_data *d)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
- register int i;
+ int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
@@ -246,7 +253,7 @@ exchange (char **argv, struct _getopt_data *d)
{
/* Top segment is the short one. */
int len = top - middle;
- register int i;
+ int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
@@ -526,23 +533,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,35 +573,78 @@ _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;
+ {
+ /* Second or later nonexact match found. */
+ 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;
-
- if (__asprintf (&buf, _("%s: option '%s' is ambiguous\n"),
- argv[0], argv[d->optind]) >= 0)
+ struct option_list first;
+ first.p = pfound;
+ first.next = ambig_list;
+ first.needs_free = 0;
+ ambig_list = &first;
+
+#if defined _LIBC
+ char *buf = NULL;
+ size_t buflen = 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 (__glibc_likely (fclose (fp) != EOF))
+ {
+ _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
+ {
+ 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 +667,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 +675,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 +688,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 +701,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 +734,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 +785,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 +793,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 +804,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 +813,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 +851,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);
@@ -838,6 +894,9 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
int indfound = 0;
int option_index;
+ if (longopts == NULL)
+ goto no_longs;
+
/* This is an option that requires an argument. */
if (*d->__nextchar != '\0')
{
@@ -850,7 +909,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 +983,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 +1023,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 +1062,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,8 +1104,10 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
}
return pfound->val;
}
- d->__nextchar = NULL;
- return 'W'; /* Let the application handle it. */
+
+ no_longs:
+ d->__nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
}
if (temp[1] == ':')
{
@@ -1076,7 +1137,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, _("\