getopt, argp: Respect rules for use of AC_LIBOBJ.
[gnulib.git] / m4 / getopt.m4
1 # getopt.m4 serial 35
2 dnl Copyright (C) 2002-2006, 2008-2011 Free Software Foundation, Inc.
3 dnl This file is free software; the Free Software Foundation
4 dnl gives unlimited permission to copy and/or distribute it,
5 dnl with or without modifications, as long as this notice is preserved.
6
7 # Request a POSIX compliant getopt function.
8 AC_DEFUN([gl_FUNC_GETOPT_POSIX],
9 [
10   m4_divert_text([DEFAULTS], [gl_getopt_required=POSIX])
11   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
12   dnl Other modules can request the gnulib implementation of the getopt
13   dnl functions unconditionally, by defining gl_REPLACE_GETOPT_ALWAYS.
14   dnl argp.m4 does this.
15   m4_ifdef([gl_REPLACE_GETOPT_ALWAYS], [
16     gl_GETOPT_IFELSE([], [])
17     REPLACE_GETOPT=1
18   ], [
19     REPLACE_GETOPT=0
20     gl_GETOPT_IFELSE([
21       REPLACE_GETOPT=1
22     ],
23     [])
24   ])
25   if test $REPLACE_GETOPT = 1; then
26     gl_REPLACE_GETOPT
27   fi
28 ])
29
30 # Request a POSIX compliant getopt function with GNU extensions (such as
31 # options with optional arguments) and the functions getopt_long,
32 # getopt_long_only.
33 AC_DEFUN([gl_FUNC_GETOPT_GNU],
34 [
35   m4_divert_text([INIT_PREPARE], [gl_getopt_required=GNU])
36
37   AC_REQUIRE([gl_FUNC_GETOPT_POSIX])
38 ])
39
40 # Request the gnulib implementation of the getopt functions unconditionally.
41 AC_DEFUN([gl_REPLACE_GETOPT],
42 [
43   dnl Arrange for getopt.h to be created.
44   gl_GETOPT_SUBSTITUTE_HEADER
45   dnl Arrange for unistd.h to include getopt.h.
46   GNULIB_UNISTD_H_GETOPT=1
47   dnl Arrange to compile the getopt implementation.
48   AC_LIBOBJ([getopt])
49   AC_LIBOBJ([getopt1])
50   gl_PREREQ_GETOPT
51 ])
52
53 # emacs' configure.in uses this.
54 AC_DEFUN([gl_GETOPT_IFELSE],
55 [
56   AC_REQUIRE([gl_GETOPT_CHECK_HEADERS])
57   AS_IF([test -n "$gl_replace_getopt"], [$1], [$2])
58 ])
59
60 # Determine whether to replace the entire getopt facility.
61 AC_DEFUN([gl_GETOPT_CHECK_HEADERS],
62 [
63   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
64   AC_REQUIRE([AC_PROG_AWK]) dnl for awk that supports ENVIRON
65
66   dnl Persuade Solaris <unistd.h> to declare optarg, optind, opterr, optopt.
67   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
68
69   gl_CHECK_NEXT_HEADERS([getopt.h])
70   if test $ac_cv_header_getopt_h = yes; then
71     HAVE_GETOPT_H=1
72   else
73     HAVE_GETOPT_H=0
74   fi
75   AC_SUBST([HAVE_GETOPT_H])
76
77   gl_replace_getopt=
78
79   dnl Test whether <getopt.h> is available.
80   if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
81     AC_CHECK_HEADERS([getopt.h], [], [gl_replace_getopt=yes])
82   fi
83
84   dnl Test whether the function getopt_long is available.
85   if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
86     AC_CHECK_FUNCS([getopt_long_only], [], [gl_replace_getopt=yes])
87   fi
88
89   dnl mingw's getopt (in libmingwex.a) does weird things when the options
90   dnl strings starts with '+' and it's not the first call.  Some internal state
91   dnl is left over from earlier calls, and neither setting optind = 0 nor
92   dnl setting optreset = 1 get rid of this internal state.
93   dnl POSIX is silent on optind vs. optreset, so we allow either behavior.
94   dnl POSIX 2008 does not specify leading '+' behavior, but see
95   dnl http://austingroupbugs.net/view.php?id=191 for a recommendation on
96   dnl the next version of POSIX.  For now, we only guarantee leading '+'
97   dnl behavior with getopt-gnu.
98   if test -z "$gl_replace_getopt"; then
99     AC_CACHE_CHECK([whether getopt is POSIX compatible],
100       [gl_cv_func_getopt_posix],
101       [
102         dnl BSD getopt_long uses an incompatible method to reset
103         dnl option processing.  Existence of the variable, in and of
104         dnl itself, is not a reason to replace getopt, but knowledge
105         dnl of the variable is needed to determine how to reset and
106         dnl whether a reset reparses the environment.  Solaris
107         dnl supports neither optreset nor optind=0, but keeps no state
108         dnl that needs a reset beyond setting optind=1; detect Solaris
109         dnl by getopt_clip.
110         AC_COMPILE_IFELSE(
111           [AC_LANG_PROGRAM(
112              [[#include <unistd.h>]],
113              [[int *p = &optreset; return optreset;]])],
114           [gl_optind_min=1],
115           [AC_COMPILE_IFELSE(
116              [AC_LANG_PROGRAM(
117                 [[#include <getopt.h>]],
118                 [[return !getopt_clip;]])],
119              [gl_optind_min=1],
120              [gl_optind_min=0])])
121
122         dnl This test fails on mingw and succeeds on many other platforms.
123         gl_save_CPPFLAGS=$CPPFLAGS
124         CPPFLAGS="$CPPFLAGS -DOPTIND_MIN=$gl_optind_min"
125         AC_RUN_IFELSE([AC_LANG_SOURCE([[
126 #include <unistd.h>
127 #include <stdlib.h>
128 #include <string.h>
129
130 int
131 main ()
132 {
133   {
134     int argc = 0;
135     char *argv[10];
136     int c;
137
138     argv[argc++] = "program";
139     argv[argc++] = "-a";
140     argv[argc++] = "foo";
141     argv[argc++] = "bar";
142     argv[argc] = NULL;
143     optind = OPTIND_MIN;
144     opterr = 0;
145
146     c = getopt (argc, argv, "ab");
147     if (!(c == 'a'))
148       return 1;
149     c = getopt (argc, argv, "ab");
150     if (!(c == -1))
151       return 2;
152     if (!(optind == 2))
153       return 3;
154   }
155   /* Some internal state exists at this point.  */
156   {
157     int argc = 0;
158     char *argv[10];
159     int c;
160
161     argv[argc++] = "program";
162     argv[argc++] = "donald";
163     argv[argc++] = "-p";
164     argv[argc++] = "billy";
165     argv[argc++] = "duck";
166     argv[argc++] = "-a";
167     argv[argc++] = "bar";
168     argv[argc] = NULL;
169     optind = OPTIND_MIN;
170     opterr = 0;
171
172     c = getopt (argc, argv, "+abp:q:");
173     if (!(c == -1))
174       return 4;
175     if (!(strcmp (argv[0], "program") == 0))
176       return 5;
177     if (!(strcmp (argv[1], "donald") == 0))
178       return 6;
179     if (!(strcmp (argv[2], "-p") == 0))
180       return 7;
181     if (!(strcmp (argv[3], "billy") == 0))
182       return 8;
183     if (!(strcmp (argv[4], "duck") == 0))
184       return 9;
185     if (!(strcmp (argv[5], "-a") == 0))
186       return 10;
187     if (!(strcmp (argv[6], "bar") == 0))
188       return 11;
189     if (!(optind == 1))
190       return 12;
191   }
192   /* Detect MacOS 10.5, AIX 7.1 bug.  */
193   {
194     char *argv[3] = { "program", "-ab", NULL };
195     optind = OPTIND_MIN;
196     opterr = 0;
197     if (getopt (2, argv, "ab:") != 'a')
198       return 13;
199     if (getopt (2, argv, "ab:") != '?')
200       return 14;
201     if (optopt != 'b')
202       return 15;
203     if (optind != 2)
204       return 16;
205   }
206
207   return 0;
208 }
209 ]])],
210           [gl_cv_func_getopt_posix=yes], [gl_cv_func_getopt_posix=no],
211           [case "$host_os" in
212              mingw*)         gl_cv_func_getopt_posix="guessing no";;
213              darwin* | aix*) gl_cv_func_getopt_posix="guessing no";;
214              *)              gl_cv_func_getopt_posix="guessing yes";;
215            esac
216           ])
217         CPPFLAGS=$gl_save_CPPFLAGS
218       ])
219     case "$gl_cv_func_getopt_posix" in
220       *no) gl_replace_getopt=yes ;;
221     esac
222   fi
223
224   if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
225     AC_CACHE_CHECK([for working GNU getopt function], [gl_cv_func_getopt_gnu],
226       [# Even with POSIXLY_CORRECT, the GNU extension of leading '-' in the
227        # optstring is necessary for programs like m4 that have POSIX-mandated
228        # semantics for supporting options interspersed with files.
229        # Also, since getopt_long is a GNU extension, we require optind=0.
230        # Bash ties 'set -o posix' to a non-exported POSIXLY_CORRECT;
231        # so take care to revert to the correct (non-)export state.
232 dnl GNU Coding Standards currently allow awk but not env; besides, env
233 dnl is ambiguous with environment values that contain newlines.
234        gl_awk_probe='BEGIN { if ("POSIXLY_CORRECT" in ENVIRON) print "x" }'
235        case ${POSIXLY_CORRECT+x}`$AWK "$gl_awk_probe" </dev/null` in
236          xx) gl_had_POSIXLY_CORRECT=exported ;;
237          x)  gl_had_POSIXLY_CORRECT=yes      ;;
238          *)  gl_had_POSIXLY_CORRECT=         ;;
239        esac
240        POSIXLY_CORRECT=1
241        export POSIXLY_CORRECT
242        AC_RUN_IFELSE(
243         [AC_LANG_PROGRAM([[#include <getopt.h>
244                            #include <stddef.h>
245                            #include <string.h>
246            ]], [[
247              int result = 0;
248              /* This code succeeds on glibc 2.8, OpenBSD 4.0, Cygwin, mingw,
249                 and fails on MacOS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5,
250                 OSF/1 5.1, Solaris 10.  */
251              {
252                char *myargv[3];
253                myargv[0] = "conftest";
254                myargv[1] = "-+";
255                myargv[2] = 0;
256                opterr = 0;
257                if (getopt (2, myargv, "+a") != '?')
258                  result |= 1;
259              }
260              /* This code succeeds on glibc 2.8, mingw,
261                 and fails on MacOS X 10.5, OpenBSD 4.0, AIX 5.2, HP-UX 11,
262                 IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x.  */
263              {
264                char *argv[] = { "program", "-p", "foo", "bar", NULL };
265
266                optind = 1;
267                if (getopt (4, argv, "p::") != 'p')
268                  result |= 2;
269                else if (optarg != NULL)
270                  result |= 4;
271                else if (getopt (4, argv, "p::") != -1)
272                  result |= 6;
273                else if (optind != 2)
274                  result |= 8;
275              }
276              /* This code succeeds on glibc 2.8 and fails on Cygwin 1.7.0.  */
277              {
278                char *argv[] = { "program", "foo", "-p", NULL };
279                optind = 0;
280                if (getopt (3, argv, "-p") != 1)
281                  result |= 16;
282                else if (getopt (3, argv, "-p") != 'p')
283                  result |= 32;
284              }
285              /* This code fails on glibc 2.11.  */
286              {
287                char *argv[] = { "program", "-b", "-a", NULL };
288                optind = opterr = 0;
289                if (getopt (3, argv, "+:a:b") != 'b')
290                  result |= 64;
291                else if (getopt (3, argv, "+:a:b") != ':')
292                  result |= 64;
293              }
294              return result;
295            ]])],
296         [gl_cv_func_getopt_gnu=yes],
297         [gl_cv_func_getopt_gnu=no],
298         [dnl Cross compiling. Guess based on host and declarations.
299          case $host_os:$ac_cv_have_decl_optreset in
300            *-gnu*:* | mingw*:*) gl_cv_func_getopt_gnu=no;;
301            *:yes)               gl_cv_func_getopt_gnu=no;;
302            *)                   gl_cv_func_getopt_gnu=yes;;
303          esac
304         ])
305        case $gl_had_POSIXLY_CORRECT in
306          exported) ;;
307          yes) AS_UNSET([POSIXLY_CORRECT]); POSIXLY_CORRECT=1 ;;
308          *) AS_UNSET([POSIXLY_CORRECT]) ;;
309        esac
310       ])
311     if test "$gl_cv_func_getopt_gnu" = "no"; then
312       gl_replace_getopt=yes
313     fi
314   fi
315 ])
316
317 # emacs' configure.in uses this.
318 AC_DEFUN([gl_GETOPT_SUBSTITUTE_HEADER],
319 [
320   GETOPT_H=getopt.h
321   AC_DEFINE([__GETOPT_PREFIX], [[rpl_]],
322     [Define to rpl_ if the getopt replacement functions and variables
323      should be used.])
324   AC_SUBST([GETOPT_H])
325 ])
326
327 # Prerequisites of lib/getopt*.
328 # emacs' configure.in uses this.
329 AC_DEFUN([gl_PREREQ_GETOPT],
330 [
331   AC_CHECK_DECLS_ONCE([getenv])
332 ])