1*44704f69SBart Van Assche /* $NetBSD: getopt_long.c,v 1.17 2004/06/20 22:20:15 jmc Exp $ */
2*44704f69SBart Van Assche
3*44704f69SBart Van Assche /*-
4*44704f69SBart Van Assche * Copyright (c) 2000 The NetBSD Foundation, Inc.
5*44704f69SBart Van Assche * All rights reserved.
6*44704f69SBart Van Assche *
7*44704f69SBart Van Assche * This code is derived from software contributed to The NetBSD Foundation
8*44704f69SBart Van Assche * by Dieter Baron and Thomas Klausner.
9*44704f69SBart Van Assche *
10*44704f69SBart Van Assche * Redistribution and use in source and binary forms, with or without
11*44704f69SBart Van Assche * modification, are permitted provided that the following conditions
12*44704f69SBart Van Assche * are met:
13*44704f69SBart Van Assche * 1. Redistributions of source code must retain the above copyright
14*44704f69SBart Van Assche * notice, this list of conditions and the following disclaimer.
15*44704f69SBart Van Assche * 2. Redistributions in binary form must reproduce the above copyright
16*44704f69SBart Van Assche * notice, this list of conditions and the following disclaimer in the
17*44704f69SBart Van Assche * documentation and/or other materials provided with the distribution.
18*44704f69SBart Van Assche * 3. All advertising materials mentioning features or use of this software
19*44704f69SBart Van Assche * must display the following acknowledgement:
20*44704f69SBart Van Assche * This product includes software developed by the NetBSD
21*44704f69SBart Van Assche * Foundation, Inc. and its contributors.
22*44704f69SBart Van Assche * 4. Neither the name of The NetBSD Foundation nor the names of its
23*44704f69SBart Van Assche * contributors may be used to endorse or promote products derived
24*44704f69SBart Van Assche * from this software without specific prior written permission.
25*44704f69SBart Van Assche *
26*44704f69SBart Van Assche * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27*44704f69SBart Van Assche * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28*44704f69SBart Van Assche * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29*44704f69SBart Van Assche * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30*44704f69SBart Van Assche * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31*44704f69SBart Van Assche * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32*44704f69SBart Van Assche * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33*44704f69SBart Van Assche * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34*44704f69SBart Van Assche * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35*44704f69SBart Van Assche * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36*44704f69SBart Van Assche * POSSIBILITY OF SUCH DAMAGE.
37*44704f69SBart Van Assche */
38*44704f69SBart Van Assche
39*44704f69SBart Van Assche /*
40*44704f69SBart Van Assche * modified May 12, 2005 by Jim Basney <[email protected]>
41*44704f69SBart Van Assche *
42*44704f69SBart Van Assche * removed #include of non-POSIX <sys/cdefs.h> <err.h>
43*44704f69SBart Van Assche * removed #include of "namespace.h"
44*44704f69SBart Van Assche * use local "port_getopt.h" instead of <getopt.h>
45*44704f69SBart Van Assche * removed REPLACE_GETOPT and HAVE_NBTOOL_CONFIG_H sections
46*44704f69SBart Van Assche * removed __P() from function declarations
47*44704f69SBart Van Assche * use ANSI C function parameter lists
48*44704f69SBart Van Assche * removed optreset support
49*44704f69SBart Van Assche * replace _DIAGASSERT() with assert()
50*44704f69SBart Van Assche * replace non-POSIX warnx(...) with fprintf(stderr, ...)
51*44704f69SBart Van Assche * added extern declarations for optarg, optind, opterr, and optopt
52*44704f69SBart Van Assche */
53*44704f69SBart Van Assche
54*44704f69SBart Van Assche #if defined(LIBC_SCCS) && !defined(lint)
55*44704f69SBart Van Assche __RCSID("$NetBSD: getopt_long.c,v 1.17 2004/06/20 22:20:15 jmc Exp $");
56*44704f69SBart Van Assche #endif /* LIBC_SCCS and not lint */
57*44704f69SBart Van Assche
58*44704f69SBart Van Assche #include <assert.h>
59*44704f69SBart Van Assche #include <errno.h>
60*44704f69SBart Van Assche #include "getopt.h"
61*44704f69SBart Van Assche #include <stdio.h>
62*44704f69SBart Van Assche #include <stdlib.h>
63*44704f69SBart Van Assche #include <string.h>
64*44704f69SBart Van Assche
65*44704f69SBart Van Assche #ifdef __weak_alias
66*44704f69SBart Van Assche __weak_alias(getopt_long,_getopt_long)
67*44704f69SBart Van Assche #endif
68*44704f69SBart Van Assche
69*44704f69SBart Van Assche #if !HAVE_GETOPT_LONG
70*44704f69SBart Van Assche #define IGNORE_FIRST (*options == '-' || *options == '+')
71*44704f69SBart Van Assche #define PRINT_ERROR ((opterr) && ((*options != ':') \
72*44704f69SBart Van Assche || (IGNORE_FIRST && options[1] != ':')))
73*44704f69SBart Van Assche #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
74*44704f69SBart Van Assche #define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
75*44704f69SBart Van Assche /* XXX: GNU ignores PC if *options == '-' */
76*44704f69SBart Van Assche #define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
77*44704f69SBart Van Assche
78*44704f69SBart Van Assche /* return values */
79*44704f69SBart Van Assche #define BADCH (int)'?'
80*44704f69SBart Van Assche #define BADARG ((IGNORE_FIRST && options[1] == ':') \
81*44704f69SBart Van Assche || (*options == ':') ? (int)':' : (int)'?')
82*44704f69SBart Van Assche #define INORDER (int)1
83*44704f69SBart Van Assche
84*44704f69SBart Van Assche #define EMSG ""
85*44704f69SBart Van Assche
86*44704f69SBart Van Assche extern char *optarg;
87*44704f69SBart Van Assche extern int optind, opterr, optopt;
88*44704f69SBart Van Assche
89*44704f69SBart Van Assche static int getopt_internal (int, char * const *, const char *);
90*44704f69SBart Van Assche static int gcd (int, int);
91*44704f69SBart Van Assche static void permute_args (int, int, int, char * const *);
92*44704f69SBart Van Assche
93*44704f69SBart Van Assche static char *place = EMSG; /* option letter processing */
94*44704f69SBart Van Assche
95*44704f69SBart Van Assche static int nonopt_start = -1; /* first non option argument (for permute) */
96*44704f69SBart Van Assche static int nonopt_end = -1; /* first option after non options (for permute) */
97*44704f69SBart Van Assche
98*44704f69SBart Van Assche /* Error messages */
99*44704f69SBart Van Assche static const char recargchar[] = "option requires an argument -- %c";
100*44704f69SBart Van Assche static const char recargstring[] = "option requires an argument -- %s";
101*44704f69SBart Van Assche static const char ambig[] = "ambiguous option -- %.*s";
102*44704f69SBart Van Assche static const char noarg[] = "option doesn't take an argument -- %.*s";
103*44704f69SBart Van Assche static const char illoptchar[] = "unknown option -- %c";
104*44704f69SBart Van Assche static const char illoptstring[] = "unknown option -- %s";
105*44704f69SBart Van Assche
106*44704f69SBart Van Assche
107*44704f69SBart Van Assche /*
108*44704f69SBart Van Assche * Compute the greatest common divisor of a and b.
109*44704f69SBart Van Assche */
110*44704f69SBart Van Assche static int
gcd(int a,int b)111*44704f69SBart Van Assche gcd(int a, int b)
112*44704f69SBart Van Assche {
113*44704f69SBart Van Assche int c;
114*44704f69SBart Van Assche
115*44704f69SBart Van Assche c = a % b;
116*44704f69SBart Van Assche while (c != 0) {
117*44704f69SBart Van Assche a = b;
118*44704f69SBart Van Assche b = c;
119*44704f69SBart Van Assche c = a % b;
120*44704f69SBart Van Assche }
121*44704f69SBart Van Assche
122*44704f69SBart Van Assche return b;
123*44704f69SBart Van Assche }
124*44704f69SBart Van Assche
125*44704f69SBart Van Assche /*
126*44704f69SBart Van Assche * Exchange the block from nonopt_start to nonopt_end with the block
127*44704f69SBart Van Assche * from nonopt_end to opt_end (keeping the same order of arguments
128*44704f69SBart Van Assche * in each block).
129*44704f69SBart Van Assche */
130*44704f69SBart Van Assche static void
permute_args(int panonopt_start,int panonopt_end,int opt_end,char * const * nargv)131*44704f69SBart Van Assche permute_args(int panonopt_start, int panonopt_end, int opt_end,
132*44704f69SBart Van Assche char * const *nargv)
133*44704f69SBart Van Assche {
134*44704f69SBart Van Assche int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
135*44704f69SBart Van Assche char *swap;
136*44704f69SBart Van Assche
137*44704f69SBart Van Assche assert(nargv != NULL);
138*44704f69SBart Van Assche
139*44704f69SBart Van Assche /*
140*44704f69SBart Van Assche * compute lengths of blocks and number and size of cycles
141*44704f69SBart Van Assche */
142*44704f69SBart Van Assche nnonopts = panonopt_end - panonopt_start;
143*44704f69SBart Van Assche nopts = opt_end - panonopt_end;
144*44704f69SBart Van Assche ncycle = gcd(nnonopts, nopts);
145*44704f69SBart Van Assche cyclelen = (opt_end - panonopt_start) / ncycle;
146*44704f69SBart Van Assche
147*44704f69SBart Van Assche for (i = 0; i < ncycle; i++) {
148*44704f69SBart Van Assche cstart = panonopt_end+i;
149*44704f69SBart Van Assche pos = cstart;
150*44704f69SBart Van Assche for (j = 0; j < cyclelen; j++) {
151*44704f69SBart Van Assche if (pos >= panonopt_end)
152*44704f69SBart Van Assche pos -= nnonopts;
153*44704f69SBart Van Assche else
154*44704f69SBart Van Assche pos += nopts;
155*44704f69SBart Van Assche swap = nargv[pos];
156*44704f69SBart Van Assche /* LINTED const cast */
157*44704f69SBart Van Assche ((char **) nargv)[pos] = nargv[cstart];
158*44704f69SBart Van Assche /* LINTED const cast */
159*44704f69SBart Van Assche ((char **)nargv)[cstart] = swap;
160*44704f69SBart Van Assche }
161*44704f69SBart Van Assche }
162*44704f69SBart Van Assche }
163*44704f69SBart Van Assche
164*44704f69SBart Van Assche /*
165*44704f69SBart Van Assche * getopt_internal --
166*44704f69SBart Van Assche * Parse argc/argv argument vector. Called by user level routines.
167*44704f69SBart Van Assche * Returns -2 if -- is found (can be long option or end of options marker).
168*44704f69SBart Van Assche */
169*44704f69SBart Van Assche static int
getopt_internal(int nargc,char * const * nargv,const char * options)170*44704f69SBart Van Assche getopt_internal(int nargc, char * const *nargv, const char *options)
171*44704f69SBart Van Assche {
172*44704f69SBart Van Assche char *oli; /* option letter list index */
173*44704f69SBart Van Assche int optchar;
174*44704f69SBart Van Assche
175*44704f69SBart Van Assche assert(nargv != NULL);
176*44704f69SBart Van Assche assert(options != NULL);
177*44704f69SBart Van Assche
178*44704f69SBart Van Assche optarg = NULL;
179*44704f69SBart Van Assche
180*44704f69SBart Van Assche /*
181*44704f69SBart Van Assche * XXX Some programs (like rsyncd) expect to be able to
182*44704f69SBart Van Assche * XXX re-initialize optind to 0 and have getopt_long(3)
183*44704f69SBart Van Assche * XXX properly function again. Work around this braindamage.
184*44704f69SBart Van Assche */
185*44704f69SBart Van Assche if (optind == 0)
186*44704f69SBart Van Assche optind = 1;
187*44704f69SBart Van Assche
188*44704f69SBart Van Assche start:
189*44704f69SBart Van Assche if (!*place) { /* update scanning pointer */
190*44704f69SBart Van Assche if (optind >= nargc) { /* end of argument vector */
191*44704f69SBart Van Assche place = EMSG;
192*44704f69SBart Van Assche if (nonopt_end != -1) {
193*44704f69SBart Van Assche /* do permutation, if we have to */
194*44704f69SBart Van Assche permute_args(nonopt_start, nonopt_end,
195*44704f69SBart Van Assche optind, nargv);
196*44704f69SBart Van Assche optind -= nonopt_end - nonopt_start;
197*44704f69SBart Van Assche }
198*44704f69SBart Van Assche else if (nonopt_start != -1) {
199*44704f69SBart Van Assche /*
200*44704f69SBart Van Assche * If we skipped non-options, set optind
201*44704f69SBart Van Assche * to the first of them.
202*44704f69SBart Van Assche */
203*44704f69SBart Van Assche optind = nonopt_start;
204*44704f69SBart Van Assche }
205*44704f69SBart Van Assche nonopt_start = nonopt_end = -1;
206*44704f69SBart Van Assche return -1;
207*44704f69SBart Van Assche }
208*44704f69SBart Van Assche if ((*(place = nargv[optind]) != '-')
209*44704f69SBart Van Assche || (place[1] == '\0')) { /* found non-option */
210*44704f69SBart Van Assche place = EMSG;
211*44704f69SBart Van Assche if (IN_ORDER) {
212*44704f69SBart Van Assche /*
213*44704f69SBart Van Assche * GNU extension:
214*44704f69SBart Van Assche * return non-option as argument to option 1
215*44704f69SBart Van Assche */
216*44704f69SBart Van Assche optarg = nargv[optind++];
217*44704f69SBart Van Assche return INORDER;
218*44704f69SBart Van Assche }
219*44704f69SBart Van Assche if (!PERMUTE) {
220*44704f69SBart Van Assche /*
221*44704f69SBart Van Assche * if no permutation wanted, stop parsing
222*44704f69SBart Van Assche * at first non-option
223*44704f69SBart Van Assche */
224*44704f69SBart Van Assche return -1;
225*44704f69SBart Van Assche }
226*44704f69SBart Van Assche /* do permutation */
227*44704f69SBart Van Assche if (nonopt_start == -1)
228*44704f69SBart Van Assche nonopt_start = optind;
229*44704f69SBart Van Assche else if (nonopt_end != -1) {
230*44704f69SBart Van Assche permute_args(nonopt_start, nonopt_end,
231*44704f69SBart Van Assche optind, nargv);
232*44704f69SBart Van Assche nonopt_start = optind -
233*44704f69SBart Van Assche (nonopt_end - nonopt_start);
234*44704f69SBart Van Assche nonopt_end = -1;
235*44704f69SBart Van Assche }
236*44704f69SBart Van Assche optind++;
237*44704f69SBart Van Assche /* process next argument */
238*44704f69SBart Van Assche goto start;
239*44704f69SBart Van Assche }
240*44704f69SBart Van Assche if (nonopt_start != -1 && nonopt_end == -1)
241*44704f69SBart Van Assche nonopt_end = optind;
242*44704f69SBart Van Assche if (place[1] && *++place == '-') { /* found "--" */
243*44704f69SBart Van Assche place++;
244*44704f69SBart Van Assche return -2;
245*44704f69SBart Van Assche }
246*44704f69SBart Van Assche }
247*44704f69SBart Van Assche if ((optchar = (int)*place++) == (int)':' ||
248*44704f69SBart Van Assche (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
249*44704f69SBart Van Assche /* option letter unknown or ':' */
250*44704f69SBart Van Assche if (!*place)
251*44704f69SBart Van Assche ++optind;
252*44704f69SBart Van Assche if (PRINT_ERROR)
253*44704f69SBart Van Assche fprintf(stderr, illoptchar, optchar);
254*44704f69SBart Van Assche optopt = optchar;
255*44704f69SBart Van Assche return BADCH;
256*44704f69SBart Van Assche }
257*44704f69SBart Van Assche if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
258*44704f69SBart Van Assche /* XXX: what if no long options provided (called by getopt)? */
259*44704f69SBart Van Assche if (*place)
260*44704f69SBart Van Assche return -2;
261*44704f69SBart Van Assche
262*44704f69SBart Van Assche if (++optind >= nargc) { /* no arg */
263*44704f69SBart Van Assche place = EMSG;
264*44704f69SBart Van Assche if (PRINT_ERROR)
265*44704f69SBart Van Assche fprintf(stderr, recargchar, optchar);
266*44704f69SBart Van Assche optopt = optchar;
267*44704f69SBart Van Assche return BADARG;
268*44704f69SBart Van Assche } else /* white space */
269*44704f69SBart Van Assche place = nargv[optind];
270*44704f69SBart Van Assche /*
271*44704f69SBart Van Assche * Handle -W arg the same as --arg (which causes getopt to
272*44704f69SBart Van Assche * stop parsing).
273*44704f69SBart Van Assche */
274*44704f69SBart Van Assche return -2;
275*44704f69SBart Van Assche }
276*44704f69SBart Van Assche if (*++oli != ':') { /* doesn't take argument */
277*44704f69SBart Van Assche if (!*place)
278*44704f69SBart Van Assche ++optind;
279*44704f69SBart Van Assche } else { /* takes (optional) argument */
280*44704f69SBart Van Assche optarg = NULL;
281*44704f69SBart Van Assche if (*place) /* no white space */
282*44704f69SBart Van Assche optarg = place;
283*44704f69SBart Van Assche /* XXX: disable test for :: if PC? (GNU doesn't) */
284*44704f69SBart Van Assche else if (oli[1] != ':') { /* arg not optional */
285*44704f69SBart Van Assche if (++optind >= nargc) { /* no arg */
286*44704f69SBart Van Assche place = EMSG;
287*44704f69SBart Van Assche if (PRINT_ERROR)
288*44704f69SBart Van Assche fprintf(stderr, recargchar, optchar);
289*44704f69SBart Van Assche optopt = optchar;
290*44704f69SBart Van Assche return BADARG;
291*44704f69SBart Van Assche } else
292*44704f69SBart Van Assche optarg = nargv[optind];
293*44704f69SBart Van Assche }
294*44704f69SBart Van Assche place = EMSG;
295*44704f69SBart Van Assche ++optind;
296*44704f69SBart Van Assche }
297*44704f69SBart Van Assche /* dump back option letter */
298*44704f69SBart Van Assche return optchar;
299*44704f69SBart Van Assche }
300*44704f69SBart Van Assche
301*44704f69SBart Van Assche /*
302*44704f69SBart Van Assche * getopt_long --
303*44704f69SBart Van Assche * Parse argc/argv argument vector.
304*44704f69SBart Van Assche */
305*44704f69SBart Van Assche int
getopt_long(int nargc,char * const * nargv,const char * options,const struct option * long_options,int * idx)306*44704f69SBart Van Assche getopt_long(int nargc, char * const *nargv, const char *options,
307*44704f69SBart Van Assche const struct option *long_options, int *idx)
308*44704f69SBart Van Assche {
309*44704f69SBart Van Assche int retval;
310*44704f69SBart Van Assche
311*44704f69SBart Van Assche assert(nargv != NULL);
312*44704f69SBart Van Assche assert(options != NULL);
313*44704f69SBart Van Assche assert(long_options != NULL);
314*44704f69SBart Van Assche /* idx may be NULL */
315*44704f69SBart Van Assche
316*44704f69SBart Van Assche if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
317*44704f69SBart Van Assche char *current_argv, *has_equal;
318*44704f69SBart Van Assche size_t current_argv_len;
319*44704f69SBart Van Assche int i, match;
320*44704f69SBart Van Assche
321*44704f69SBart Van Assche current_argv = place;
322*44704f69SBart Van Assche match = -1;
323*44704f69SBart Van Assche
324*44704f69SBart Van Assche optind++;
325*44704f69SBart Van Assche place = EMSG;
326*44704f69SBart Van Assche
327*44704f69SBart Van Assche if (*current_argv == '\0') { /* found "--" */
328*44704f69SBart Van Assche /*
329*44704f69SBart Van Assche * We found an option (--), so if we skipped
330*44704f69SBart Van Assche * non-options, we have to permute.
331*44704f69SBart Van Assche */
332*44704f69SBart Van Assche if (nonopt_end != -1) {
333*44704f69SBart Van Assche permute_args(nonopt_start, nonopt_end,
334*44704f69SBart Van Assche optind, nargv);
335*44704f69SBart Van Assche optind -= nonopt_end - nonopt_start;
336*44704f69SBart Van Assche }
337*44704f69SBart Van Assche nonopt_start = nonopt_end = -1;
338*44704f69SBart Van Assche return -1;
339*44704f69SBart Van Assche }
340*44704f69SBart Van Assche if ((has_equal = strchr(current_argv, '=')) != NULL) {
341*44704f69SBart Van Assche /* argument found (--option=arg) */
342*44704f69SBart Van Assche current_argv_len = has_equal - current_argv;
343*44704f69SBart Van Assche has_equal++;
344*44704f69SBart Van Assche } else
345*44704f69SBart Van Assche current_argv_len = strlen(current_argv);
346*44704f69SBart Van Assche
347*44704f69SBart Van Assche for (i = 0; long_options[i].name; i++) {
348*44704f69SBart Van Assche /* find matching long option */
349*44704f69SBart Van Assche if (strncmp(current_argv, long_options[i].name,
350*44704f69SBart Van Assche current_argv_len))
351*44704f69SBart Van Assche continue;
352*44704f69SBart Van Assche
353*44704f69SBart Van Assche if (strlen(long_options[i].name) ==
354*44704f69SBart Van Assche (unsigned)current_argv_len) {
355*44704f69SBart Van Assche /* exact match */
356*44704f69SBart Van Assche match = i;
357*44704f69SBart Van Assche break;
358*44704f69SBart Van Assche }
359*44704f69SBart Van Assche if (match == -1) /* partial match */
360*44704f69SBart Van Assche match = i;
361*44704f69SBart Van Assche else {
362*44704f69SBart Van Assche /* ambiguous abbreviation */
363*44704f69SBart Van Assche if (PRINT_ERROR)
364*44704f69SBart Van Assche fprintf(stderr, ambig, (int)current_argv_len,
365*44704f69SBart Van Assche current_argv);
366*44704f69SBart Van Assche optopt = 0;
367*44704f69SBart Van Assche return BADCH;
368*44704f69SBart Van Assche }
369*44704f69SBart Van Assche }
370*44704f69SBart Van Assche if (match != -1) { /* option found */
371*44704f69SBart Van Assche if (long_options[match].has_arg == no_argument
372*44704f69SBart Van Assche && has_equal) {
373*44704f69SBart Van Assche if (PRINT_ERROR)
374*44704f69SBart Van Assche fprintf(stderr, noarg, (int)current_argv_len,
375*44704f69SBart Van Assche current_argv);
376*44704f69SBart Van Assche /*
377*44704f69SBart Van Assche * XXX: GNU sets optopt to val regardless of
378*44704f69SBart Van Assche * flag
379*44704f69SBart Van Assche */
380*44704f69SBart Van Assche if (long_options[match].flag == NULL)
381*44704f69SBart Van Assche optopt = long_options[match].val;
382*44704f69SBart Van Assche else
383*44704f69SBart Van Assche optopt = 0;
384*44704f69SBart Van Assche return BADARG;
385*44704f69SBart Van Assche }
386*44704f69SBart Van Assche if (long_options[match].has_arg == required_argument ||
387*44704f69SBart Van Assche long_options[match].has_arg == optional_argument) {
388*44704f69SBart Van Assche if (has_equal)
389*44704f69SBart Van Assche optarg = has_equal;
390*44704f69SBart Van Assche else if (long_options[match].has_arg ==
391*44704f69SBart Van Assche required_argument) {
392*44704f69SBart Van Assche /*
393*44704f69SBart Van Assche * optional argument doesn't use
394*44704f69SBart Van Assche * next nargv
395*44704f69SBart Van Assche */
396*44704f69SBart Van Assche optarg = nargv[optind++];
397*44704f69SBart Van Assche }
398*44704f69SBart Van Assche }
399*44704f69SBart Van Assche if ((long_options[match].has_arg == required_argument)
400*44704f69SBart Van Assche && (optarg == NULL)) {
401*44704f69SBart Van Assche /*
402*44704f69SBart Van Assche * Missing argument; leading ':'
403*44704f69SBart Van Assche * indicates no error should be generated
404*44704f69SBart Van Assche */
405*44704f69SBart Van Assche if (PRINT_ERROR)
406*44704f69SBart Van Assche fprintf(stderr, recargstring, current_argv);
407*44704f69SBart Van Assche /*
408*44704f69SBart Van Assche * XXX: GNU sets optopt to val regardless
409*44704f69SBart Van Assche * of flag
410*44704f69SBart Van Assche */
411*44704f69SBart Van Assche if (long_options[match].flag == NULL)
412*44704f69SBart Van Assche optopt = long_options[match].val;
413*44704f69SBart Van Assche else
414*44704f69SBart Van Assche optopt = 0;
415*44704f69SBart Van Assche --optind;
416*44704f69SBart Van Assche return BADARG;
417*44704f69SBart Van Assche }
418*44704f69SBart Van Assche } else { /* unknown option */
419*44704f69SBart Van Assche if (PRINT_ERROR)
420*44704f69SBart Van Assche fprintf(stderr, illoptstring, current_argv);
421*44704f69SBart Van Assche optopt = 0;
422*44704f69SBart Van Assche return BADCH;
423*44704f69SBart Van Assche }
424*44704f69SBart Van Assche if (long_options[match].flag) {
425*44704f69SBart Van Assche *long_options[match].flag = long_options[match].val;
426*44704f69SBart Van Assche retval = 0;
427*44704f69SBart Van Assche } else
428*44704f69SBart Van Assche retval = long_options[match].val;
429*44704f69SBart Van Assche if (idx)
430*44704f69SBart Van Assche *idx = match;
431*44704f69SBart Van Assche }
432*44704f69SBart Van Assche return retval;
433*44704f69SBart Van Assche }
434*44704f69SBart Van Assche #endif /* !GETOPT_LONG */
435