[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] getopt: match recent glibc fixes and posix ruling
From: |
Eric Blake |
Subject: |
[PATCH 2/2] getopt: match recent glibc fixes and posix ruling |
Date: |
Sat, 10 Apr 2010 13:29:36 -0600 |
The POSIX folks admitted that codifying the behavior of GNU
getopt on a leading '+' in optstring is worthwhile, for writing
programs such as env(1) even when POSIXLY_CORRECT is not defined.
http://austingroupbugs.net/view.php?id=191
Although it technically isn't part of POSIX 2008, there are
enough existing non-GNU implementations that already comply
that it is worth enforcing.
* tests/test-getopt.h (test_getopt): Strengthen tests of leading
'+' handling.
* tests/test-getopt_long.h (test_getopt_long): Strengthen test of
'W;' handling.
* m4/getopt.m4 (gl_GETOPT_CHECK_HEADERS): Detect glibc 2.11 bug.
* doc/posix-functions/getopt.texi (getopt): Document this.
* doc/glibc-functions/getopt_long.texi (getopt_long): Likewise.
* doc/glibc-functions/getopt_long_only.texi (getopt_long_only):
Likewise.
---
ChangeLog | 11 +++
doc/glibc-functions/getopt_long.texi | 15 ++--
doc/glibc-functions/getopt_long_only.texi | 15 ++--
doc/posix-functions/getopt.texi | 13 ++--
m4/getopt.m4 | 24 ++++++-
tests/test-getopt.h | 112 +++++++++++++++++++++++++++--
tests/test-getopt_long.h | 17 +++--
7 files changed, 173 insertions(+), 34 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index fea598f..5c72a7e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2010-04-10 Eric Blake <address@hidden>
+ getopt: match recent glibc fixes and posix ruling
+ * tests/test-getopt.h (test_getopt): Strengthen tests of leading
+ '+' handling.
+ * tests/test-getopt_long.h (test_getopt_long): Strengthen test of
+ 'W;' handling.
+ * m4/getopt.m4 (gl_GETOPT_CHECK_HEADERS): Detect glibc 2.11 bug.
+ * doc/posix-functions/getopt.texi (getopt): Document this.
+ * doc/glibc-functions/getopt_long.texi (getopt_long): Likewise.
+ * doc/glibc-functions/getopt_long_only.texi (getopt_long_only):
+ Likewise.
+
getopt: merge bug fixes from glibc
* lib/getopt.c (_getopt_internal_r): Use correct message for 'W;'
diagnostics. Honor '+:' correctly. Reject ';'.
diff --git a/doc/glibc-functions/getopt_long.texi
b/doc/glibc-functions/getopt_long.texi
index 0472514..b06797d 100644
--- a/doc/glibc-functions/getopt_long.texi
+++ b/doc/glibc-functions/getopt_long.texi
@@ -7,6 +7,14 @@ getopt_long
Portability problems fixed by Gnulib:
@itemize
@item
+The function @code{getopt_long} does not obey the combination of
address@hidden and @samp{:} flags in the options string on some platforms:
+glibc 2.11.
address@hidden
+The use of @samp{W;} in the optstring argument to does not always
+allow @code{-W foo} to behave synonymously with @code{--foo}:
+glibc 2.11.
address@hidden
The function @code{getopt_long} does not support the @samp{+} flag in
the options string on some platforms:
MacOS X 10.5, AIX 5.2, OSF/1 5.1, Solaris 10.
@@ -29,11 +37,4 @@ getopt_long
Portability problems not fixed by Gnulib:
@itemize
address@hidden
-The glibc extension of using @samp{W;} in the optstring argument to
-allow @code{-W foo} to behave synonymously with @code{--foo} is not
-very reliable, even in glibc.
address@hidden
-Mixing a leading @samp{-} or @samp{+} with a leading @samp{:} in the
-optstring argument has inconsistent effects across platforms.
@end itemize
diff --git a/doc/glibc-functions/getopt_long_only.texi
b/doc/glibc-functions/getopt_long_only.texi
index 13edfb4..73352a1 100644
--- a/doc/glibc-functions/getopt_long_only.texi
+++ b/doc/glibc-functions/getopt_long_only.texi
@@ -7,6 +7,14 @@ getopt_long_only
Portability problems fixed by Gnulib:
@itemize
@item
+The function @code{getopt_long_only} does not obey the combination of
address@hidden and @samp{:} flags in the options string on some platforms:
+glibc 2.11.
address@hidden
+The use of @samp{W;} in the optstring argument to does not always
+allow @code{-W foo} to behave synonymously with @code{--foo}:
+glibc 2.11.
address@hidden
The function @code{getopt_long_only} does not support the @samp{+}
flag in the options string on some platforms:
MacOS X 10.5, AIX 5.2, OSF/1 5.1, Solaris 10.
@@ -31,14 +39,7 @@ getopt_long_only
Portability problems not fixed by Gnulib:
@itemize
@item
-The glibc extension of using @samp{W;} in the optstring argument to
-allow @code{-W foo} to behave synonymously with @code{--foo} is not
-very reliable.
address@hidden
Some implementations return success instead of reporting an ambiguity
if user's option is a prefix of two long options with the same flag:
FreeBSD.
address@hidden
-Mixing a leading @samp{-} or @samp{+} with a leading @samp{:} in the
-optstring argument has inconsistent effects across platforms.
@end itemize
diff --git a/doc/posix-functions/getopt.texi b/doc/posix-functions/getopt.texi
index 822dbb3..b55fd26 100644
--- a/doc/posix-functions/getopt.texi
+++ b/doc/posix-functions/getopt.texi
@@ -13,6 +13,10 @@ getopt
Portability problems fixed by either Gnulib module @code{getopt-posix} or
@code{getopt-gnu}:
@itemize
@item
+The function @code{getopt} does not support the @samp{+} flag in the options
+string on some platforms:
+MacOS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10.
address@hidden
The @code{getopt} function keeps some internal state that cannot be explicitly
reset on some platforms:
mingw.
@@ -21,9 +25,9 @@ getopt
Portability problems fixed by Gnulib module @code{getopt-gnu}:
@itemize
@item
-The function @code{getopt} does not support the @samp{+} flag in the options
-string on some platforms:
-MacOS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10.
+The function @code{getopt} does not obey the combination of @samp{+}
+and @samp{:} flags in the options string on some platforms:
+glibc 2.11.
@item
The function @code{getopt} does not obey the @samp{-} flag in the options
string when @env{POSIXLY_CORRECT} is set on some platforms:
@@ -57,7 +61,4 @@ getopt
@code{optind} to 0. Other implementations provide @code{optreset},
causing a reset by setting it non-zero, although it does not
necessarily re-read @env{POSIXLY_CORRECT}.
address@hidden
-Mixing a leading @samp{-} or @samp{+} with a leading @samp{:} in the
-optstring argument has inconsistent effects across platforms.
@end itemize
diff --git a/m4/getopt.m4 b/m4/getopt.m4
index a19805e..8449034 100644
--- a/m4/getopt.m4
+++ b/m4/getopt.m4
@@ -1,4 +1,4 @@
-# getopt.m4 serial 24
+# getopt.m4 serial 25
dnl Copyright (C) 2002-2006, 2008-2010 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -88,6 +88,8 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS],
dnl strings starts with '+' and it's not the first call. Some internal state
dnl is left over from earlier calls, and neither setting optind = 0 nor
dnl setting optreset = 1 get rid of this internal state.
+ dnl glibc 2.11 mishandles optstring starting with "+:", in conflict with
+ dnl the POSIX recommendation http://austingroupbugs.net/view.php?id=191.
dnl POSIX is silent on optind vs. optreset, so we allow either behavior.
if test -z "$gl_replace_getopt"; then
AC_CACHE_CHECK([whether getopt is POSIX compatible],
@@ -167,6 +169,26 @@ main ()
if (!(optind == 1))
return 12;
}
+ /* Detect glibc 2.11 bug. */
+ {
+ int argc = 0;
+ char *argv[4];
+ int c;
+
+ argv[argc++] = "program";
+ argv[argc++] = "-b";
+ argv[argc++] = "-a";
+ argv[argc] = NULL;
+ optind = OPTIND_MIN;
+ opterr = 0;
+
+ c = getopt (argc, argv, "+:a:b");
+ if (!(c == 'b'))
+ return 13;
+ c = getopt (argc, argv, "+:a:b");
+ if (!(c == ':'))
+ return 14;
+ }
return 0;
}
diff --git a/tests/test-getopt.h b/tests/test-getopt.h
index 96db7a5..7bfef0b 100644
--- a/tests/test-getopt.h
+++ b/tests/test-getopt.h
@@ -1124,10 +1124,6 @@ test_getopt (void)
argv[argc++] = "-+";
argv[argc] = NULL;
optind = start;
- /* Suppress output, since glibc is inconsistent on whether this
- prints a message:
- http://sources.redhat.com/bugzilla/show_bug.cgi?id=11039 */
- opterr = 0;
getopt_loop (argc, argv, "+abp:q:",
&a_seen, &b_seen, &p_value, &q_value,
&non_options_count, non_options, &unrecognized, &output);
@@ -1138,7 +1134,7 @@ test_getopt (void)
ASSERT (non_options_count == 0);
ASSERT (unrecognized == '+');
ASSERT (optind == 2);
- ASSERT (!output);
+ ASSERT (output);
}
/* Check that '--' ends the argument processing. */
@@ -1263,6 +1259,108 @@ test_getopt (void)
}
}
- /* No tests of "-:..." or "+:...", due to glibc bug:
- http://sources.redhat.com/bugzilla/show_bug.cgi?id=11039 */
+ /* Require compliance with POSIX interpretation that leading '+'
+ must be supported. http://austingroupbugs.net/view.php?id=191 */
+ for (start = OPTIND_MIN; start <= 1; start++)
+ {
+ int a_seen = 0;
+ int b_seen = 0;
+ const char *p_value = NULL;
+ const char *q_value = NULL;
+ int non_options_count = 0;
+ const char *non_options[10];
+ int unrecognized = 0;
+ bool output;
+ int argc = 0;
+ const char *argv[10];
+
+ argv[argc++] = "program";
+ argv[argc++] = "donald";
+ argv[argc++] = "-p";
+ argv[argc++] = "billy";
+ argv[argc++] = "duck";
+ argv[argc++] = "-a";
+ argv[argc++] = "bar";
+ argv[argc] = NULL;
+ optind = start;
+ opterr = 1;
+ getopt_loop (argc, argv, "+:abp:q:",
+ &a_seen, &b_seen, &p_value, &q_value,
+ &non_options_count, non_options, &unrecognized, &output);
+ ASSERT (strcmp (argv[0], "program") == 0);
+ ASSERT (strcmp (argv[1], "donald") == 0);
+ ASSERT (strcmp (argv[2], "-p") == 0);
+ ASSERT (strcmp (argv[3], "billy") == 0);
+ ASSERT (strcmp (argv[4], "duck") == 0);
+ ASSERT (strcmp (argv[5], "-a") == 0);
+ ASSERT (strcmp (argv[6], "bar") == 0);
+ ASSERT (argv[7] == NULL);
+ ASSERT (a_seen == 0);
+ ASSERT (b_seen == 0);
+ ASSERT (p_value == NULL);
+ ASSERT (q_value == NULL);
+ ASSERT (non_options_count == 0);
+ ASSERT (unrecognized == 0);
+ ASSERT (optind == 1);
+ ASSERT (!output);
+ }
+ for (start = OPTIND_MIN; start <= 1; start++)
+ {
+ int a_seen = 0;
+ int b_seen = 0;
+ const char *p_value = NULL;
+ const char *q_value = NULL;
+ int non_options_count = 0;
+ const char *non_options[10];
+ int unrecognized = 0;
+ bool output;
+ int argc = 0;
+ const char *argv[10];
+
+ argv[argc++] = "program";
+ argv[argc++] = "-p";
+ argv[argc] = NULL;
+ optind = start;
+ getopt_loop (argc, argv, "+:abp:q:",
+ &a_seen, &b_seen, &p_value, &q_value,
+ &non_options_count, non_options, &unrecognized, &output);
+ ASSERT (a_seen == 0);
+ ASSERT (b_seen == 0);
+ ASSERT (p_value == NULL);
+ ASSERT (q_value == NULL);
+ ASSERT (non_options_count == 0);
+ ASSERT (unrecognized == 'p');
+ ASSERT (optind == 2);
+ ASSERT (!output);
+ }
+ for (start = OPTIND_MIN; start <= 1; start++)
+ {
+ int a_seen = 0;
+ int b_seen = 0;
+ const char *p_value = NULL;
+ const char *q_value = NULL;
+ int non_options_count = 0;
+ const char *non_options[10];
+ int unrecognized = 0;
+ bool output;
+ int argc = 0;
+ const char *argv[10];
+
+ argv[argc++] = "program";
+ argv[argc++] = "-b";
+ argv[argc++] = "-p";
+ argv[argc] = NULL;
+ optind = start;
+ getopt_loop (argc, argv, "+:abp:q:",
+ &a_seen, &b_seen, &p_value, &q_value,
+ &non_options_count, non_options, &unrecognized, &output);
+ ASSERT (a_seen == 0);
+ ASSERT (b_seen == 1);
+ ASSERT (p_value == NULL);
+ ASSERT (q_value == NULL);
+ ASSERT (non_options_count == 0);
+ ASSERT (unrecognized == 'p');
+ ASSERT (optind == 3);
+ ASSERT (!output);
+ }
}
diff --git a/tests/test-getopt_long.h b/tests/test-getopt_long.h
index 5f103c8..0e58fec 100644
--- a/tests/test-getopt_long.h
+++ b/tests/test-getopt_long.h
@@ -1151,8 +1151,7 @@ test_getopt_long (void)
&non_options_count, non_options, &unrecognized);
ASSERT (a_seen == 0);
ASSERT (b_seen == 0);
- /* glibc bug http://sources.redhat.com/bugzilla/show_bug.cgi?id=11041 */
- /* ASSERT (p_value == NULL); */
+ ASSERT (p_value == NULL);
ASSERT (q_value == NULL);
ASSERT (non_options_count == 0);
ASSERT (unrecognized == 0);
@@ -2079,8 +2078,11 @@ test_getopt_long_only (void)
opterr = 0;
c = do_getopt_long_only (argc, argv, "ab", long_options_required,
&option_index);
- /* glibc bug http://sources.redhat.com/bugzilla/show_bug.cgi?id=11041 */
- /* ASSERT (c == 1003); */
+ /* glibc getopt_long_only is intentionally different from
+ getopt_long when handling a prefix that is common to two
+ spellings, when both spellings have the same option directives.
+ BSD getopt_long_only treats both cases the same. */
+ ASSERT (c == 1003 || c == '?');
ASSERT (optind == 2);
}
{
@@ -2096,8 +2098,11 @@ test_getopt_long_only (void)
opterr = 0;
c = do_getopt_long_only (argc, argv, "abx::", long_options_required,
&option_index);
- /* glibc bug http://sources.redhat.com/bugzilla/show_bug.cgi?id=11041 */
- /* ASSERT (c == 1003); */
+ /* glibc getopt_long_only is intentionally different from
+ getopt_long when handling a prefix that is common to two
+ spellings, when both spellings have the same option directives.
+ BSD getopt_long_only treats both cases the same. */
+ ASSERT (c == 1003 || c == '?');
ASSERT (optind == 2);
ASSERT (optarg == NULL);
}
--
1.6.6.1
- [PATCH 1/2] getopt: merge bug fixes from glibc, Eric Blake, 2010/04/10
- [PATCH 2/2] getopt: match recent glibc fixes and posix ruling,
Eric Blake <=
- [PATCH 1/5] getopt-posix: avoid spurious failure on FreeBSD, Eric Blake, 2010/04/13
- [PATCH 2/5] getopt-posix: avoid spurious failure on Solaris, Eric Blake, 2010/04/13
- [PATCH 0/5] sync getopt to glibc, Eric Blake, 2010/04/13
- [PATCH 3/5] getopt-posix: detect MacOS bug, Eric Blake, 2010/04/13
- [PATCH 5/5] getopt-gnu: match recent glibc fixes and posix ruling, Eric Blake, 2010/04/13
- [PATCH 4/5] getopt: merge bug fixes from glibc, Eric Blake, 2010/04/13