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