Home | History | Annotate | Download | only in m4
      1 # getopt.m4 serial 44
      2 dnl Copyright (C) 2002-2006, 2008-2012 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   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.
     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 # Determine whether to replace the entire getopt facility.
     41 AC_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 
     91 int
     92 main ()
     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 
    123 int
    124 main ()
    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 
    169 int
    170 main ()
    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.
    209 dnl GNU Coding Standards currently allow awk but not env; besides, env
    210 dnl 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 
    355 AC_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*.
    365 AC_DEFUN([gl_PREREQ_GETOPT],
    366 [
    367   AC_CHECK_DECLS_ONCE([getenv])
    368 ])
    369