1# getopt.m4 serial 21
2dnl Copyright (C) 2002-2006, 2008-2009 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  gl_GETOPT_IFELSE([
13    gl_REPLACE_GETOPT
14  ],
15  [])
16])
17
18# Request a POSIX compliant getopt function with GNU extensions (such as
19# options with optional arguments) and the functions getopt_long,
20# getopt_long_only.
21AC_DEFUN([gl_FUNC_GETOPT_GNU],
22[
23  m4_divert_text([INIT_PREPARE], [gl_getopt_required=GNU])
24
25  AC_REQUIRE([gl_FUNC_GETOPT_POSIX])
26])
27
28# Request the gnulib implementation of the getopt functions unconditionally.
29# argp.m4 uses this.
30AC_DEFUN([gl_REPLACE_GETOPT],
31[
32  dnl Arrange for getopt.h to be created.
33  gl_GETOPT_SUBSTITUTE_HEADER
34  dnl Arrange for unistd.h to include getopt.h.
35  GNULIB_UNISTD_H_GETOPT=1
36  dnl Arrange to compile the getopt implementation.
37  AC_LIBOBJ([getopt])
38  AC_LIBOBJ([getopt1])
39  gl_PREREQ_GETOPT
40])
41
42# emacs' configure.in uses this.
43AC_DEFUN([gl_GETOPT_IFELSE],
44[
45  AC_REQUIRE([gl_GETOPT_CHECK_HEADERS])
46  AS_IF([test -n "$gl_replace_getopt"], [$1], [$2])
47])
48
49# Determine whether to replace the entire getopt facility.
50AC_DEFUN([gl_GETOPT_CHECK_HEADERS],
51[
52  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
53
54  dnl Persuade Solaris <unistd.h> to declare optarg, optind, opterr, optopt.
55  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
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 BSD getopt_long uses an incompatible method to reset option processing,
70  dnl but the testsuite does not show a need to use this 'optreset' variable.
71  if false && test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
72    AC_CHECK_DECL([optreset], [gl_replace_getopt=yes], [],
73      [#include <getopt.h>])
74  fi
75
76  dnl mingw's getopt (in libmingwex.a) does weird things when the options
77  dnl strings starts with '+' and it's not the first call.  Some internal state
78  dnl is left over from earlier calls, and neither setting optind = 0 nor
79  dnl setting optreset = 1 get rid of this internal state.
80  if test -z "$gl_replace_getopt"; then
81    AC_CACHE_CHECK([whether getopt is POSIX compatible],
82      [gl_cv_func_getopt_posix],
83      [
84        dnl This test fails on mingw and succeeds on all other platforms.
85        AC_TRY_RUN([
86#include <unistd.h>
87#include <stdlib.h>
88#include <string.h>
89
90/* The glibc implementation of getopt supports setting optind = 0 as a means
91   of clearing the internal state, but other implementations don't.  */
92#if (__GLIBC__ >= 2)
93# define OPTIND_MIN 0
94#else
95# define OPTIND_MIN 1
96#endif
97
98int
99main ()
100{
101  {
102    int argc = 0;
103    char *argv[10];
104    int c;
105
106    argv[argc++] = "program";
107    argv[argc++] = "-a";
108    argv[argc++] = "foo";
109    argv[argc++] = "bar";
110    optind = OPTIND_MIN;
111    opterr = 0;
112
113    c = getopt (argc, argv, "ab");
114    if (!(c == 'a'))
115      return 1;
116    c = getopt (argc, argv, "ab");
117    if (!(c == -1))
118      return 2;
119    if (!(optind == 2))
120      return 3;
121  }
122  /* Some internal state exists at this point.  */
123  {
124    int argc = 0;
125    char *argv[10];
126    int c;
127
128    argv[argc++] = "program";
129    argv[argc++] = "donald";
130    argv[argc++] = "-p";
131    argv[argc++] = "billy";
132    argv[argc++] = "duck";
133    argv[argc++] = "-a";
134    argv[argc++] = "bar";
135    optind = OPTIND_MIN;
136    opterr = 0;
137
138    c = getopt (argc, argv, "+abp:q:");
139    if (!(c == -1))
140      return 4;
141    if (!(strcmp (argv[0], "program") == 0))
142      return 5;
143    if (!(strcmp (argv[1], "donald") == 0))
144      return 6;
145    if (!(strcmp (argv[2], "-p") == 0))
146      return 7;
147    if (!(strcmp (argv[3], "billy") == 0))
148      return 8;
149    if (!(strcmp (argv[4], "duck") == 0))
150      return 9;
151    if (!(strcmp (argv[5], "-a") == 0))
152      return 10;
153    if (!(strcmp (argv[6], "bar") == 0))
154      return 11;
155    if (!(optind == 1))
156      return 12;
157  }
158
159  return 0;
160}
161],
162          [gl_cv_func_getopt_posix=yes], [gl_cv_func_getopt_posix=no],
163          [case "$host_os" in
164             mingw*) gl_cv_func_getopt_posix="guessing no";;
165             *)      gl_cv_func_getopt_posix="guessing yes";;
166           esac
167          ])
168      ])
169    case "$gl_cv_func_getopt_posix" in
170      *no) gl_replace_getopt=yes ;;
171    esac
172  fi
173
174  if test -z "$gl_replace_getopt" && test $gl_getopt_required = GNU; then
175    AC_CACHE_CHECK([for working GNU getopt function], [gl_cv_func_getopt_gnu],
176      [AC_RUN_IFELSE(
177	[AC_LANG_PROGRAM([[#include <getopt.h>
178			   #include <stddef.h>
179			   #include <string.h>]],
180	   [[
181             /* This code succeeds on glibc 2.8, OpenBSD 4.0, Cygwin, mingw,
182                and fails on MacOS X 10.5, AIX 5.2, HP-UX 11, IRIX 6.5,
183                OSF/1 5.1, Solaris 10.  */
184             {
185               char *myargv[3];
186               myargv[0] = "conftest";
187               myargv[1] = "-+";
188               myargv[2] = 0;
189               opterr = 0;
190               if (getopt (2, myargv, "+a") != '?')
191                 return 1;
192             }
193             /* This code succeeds on glibc 2.8, mingw,
194                and fails on MacOS X 10.5, OpenBSD 4.0, AIX 5.2, HP-UX 11,
195                IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin.  */
196             {
197               char *argv[] = { "program", "-p", "foo", "bar" };
198
199               optind = 1;
200               if (getopt (4, argv, "p::") != 'p')
201                 return 2;
202               if (optarg != NULL)
203                 return 3;
204               if (getopt (4, argv, "p::") != -1)
205                 return 4;
206               if (optind != 2)
207                 return 5;
208             }
209             return 0;
210	   ]])],
211	[gl_cv_func_getopt_gnu=yes],
212	[gl_cv_func_getopt_gnu=no],
213	[dnl Cross compiling. Guess based on host and declarations.
214         case "$host_os" in
215           *-gnu* | mingw*) gl_cv_func_getopt_gnu=no;;
216           *)               gl_cv_func_getopt_gnu=yes;;
217         esac
218        ])
219      ])
220    if test "$gl_cv_func_getopt_gnu" = "no"; then
221      gl_replace_getopt=yes
222    fi
223  fi
224])
225
226# emacs' configure.in uses this.
227AC_DEFUN([gl_GETOPT_SUBSTITUTE_HEADER],
228[
229  GETOPT_H=getopt.h
230  AC_DEFINE([__GETOPT_PREFIX], [[rpl_]],
231    [Define to rpl_ if the getopt replacement functions and variables
232     should be used.])
233  AC_SUBST([GETOPT_H])
234])
235
236# Prerequisites of lib/getopt*.
237# emacs' configure.in uses this.
238AC_DEFUN([gl_PREREQ_GETOPT],
239[
240  AC_CHECK_DECLS_ONCE([getenv])
241])
242