1# getopt.m4 serial 44
2dnl Copyright (C) 2002-2006, 2008-2012 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7# Request a POSIX compliant getopt function.
8AC_DEFUN([gl_FUNC_GETOPT_POSIX],
9[
10  m4_divert_text([DEFAULTS], [gl_getopt_required=POSIX])
11  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
12  AC_REQUIRE([gl_GETOPT_CHECK_HEADERS])
13  dnl Other modules can request the gnulib implementation of the getopt
14  dnl functions unconditionally, by defining gl_REPLACE_GETOPT_ALWAYS.
15  dnl argp.m4 does this.
16  m4_ifdef([gl_REPLACE_GETOPT_ALWAYS], [
17    REPLACE_GETOPT=1
18  ], [
19    REPLACE_GETOPT=0
20    if test -n "$gl_replace_getopt"; then
21      REPLACE_GETOPT=1
22    fi
23  ])
24  if test $REPLACE_GETOPT = 1; then
25    dnl Arrange for getopt.h to be created.
26    gl_GETOPT_SUBSTITUTE_HEADER
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.
33AC_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# Determine whether to replace the entire getopt facility.
41AC_DEFUN([gl_GETOPT_CHECK_HEADERS],
42[
43  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
44  AC_REQUIRE([AC_PROG_AWK]) dnl for awk that supports ENVIRON
45
46  dnl Persuade Solaris <unistd.h> to declare optarg, optind, opterr, optopt.
47  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
48
49  gl_CHECK_NEXT_HEADERS([getopt.h])
50  if test $ac_cv_header_getopt_h = yes; then
51    HAVE_GETOPT_H=1
52  else
53    HAVE_GETOPT_H=0
54  fi
55  AC_SUBST([HAVE_GETOPT_H])
56
57  gl_replace_getopt=
58
59  dnl Test whether <getopt.h> is available.
60  if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
61    AC_CHECK_HEADERS([getopt.h], [], [gl_replace_getopt=yes])
62  fi
63
64  dnl Test whether the function getopt_long is available.
65  if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
66    AC_CHECK_FUNCS([getopt_long_only], [], [gl_replace_getopt=yes])
67  fi
68
69  dnl POSIX 2008 does not specify leading '+' behavior, but see
70  dnl http://austingroupbugs.net/view.php?id=191 for a recommendation on
71  dnl the next version of POSIX.  For now, we only guarantee leading '+'
72  dnl behavior with getopt-gnu.
73  if test -z "$gl_replace_getopt"; then
74    AC_CACHE_CHECK([whether getopt is POSIX compatible],
75      [gl_cv_func_getopt_posix],
76      [
77        dnl Merging these three different test programs into a single one
78        dnl would require a reset mechanism. On BSD systems, it can be done
79        dnl through 'optreset'; on some others (glibc), it can be done by
80        dnl setting 'optind' to 0; on others again (HP-UX, IRIX, OSF/1,
81        dnl Solaris 9, musl libc), there is no such mechanism.
82        if test $cross_compiling = no; then
83          dnl Sanity check. Succeeds everywhere (except on MSVC,
84          dnl which lacks <unistd.h> and getopt() entirely).
85          AC_RUN_IFELSE(
86            [AC_LANG_SOURCE([[
87#include <unistd.h>
88#include <stdlib.h>
89#include <string.h>
90
91int
92main ()
93{
94  static char program[] = "program";
95  static char a[] = "-a";
96  static char foo[] = "foo";
97  static char bar[] = "bar";
98  char *argv[] = { program, a, foo, bar, NULL };
99  int c;
100
101  c = getopt (4, argv, "ab");
102  if (!(c == 'a'))
103    return 1;
104  c = getopt (4, argv, "ab");
105  if (!(c == -1))
106    return 2;
107  if (!(optind == 2))
108    return 3;
109  return 0;
110}
111]])],
112            [gl_cv_func_getopt_posix=maybe],
113            [gl_cv_func_getopt_posix=no])
114          if test $gl_cv_func_getopt_posix = maybe; then
115            dnl Sanity check with '+'. Succeeds everywhere (except on MSVC,
116            dnl which lacks <unistd.h> and getopt() entirely).
117            AC_RUN_IFELSE(
118              [AC_LANG_SOURCE([[
119#include <unistd.h>
120#include <stdlib.h>
121#include <string.h>
122
123int
124main ()
125{
126  static char program[] = "program";
127  static char donald[] = "donald";
128  static char p[] = "-p";
129  static char billy[] = "billy";
130  static char duck[] = "duck";
131  static char a[] = "-a";
132  static char bar[] = "bar";
133  char *argv[] = { program, donald, p, billy, duck, a, bar, NULL };
134  int c;
135
136  c = getopt (7, argv, "+abp:q:");
137  if (!(c == -1))
138    return 4;
139  if (!(strcmp (argv[0], "program") == 0))
140    return 5;
141  if (!(strcmp (argv[1], "donald") == 0))
142    return 6;
143  if (!(strcmp (argv[2], "-p") == 0))
144    return 7;
145  if (!(strcmp (argv[3], "billy") == 0))
146    return 8;
147  if (!(strcmp (argv[4], "duck") == 0))
148    return 9;
149  if (!(strcmp (argv[5], "-a") == 0))
150    return 10;
151  if (!(strcmp (argv[6], "bar") == 0))
152    return 11;
153  if (!(optind == 1))
154    return 12;
155  return 0;
156}
157]])],
158              [gl_cv_func_getopt_posix=maybe],
159              [gl_cv_func_getopt_posix=no])
160          fi
161          if test $gl_cv_func_getopt_posix = maybe; then
162            dnl Detect Mac OS X 10.5, AIX 7.1, mingw bug.
163            AC_RUN_IFELSE(
164              [AC_LANG_SOURCE([[
165#include <unistd.h>
166#include <stdlib.h>
167#include <string.h>
168
169int
170main ()
171{
172  static char program[] = "program";
173  static char ab[] = "-ab";
174  char *argv[3] = { program, ab, NULL };
175  if (getopt (2, argv, "ab:") != 'a')
176    return 13;
177  if (getopt (2, argv, "ab:") != '?')
178    return 14;
179  if (optopt != 'b')
180    return 15;
181  if (optind != 2)
182    return 16;
183  return 0;
184}
185]])],
186              [gl_cv_func_getopt_posix=yes],
187              [gl_cv_func_getopt_posix=no])
188          fi
189        else
190          case "$host_os" in
191            darwin* | aix* | mingw*) gl_cv_func_getopt_posix="guessing no";;
192            *)                       gl_cv_func_getopt_posix="guessing yes";;
193          esac
194        fi
195      ])
196    case "$gl_cv_func_getopt_posix" in
197      *no) gl_replace_getopt=yes ;;
198    esac
199  fi
200
201  if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
202    AC_CACHE_CHECK([for working GNU getopt function], [gl_cv_func_getopt_gnu],
203      [# Even with POSIXLY_CORRECT, the GNU extension of leading '-' in the
204       # optstring is necessary for programs like m4 that have POSIX-mandated
205       # semantics for supporting options interspersed with files.
206       # Also, since getopt_long is a GNU extension, we require optind=0.
207       # Bash ties 'set -o posix' to a non-exported POSIXLY_CORRECT;
208       # so take care to revert to the correct (non-)export state.
209dnl GNU Coding Standards currently allow awk but not env; besides, env
210dnl is ambiguous with environment values that contain newlines.
211       gl_awk_probe='BEGIN { if ("POSIXLY_CORRECT" in ENVIRON) print "x" }'
212       case ${POSIXLY_CORRECT+x}`$AWK "$gl_awk_probe" </dev/null` in
213         xx) gl_had_POSIXLY_CORRECT=exported ;;
214         x)  gl_had_POSIXLY_CORRECT=yes      ;;
215         *)  gl_had_POSIXLY_CORRECT=         ;;
216       esac
217       POSIXLY_CORRECT=1
218       export POSIXLY_CORRECT
219       AC_RUN_IFELSE(
220        [AC_LANG_PROGRAM([[#include <getopt.h>
221                           #include <stddef.h>
222                           #include <string.h>
223           ]GL_NOCRASH[
224           ]], [[
225             int result = 0;
226
227             nocrash_init();
228
229             /* This code succeeds on glibc 2.8, OpenBSD 4.0, Cygwin, mingw,
230                and fails on Mac OS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5,
231                OSF/1 5.1, Solaris 10.  */
232             {
233               static char conftest[] = "conftest";
234               static char plus[] = "-+";
235               char *argv[3] = { conftest, plus, NULL };
236               opterr = 0;
237               if (getopt (2, argv, "+a") != '?')
238                 result |= 1;
239             }
240             /* This code succeeds on glibc 2.8, mingw,
241                and fails on Mac OS X 10.5, OpenBSD 4.0, AIX 5.2, HP-UX 11,
242                IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x.  */
243             {
244               static char program[] = "program";
245               static char p[] = "-p";
246               static char foo[] = "foo";
247               static char bar[] = "bar";
248               char *argv[] = { program, p, foo, bar, NULL };
249
250               optind = 1;
251               if (getopt (4, argv, "p::") != 'p')
252                 result |= 2;
253               else if (optarg != NULL)
254                 result |= 4;
255               else if (getopt (4, argv, "p::") != -1)
256                 result |= 6;
257               else if (optind != 2)
258                 result |= 8;
259             }
260             /* This code succeeds on glibc 2.8 and fails on Cygwin 1.7.0.  */
261             {
262               static char program[] = "program";
263               static char foo[] = "foo";
264               static char p[] = "-p";
265               char *argv[] = { program, foo, p, NULL };
266               optind = 0;
267               if (getopt (3, argv, "-p") != 1)
268                 result |= 16;
269               else if (getopt (3, argv, "-p") != 'p')
270                 result |= 16;
271             }
272             /* This code fails on glibc 2.11.  */
273             {
274               static char program[] = "program";
275               static char b[] = "-b";
276               static char a[] = "-a";
277               char *argv[] = { program, b, a, NULL };
278               optind = opterr = 0;
279               if (getopt (3, argv, "+:a:b") != 'b')
280                 result |= 32;
281               else if (getopt (3, argv, "+:a:b") != ':')
282                 result |= 32;
283             }
284             /* This code dumps core on glibc 2.14.  */
285             {
286               static char program[] = "program";
287               static char w[] = "-W";
288               static char dummy[] = "dummy";
289               char *argv[] = { program, w, dummy, NULL };
290               optind = opterr = 1;
291               if (getopt (3, argv, "W;") != 'W')
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. Assume the worst, even on glibc platforms.
299         gl_cv_func_getopt_gnu="guessing no"
300        ])
301       case $gl_had_POSIXLY_CORRECT in
302         exported) ;;
303         yes) AS_UNSET([POSIXLY_CORRECT]); POSIXLY_CORRECT=1 ;;
304         *) AS_UNSET([POSIXLY_CORRECT]) ;;
305       esac
306      ])
307    if test "$gl_cv_func_getopt_gnu" != yes; then
308      gl_replace_getopt=yes
309    else
310      AC_CACHE_CHECK([for working GNU getopt_long function],
311        [gl_cv_func_getopt_long_gnu],
312        [AC_RUN_IFELSE(
313           [AC_LANG_PROGRAM(
314              [[#include <getopt.h>
315                #include <stddef.h>
316                #include <string.h>
317              ]],
318              [[static const struct option long_options[] =
319                  {
320                    { "xtremely-",no_argument,       NULL, 1003 },
321                    { "xtra",     no_argument,       NULL, 1001 },
322                    { "xtreme",   no_argument,       NULL, 1002 },
323                    { "xtremely", no_argument,       NULL, 1003 },
324                    { NULL,       0,                 NULL, 0 }
325                  };
326                /* This code fails on OpenBSD 5.0.  */
327                {
328                  static char program[] = "program";
329                  static char xtremel[] = "--xtremel";
330                  char *argv[] = { program, xtremel, NULL };
331                  int option_index;
332                  optind = 1; opterr = 0;
333                  if (getopt_long (2, argv, "", long_options, &option_index) != 1003)
334                    return 1;
335                }
336                return 0;
337              ]])],
338           [gl_cv_func_getopt_long_gnu=yes],
339           [gl_cv_func_getopt_long_gnu=no],
340           [dnl Cross compiling. Guess no on OpenBSD, yes otherwise.
341            case "$host_os" in
342              openbsd*) gl_cv_func_getopt_long_gnu="guessing no";;
343              *)        gl_cv_func_getopt_long_gnu="guessing yes";;
344            esac
345           ])
346        ])
347      case "$gl_cv_func_getopt_long_gnu" in
348        *yes) ;;
349        *) gl_replace_getopt=yes ;;
350      esac
351    fi
352  fi
353])
354
355AC_DEFUN([gl_GETOPT_SUBSTITUTE_HEADER],
356[
357  GETOPT_H=getopt.h
358  AC_DEFINE([__GETOPT_PREFIX], [[rpl_]],
359    [Define to rpl_ if the getopt replacement functions and variables
360     should be used.])
361  AC_SUBST([GETOPT_H])
362])
363
364# Prerequisites of lib/getopt*.
365AC_DEFUN([gl_PREREQ_GETOPT],
366[
367  AC_CHECK_DECLS_ONCE([getenv])
368])
369