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