1*4d9fdb46SRobert Mustacchi /* $NetBSD: getopt.c,v 1.1 2009/03/22 22:33:13 joerg Exp $*/
2*4d9fdb46SRobert Mustacchi /*  Modified by David Anderson to work with GNU/Linux and freebsd.
3*4d9fdb46SRobert Mustacchi     Added {} for clarity.
4*4d9fdb46SRobert Mustacchi     Switched to standard dwarfdump formatting.
5*4d9fdb46SRobert Mustacchi     Treatment of : modified so that :: gets dwoptarg NULL
6*4d9fdb46SRobert Mustacchi     if space follows the letter
7*4d9fdb46SRobert Mustacchi     (the dwoptarg is set to null).
8*4d9fdb46SRobert Mustacchi     renamed to make it clear this is a private version.
9*4d9fdb46SRobert Mustacchi     Oct 17 2017: Created dwgetopt_long(). See dwgetopt.h
10*4d9fdb46SRobert Mustacchi */
11*4d9fdb46SRobert Mustacchi /*
12*4d9fdb46SRobert Mustacchi * Copyright (c) 1987, 1993, 1994
13*4d9fdb46SRobert Mustacchi * The Regents of the University of California.  All rights reserved.
14*4d9fdb46SRobert Mustacchi *
15*4d9fdb46SRobert Mustacchi * Redistribution and use in source and binary forms, with or without
16*4d9fdb46SRobert Mustacchi * modification, are permitted provided that the following conditions
17*4d9fdb46SRobert Mustacchi * are met:
18*4d9fdb46SRobert Mustacchi * 1. Redistributions of source code must retain the above copyright
19*4d9fdb46SRobert Mustacchi *    notice, this list of conditions and the following disclaimer.
20*4d9fdb46SRobert Mustacchi * 2. Redistributions in binary form must reproduce the above copyright
21*4d9fdb46SRobert Mustacchi *    notice, this list of conditions and the following disclaimer in the
22*4d9fdb46SRobert Mustacchi *    documentation and/or other materials provided with the distribution.
23*4d9fdb46SRobert Mustacchi * 3. Neither the name of the University nor the names of its contributors
24*4d9fdb46SRobert Mustacchi *    may be used to endorse or promote products derived from this software
25*4d9fdb46SRobert Mustacchi *    without specific prior written permission.
26*4d9fdb46SRobert Mustacchi *
27*4d9fdb46SRobert Mustacchi * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28*4d9fdb46SRobert Mustacchi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29*4d9fdb46SRobert Mustacchi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30*4d9fdb46SRobert Mustacchi * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31*4d9fdb46SRobert Mustacchi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32*4d9fdb46SRobert Mustacchi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33*4d9fdb46SRobert Mustacchi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34*4d9fdb46SRobert Mustacchi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35*4d9fdb46SRobert Mustacchi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36*4d9fdb46SRobert Mustacchi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37*4d9fdb46SRobert Mustacchi * SUCH DAMAGE.
38*4d9fdb46SRobert Mustacchi */
39*4d9fdb46SRobert Mustacchi 
40*4d9fdb46SRobert Mustacchi /*  This does not presently handle the option string
41*4d9fdb46SRobert Mustacchi     leading + or leading - features. Such are not used
42*4d9fdb46SRobert Mustacchi     by by libdwarfdump.  Nor does it understand the
43*4d9fdb46SRobert Mustacchi     GNU Env var POSIXLY_CORRECT .
44*4d9fdb46SRobert Mustacchi     It does know of the leading ":" in the option string.
45*4d9fdb46SRobert Mustacchi     See BADCH below.
46*4d9fdb46SRobert Mustacchi     */
47*4d9fdb46SRobert Mustacchi 
48*4d9fdb46SRobert Mustacchi #include <stdio.h>
49*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDLIB_H
50*4d9fdb46SRobert Mustacchi #include <stdlib.h>
51*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDLIB_H */
52*4d9fdb46SRobert Mustacchi #include <string.h> /* For strchr */
53*4d9fdb46SRobert Mustacchi #include "dwgetopt.h"
54*4d9fdb46SRobert Mustacchi 
55*4d9fdb46SRobert Mustacchi #define STRIP_OFF_CONSTNESS(a)  ((void *)(size_t)(const void *)(a))
56*4d9fdb46SRobert Mustacchi 
57*4d9fdb46SRobert Mustacchi int dwopterr = 1,    /* if error message should be printed */
58*4d9fdb46SRobert Mustacchi     dwoptind = 1,    /* index into parent argv vector */
59*4d9fdb46SRobert Mustacchi     dwoptopt,        /* character checked for validity */
60*4d9fdb46SRobert Mustacchi     dwoptreset;      /* reset getopt */
61*4d9fdb46SRobert Mustacchi char *dwoptarg;      /* argument associated with option */
62*4d9fdb46SRobert Mustacchi 
63*4d9fdb46SRobert Mustacchi #define BADCH   (int)'?'
64*4d9fdb46SRobert Mustacchi #define BADARG  (int)':'
65*4d9fdb46SRobert Mustacchi #define EMSG    ""
66*4d9fdb46SRobert Mustacchi 
67*4d9fdb46SRobert Mustacchi #define TRUE 1
68*4d9fdb46SRobert Mustacchi #define FALSE 0
69*4d9fdb46SRobert Mustacchi 
70*4d9fdb46SRobert Mustacchi #if 0 /* FOR DEBUGGING ONLY */
71*4d9fdb46SRobert Mustacchi /*  Use for testing dwgetopt only.
72*4d9fdb46SRobert Mustacchi     Not a standard function. */
73*4d9fdb46SRobert Mustacchi void
74*4d9fdb46SRobert Mustacchi dwgetoptresetfortestingonly(void)
75*4d9fdb46SRobert Mustacchi {
76*4d9fdb46SRobert Mustacchi    dwopterr   = 1;
77*4d9fdb46SRobert Mustacchi    dwoptind   = 1;
78*4d9fdb46SRobert Mustacchi    dwoptopt   = 0;
79*4d9fdb46SRobert Mustacchi    dwoptreset = 0;
80*4d9fdb46SRobert Mustacchi    dwoptarg   = 0;
81*4d9fdb46SRobert Mustacchi }
82*4d9fdb46SRobert Mustacchi #endif /* FOR DEBUGGING ONLY */
83*4d9fdb46SRobert Mustacchi 
84*4d9fdb46SRobert Mustacchi 
85*4d9fdb46SRobert Mustacchi static const char *place = EMSG;/* option letter processing */
86*4d9fdb46SRobert Mustacchi 
87*4d9fdb46SRobert Mustacchi 
88*4d9fdb46SRobert Mustacchi /*  Post Condition:
89*4d9fdb46SRobert Mustacchi     if return FALSE then *argerr is set false. */
90*4d9fdb46SRobert Mustacchi static int
dwoptnamematches(const struct dwoption * dwlopt,const char * iplace,const char ** argloc,int * argerr)91*4d9fdb46SRobert Mustacchi dwoptnamematches(
92*4d9fdb46SRobert Mustacchi     const struct dwoption *dwlopt,
93*4d9fdb46SRobert Mustacchi     const char *iplace,
94*4d9fdb46SRobert Mustacchi     const char **argloc,
95*4d9fdb46SRobert Mustacchi     int *argerr)
96*4d9fdb46SRobert Mustacchi {
97*4d9fdb46SRobert Mustacchi 
98*4d9fdb46SRobert Mustacchi     const char *eq = 0;
99*4d9fdb46SRobert Mustacchi     size_t namelen = 0;
100*4d9fdb46SRobert Mustacchi     size_t arglen = 0;
101*4d9fdb46SRobert Mustacchi     int d = 0;
102*4d9fdb46SRobert Mustacchi 
103*4d9fdb46SRobert Mustacchi     for(eq = iplace; *eq; ++eq) {
104*4d9fdb46SRobert Mustacchi         if (*eq != '=') {
105*4d9fdb46SRobert Mustacchi             continue;
106*4d9fdb46SRobert Mustacchi         }
107*4d9fdb46SRobert Mustacchi         /* Found  =, arg should follow */
108*4d9fdb46SRobert Mustacchi         namelen = (eq - iplace);
109*4d9fdb46SRobert Mustacchi         if (namelen != (unsigned)strlen(dwlopt->name)) {
110*4d9fdb46SRobert Mustacchi             return FALSE;
111*4d9fdb46SRobert Mustacchi         }
112*4d9fdb46SRobert Mustacchi         eq++;
113*4d9fdb46SRobert Mustacchi         arglen = strlen(eq);
114*4d9fdb46SRobert Mustacchi         break;
115*4d9fdb46SRobert Mustacchi     }
116*4d9fdb46SRobert Mustacchi     if (namelen) {
117*4d9fdb46SRobert Mustacchi         d = strncmp(iplace,dwlopt->name,namelen);
118*4d9fdb46SRobert Mustacchi         if (d) {
119*4d9fdb46SRobert Mustacchi             return FALSE;
120*4d9fdb46SRobert Mustacchi         }
121*4d9fdb46SRobert Mustacchi         if (dwlopt->has_arg == 0) {
122*4d9fdb46SRobert Mustacchi             *argerr = TRUE;
123*4d9fdb46SRobert Mustacchi             return TRUE;
124*4d9fdb46SRobert Mustacchi         }
125*4d9fdb46SRobert Mustacchi         if (arglen) {
126*4d9fdb46SRobert Mustacchi             /*  Discarding const, avoiding warning.
127*4d9fdb46SRobert Mustacchi                 Data is in user space, so this is ok. */
128*4d9fdb46SRobert Mustacchi             dwoptarg = (char *)eq;
129*4d9fdb46SRobert Mustacchi             *argloc = (const char *)eq;
130*4d9fdb46SRobert Mustacchi         } else {
131*4d9fdb46SRobert Mustacchi             /* Has arg = but arg is empty. */
132*4d9fdb46SRobert Mustacchi             dwoptarg = 0;
133*4d9fdb46SRobert Mustacchi         }
134*4d9fdb46SRobert Mustacchi         return TRUE;
135*4d9fdb46SRobert Mustacchi     } else {
136*4d9fdb46SRobert Mustacchi         d = strcmp(iplace,dwlopt->name);
137*4d9fdb46SRobert Mustacchi         if (d) {
138*4d9fdb46SRobert Mustacchi             return FALSE;
139*4d9fdb46SRobert Mustacchi         }
140*4d9fdb46SRobert Mustacchi         if (dwlopt->has_arg == 1) {
141*4d9fdb46SRobert Mustacchi             *argerr = TRUE;
142*4d9fdb46SRobert Mustacchi             return TRUE;
143*4d9fdb46SRobert Mustacchi         }
144*4d9fdb46SRobert Mustacchi         dwoptarg = 0;
145*4d9fdb46SRobert Mustacchi         return TRUE;
146*4d9fdb46SRobert Mustacchi     }
147*4d9fdb46SRobert Mustacchi }
148*4d9fdb46SRobert Mustacchi 
149*4d9fdb46SRobert Mustacchi 
150*4d9fdb46SRobert Mustacchi 
151*4d9fdb46SRobert Mustacchi /*  dwgetopt_long
152*4d9fdb46SRobert Mustacchi     A reimplemenation of  a portion of
153*4d9fdb46SRobert Mustacchi     the getopt(3) GNU/Linux  getopt_long().
154*4d9fdb46SRobert Mustacchi     See dwgetopt.h for more details.
155*4d9fdb46SRobert Mustacchi */
dwgetopt_long(int nargc,char * const nargv[],const char * ostr,const struct dwoption * longopts,int * longindex)156*4d9fdb46SRobert Mustacchi int dwgetopt_long(int nargc, char *const nargv[],
157*4d9fdb46SRobert Mustacchi     const char *ostr,
158*4d9fdb46SRobert Mustacchi     const struct dwoption* longopts,
159*4d9fdb46SRobert Mustacchi     int *longindex)
160*4d9fdb46SRobert Mustacchi {
161*4d9fdb46SRobert Mustacchi     char *lplace = 0;
162*4d9fdb46SRobert Mustacchi     if (dwoptreset) {
163*4d9fdb46SRobert Mustacchi         /*  Not really supported. */
164*4d9fdb46SRobert Mustacchi         place = EMSG;
165*4d9fdb46SRobert Mustacchi         return (-1);
166*4d9fdb46SRobert Mustacchi     }
167*4d9fdb46SRobert Mustacchi     if (*place) {
168*4d9fdb46SRobert Mustacchi         int v = dwgetopt(nargc,nargv,ostr);
169*4d9fdb46SRobert Mustacchi         return v;
170*4d9fdb46SRobert Mustacchi     }
171*4d9fdb46SRobert Mustacchi     /*  Use local lplace in case we need to call getopt()
172*4d9fdb46SRobert Mustacchi         just below. */
173*4d9fdb46SRobert Mustacchi     lplace = nargv[dwoptind];
174*4d9fdb46SRobert Mustacchi     if (dwoptind >= nargc || *lplace++ != '-') {
175*4d9fdb46SRobert Mustacchi         /* Argument is absent or is not an option */
176*4d9fdb46SRobert Mustacchi         place = EMSG;
177*4d9fdb46SRobert Mustacchi         return (-1);
178*4d9fdb46SRobert Mustacchi     }
179*4d9fdb46SRobert Mustacchi     if  (*lplace  != '-') {
180*4d9fdb46SRobert Mustacchi         /* Notice place not  disturbed. */
181*4d9fdb46SRobert Mustacchi         int v = dwgetopt(nargc,nargv,ostr);
182*4d9fdb46SRobert Mustacchi         return v;
183*4d9fdb46SRobert Mustacchi     }
184*4d9fdb46SRobert Mustacchi     /*  Starts with two dashes.
185*4d9fdb46SRobert Mustacchi         Now we set the global place */
186*4d9fdb46SRobert Mustacchi     place = lplace+1;
187*4d9fdb46SRobert Mustacchi     if (!*place) {
188*4d9fdb46SRobert Mustacchi         /* "--" => end of options */
189*4d9fdb46SRobert Mustacchi         ++dwoptind;
190*4d9fdb46SRobert Mustacchi         place = EMSG;
191*4d9fdb46SRobert Mustacchi         return (-1);
192*4d9fdb46SRobert Mustacchi     }
193*4d9fdb46SRobert Mustacchi 
194*4d9fdb46SRobert Mustacchi     /* We think this is a longopt. */
195*4d9fdb46SRobert Mustacchi     {
196*4d9fdb46SRobert Mustacchi     int lo_num = 0;
197*4d9fdb46SRobert Mustacchi 
198*4d9fdb46SRobert Mustacchi     for(;;lo_num++) {
199*4d9fdb46SRobert Mustacchi         const struct dwoption *dwlopt = longopts +lo_num;
200*4d9fdb46SRobert Mustacchi         const char * argloc = 0;
201*4d9fdb46SRobert Mustacchi         int argerr = 0;
202*4d9fdb46SRobert Mustacchi         int resmatch = 0;
203*4d9fdb46SRobert Mustacchi 
204*4d9fdb46SRobert Mustacchi         if (!dwlopt->name) {
205*4d9fdb46SRobert Mustacchi             dwoptind++;
206*4d9fdb46SRobert Mustacchi             (void)fprintf(stderr,
207*4d9fdb46SRobert Mustacchi                 "%s: invalid long option '--%s'\n",
208*4d9fdb46SRobert Mustacchi                 nargv[0]?nargv[0]:"",
209*4d9fdb46SRobert Mustacchi                 place);
210*4d9fdb46SRobert Mustacchi             /* Leave longindex unchanged. */
211*4d9fdb46SRobert Mustacchi             place = EMSG;
212*4d9fdb46SRobert Mustacchi             return (BADCH);
213*4d9fdb46SRobert Mustacchi         }
214*4d9fdb46SRobert Mustacchi         resmatch= dwoptnamematches(dwlopt,place,
215*4d9fdb46SRobert Mustacchi             &argloc,&argerr);
216*4d9fdb46SRobert Mustacchi         if (resmatch) {
217*4d9fdb46SRobert Mustacchi             dwoptarg = 0;
218*4d9fdb46SRobert Mustacchi             if (argloc) {
219*4d9fdb46SRobert Mustacchi                 /* Must drop const here. Ugh. */
220*4d9fdb46SRobert Mustacchi                 dwoptarg = (char *)argloc;
221*4d9fdb46SRobert Mustacchi             }
222*4d9fdb46SRobert Mustacchi         }
223*4d9fdb46SRobert Mustacchi         if (argerr) {
224*4d9fdb46SRobert Mustacchi             /*  resmatch  == TRUE
225*4d9fdb46SRobert Mustacchi 
226*4d9fdb46SRobert Mustacchi                 arg option  missing if required, present
227*4d9fdb46SRobert Mustacchi                 but not allowed.
228*4d9fdb46SRobert Mustacchi                 GNU Behavior not well documented.
229*4d9fdb46SRobert Mustacchi                 Had to experiment.
230*4d9fdb46SRobert Mustacchi 
231*4d9fdb46SRobert Mustacchi                 if argument-not-allowed, and we have one,
232*4d9fdb46SRobert Mustacchi                 do ???
233*4d9fdb46SRobert Mustacchi 
234*4d9fdb46SRobert Mustacchi                 If argument-required,
235*4d9fdb46SRobert Mustacchi                 then here GNU
236*4d9fdb46SRobert Mustacchi                 would take the next argv as the argument.
237*4d9fdb46SRobert Mustacchi                 we are not currently doing that. */
238*4d9fdb46SRobert Mustacchi             /**longindex = lo_num; */
239*4d9fdb46SRobert Mustacchi             if (dwlopt->has_arg) {
240*4d9fdb46SRobert Mustacchi                 /*  Missing required arg, this does not
241*4d9fdb46SRobert Mustacchi                     match GNU getopt_long behavior
242*4d9fdb46SRobert Mustacchi                     of taking next argv as the arg value.
243*4d9fdb46SRobert Mustacchi                     and thus making getopt_long succeed. */
244*4d9fdb46SRobert Mustacchi                 (void)fprintf(stderr,
245*4d9fdb46SRobert Mustacchi                     "%s: missing required long option argument '--%s'\n",
246*4d9fdb46SRobert Mustacchi                     nargv[0]?nargv[0]:"",
247*4d9fdb46SRobert Mustacchi                     place);
248*4d9fdb46SRobert Mustacchi             } else {
249*4d9fdb46SRobert Mustacchi                 /* has arg but should not */
250*4d9fdb46SRobert Mustacchi                 (void)fprintf(stderr,
251*4d9fdb46SRobert Mustacchi                     "%s: option '--%s' does not allow an argument\n",
252*4d9fdb46SRobert Mustacchi                     nargv[0]?nargv[0]:"",
253*4d9fdb46SRobert Mustacchi                     dwlopt->name);
254*4d9fdb46SRobert Mustacchi             }
255*4d9fdb46SRobert Mustacchi             dwoptind++;
256*4d9fdb46SRobert Mustacchi             place = EMSG;
257*4d9fdb46SRobert Mustacchi             return (BADCH);
258*4d9fdb46SRobert Mustacchi         }
259*4d9fdb46SRobert Mustacchi         if (resmatch) {
260*4d9fdb46SRobert Mustacchi             *longindex = lo_num;
261*4d9fdb46SRobert Mustacchi             place = EMSG;
262*4d9fdb46SRobert Mustacchi             dwoptind++;
263*4d9fdb46SRobert Mustacchi             return dwlopt->val;
264*4d9fdb46SRobert Mustacchi         }
265*4d9fdb46SRobert Mustacchi     }
266*4d9fdb46SRobert Mustacchi     /* Can never get here */
267*4d9fdb46SRobert Mustacchi     place = EMSG;
268*4d9fdb46SRobert Mustacchi     dwoptind++;
269*4d9fdb46SRobert Mustacchi     return (-1);
270*4d9fdb46SRobert Mustacchi     }
271*4d9fdb46SRobert Mustacchi }
272*4d9fdb46SRobert Mustacchi 
273*4d9fdb46SRobert Mustacchi /*
274*4d9fdb46SRobert Mustacchi     * getopt --
275*4d9fdb46SRobert Mustacchi     * Parse argc/argv argument vector.
276*4d9fdb46SRobert Mustacchi     * a: means
277*4d9fdb46SRobert Mustacchi     *     -afoo
278*4d9fdb46SRobert Mustacchi     *     -a foo
279*4d9fdb46SRobert Mustacchi     *     and 'foo' is returned in dwoptarg
280*4d9fdb46SRobert Mustacchi     *  b:: means
281*4d9fdb46SRobert Mustacchi     *     -b
282*4d9fdb46SRobert Mustacchi     *        and dwoptarg is null
283*4d9fdb46SRobert Mustacchi     *     -bother
284*4d9fdb46SRobert Mustacchi     *        and dwoptarg is 'other'
285*4d9fdb46SRobert Mustacchi     */
286*4d9fdb46SRobert Mustacchi int
dwgetopt(int nargc,char * const nargv[],const char * ostr)287*4d9fdb46SRobert Mustacchi dwgetopt(int nargc, char * const nargv[], const char *ostr)
288*4d9fdb46SRobert Mustacchi {
289*4d9fdb46SRobert Mustacchi     char *oli;                      /* option letter list index */
290*4d9fdb46SRobert Mustacchi 
291*4d9fdb46SRobert Mustacchi     if (dwoptreset || *place == 0) { /* update scanning pointer */
292*4d9fdb46SRobert Mustacchi         dwoptreset = 0;
293*4d9fdb46SRobert Mustacchi         place = nargv[dwoptind];
294*4d9fdb46SRobert Mustacchi 
295*4d9fdb46SRobert Mustacchi         if (dwoptind >= nargc || *place++ != '-') {
296*4d9fdb46SRobert Mustacchi             /* Argument is absent or is not an option */
297*4d9fdb46SRobert Mustacchi             place = EMSG;
298*4d9fdb46SRobert Mustacchi             return (-1);
299*4d9fdb46SRobert Mustacchi         }
300*4d9fdb46SRobert Mustacchi         dwoptopt = *place++;
301*4d9fdb46SRobert Mustacchi         if (dwoptopt == '-' && *place == 0) {
302*4d9fdb46SRobert Mustacchi             /* "--" => end of options */
303*4d9fdb46SRobert Mustacchi             ++dwoptind;
304*4d9fdb46SRobert Mustacchi             place = EMSG;
305*4d9fdb46SRobert Mustacchi             return (-1);
306*4d9fdb46SRobert Mustacchi         }
307*4d9fdb46SRobert Mustacchi         if (dwoptopt == 0) {
308*4d9fdb46SRobert Mustacchi             /* Solitary '-', treat as a '-' option
309*4d9fdb46SRobert Mustacchi                 if the program (eg su) is looking for it. */
310*4d9fdb46SRobert Mustacchi             place = EMSG;
311*4d9fdb46SRobert Mustacchi             if (strchr(ostr, '-') == NULL) {
312*4d9fdb46SRobert Mustacchi                 return -1;
313*4d9fdb46SRobert Mustacchi             }
314*4d9fdb46SRobert Mustacchi             dwoptopt = '-';
315*4d9fdb46SRobert Mustacchi         }
316*4d9fdb46SRobert Mustacchi     } else {
317*4d9fdb46SRobert Mustacchi         dwoptopt = *place++;
318*4d9fdb46SRobert Mustacchi     }
319*4d9fdb46SRobert Mustacchi     /* See if option letter is one the caller wanted... */
320*4d9fdb46SRobert Mustacchi     if (dwoptopt == ':' || (oli = strchr(ostr, dwoptopt)) == NULL) {
321*4d9fdb46SRobert Mustacchi         if (*place == 0) {
322*4d9fdb46SRobert Mustacchi             ++dwoptind;
323*4d9fdb46SRobert Mustacchi         }
324*4d9fdb46SRobert Mustacchi         if (dwopterr && *ostr != ':') {
325*4d9fdb46SRobert Mustacchi             (void)fprintf(stderr,
326*4d9fdb46SRobert Mustacchi                 "%s: invalid option -- '%c'\n",
327*4d9fdb46SRobert Mustacchi                 nargv[0]?nargv[0]:"",
328*4d9fdb46SRobert Mustacchi                 dwoptopt);
329*4d9fdb46SRobert Mustacchi         }
330*4d9fdb46SRobert Mustacchi         return (BADCH);
331*4d9fdb46SRobert Mustacchi     }
332*4d9fdb46SRobert Mustacchi 
333*4d9fdb46SRobert Mustacchi     /* Does this option need an argument? */
334*4d9fdb46SRobert Mustacchi     if (oli[1] != ':') {
335*4d9fdb46SRobert Mustacchi         /* don't need argument */
336*4d9fdb46SRobert Mustacchi         dwoptarg = NULL;
337*4d9fdb46SRobert Mustacchi         if (*place == 0) {
338*4d9fdb46SRobert Mustacchi             ++dwoptind;
339*4d9fdb46SRobert Mustacchi         }
340*4d9fdb46SRobert Mustacchi     } else {
341*4d9fdb46SRobert Mustacchi         int reqnextarg = 1;
342*4d9fdb46SRobert Mustacchi         if (oli[1] && (oli[2] == ':')) {
343*4d9fdb46SRobert Mustacchi             /* Pair of :: means special treatment of dwoptarg */
344*4d9fdb46SRobert Mustacchi             reqnextarg = 0;
345*4d9fdb46SRobert Mustacchi         }
346*4d9fdb46SRobert Mustacchi         /* Option-argument is either the rest of this argument or the
347*4d9fdb46SRobert Mustacchi         entire next argument. */
348*4d9fdb46SRobert Mustacchi         if (*place ) {
349*4d9fdb46SRobert Mustacchi             /* Whether : or :: */
350*4d9fdb46SRobert Mustacchi             dwoptarg = STRIP_OFF_CONSTNESS(place);
351*4d9fdb46SRobert Mustacchi         } else if (reqnextarg) {
352*4d9fdb46SRobert Mustacchi             /* ! *place */
353*4d9fdb46SRobert Mustacchi             if (nargc > (++dwoptind)) {
354*4d9fdb46SRobert Mustacchi                 dwoptarg = nargv[dwoptind];
355*4d9fdb46SRobert Mustacchi             } else {
356*4d9fdb46SRobert Mustacchi                 place=EMSG;
357*4d9fdb46SRobert Mustacchi                 /*  Next arg required, but is missing */
358*4d9fdb46SRobert Mustacchi                 if (*ostr == ':') {
359*4d9fdb46SRobert Mustacchi                     /* Leading : in ostr calls for BADARG return. */
360*4d9fdb46SRobert Mustacchi                     return (BADARG);
361*4d9fdb46SRobert Mustacchi                 }
362*4d9fdb46SRobert Mustacchi                 if (dwopterr) {
363*4d9fdb46SRobert Mustacchi                     (void)fprintf(stderr,
364*4d9fdb46SRobert Mustacchi                         "%s: option requires an argument. -- '%c'\n",
365*4d9fdb46SRobert Mustacchi                         nargv[0]?nargv[0]:"",
366*4d9fdb46SRobert Mustacchi                         dwoptopt);
367*4d9fdb46SRobert Mustacchi                 }
368*4d9fdb46SRobert Mustacchi                 return (BADCH);
369*4d9fdb46SRobert Mustacchi             }
370*4d9fdb46SRobert Mustacchi         } else {
371*4d9fdb46SRobert Mustacchi             /* ! *place */
372*4d9fdb46SRobert Mustacchi             /* The key part of :: treatment. */
373*4d9fdb46SRobert Mustacchi             dwoptarg = NULL;
374*4d9fdb46SRobert Mustacchi         }
375*4d9fdb46SRobert Mustacchi         place = EMSG;
376*4d9fdb46SRobert Mustacchi         ++dwoptind;
377*4d9fdb46SRobert Mustacchi     }
378*4d9fdb46SRobert Mustacchi     return (dwoptopt);  /* return option letter */
379*4d9fdb46SRobert Mustacchi }
380