1*b0d29bc4SBrooks Davisdnl Copyright 2010 The Kyua Authors. 2*b0d29bc4SBrooks Davisdnl All rights reserved. 3*b0d29bc4SBrooks Davisdnl 4*b0d29bc4SBrooks Davisdnl Redistribution and use in source and binary forms, with or without 5*b0d29bc4SBrooks Davisdnl modification, are permitted provided that the following conditions are 6*b0d29bc4SBrooks Davisdnl met: 7*b0d29bc4SBrooks Davisdnl 8*b0d29bc4SBrooks Davisdnl * Redistributions of source code must retain the above copyright 9*b0d29bc4SBrooks Davisdnl notice, this list of conditions and the following disclaimer. 10*b0d29bc4SBrooks Davisdnl * Redistributions in binary form must reproduce the above copyright 11*b0d29bc4SBrooks Davisdnl notice, this list of conditions and the following disclaimer in the 12*b0d29bc4SBrooks Davisdnl documentation and/or other materials provided with the distribution. 13*b0d29bc4SBrooks Davisdnl * Neither the name of Google Inc. nor the names of its contributors 14*b0d29bc4SBrooks Davisdnl may be used to endorse or promote products derived from this software 15*b0d29bc4SBrooks Davisdnl without specific prior written permission. 16*b0d29bc4SBrooks Davisdnl 17*b0d29bc4SBrooks Davisdnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*b0d29bc4SBrooks Davisdnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*b0d29bc4SBrooks Davisdnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*b0d29bc4SBrooks Davisdnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*b0d29bc4SBrooks Davisdnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*b0d29bc4SBrooks Davisdnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*b0d29bc4SBrooks Davisdnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*b0d29bc4SBrooks Davisdnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*b0d29bc4SBrooks Davisdnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*b0d29bc4SBrooks Davisdnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*b0d29bc4SBrooks Davisdnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*b0d29bc4SBrooks Davis 29*b0d29bc4SBrooks Davis 30*b0d29bc4SBrooks Davisdnl Checks if getopt(3) supports a + sign to enforce POSIX correctness. 31*b0d29bc4SBrooks Davisdnl 32*b0d29bc4SBrooks Davisdnl In the GNU implementation of getopt(3), we need to pass a + sign at 33*b0d29bc4SBrooks Davisdnl the beginning of the options string to request POSIX behavior. 34*b0d29bc4SBrooks Davisdnl 35*b0d29bc4SBrooks Davisdnl Defines HAVE_GETOPT_GNU if a + sign is supported. 36*b0d29bc4SBrooks DavisAC_DEFUN([_KYUA_GETOPT_GNU], [ 37*b0d29bc4SBrooks Davis AC_CACHE_CHECK( 38*b0d29bc4SBrooks Davis [whether getopt allows a + sign for POSIX behavior optreset], 39*b0d29bc4SBrooks Davis [kyua_cv_getopt_gnu], [ 40*b0d29bc4SBrooks Davis AC_RUN_IFELSE([AC_LANG_PROGRAM([#include <stdlib.h> 41*b0d29bc4SBrooks Davis#include <string.h> 42*b0d29bc4SBrooks Davis#include <unistd.h>], [ 43*b0d29bc4SBrooks Davis int argc = 4; 44*b0d29bc4SBrooks Davis char* argv@<:@5@:>@ = { 45*b0d29bc4SBrooks Davis strdup("conftest"), 46*b0d29bc4SBrooks Davis strdup("-+"), 47*b0d29bc4SBrooks Davis strdup("-a"), 48*b0d29bc4SBrooks Davis strdup("bar"), 49*b0d29bc4SBrooks Davis NULL 50*b0d29bc4SBrooks Davis }; 51*b0d29bc4SBrooks Davis int ch; 52*b0d29bc4SBrooks Davis int seen_a = 0, seen_plus = 0; 53*b0d29bc4SBrooks Davis 54*b0d29bc4SBrooks Davis while ((ch = getopt(argc, argv, "+a:")) != -1) { 55*b0d29bc4SBrooks Davis switch (ch) { 56*b0d29bc4SBrooks Davis case 'a': 57*b0d29bc4SBrooks Davis seen_a = 1; 58*b0d29bc4SBrooks Davis break; 59*b0d29bc4SBrooks Davis 60*b0d29bc4SBrooks Davis case '+': 61*b0d29bc4SBrooks Davis seen_plus = 1; 62*b0d29bc4SBrooks Davis break; 63*b0d29bc4SBrooks Davis 64*b0d29bc4SBrooks Davis case '?': 65*b0d29bc4SBrooks Davis default: 66*b0d29bc4SBrooks Davis ; 67*b0d29bc4SBrooks Davis } 68*b0d29bc4SBrooks Davis } 69*b0d29bc4SBrooks Davis 70*b0d29bc4SBrooks Davis return (seen_a && !seen_plus) ? EXIT_SUCCESS : EXIT_FAILURE; 71*b0d29bc4SBrooks Davis])], 72*b0d29bc4SBrooks Davis [kyua_cv_getopt_gnu=yes], 73*b0d29bc4SBrooks Davis [kyua_cv_getopt_gnu=no]) 74*b0d29bc4SBrooks Davis ]) 75*b0d29bc4SBrooks Davis if test "${kyua_cv_getopt_gnu}" = yes; then 76*b0d29bc4SBrooks Davis AC_DEFINE([HAVE_GETOPT_GNU], [1], 77*b0d29bc4SBrooks Davis [Define to 1 if getopt allows a + sign for POSIX behavior]) 78*b0d29bc4SBrooks Davis fi 79*b0d29bc4SBrooks Davis]) 80*b0d29bc4SBrooks Davis 81*b0d29bc4SBrooks Davisdnl Checks if optreset exists to reset the processing of getopt(3) options. 82*b0d29bc4SBrooks Davisdnl 83*b0d29bc4SBrooks Davisdnl getopt(3) has an optreset global variable to reset internal state 84*b0d29bc4SBrooks Davisdnl before calling getopt(3) again. However, optreset is not standard and 85*b0d29bc4SBrooks Davisdnl is only present in the BSD versions of getopt(3). 86*b0d29bc4SBrooks Davisdnl 87*b0d29bc4SBrooks Davisdnl Defines HAVE_GETOPT_WITH_OPTRESET if optreset exists. 88*b0d29bc4SBrooks DavisAC_DEFUN([_KYUA_GETOPT_WITH_OPTRESET], [ 89*b0d29bc4SBrooks Davis AC_CACHE_CHECK( 90*b0d29bc4SBrooks Davis [whether getopt has optreset], 91*b0d29bc4SBrooks Davis [kyua_cv_getopt_optreset], [ 92*b0d29bc4SBrooks Davis AC_COMPILE_IFELSE([AC_LANG_SOURCE([ 93*b0d29bc4SBrooks Davis#include <stdlib.h> 94*b0d29bc4SBrooks Davis#include <unistd.h> 95*b0d29bc4SBrooks Davis 96*b0d29bc4SBrooks Davisint 97*b0d29bc4SBrooks Davismain(void) 98*b0d29bc4SBrooks Davis{ 99*b0d29bc4SBrooks Davis optreset = 1; 100*b0d29bc4SBrooks Davis return EXIT_SUCCESS; 101*b0d29bc4SBrooks Davis} 102*b0d29bc4SBrooks Davis])], 103*b0d29bc4SBrooks Davis [kyua_cv_getopt_optreset=yes], 104*b0d29bc4SBrooks Davis [kyua_cv_getopt_optreset=no]) 105*b0d29bc4SBrooks Davis ]) 106*b0d29bc4SBrooks Davis if test "${kyua_cv_getopt_optreset}" = yes; then 107*b0d29bc4SBrooks Davis AC_DEFINE([HAVE_GETOPT_WITH_OPTRESET], [1], 108*b0d29bc4SBrooks Davis [Define to 1 if getopt has optreset]) 109*b0d29bc4SBrooks Davis fi 110*b0d29bc4SBrooks Davis]) 111*b0d29bc4SBrooks Davis 112*b0d29bc4SBrooks Davis 113*b0d29bc4SBrooks Davisdnl Checks the value to pass to optind to reset getopt(3) processing. 114*b0d29bc4SBrooks Davisdnl 115*b0d29bc4SBrooks Davisdnl The standard value to pass to optind to reset the processing of command 116*b0d29bc4SBrooks Davisdnl lines with getopt(3) is 1. However, the GNU extensions to getopt_long(3) 117*b0d29bc4SBrooks Davisdnl are not properly reset unless optind is set to 0, causing crashes later 118*b0d29bc4SBrooks Davisdnl on and incorrect option processing behavior. 119*b0d29bc4SBrooks Davisdnl 120*b0d29bc4SBrooks Davisdnl Sets the GETOPT_OPTIND_RESET_VALUE macro to the integer value that has to 121*b0d29bc4SBrooks Davisdnl be passed to optind to reset option processing. 122*b0d29bc4SBrooks DavisAC_DEFUN([_KYUA_GETOPT_OPTIND_RESET_VALUE], [ 123*b0d29bc4SBrooks Davis AC_CACHE_CHECK( 124*b0d29bc4SBrooks Davis [for the optind value to reset getopt processing], 125*b0d29bc4SBrooks Davis [kyua_cv_getopt_optind_reset_value], [ 126*b0d29bc4SBrooks Davis AC_RUN_IFELSE([AC_LANG_SOURCE([ 127*b0d29bc4SBrooks Davis#include <stdlib.h> 128*b0d29bc4SBrooks Davis#include <string.h> 129*b0d29bc4SBrooks Davis#include <unistd.h> 130*b0d29bc4SBrooks Davis 131*b0d29bc4SBrooks Davisstatic void 132*b0d29bc4SBrooks Davisfirst_pass(void) 133*b0d29bc4SBrooks Davis{ 134*b0d29bc4SBrooks Davis int argc, ch, flag; 135*b0d29bc4SBrooks Davis char* argv@<:@5@:>@; 136*b0d29bc4SBrooks Davis 137*b0d29bc4SBrooks Davis argc = 4; 138*b0d29bc4SBrooks Davis argv@<:@0@:>@ = strdup("progname"); 139*b0d29bc4SBrooks Davis argv@<:@1@:>@ = strdup("-a"); 140*b0d29bc4SBrooks Davis argv@<:@2@:>@ = strdup("foo"); 141*b0d29bc4SBrooks Davis argv@<:@3@:>@ = strdup("bar"); 142*b0d29bc4SBrooks Davis argv@<:@4@:>@ = NULL; 143*b0d29bc4SBrooks Davis 144*b0d29bc4SBrooks Davis flag = 0; 145*b0d29bc4SBrooks Davis while ((ch = getopt(argc, argv, "+:a")) != -1) { 146*b0d29bc4SBrooks Davis switch (ch) { 147*b0d29bc4SBrooks Davis case 'a': 148*b0d29bc4SBrooks Davis flag = 1; 149*b0d29bc4SBrooks Davis break; 150*b0d29bc4SBrooks Davis default: 151*b0d29bc4SBrooks Davis break; 152*b0d29bc4SBrooks Davis } 153*b0d29bc4SBrooks Davis } 154*b0d29bc4SBrooks Davis if (!flag) { 155*b0d29bc4SBrooks Davis exit(EXIT_FAILURE); 156*b0d29bc4SBrooks Davis } 157*b0d29bc4SBrooks Davis} 158*b0d29bc4SBrooks Davis 159*b0d29bc4SBrooks Davisstatic void 160*b0d29bc4SBrooks Davissecond_pass(void) 161*b0d29bc4SBrooks Davis{ 162*b0d29bc4SBrooks Davis int argc, ch, flag; 163*b0d29bc4SBrooks Davis char* argv@<:@5@:>@; 164*b0d29bc4SBrooks Davis 165*b0d29bc4SBrooks Davis argc = 4; 166*b0d29bc4SBrooks Davis argv@<:@0@:>@ = strdup("progname"); 167*b0d29bc4SBrooks Davis argv@<:@1@:>@ = strdup("-b"); 168*b0d29bc4SBrooks Davis argv@<:@2@:>@ = strdup("foo"); 169*b0d29bc4SBrooks Davis argv@<:@3@:>@ = strdup("bar"); 170*b0d29bc4SBrooks Davis argv@<:@4@:>@ = NULL; 171*b0d29bc4SBrooks Davis 172*b0d29bc4SBrooks Davis flag = 0; 173*b0d29bc4SBrooks Davis while ((ch = getopt(argc, argv, "b")) != -1) { 174*b0d29bc4SBrooks Davis switch (ch) { 175*b0d29bc4SBrooks Davis case 'b': 176*b0d29bc4SBrooks Davis flag = 1; 177*b0d29bc4SBrooks Davis break; 178*b0d29bc4SBrooks Davis default: 179*b0d29bc4SBrooks Davis break; 180*b0d29bc4SBrooks Davis } 181*b0d29bc4SBrooks Davis } 182*b0d29bc4SBrooks Davis if (!flag) { 183*b0d29bc4SBrooks Davis exit(EXIT_FAILURE); 184*b0d29bc4SBrooks Davis } 185*b0d29bc4SBrooks Davis} 186*b0d29bc4SBrooks Davis 187*b0d29bc4SBrooks Davisint 188*b0d29bc4SBrooks Davismain(void) 189*b0d29bc4SBrooks Davis{ 190*b0d29bc4SBrooks Davis /* We do two passes in two different functions to prevent the reuse of 191*b0d29bc4SBrooks Davis * variables and, specially, to force the use of two different argument 192*b0d29bc4SBrooks Davis * vectors. */ 193*b0d29bc4SBrooks Davis first_pass(); 194*b0d29bc4SBrooks Davis optind = 0; 195*b0d29bc4SBrooks Davis second_pass(); 196*b0d29bc4SBrooks Davis return EXIT_SUCCESS; 197*b0d29bc4SBrooks Davis} 198*b0d29bc4SBrooks Davis])], 199*b0d29bc4SBrooks Davis [kyua_cv_getopt_optind_reset_value=0], 200*b0d29bc4SBrooks Davis [kyua_cv_getopt_optind_reset_value=1]) 201*b0d29bc4SBrooks Davis ]) 202*b0d29bc4SBrooks Davis AC_DEFINE_UNQUOTED([GETOPT_OPTIND_RESET_VALUE], 203*b0d29bc4SBrooks Davis [${kyua_cv_getopt_optind_reset_value}], 204*b0d29bc4SBrooks Davis [Define to the optind value to reset getopt processing]) 205*b0d29bc4SBrooks Davis]) 206*b0d29bc4SBrooks Davis 207*b0d29bc4SBrooks Davis 208*b0d29bc4SBrooks Davisdnl Wrapper macro to detect all getopt(3) necessary features. 209*b0d29bc4SBrooks DavisAC_DEFUN([KYUA_GETOPT], [ 210*b0d29bc4SBrooks Davis _KYUA_GETOPT_GNU 211*b0d29bc4SBrooks Davis _KYUA_GETOPT_OPTIND_RESET_VALUE 212*b0d29bc4SBrooks Davis _KYUA_GETOPT_WITH_OPTRESET 213*b0d29bc4SBrooks Davis]) 214