diff options
author | Eric Blake <ebb9@byu.net> | 2009-11-27 17:47:21 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2009-11-27 20:29:00 -0700 |
commit | c0c5acfbe255f5542bc1c81c7aec223d95e504a6 (patch) | |
tree | 6468907399b6bf7841b10092d149a829a9bc3185 /m4 | |
parent | 6184bd1482b08fb6e3076931b73cbf09639509bc (diff) | |
download | gnulib-c0c5acfbe255f5542bc1c81c7aec223d95e504a6.tar.gz |
getopt-gnu: flush out another BSD bug
POSIX requires 'echo foo > bar; m4 -Dfoo=1 bar -Dfoo=2 bar' to
output '1' then '2'. To achieve this, m4 relies on the GNU
getopt{,_long} extension of a leading '-'. However, BSD getopt
fails to honor this extension when POSIXLY_CORRECT.
Also, BSD getopt fails to reparse POSIXLY_CORRECT from the
environment even when a reset is requested (whether by
optreset=1 or by optind=0).
* m4/getopt.m4 (gl_GETOPT_CHECK_HEADERS): Test for the bug.
* tests/test-getopt.c (main): Check POSIXLY_CORRECT first, to
flush out BSD bug.
* tests/test-getopt.h (test_getopt): End lists with NULL.
* tests/test-getopt_long.h (test_getopt_long): Likewise.
(test_getopt_long_posix): Enhance test.
* modules/getopt-posix-tests (Depends-on): Add stdbool.
* doc/glibc-functions/getopt_long.texi (getopt_long): Mention
getopt-gnu.
* doc/glibc-functions/getopt_long_only.texi (getopt_long_only):
Likewise.
Signed-off-by: Eric Blake <ebb9@byu.net>
Diffstat (limited to 'm4')
-rw-r--r-- | m4/getopt.m4 | 60 |
1 files changed, 43 insertions, 17 deletions
diff --git a/m4/getopt.m4 b/m4/getopt.m4 index 8f0c36c51e..264b57f9f2 100644 --- a/m4/getopt.m4 +++ b/m4/getopt.m4 @@ -1,4 +1,4 @@ -# getopt.m4 serial 23 +# getopt.m4 serial 24 dnl Copyright (C) 2002-2006, 2008-2009 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -75,11 +75,13 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS], AC_CHECK_FUNCS([getopt_long_only], [], [gl_replace_getopt=yes]) fi - dnl BSD getopt_long uses an incompatible method to reset option processing, - dnl but the testsuite does not show a need to use this 'optreset' variable. - if false && test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then - AC_CHECK_DECL([optreset], [gl_replace_getopt=yes], [], - [#include <getopt.h>]) + dnl BSD getopt_long uses an incompatible method to reset option processing. + dnl Existence of the variable, in and of itself, is not a reason to replace + dnl getopt, but knowledge of the variable is needed to determine how to + dnl reset and whether a reset reparses the environment. + if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then + AC_CHECK_DECLS([optreset], [], [], + [[#include <getopt.h>]]) fi dnl mingw's getopt (in libmingwex.a) does weird things when the options @@ -96,9 +98,7 @@ AC_DEFUN([gl_GETOPT_CHECK_HEADERS], #include <stdlib.h> #include <string.h> -/* The glibc implementation of getopt supports setting optind = 0 as a means - of clearing the internal state, but other implementations don't. */ -#if (__GLIBC__ >= 2) +#if !HAVE_DECL_OPTRESET # define OPTIND_MIN 0 #else # define OPTIND_MIN 1 @@ -116,6 +116,7 @@ main () argv[argc++] = "-a"; argv[argc++] = "foo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = OPTIND_MIN; opterr = 0; @@ -141,6 +142,7 @@ main () argv[argc++] = "duck"; argv[argc++] = "-a"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = OPTIND_MIN; opterr = 0; @@ -182,11 +184,22 @@ main () if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then AC_CACHE_CHECK([for working GNU getopt function], [gl_cv_func_getopt_gnu], - [AC_RUN_IFELSE( + [# Even with POSIXLY_CORRECT, the GNU extension of leading '-' in the + # optstring is necessary for programs like m4 that have POSIX-mandated + # semantics for supporting options interspersed with files. + gl_had_POSIXLY_CORRECT=${POSIXLY_CORRECT:+yes} + POSIXLY_CORRECT=1 + export POSIXLY_CORRECT + AC_RUN_IFELSE( [AC_LANG_PROGRAM([[#include <getopt.h> #include <stddef.h> - #include <string.h>]], - [[ + #include <string.h> +#if !HAVE_DECL_OPTRESET +# define OPTIND_MIN 0 +#else +# define OPTIND_MIN (optreset = 1) +#endif + ]], [[ /* This code succeeds on glibc 2.8, OpenBSD 4.0, Cygwin, mingw, and fails on MacOS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10. */ @@ -201,9 +214,9 @@ main () } /* This code succeeds on glibc 2.8, mingw, and fails on MacOS X 10.5, OpenBSD 4.0, AIX 5.2, HP-UX 11, - IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin. */ + IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x. */ { - char *argv[] = { "program", "-p", "foo", "bar" }; + char *argv[] = { "program", "-p", "foo", "bar", NULL }; optind = 1; if (getopt (4, argv, "p::") != 'p') @@ -215,16 +228,29 @@ main () if (optind != 2) return 5; } + /* This code succeeds on glibc 2.8 and fails on Cygwin 1.7.0. */ + { + char *argv[] = { "program", "foo", "-p", NULL }; + optind = OPTIND_MIN; + if (getopt (3, argv, "-p") != 1) + return 6; + if (getopt (3, argv, "-p") != 'p') + return 7; + } return 0; ]])], [gl_cv_func_getopt_gnu=yes], [gl_cv_func_getopt_gnu=no], [dnl Cross compiling. Guess based on host and declarations. - case "$host_os" in - *-gnu* | mingw*) gl_cv_func_getopt_gnu=no;; - *) gl_cv_func_getopt_gnu=yes;; + case $host_os:$ac_cv_have_decl_optreset in + *-gnu*:* | mingw*:*) gl_cv_func_getopt_gnu=no;; + *:yes) gl_cv_func_getopt_gnu=no;; + *) gl_cv_func_getopt_gnu=yes;; esac ]) + if test "$gl_had_POSIXLY_CORRECT" != yes; then + AS_UNSET([POSIXLY_CORRECT]) + fi ]) if test "$gl_cv_func_getopt_gnu" = "no"; then gl_replace_getopt=yes |