1*9663SMark.Logan@Sun.COM /* Getopt for GNU.
2*9663SMark.Logan@Sun.COM NOTE: getopt is now part of the C library, so if you don't know what
3*9663SMark.Logan@Sun.COM "Keep this file name-space clean" means, talk to drepper@gnu.org
4*9663SMark.Logan@Sun.COM before changing it!
5*9663SMark.Logan@Sun.COM Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
6*9663SMark.Logan@Sun.COM Free Software Foundation, Inc.
7*9663SMark.Logan@Sun.COM This file is part of the GNU C Library.
8*9663SMark.Logan@Sun.COM
9*9663SMark.Logan@Sun.COM This program is free software; you can redistribute it and/or modify
10*9663SMark.Logan@Sun.COM it under the terms of the GNU General Public License as published by
11*9663SMark.Logan@Sun.COM the Free Software Foundation; either version 2, or (at your option)
12*9663SMark.Logan@Sun.COM any later version.
13*9663SMark.Logan@Sun.COM
14*9663SMark.Logan@Sun.COM This program is distributed in the hope that it will be useful,
15*9663SMark.Logan@Sun.COM but WITHOUT ANY WARRANTY; without even the implied warranty of
16*9663SMark.Logan@Sun.COM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*9663SMark.Logan@Sun.COM GNU General Public License for more details.
18*9663SMark.Logan@Sun.COM
19*9663SMark.Logan@Sun.COM You should have received a copy of the GNU General Public License along
20*9663SMark.Logan@Sun.COM with this program; if not, write to the Free Software Foundation,
21*9663SMark.Logan@Sun.COM Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22*9663SMark.Logan@Sun.COM
23*9663SMark.Logan@Sun.COM #ifndef _LIBC
24*9663SMark.Logan@Sun.COM # include <config.h>
25*9663SMark.Logan@Sun.COM #endif
26*9663SMark.Logan@Sun.COM
27*9663SMark.Logan@Sun.COM #include "getopt.h"
28*9663SMark.Logan@Sun.COM
29*9663SMark.Logan@Sun.COM #include <stdio.h>
30*9663SMark.Logan@Sun.COM #include <stdlib.h>
31*9663SMark.Logan@Sun.COM #include <string.h>
32*9663SMark.Logan@Sun.COM #include <unistd.h>
33*9663SMark.Logan@Sun.COM
34*9663SMark.Logan@Sun.COM #ifdef __VMS
35*9663SMark.Logan@Sun.COM # include <unixlib.h>
36*9663SMark.Logan@Sun.COM #endif
37*9663SMark.Logan@Sun.COM
38*9663SMark.Logan@Sun.COM #ifdef _LIBC
39*9663SMark.Logan@Sun.COM # include <libintl.h>
40*9663SMark.Logan@Sun.COM #else
41*9663SMark.Logan@Sun.COM # include "gettext.h"
42*9663SMark.Logan@Sun.COM # define _(msgid) gettext (msgid)
43*9663SMark.Logan@Sun.COM #endif
44*9663SMark.Logan@Sun.COM
45*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
46*9663SMark.Logan@Sun.COM # include <wchar.h>
47*9663SMark.Logan@Sun.COM #endif
48*9663SMark.Logan@Sun.COM
49*9663SMark.Logan@Sun.COM #ifndef attribute_hidden
50*9663SMark.Logan@Sun.COM # define attribute_hidden
51*9663SMark.Logan@Sun.COM #endif
52*9663SMark.Logan@Sun.COM
53*9663SMark.Logan@Sun.COM /* Unlike standard Unix `getopt', functions like `getopt_long'
54*9663SMark.Logan@Sun.COM let the user intersperse the options with the other arguments.
55*9663SMark.Logan@Sun.COM
56*9663SMark.Logan@Sun.COM As `getopt_long' works, it permutes the elements of ARGV so that,
57*9663SMark.Logan@Sun.COM when it is done, all the options precede everything else. Thus
58*9663SMark.Logan@Sun.COM all application programs are extended to handle flexible argument order.
59*9663SMark.Logan@Sun.COM
60*9663SMark.Logan@Sun.COM Using `getopt' or setting the environment variable POSIXLY_CORRECT
61*9663SMark.Logan@Sun.COM disables permutation.
62*9663SMark.Logan@Sun.COM Then the application's behavior is completely standard.
63*9663SMark.Logan@Sun.COM
64*9663SMark.Logan@Sun.COM GNU application programs can use a third alternative mode in which
65*9663SMark.Logan@Sun.COM they can distinguish the relative order of options and other arguments. */
66*9663SMark.Logan@Sun.COM
67*9663SMark.Logan@Sun.COM #include "getopt_int.h"
68*9663SMark.Logan@Sun.COM
69*9663SMark.Logan@Sun.COM /* For communication from `getopt' to the caller.
70*9663SMark.Logan@Sun.COM When `getopt' finds an option that takes an argument,
71*9663SMark.Logan@Sun.COM the argument value is returned here.
72*9663SMark.Logan@Sun.COM Also, when `ordering' is RETURN_IN_ORDER,
73*9663SMark.Logan@Sun.COM each non-option ARGV-element is returned here. */
74*9663SMark.Logan@Sun.COM
75*9663SMark.Logan@Sun.COM char *optarg;
76*9663SMark.Logan@Sun.COM
77*9663SMark.Logan@Sun.COM /* Index in ARGV of the next element to be scanned.
78*9663SMark.Logan@Sun.COM This is used for communication to and from the caller
79*9663SMark.Logan@Sun.COM and for communication between successive calls to `getopt'.
80*9663SMark.Logan@Sun.COM
81*9663SMark.Logan@Sun.COM On entry to `getopt', zero means this is the first call; initialize.
82*9663SMark.Logan@Sun.COM
83*9663SMark.Logan@Sun.COM When `getopt' returns -1, this is the index of the first of the
84*9663SMark.Logan@Sun.COM non-option elements that the caller should itself scan.
85*9663SMark.Logan@Sun.COM
86*9663SMark.Logan@Sun.COM Otherwise, `optind' communicates from one call to the next
87*9663SMark.Logan@Sun.COM how much of ARGV has been scanned so far. */
88*9663SMark.Logan@Sun.COM
89*9663SMark.Logan@Sun.COM /* 1003.2 says this must be 1 before any call. */
90*9663SMark.Logan@Sun.COM int optind = 1;
91*9663SMark.Logan@Sun.COM
92*9663SMark.Logan@Sun.COM /* Callers store zero here to inhibit the error message
93*9663SMark.Logan@Sun.COM for unrecognized options. */
94*9663SMark.Logan@Sun.COM
95*9663SMark.Logan@Sun.COM int opterr = 1;
96*9663SMark.Logan@Sun.COM
97*9663SMark.Logan@Sun.COM /* Set to an option character which was unrecognized.
98*9663SMark.Logan@Sun.COM This must be initialized on some systems to avoid linking in the
99*9663SMark.Logan@Sun.COM system's own getopt implementation. */
100*9663SMark.Logan@Sun.COM
101*9663SMark.Logan@Sun.COM int optopt = '?';
102*9663SMark.Logan@Sun.COM
103*9663SMark.Logan@Sun.COM /* Keep a global copy of all internal members of getopt_data. */
104*9663SMark.Logan@Sun.COM
105*9663SMark.Logan@Sun.COM static struct _getopt_data getopt_data;
106*9663SMark.Logan@Sun.COM
107*9663SMark.Logan@Sun.COM
108*9663SMark.Logan@Sun.COM #if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
109*9663SMark.Logan@Sun.COM extern char *getenv ();
110*9663SMark.Logan@Sun.COM #endif
111*9663SMark.Logan@Sun.COM
112*9663SMark.Logan@Sun.COM #ifdef _LIBC
113*9663SMark.Logan@Sun.COM /* Stored original parameters.
114*9663SMark.Logan@Sun.COM XXX This is no good solution. We should rather copy the args so
115*9663SMark.Logan@Sun.COM that we can compare them later. But we must not use malloc(3). */
116*9663SMark.Logan@Sun.COM extern int __libc_argc;
117*9663SMark.Logan@Sun.COM extern char **__libc_argv;
118*9663SMark.Logan@Sun.COM
119*9663SMark.Logan@Sun.COM /* Bash 2.0 gives us an environment variable containing flags
120*9663SMark.Logan@Sun.COM indicating ARGV elements that should not be considered arguments. */
121*9663SMark.Logan@Sun.COM
122*9663SMark.Logan@Sun.COM # ifdef USE_NONOPTION_FLAGS
123*9663SMark.Logan@Sun.COM /* Defined in getopt_init.c */
124*9663SMark.Logan@Sun.COM extern char *__getopt_nonoption_flags;
125*9663SMark.Logan@Sun.COM # endif
126*9663SMark.Logan@Sun.COM
127*9663SMark.Logan@Sun.COM # ifdef USE_NONOPTION_FLAGS
128*9663SMark.Logan@Sun.COM # define SWAP_FLAGS(ch1, ch2) \
129*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_len > 0) \
130*9663SMark.Logan@Sun.COM { \
131*9663SMark.Logan@Sun.COM char __tmp = __getopt_nonoption_flags[ch1]; \
132*9663SMark.Logan@Sun.COM __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
133*9663SMark.Logan@Sun.COM __getopt_nonoption_flags[ch2] = __tmp; \
134*9663SMark.Logan@Sun.COM }
135*9663SMark.Logan@Sun.COM # else
136*9663SMark.Logan@Sun.COM # define SWAP_FLAGS(ch1, ch2)
137*9663SMark.Logan@Sun.COM # endif
138*9663SMark.Logan@Sun.COM #else /* !_LIBC */
139*9663SMark.Logan@Sun.COM # define SWAP_FLAGS(ch1, ch2)
140*9663SMark.Logan@Sun.COM #endif /* _LIBC */
141*9663SMark.Logan@Sun.COM
142*9663SMark.Logan@Sun.COM /* Exchange two adjacent subsequences of ARGV.
143*9663SMark.Logan@Sun.COM One subsequence is elements [first_nonopt,last_nonopt)
144*9663SMark.Logan@Sun.COM which contains all the non-options that have been skipped so far.
145*9663SMark.Logan@Sun.COM The other is elements [last_nonopt,optind), which contains all
146*9663SMark.Logan@Sun.COM the options processed since those non-options were skipped.
147*9663SMark.Logan@Sun.COM
148*9663SMark.Logan@Sun.COM `first_nonopt' and `last_nonopt' are relocated so that they describe
149*9663SMark.Logan@Sun.COM the new indices of the non-options in ARGV after they are moved. */
150*9663SMark.Logan@Sun.COM
151*9663SMark.Logan@Sun.COM static void
exchange(char ** argv,struct _getopt_data * d)152*9663SMark.Logan@Sun.COM exchange (char **argv, struct _getopt_data *d)
153*9663SMark.Logan@Sun.COM {
154*9663SMark.Logan@Sun.COM int bottom = d->__first_nonopt;
155*9663SMark.Logan@Sun.COM int middle = d->__last_nonopt;
156*9663SMark.Logan@Sun.COM int top = d->optind;
157*9663SMark.Logan@Sun.COM char *tem;
158*9663SMark.Logan@Sun.COM
159*9663SMark.Logan@Sun.COM /* Exchange the shorter segment with the far end of the longer segment.
160*9663SMark.Logan@Sun.COM That puts the shorter segment into the right place.
161*9663SMark.Logan@Sun.COM It leaves the longer segment in the right place overall,
162*9663SMark.Logan@Sun.COM but it consists of two parts that need to be swapped next. */
163*9663SMark.Logan@Sun.COM
164*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_NONOPTION_FLAGS
165*9663SMark.Logan@Sun.COM /* First make sure the handling of the `__getopt_nonoption_flags'
166*9663SMark.Logan@Sun.COM string can work normally. Our top argument must be in the range
167*9663SMark.Logan@Sun.COM of the string. */
168*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
169*9663SMark.Logan@Sun.COM {
170*9663SMark.Logan@Sun.COM /* We must extend the array. The user plays games with us and
171*9663SMark.Logan@Sun.COM presents new arguments. */
172*9663SMark.Logan@Sun.COM char *new_str = malloc (top + 1);
173*9663SMark.Logan@Sun.COM if (new_str == NULL)
174*9663SMark.Logan@Sun.COM d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
175*9663SMark.Logan@Sun.COM else
176*9663SMark.Logan@Sun.COM {
177*9663SMark.Logan@Sun.COM memset (__mempcpy (new_str, __getopt_nonoption_flags,
178*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len),
179*9663SMark.Logan@Sun.COM '\0', top + 1 - d->__nonoption_flags_max_len);
180*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = top + 1;
181*9663SMark.Logan@Sun.COM __getopt_nonoption_flags = new_str;
182*9663SMark.Logan@Sun.COM }
183*9663SMark.Logan@Sun.COM }
184*9663SMark.Logan@Sun.COM #endif
185*9663SMark.Logan@Sun.COM
186*9663SMark.Logan@Sun.COM while (top > middle && middle > bottom)
187*9663SMark.Logan@Sun.COM {
188*9663SMark.Logan@Sun.COM if (top - middle > middle - bottom)
189*9663SMark.Logan@Sun.COM {
190*9663SMark.Logan@Sun.COM /* Bottom segment is the short one. */
191*9663SMark.Logan@Sun.COM int len = middle - bottom;
192*9663SMark.Logan@Sun.COM register int i;
193*9663SMark.Logan@Sun.COM
194*9663SMark.Logan@Sun.COM /* Swap it with the top part of the top segment. */
195*9663SMark.Logan@Sun.COM for (i = 0; i < len; i++)
196*9663SMark.Logan@Sun.COM {
197*9663SMark.Logan@Sun.COM tem = argv[bottom + i];
198*9663SMark.Logan@Sun.COM argv[bottom + i] = argv[top - (middle - bottom) + i];
199*9663SMark.Logan@Sun.COM argv[top - (middle - bottom) + i] = tem;
200*9663SMark.Logan@Sun.COM SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
201*9663SMark.Logan@Sun.COM }
202*9663SMark.Logan@Sun.COM /* Exclude the moved bottom segment from further swapping. */
203*9663SMark.Logan@Sun.COM top -= len;
204*9663SMark.Logan@Sun.COM }
205*9663SMark.Logan@Sun.COM else
206*9663SMark.Logan@Sun.COM {
207*9663SMark.Logan@Sun.COM /* Top segment is the short one. */
208*9663SMark.Logan@Sun.COM int len = top - middle;
209*9663SMark.Logan@Sun.COM register int i;
210*9663SMark.Logan@Sun.COM
211*9663SMark.Logan@Sun.COM /* Swap it with the bottom part of the bottom segment. */
212*9663SMark.Logan@Sun.COM for (i = 0; i < len; i++)
213*9663SMark.Logan@Sun.COM {
214*9663SMark.Logan@Sun.COM tem = argv[bottom + i];
215*9663SMark.Logan@Sun.COM argv[bottom + i] = argv[middle + i];
216*9663SMark.Logan@Sun.COM argv[middle + i] = tem;
217*9663SMark.Logan@Sun.COM SWAP_FLAGS (bottom + i, middle + i);
218*9663SMark.Logan@Sun.COM }
219*9663SMark.Logan@Sun.COM /* Exclude the moved top segment from further swapping. */
220*9663SMark.Logan@Sun.COM bottom += len;
221*9663SMark.Logan@Sun.COM }
222*9663SMark.Logan@Sun.COM }
223*9663SMark.Logan@Sun.COM
224*9663SMark.Logan@Sun.COM /* Update records for the slots the non-options now occupy. */
225*9663SMark.Logan@Sun.COM
226*9663SMark.Logan@Sun.COM d->__first_nonopt += (d->optind - d->__last_nonopt);
227*9663SMark.Logan@Sun.COM d->__last_nonopt = d->optind;
228*9663SMark.Logan@Sun.COM }
229*9663SMark.Logan@Sun.COM
230*9663SMark.Logan@Sun.COM /* Initialize the internal data when the first call is made. */
231*9663SMark.Logan@Sun.COM
232*9663SMark.Logan@Sun.COM static const char *
_getopt_initialize(int argc,char ** argv,const char * optstring,int posixly_correct,struct _getopt_data * d)233*9663SMark.Logan@Sun.COM _getopt_initialize (int argc, char **argv, const char *optstring,
234*9663SMark.Logan@Sun.COM int posixly_correct, struct _getopt_data *d)
235*9663SMark.Logan@Sun.COM {
236*9663SMark.Logan@Sun.COM /* Start processing options with ARGV-element 1 (since ARGV-element 0
237*9663SMark.Logan@Sun.COM is the program name); the sequence of previously skipped
238*9663SMark.Logan@Sun.COM non-option ARGV-elements is empty. */
239*9663SMark.Logan@Sun.COM
240*9663SMark.Logan@Sun.COM d->__first_nonopt = d->__last_nonopt = d->optind;
241*9663SMark.Logan@Sun.COM
242*9663SMark.Logan@Sun.COM d->__nextchar = NULL;
243*9663SMark.Logan@Sun.COM
244*9663SMark.Logan@Sun.COM d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
245*9663SMark.Logan@Sun.COM
246*9663SMark.Logan@Sun.COM /* Determine how to handle the ordering of options and nonoptions. */
247*9663SMark.Logan@Sun.COM
248*9663SMark.Logan@Sun.COM if (optstring[0] == '-')
249*9663SMark.Logan@Sun.COM {
250*9663SMark.Logan@Sun.COM d->__ordering = RETURN_IN_ORDER;
251*9663SMark.Logan@Sun.COM ++optstring;
252*9663SMark.Logan@Sun.COM }
253*9663SMark.Logan@Sun.COM else if (optstring[0] == '+')
254*9663SMark.Logan@Sun.COM {
255*9663SMark.Logan@Sun.COM d->__ordering = REQUIRE_ORDER;
256*9663SMark.Logan@Sun.COM ++optstring;
257*9663SMark.Logan@Sun.COM }
258*9663SMark.Logan@Sun.COM else if (d->__posixly_correct)
259*9663SMark.Logan@Sun.COM d->__ordering = REQUIRE_ORDER;
260*9663SMark.Logan@Sun.COM else
261*9663SMark.Logan@Sun.COM d->__ordering = PERMUTE;
262*9663SMark.Logan@Sun.COM
263*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_NONOPTION_FLAGS
264*9663SMark.Logan@Sun.COM if (!d->__posixly_correct
265*9663SMark.Logan@Sun.COM && argc == __libc_argc && argv == __libc_argv)
266*9663SMark.Logan@Sun.COM {
267*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_max_len == 0)
268*9663SMark.Logan@Sun.COM {
269*9663SMark.Logan@Sun.COM if (__getopt_nonoption_flags == NULL
270*9663SMark.Logan@Sun.COM || __getopt_nonoption_flags[0] == '\0')
271*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = -1;
272*9663SMark.Logan@Sun.COM else
273*9663SMark.Logan@Sun.COM {
274*9663SMark.Logan@Sun.COM const char *orig_str = __getopt_nonoption_flags;
275*9663SMark.Logan@Sun.COM int len = d->__nonoption_flags_max_len = strlen (orig_str);
276*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_max_len < argc)
277*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = argc;
278*9663SMark.Logan@Sun.COM __getopt_nonoption_flags =
279*9663SMark.Logan@Sun.COM (char *) malloc (d->__nonoption_flags_max_len);
280*9663SMark.Logan@Sun.COM if (__getopt_nonoption_flags == NULL)
281*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = -1;
282*9663SMark.Logan@Sun.COM else
283*9663SMark.Logan@Sun.COM memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
284*9663SMark.Logan@Sun.COM '\0', d->__nonoption_flags_max_len - len);
285*9663SMark.Logan@Sun.COM }
286*9663SMark.Logan@Sun.COM }
287*9663SMark.Logan@Sun.COM d->__nonoption_flags_len = d->__nonoption_flags_max_len;
288*9663SMark.Logan@Sun.COM }
289*9663SMark.Logan@Sun.COM else
290*9663SMark.Logan@Sun.COM d->__nonoption_flags_len = 0;
291*9663SMark.Logan@Sun.COM #endif
292*9663SMark.Logan@Sun.COM
293*9663SMark.Logan@Sun.COM return optstring;
294*9663SMark.Logan@Sun.COM }
295*9663SMark.Logan@Sun.COM
296*9663SMark.Logan@Sun.COM /* Scan elements of ARGV (whose length is ARGC) for option characters
297*9663SMark.Logan@Sun.COM given in OPTSTRING.
298*9663SMark.Logan@Sun.COM
299*9663SMark.Logan@Sun.COM If an element of ARGV starts with '-', and is not exactly "-" or "--",
300*9663SMark.Logan@Sun.COM then it is an option element. The characters of this element
301*9663SMark.Logan@Sun.COM (aside from the initial '-') are option characters. If `getopt'
302*9663SMark.Logan@Sun.COM is called repeatedly, it returns successively each of the option characters
303*9663SMark.Logan@Sun.COM from each of the option elements.
304*9663SMark.Logan@Sun.COM
305*9663SMark.Logan@Sun.COM If `getopt' finds another option character, it returns that character,
306*9663SMark.Logan@Sun.COM updating `optind' and `nextchar' so that the next call to `getopt' can
307*9663SMark.Logan@Sun.COM resume the scan with the following option character or ARGV-element.
308*9663SMark.Logan@Sun.COM
309*9663SMark.Logan@Sun.COM If there are no more option characters, `getopt' returns -1.
310*9663SMark.Logan@Sun.COM Then `optind' is the index in ARGV of the first ARGV-element
311*9663SMark.Logan@Sun.COM that is not an option. (The ARGV-elements have been permuted
312*9663SMark.Logan@Sun.COM so that those that are not options now come last.)
313*9663SMark.Logan@Sun.COM
314*9663SMark.Logan@Sun.COM OPTSTRING is a string containing the legitimate option characters.
315*9663SMark.Logan@Sun.COM If an option character is seen that is not listed in OPTSTRING,
316*9663SMark.Logan@Sun.COM return '?' after printing an error message. If you set `opterr' to
317*9663SMark.Logan@Sun.COM zero, the error message is suppressed but we still return '?'.
318*9663SMark.Logan@Sun.COM
319*9663SMark.Logan@Sun.COM If a char in OPTSTRING is followed by a colon, that means it wants an arg,
320*9663SMark.Logan@Sun.COM so the following text in the same ARGV-element, or the text of the following
321*9663SMark.Logan@Sun.COM ARGV-element, is returned in `optarg'. Two colons mean an option that
322*9663SMark.Logan@Sun.COM wants an optional arg; if there is text in the current ARGV-element,
323*9663SMark.Logan@Sun.COM it is returned in `optarg', otherwise `optarg' is set to zero.
324*9663SMark.Logan@Sun.COM
325*9663SMark.Logan@Sun.COM If OPTSTRING starts with `-' or `+', it requests different methods of
326*9663SMark.Logan@Sun.COM handling the non-option ARGV-elements.
327*9663SMark.Logan@Sun.COM See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
328*9663SMark.Logan@Sun.COM
329*9663SMark.Logan@Sun.COM Long-named options begin with `--' instead of `-'.
330*9663SMark.Logan@Sun.COM Their names may be abbreviated as long as the abbreviation is unique
331*9663SMark.Logan@Sun.COM or is an exact match for some defined option. If they have an
332*9663SMark.Logan@Sun.COM argument, it follows the option name in the same ARGV-element, separated
333*9663SMark.Logan@Sun.COM from the option name by a `=', or else the in next ARGV-element.
334*9663SMark.Logan@Sun.COM When `getopt' finds a long-named option, it returns 0 if that option's
335*9663SMark.Logan@Sun.COM `flag' field is nonzero, the value of the option's `val' field
336*9663SMark.Logan@Sun.COM if the `flag' field is zero.
337*9663SMark.Logan@Sun.COM
338*9663SMark.Logan@Sun.COM LONGOPTS is a vector of `struct option' terminated by an
339*9663SMark.Logan@Sun.COM element containing a name which is zero.
340*9663SMark.Logan@Sun.COM
341*9663SMark.Logan@Sun.COM LONGIND returns the index in LONGOPT of the long-named option found.
342*9663SMark.Logan@Sun.COM It is only valid when a long-named option has been found by the most
343*9663SMark.Logan@Sun.COM recent call.
344*9663SMark.Logan@Sun.COM
345*9663SMark.Logan@Sun.COM If LONG_ONLY is nonzero, '-' as well as '--' can introduce
346*9663SMark.Logan@Sun.COM long-named options.
347*9663SMark.Logan@Sun.COM
348*9663SMark.Logan@Sun.COM If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT
349*9663SMark.Logan@Sun.COM environment variable were set. */
350*9663SMark.Logan@Sun.COM
351*9663SMark.Logan@Sun.COM int
_getopt_internal_r(int argc,char ** argv,const char * optstring,const struct option * longopts,int * longind,int long_only,int posixly_correct,struct _getopt_data * d)352*9663SMark.Logan@Sun.COM _getopt_internal_r (int argc, char **argv, const char *optstring,
353*9663SMark.Logan@Sun.COM const struct option *longopts, int *longind,
354*9663SMark.Logan@Sun.COM int long_only, int posixly_correct, struct _getopt_data *d)
355*9663SMark.Logan@Sun.COM {
356*9663SMark.Logan@Sun.COM int print_errors = d->opterr;
357*9663SMark.Logan@Sun.COM if (optstring[0] == ':')
358*9663SMark.Logan@Sun.COM print_errors = 0;
359*9663SMark.Logan@Sun.COM
360*9663SMark.Logan@Sun.COM if (argc < 1)
361*9663SMark.Logan@Sun.COM return -1;
362*9663SMark.Logan@Sun.COM
363*9663SMark.Logan@Sun.COM d->optarg = NULL;
364*9663SMark.Logan@Sun.COM
365*9663SMark.Logan@Sun.COM if (d->optind == 0 || !d->__initialized)
366*9663SMark.Logan@Sun.COM {
367*9663SMark.Logan@Sun.COM if (d->optind == 0)
368*9663SMark.Logan@Sun.COM d->optind = 1; /* Don't scan ARGV[0], the program name. */
369*9663SMark.Logan@Sun.COM optstring = _getopt_initialize (argc, argv, optstring,
370*9663SMark.Logan@Sun.COM posixly_correct, d);
371*9663SMark.Logan@Sun.COM d->__initialized = 1;
372*9663SMark.Logan@Sun.COM }
373*9663SMark.Logan@Sun.COM
374*9663SMark.Logan@Sun.COM /* Test whether ARGV[optind] points to a non-option argument.
375*9663SMark.Logan@Sun.COM Either it does not have option syntax, or there is an environment flag
376*9663SMark.Logan@Sun.COM from the shell indicating it is not an option. The later information
377*9663SMark.Logan@Sun.COM is only used when the used in the GNU libc. */
378*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_NONOPTION_FLAGS
379*9663SMark.Logan@Sun.COM # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
380*9663SMark.Logan@Sun.COM || (d->optind < d->__nonoption_flags_len \
381*9663SMark.Logan@Sun.COM && __getopt_nonoption_flags[d->optind] == '1'))
382*9663SMark.Logan@Sun.COM #else
383*9663SMark.Logan@Sun.COM # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
384*9663SMark.Logan@Sun.COM #endif
385*9663SMark.Logan@Sun.COM
386*9663SMark.Logan@Sun.COM if (d->__nextchar == NULL || *d->__nextchar == '\0')
387*9663SMark.Logan@Sun.COM {
388*9663SMark.Logan@Sun.COM /* Advance to the next ARGV-element. */
389*9663SMark.Logan@Sun.COM
390*9663SMark.Logan@Sun.COM /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
391*9663SMark.Logan@Sun.COM moved back by the user (who may also have changed the arguments). */
392*9663SMark.Logan@Sun.COM if (d->__last_nonopt > d->optind)
393*9663SMark.Logan@Sun.COM d->__last_nonopt = d->optind;
394*9663SMark.Logan@Sun.COM if (d->__first_nonopt > d->optind)
395*9663SMark.Logan@Sun.COM d->__first_nonopt = d->optind;
396*9663SMark.Logan@Sun.COM
397*9663SMark.Logan@Sun.COM if (d->__ordering == PERMUTE)
398*9663SMark.Logan@Sun.COM {
399*9663SMark.Logan@Sun.COM /* If we have just processed some options following some non-options,
400*9663SMark.Logan@Sun.COM exchange them so that the options come first. */
401*9663SMark.Logan@Sun.COM
402*9663SMark.Logan@Sun.COM if (d->__first_nonopt != d->__last_nonopt
403*9663SMark.Logan@Sun.COM && d->__last_nonopt != d->optind)
404*9663SMark.Logan@Sun.COM exchange ((char **) argv, d);
405*9663SMark.Logan@Sun.COM else if (d->__last_nonopt != d->optind)
406*9663SMark.Logan@Sun.COM d->__first_nonopt = d->optind;
407*9663SMark.Logan@Sun.COM
408*9663SMark.Logan@Sun.COM /* Skip any additional non-options
409*9663SMark.Logan@Sun.COM and extend the range of non-options previously skipped. */
410*9663SMark.Logan@Sun.COM
411*9663SMark.Logan@Sun.COM while (d->optind < argc && NONOPTION_P)
412*9663SMark.Logan@Sun.COM d->optind++;
413*9663SMark.Logan@Sun.COM d->__last_nonopt = d->optind;
414*9663SMark.Logan@Sun.COM }
415*9663SMark.Logan@Sun.COM
416*9663SMark.Logan@Sun.COM /* The special ARGV-element `--' means premature end of options.
417*9663SMark.Logan@Sun.COM Skip it like a null option,
418*9663SMark.Logan@Sun.COM then exchange with previous non-options as if it were an option,
419*9663SMark.Logan@Sun.COM then skip everything else like a non-option. */
420*9663SMark.Logan@Sun.COM
421*9663SMark.Logan@Sun.COM if (d->optind != argc && !strcmp (argv[d->optind], "--"))
422*9663SMark.Logan@Sun.COM {
423*9663SMark.Logan@Sun.COM d->optind++;
424*9663SMark.Logan@Sun.COM
425*9663SMark.Logan@Sun.COM if (d->__first_nonopt != d->__last_nonopt
426*9663SMark.Logan@Sun.COM && d->__last_nonopt != d->optind)
427*9663SMark.Logan@Sun.COM exchange ((char **) argv, d);
428*9663SMark.Logan@Sun.COM else if (d->__first_nonopt == d->__last_nonopt)
429*9663SMark.Logan@Sun.COM d->__first_nonopt = d->optind;
430*9663SMark.Logan@Sun.COM d->__last_nonopt = argc;
431*9663SMark.Logan@Sun.COM
432*9663SMark.Logan@Sun.COM d->optind = argc;
433*9663SMark.Logan@Sun.COM }
434*9663SMark.Logan@Sun.COM
435*9663SMark.Logan@Sun.COM /* If we have done all the ARGV-elements, stop the scan
436*9663SMark.Logan@Sun.COM and back over any non-options that we skipped and permuted. */
437*9663SMark.Logan@Sun.COM
438*9663SMark.Logan@Sun.COM if (d->optind == argc)
439*9663SMark.Logan@Sun.COM {
440*9663SMark.Logan@Sun.COM /* Set the next-arg-index to point at the non-options
441*9663SMark.Logan@Sun.COM that we previously skipped, so the caller will digest them. */
442*9663SMark.Logan@Sun.COM if (d->__first_nonopt != d->__last_nonopt)
443*9663SMark.Logan@Sun.COM d->optind = d->__first_nonopt;
444*9663SMark.Logan@Sun.COM return -1;
445*9663SMark.Logan@Sun.COM }
446*9663SMark.Logan@Sun.COM
447*9663SMark.Logan@Sun.COM /* If we have come to a non-option and did not permute it,
448*9663SMark.Logan@Sun.COM either stop the scan or describe it to the caller and pass it by. */
449*9663SMark.Logan@Sun.COM
450*9663SMark.Logan@Sun.COM if (NONOPTION_P)
451*9663SMark.Logan@Sun.COM {
452*9663SMark.Logan@Sun.COM if (d->__ordering == REQUIRE_ORDER)
453*9663SMark.Logan@Sun.COM return -1;
454*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++];
455*9663SMark.Logan@Sun.COM return 1;
456*9663SMark.Logan@Sun.COM }
457*9663SMark.Logan@Sun.COM
458*9663SMark.Logan@Sun.COM /* We have found another option-ARGV-element.
459*9663SMark.Logan@Sun.COM Skip the initial punctuation. */
460*9663SMark.Logan@Sun.COM
461*9663SMark.Logan@Sun.COM d->__nextchar = (argv[d->optind] + 1
462*9663SMark.Logan@Sun.COM + (longopts != NULL && argv[d->optind][1] == '-'));
463*9663SMark.Logan@Sun.COM }
464*9663SMark.Logan@Sun.COM
465*9663SMark.Logan@Sun.COM /* Decode the current option-ARGV-element. */
466*9663SMark.Logan@Sun.COM
467*9663SMark.Logan@Sun.COM /* Check whether the ARGV-element is a long option.
468*9663SMark.Logan@Sun.COM
469*9663SMark.Logan@Sun.COM If long_only and the ARGV-element has the form "-f", where f is
470*9663SMark.Logan@Sun.COM a valid short option, don't consider it an abbreviated form of
471*9663SMark.Logan@Sun.COM a long option that starts with f. Otherwise there would be no
472*9663SMark.Logan@Sun.COM way to give the -f short option.
473*9663SMark.Logan@Sun.COM
474*9663SMark.Logan@Sun.COM On the other hand, if there's a long option "fubar" and
475*9663SMark.Logan@Sun.COM the ARGV-element is "-fu", do consider that an abbreviation of
476*9663SMark.Logan@Sun.COM the long option, just like "--fu", and not "-f" with arg "u".
477*9663SMark.Logan@Sun.COM
478*9663SMark.Logan@Sun.COM This distinction seems to be the most useful approach. */
479*9663SMark.Logan@Sun.COM
480*9663SMark.Logan@Sun.COM if (longopts != NULL
481*9663SMark.Logan@Sun.COM && (argv[d->optind][1] == '-'
482*9663SMark.Logan@Sun.COM || (long_only && (argv[d->optind][2]
483*9663SMark.Logan@Sun.COM || !strchr (optstring, argv[d->optind][1])))))
484*9663SMark.Logan@Sun.COM {
485*9663SMark.Logan@Sun.COM char *nameend;
486*9663SMark.Logan@Sun.COM const struct option *p;
487*9663SMark.Logan@Sun.COM const struct option *pfound = NULL;
488*9663SMark.Logan@Sun.COM int exact = 0;
489*9663SMark.Logan@Sun.COM int ambig = 0;
490*9663SMark.Logan@Sun.COM int indfound = -1;
491*9663SMark.Logan@Sun.COM int option_index;
492*9663SMark.Logan@Sun.COM
493*9663SMark.Logan@Sun.COM for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
494*9663SMark.Logan@Sun.COM /* Do nothing. */ ;
495*9663SMark.Logan@Sun.COM
496*9663SMark.Logan@Sun.COM /* Test all long options for either exact match
497*9663SMark.Logan@Sun.COM or abbreviated matches. */
498*9663SMark.Logan@Sun.COM for (p = longopts, option_index = 0; p->name; p++, option_index++)
499*9663SMark.Logan@Sun.COM if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
500*9663SMark.Logan@Sun.COM {
501*9663SMark.Logan@Sun.COM if ((unsigned int) (nameend - d->__nextchar)
502*9663SMark.Logan@Sun.COM == (unsigned int) strlen (p->name))
503*9663SMark.Logan@Sun.COM {
504*9663SMark.Logan@Sun.COM /* Exact match found. */
505*9663SMark.Logan@Sun.COM pfound = p;
506*9663SMark.Logan@Sun.COM indfound = option_index;
507*9663SMark.Logan@Sun.COM exact = 1;
508*9663SMark.Logan@Sun.COM break;
509*9663SMark.Logan@Sun.COM }
510*9663SMark.Logan@Sun.COM else if (pfound == NULL)
511*9663SMark.Logan@Sun.COM {
512*9663SMark.Logan@Sun.COM /* First nonexact match found. */
513*9663SMark.Logan@Sun.COM pfound = p;
514*9663SMark.Logan@Sun.COM indfound = option_index;
515*9663SMark.Logan@Sun.COM }
516*9663SMark.Logan@Sun.COM else if (long_only
517*9663SMark.Logan@Sun.COM || pfound->has_arg != p->has_arg
518*9663SMark.Logan@Sun.COM || pfound->flag != p->flag
519*9663SMark.Logan@Sun.COM || pfound->val != p->val)
520*9663SMark.Logan@Sun.COM /* Second or later nonexact match found. */
521*9663SMark.Logan@Sun.COM ambig = 1;
522*9663SMark.Logan@Sun.COM }
523*9663SMark.Logan@Sun.COM
524*9663SMark.Logan@Sun.COM if (ambig && !exact)
525*9663SMark.Logan@Sun.COM {
526*9663SMark.Logan@Sun.COM if (print_errors)
527*9663SMark.Logan@Sun.COM {
528*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
529*9663SMark.Logan@Sun.COM char *buf;
530*9663SMark.Logan@Sun.COM
531*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
532*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]) >= 0)
533*9663SMark.Logan@Sun.COM {
534*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
535*9663SMark.Logan@Sun.COM
536*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
537*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
538*9663SMark.Logan@Sun.COM
539*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
540*9663SMark.Logan@Sun.COM
541*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
542*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
543*9663SMark.Logan@Sun.COM
544*9663SMark.Logan@Sun.COM free (buf);
545*9663SMark.Logan@Sun.COM }
546*9663SMark.Logan@Sun.COM #else
547*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
548*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]);
549*9663SMark.Logan@Sun.COM #endif
550*9663SMark.Logan@Sun.COM }
551*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
552*9663SMark.Logan@Sun.COM d->optind++;
553*9663SMark.Logan@Sun.COM d->optopt = 0;
554*9663SMark.Logan@Sun.COM return '?';
555*9663SMark.Logan@Sun.COM }
556*9663SMark.Logan@Sun.COM
557*9663SMark.Logan@Sun.COM if (pfound != NULL)
558*9663SMark.Logan@Sun.COM {
559*9663SMark.Logan@Sun.COM option_index = indfound;
560*9663SMark.Logan@Sun.COM d->optind++;
561*9663SMark.Logan@Sun.COM if (*nameend)
562*9663SMark.Logan@Sun.COM {
563*9663SMark.Logan@Sun.COM /* Don't test has_arg with >, because some C compilers don't
564*9663SMark.Logan@Sun.COM allow it to be used on enums. */
565*9663SMark.Logan@Sun.COM if (pfound->has_arg)
566*9663SMark.Logan@Sun.COM d->optarg = nameend + 1;
567*9663SMark.Logan@Sun.COM else
568*9663SMark.Logan@Sun.COM {
569*9663SMark.Logan@Sun.COM if (print_errors)
570*9663SMark.Logan@Sun.COM {
571*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
572*9663SMark.Logan@Sun.COM char *buf;
573*9663SMark.Logan@Sun.COM int n;
574*9663SMark.Logan@Sun.COM #endif
575*9663SMark.Logan@Sun.COM
576*9663SMark.Logan@Sun.COM if (argv[d->optind - 1][1] == '-')
577*9663SMark.Logan@Sun.COM {
578*9663SMark.Logan@Sun.COM /* --option */
579*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
580*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("\
581*9663SMark.Logan@Sun.COM %s: option `--%s' doesn't allow an argument\n"),
582*9663SMark.Logan@Sun.COM argv[0], pfound->name);
583*9663SMark.Logan@Sun.COM #else
584*9663SMark.Logan@Sun.COM fprintf (stderr, _("\
585*9663SMark.Logan@Sun.COM %s: option `--%s' doesn't allow an argument\n"),
586*9663SMark.Logan@Sun.COM argv[0], pfound->name);
587*9663SMark.Logan@Sun.COM #endif
588*9663SMark.Logan@Sun.COM }
589*9663SMark.Logan@Sun.COM else
590*9663SMark.Logan@Sun.COM {
591*9663SMark.Logan@Sun.COM /* +option or -option */
592*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
593*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("\
594*9663SMark.Logan@Sun.COM %s: option `%c%s' doesn't allow an argument\n"),
595*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1][0],
596*9663SMark.Logan@Sun.COM pfound->name);
597*9663SMark.Logan@Sun.COM #else
598*9663SMark.Logan@Sun.COM fprintf (stderr, _("\
599*9663SMark.Logan@Sun.COM %s: option `%c%s' doesn't allow an argument\n"),
600*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1][0],
601*9663SMark.Logan@Sun.COM pfound->name);
602*9663SMark.Logan@Sun.COM #endif
603*9663SMark.Logan@Sun.COM }
604*9663SMark.Logan@Sun.COM
605*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
606*9663SMark.Logan@Sun.COM if (n >= 0)
607*9663SMark.Logan@Sun.COM {
608*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
609*9663SMark.Logan@Sun.COM
610*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
611*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2
612*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL;
613*9663SMark.Logan@Sun.COM
614*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
615*9663SMark.Logan@Sun.COM
616*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
617*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
618*9663SMark.Logan@Sun.COM
619*9663SMark.Logan@Sun.COM free (buf);
620*9663SMark.Logan@Sun.COM }
621*9663SMark.Logan@Sun.COM #endif
622*9663SMark.Logan@Sun.COM }
623*9663SMark.Logan@Sun.COM
624*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
625*9663SMark.Logan@Sun.COM
626*9663SMark.Logan@Sun.COM d->optopt = pfound->val;
627*9663SMark.Logan@Sun.COM return '?';
628*9663SMark.Logan@Sun.COM }
629*9663SMark.Logan@Sun.COM }
630*9663SMark.Logan@Sun.COM else if (pfound->has_arg == 1)
631*9663SMark.Logan@Sun.COM {
632*9663SMark.Logan@Sun.COM if (d->optind < argc)
633*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++];
634*9663SMark.Logan@Sun.COM else
635*9663SMark.Logan@Sun.COM {
636*9663SMark.Logan@Sun.COM if (print_errors)
637*9663SMark.Logan@Sun.COM {
638*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
639*9663SMark.Logan@Sun.COM char *buf;
640*9663SMark.Logan@Sun.COM
641*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\
642*9663SMark.Logan@Sun.COM %s: option `%s' requires an argument\n"),
643*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]) >= 0)
644*9663SMark.Logan@Sun.COM {
645*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
646*9663SMark.Logan@Sun.COM
647*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
648*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2
649*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL;
650*9663SMark.Logan@Sun.COM
651*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
652*9663SMark.Logan@Sun.COM
653*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
654*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
655*9663SMark.Logan@Sun.COM
656*9663SMark.Logan@Sun.COM free (buf);
657*9663SMark.Logan@Sun.COM }
658*9663SMark.Logan@Sun.COM #else
659*9663SMark.Logan@Sun.COM fprintf (stderr,
660*9663SMark.Logan@Sun.COM _("%s: option `%s' requires an argument\n"),
661*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]);
662*9663SMark.Logan@Sun.COM #endif
663*9663SMark.Logan@Sun.COM }
664*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
665*9663SMark.Logan@Sun.COM d->optopt = pfound->val;
666*9663SMark.Logan@Sun.COM return optstring[0] == ':' ? ':' : '?';
667*9663SMark.Logan@Sun.COM }
668*9663SMark.Logan@Sun.COM }
669*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
670*9663SMark.Logan@Sun.COM if (longind != NULL)
671*9663SMark.Logan@Sun.COM *longind = option_index;
672*9663SMark.Logan@Sun.COM if (pfound->flag)
673*9663SMark.Logan@Sun.COM {
674*9663SMark.Logan@Sun.COM *(pfound->flag) = pfound->val;
675*9663SMark.Logan@Sun.COM return 0;
676*9663SMark.Logan@Sun.COM }
677*9663SMark.Logan@Sun.COM return pfound->val;
678*9663SMark.Logan@Sun.COM }
679*9663SMark.Logan@Sun.COM
680*9663SMark.Logan@Sun.COM /* Can't find it as a long option. If this is not getopt_long_only,
681*9663SMark.Logan@Sun.COM or the option starts with '--' or is not a valid short
682*9663SMark.Logan@Sun.COM option, then it's an error.
683*9663SMark.Logan@Sun.COM Otherwise interpret it as a short option. */
684*9663SMark.Logan@Sun.COM if (!long_only || argv[d->optind][1] == '-'
685*9663SMark.Logan@Sun.COM || strchr (optstring, *d->__nextchar) == NULL)
686*9663SMark.Logan@Sun.COM {
687*9663SMark.Logan@Sun.COM if (print_errors)
688*9663SMark.Logan@Sun.COM {
689*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
690*9663SMark.Logan@Sun.COM char *buf;
691*9663SMark.Logan@Sun.COM int n;
692*9663SMark.Logan@Sun.COM #endif
693*9663SMark.Logan@Sun.COM
694*9663SMark.Logan@Sun.COM if (argv[d->optind][1] == '-')
695*9663SMark.Logan@Sun.COM {
696*9663SMark.Logan@Sun.COM /* --option */
697*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
698*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
699*9663SMark.Logan@Sun.COM argv[0], d->__nextchar);
700*9663SMark.Logan@Sun.COM #else
701*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
702*9663SMark.Logan@Sun.COM argv[0], d->__nextchar);
703*9663SMark.Logan@Sun.COM #endif
704*9663SMark.Logan@Sun.COM }
705*9663SMark.Logan@Sun.COM else
706*9663SMark.Logan@Sun.COM {
707*9663SMark.Logan@Sun.COM /* +option or -option */
708*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
709*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
710*9663SMark.Logan@Sun.COM argv[0], argv[d->optind][0], d->__nextchar);
711*9663SMark.Logan@Sun.COM #else
712*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
713*9663SMark.Logan@Sun.COM argv[0], argv[d->optind][0], d->__nextchar);
714*9663SMark.Logan@Sun.COM #endif
715*9663SMark.Logan@Sun.COM }
716*9663SMark.Logan@Sun.COM
717*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
718*9663SMark.Logan@Sun.COM if (n >= 0)
719*9663SMark.Logan@Sun.COM {
720*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
721*9663SMark.Logan@Sun.COM
722*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
723*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
724*9663SMark.Logan@Sun.COM
725*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
726*9663SMark.Logan@Sun.COM
727*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
728*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
729*9663SMark.Logan@Sun.COM
730*9663SMark.Logan@Sun.COM free (buf);
731*9663SMark.Logan@Sun.COM }
732*9663SMark.Logan@Sun.COM #endif
733*9663SMark.Logan@Sun.COM }
734*9663SMark.Logan@Sun.COM d->__nextchar = (char *) "";
735*9663SMark.Logan@Sun.COM d->optind++;
736*9663SMark.Logan@Sun.COM d->optopt = 0;
737*9663SMark.Logan@Sun.COM return '?';
738*9663SMark.Logan@Sun.COM }
739*9663SMark.Logan@Sun.COM }
740*9663SMark.Logan@Sun.COM
741*9663SMark.Logan@Sun.COM /* Look at and handle the next short option-character. */
742*9663SMark.Logan@Sun.COM
743*9663SMark.Logan@Sun.COM {
744*9663SMark.Logan@Sun.COM char c = *d->__nextchar++;
745*9663SMark.Logan@Sun.COM char *temp = strchr (optstring, c);
746*9663SMark.Logan@Sun.COM
747*9663SMark.Logan@Sun.COM /* Increment `optind' when we start to process its last character. */
748*9663SMark.Logan@Sun.COM if (*d->__nextchar == '\0')
749*9663SMark.Logan@Sun.COM ++d->optind;
750*9663SMark.Logan@Sun.COM
751*9663SMark.Logan@Sun.COM if (temp == NULL || c == ':')
752*9663SMark.Logan@Sun.COM {
753*9663SMark.Logan@Sun.COM if (print_errors)
754*9663SMark.Logan@Sun.COM {
755*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
756*9663SMark.Logan@Sun.COM char *buf;
757*9663SMark.Logan@Sun.COM int n;
758*9663SMark.Logan@Sun.COM #endif
759*9663SMark.Logan@Sun.COM
760*9663SMark.Logan@Sun.COM if (d->__posixly_correct)
761*9663SMark.Logan@Sun.COM {
762*9663SMark.Logan@Sun.COM /* 1003.2 specifies the format of this message. */
763*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
764*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
765*9663SMark.Logan@Sun.COM argv[0], c);
766*9663SMark.Logan@Sun.COM #else
767*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
768*9663SMark.Logan@Sun.COM #endif
769*9663SMark.Logan@Sun.COM }
770*9663SMark.Logan@Sun.COM else
771*9663SMark.Logan@Sun.COM {
772*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
773*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
774*9663SMark.Logan@Sun.COM argv[0], c);
775*9663SMark.Logan@Sun.COM #else
776*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
777*9663SMark.Logan@Sun.COM #endif
778*9663SMark.Logan@Sun.COM }
779*9663SMark.Logan@Sun.COM
780*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
781*9663SMark.Logan@Sun.COM if (n >= 0)
782*9663SMark.Logan@Sun.COM {
783*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
784*9663SMark.Logan@Sun.COM
785*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
786*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
787*9663SMark.Logan@Sun.COM
788*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
789*9663SMark.Logan@Sun.COM
790*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
791*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
792*9663SMark.Logan@Sun.COM
793*9663SMark.Logan@Sun.COM free (buf);
794*9663SMark.Logan@Sun.COM }
795*9663SMark.Logan@Sun.COM #endif
796*9663SMark.Logan@Sun.COM }
797*9663SMark.Logan@Sun.COM d->optopt = c;
798*9663SMark.Logan@Sun.COM return '?';
799*9663SMark.Logan@Sun.COM }
800*9663SMark.Logan@Sun.COM /* Convenience. Treat POSIX -W foo same as long option --foo */
801*9663SMark.Logan@Sun.COM if (temp[0] == 'W' && temp[1] == ';')
802*9663SMark.Logan@Sun.COM {
803*9663SMark.Logan@Sun.COM char *nameend;
804*9663SMark.Logan@Sun.COM const struct option *p;
805*9663SMark.Logan@Sun.COM const struct option *pfound = NULL;
806*9663SMark.Logan@Sun.COM int exact = 0;
807*9663SMark.Logan@Sun.COM int ambig = 0;
808*9663SMark.Logan@Sun.COM int indfound = 0;
809*9663SMark.Logan@Sun.COM int option_index;
810*9663SMark.Logan@Sun.COM
811*9663SMark.Logan@Sun.COM /* This is an option that requires an argument. */
812*9663SMark.Logan@Sun.COM if (*d->__nextchar != '\0')
813*9663SMark.Logan@Sun.COM {
814*9663SMark.Logan@Sun.COM d->optarg = d->__nextchar;
815*9663SMark.Logan@Sun.COM /* If we end this ARGV-element by taking the rest as an arg,
816*9663SMark.Logan@Sun.COM we must advance to the next element now. */
817*9663SMark.Logan@Sun.COM d->optind++;
818*9663SMark.Logan@Sun.COM }
819*9663SMark.Logan@Sun.COM else if (d->optind == argc)
820*9663SMark.Logan@Sun.COM {
821*9663SMark.Logan@Sun.COM if (print_errors)
822*9663SMark.Logan@Sun.COM {
823*9663SMark.Logan@Sun.COM /* 1003.2 specifies the format of this message. */
824*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
825*9663SMark.Logan@Sun.COM char *buf;
826*9663SMark.Logan@Sun.COM
827*9663SMark.Logan@Sun.COM if (__asprintf (&buf,
828*9663SMark.Logan@Sun.COM _("%s: option requires an argument -- %c\n"),
829*9663SMark.Logan@Sun.COM argv[0], c) >= 0)
830*9663SMark.Logan@Sun.COM {
831*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
832*9663SMark.Logan@Sun.COM
833*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
834*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
835*9663SMark.Logan@Sun.COM
836*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
837*9663SMark.Logan@Sun.COM
838*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
839*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
840*9663SMark.Logan@Sun.COM
841*9663SMark.Logan@Sun.COM free (buf);
842*9663SMark.Logan@Sun.COM }
843*9663SMark.Logan@Sun.COM #else
844*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: option requires an argument -- %c\n"),
845*9663SMark.Logan@Sun.COM argv[0], c);
846*9663SMark.Logan@Sun.COM #endif
847*9663SMark.Logan@Sun.COM }
848*9663SMark.Logan@Sun.COM d->optopt = c;
849*9663SMark.Logan@Sun.COM if (optstring[0] == ':')
850*9663SMark.Logan@Sun.COM c = ':';
851*9663SMark.Logan@Sun.COM else
852*9663SMark.Logan@Sun.COM c = '?';
853*9663SMark.Logan@Sun.COM return c;
854*9663SMark.Logan@Sun.COM }
855*9663SMark.Logan@Sun.COM else
856*9663SMark.Logan@Sun.COM /* We already incremented `d->optind' once;
857*9663SMark.Logan@Sun.COM increment it again when taking next ARGV-elt as argument. */
858*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++];
859*9663SMark.Logan@Sun.COM
860*9663SMark.Logan@Sun.COM /* optarg is now the argument, see if it's in the
861*9663SMark.Logan@Sun.COM table of longopts. */
862*9663SMark.Logan@Sun.COM
863*9663SMark.Logan@Sun.COM for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
864*9663SMark.Logan@Sun.COM nameend++)
865*9663SMark.Logan@Sun.COM /* Do nothing. */ ;
866*9663SMark.Logan@Sun.COM
867*9663SMark.Logan@Sun.COM /* Test all long options for either exact match
868*9663SMark.Logan@Sun.COM or abbreviated matches. */
869*9663SMark.Logan@Sun.COM for (p = longopts, option_index = 0; p->name; p++, option_index++)
870*9663SMark.Logan@Sun.COM if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
871*9663SMark.Logan@Sun.COM {
872*9663SMark.Logan@Sun.COM if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
873*9663SMark.Logan@Sun.COM {
874*9663SMark.Logan@Sun.COM /* Exact match found. */
875*9663SMark.Logan@Sun.COM pfound = p;
876*9663SMark.Logan@Sun.COM indfound = option_index;
877*9663SMark.Logan@Sun.COM exact = 1;
878*9663SMark.Logan@Sun.COM break;
879*9663SMark.Logan@Sun.COM }
880*9663SMark.Logan@Sun.COM else if (pfound == NULL)
881*9663SMark.Logan@Sun.COM {
882*9663SMark.Logan@Sun.COM /* First nonexact match found. */
883*9663SMark.Logan@Sun.COM pfound = p;
884*9663SMark.Logan@Sun.COM indfound = option_index;
885*9663SMark.Logan@Sun.COM }
886*9663SMark.Logan@Sun.COM else
887*9663SMark.Logan@Sun.COM /* Second or later nonexact match found. */
888*9663SMark.Logan@Sun.COM ambig = 1;
889*9663SMark.Logan@Sun.COM }
890*9663SMark.Logan@Sun.COM if (ambig && !exact)
891*9663SMark.Logan@Sun.COM {
892*9663SMark.Logan@Sun.COM if (print_errors)
893*9663SMark.Logan@Sun.COM {
894*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
895*9663SMark.Logan@Sun.COM char *buf;
896*9663SMark.Logan@Sun.COM
897*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
898*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]) >= 0)
899*9663SMark.Logan@Sun.COM {
900*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
901*9663SMark.Logan@Sun.COM
902*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
903*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
904*9663SMark.Logan@Sun.COM
905*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
906*9663SMark.Logan@Sun.COM
907*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
908*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
909*9663SMark.Logan@Sun.COM
910*9663SMark.Logan@Sun.COM free (buf);
911*9663SMark.Logan@Sun.COM }
912*9663SMark.Logan@Sun.COM #else
913*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
914*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]);
915*9663SMark.Logan@Sun.COM #endif
916*9663SMark.Logan@Sun.COM }
917*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
918*9663SMark.Logan@Sun.COM d->optind++;
919*9663SMark.Logan@Sun.COM return '?';
920*9663SMark.Logan@Sun.COM }
921*9663SMark.Logan@Sun.COM if (pfound != NULL)
922*9663SMark.Logan@Sun.COM {
923*9663SMark.Logan@Sun.COM option_index = indfound;
924*9663SMark.Logan@Sun.COM if (*nameend)
925*9663SMark.Logan@Sun.COM {
926*9663SMark.Logan@Sun.COM /* Don't test has_arg with >, because some C compilers don't
927*9663SMark.Logan@Sun.COM allow it to be used on enums. */
928*9663SMark.Logan@Sun.COM if (pfound->has_arg)
929*9663SMark.Logan@Sun.COM d->optarg = nameend + 1;
930*9663SMark.Logan@Sun.COM else
931*9663SMark.Logan@Sun.COM {
932*9663SMark.Logan@Sun.COM if (print_errors)
933*9663SMark.Logan@Sun.COM {
934*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
935*9663SMark.Logan@Sun.COM char *buf;
936*9663SMark.Logan@Sun.COM
937*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\
938*9663SMark.Logan@Sun.COM %s: option `-W %s' doesn't allow an argument\n"),
939*9663SMark.Logan@Sun.COM argv[0], pfound->name) >= 0)
940*9663SMark.Logan@Sun.COM {
941*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
942*9663SMark.Logan@Sun.COM
943*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
944*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2
945*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL;
946*9663SMark.Logan@Sun.COM
947*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
948*9663SMark.Logan@Sun.COM
949*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
950*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
951*9663SMark.Logan@Sun.COM
952*9663SMark.Logan@Sun.COM free (buf);
953*9663SMark.Logan@Sun.COM }
954*9663SMark.Logan@Sun.COM #else
955*9663SMark.Logan@Sun.COM fprintf (stderr, _("\
956*9663SMark.Logan@Sun.COM %s: option `-W %s' doesn't allow an argument\n"),
957*9663SMark.Logan@Sun.COM argv[0], pfound->name);
958*9663SMark.Logan@Sun.COM #endif
959*9663SMark.Logan@Sun.COM }
960*9663SMark.Logan@Sun.COM
961*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
962*9663SMark.Logan@Sun.COM return '?';
963*9663SMark.Logan@Sun.COM }
964*9663SMark.Logan@Sun.COM }
965*9663SMark.Logan@Sun.COM else if (pfound->has_arg == 1)
966*9663SMark.Logan@Sun.COM {
967*9663SMark.Logan@Sun.COM if (d->optind < argc)
968*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++];
969*9663SMark.Logan@Sun.COM else
970*9663SMark.Logan@Sun.COM {
971*9663SMark.Logan@Sun.COM if (print_errors)
972*9663SMark.Logan@Sun.COM {
973*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
974*9663SMark.Logan@Sun.COM char *buf;
975*9663SMark.Logan@Sun.COM
976*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\
977*9663SMark.Logan@Sun.COM %s: option `%s' requires an argument\n"),
978*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]) >= 0)
979*9663SMark.Logan@Sun.COM {
980*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
981*9663SMark.Logan@Sun.COM
982*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
983*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2
984*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL;
985*9663SMark.Logan@Sun.COM
986*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
987*9663SMark.Logan@Sun.COM
988*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
989*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
990*9663SMark.Logan@Sun.COM
991*9663SMark.Logan@Sun.COM free (buf);
992*9663SMark.Logan@Sun.COM }
993*9663SMark.Logan@Sun.COM #else
994*9663SMark.Logan@Sun.COM fprintf (stderr,
995*9663SMark.Logan@Sun.COM _("%s: option `%s' requires an argument\n"),
996*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]);
997*9663SMark.Logan@Sun.COM #endif
998*9663SMark.Logan@Sun.COM }
999*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
1000*9663SMark.Logan@Sun.COM return optstring[0] == ':' ? ':' : '?';
1001*9663SMark.Logan@Sun.COM }
1002*9663SMark.Logan@Sun.COM }
1003*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar);
1004*9663SMark.Logan@Sun.COM if (longind != NULL)
1005*9663SMark.Logan@Sun.COM *longind = option_index;
1006*9663SMark.Logan@Sun.COM if (pfound->flag)
1007*9663SMark.Logan@Sun.COM {
1008*9663SMark.Logan@Sun.COM *(pfound->flag) = pfound->val;
1009*9663SMark.Logan@Sun.COM return 0;
1010*9663SMark.Logan@Sun.COM }
1011*9663SMark.Logan@Sun.COM return pfound->val;
1012*9663SMark.Logan@Sun.COM }
1013*9663SMark.Logan@Sun.COM d->__nextchar = NULL;
1014*9663SMark.Logan@Sun.COM return 'W'; /* Let the application handle it. */
1015*9663SMark.Logan@Sun.COM }
1016*9663SMark.Logan@Sun.COM if (temp[1] == ':')
1017*9663SMark.Logan@Sun.COM {
1018*9663SMark.Logan@Sun.COM if (temp[2] == ':')
1019*9663SMark.Logan@Sun.COM {
1020*9663SMark.Logan@Sun.COM /* This is an option that accepts an argument optionally. */
1021*9663SMark.Logan@Sun.COM if (*d->__nextchar != '\0')
1022*9663SMark.Logan@Sun.COM {
1023*9663SMark.Logan@Sun.COM d->optarg = d->__nextchar;
1024*9663SMark.Logan@Sun.COM d->optind++;
1025*9663SMark.Logan@Sun.COM }
1026*9663SMark.Logan@Sun.COM else
1027*9663SMark.Logan@Sun.COM d->optarg = NULL;
1028*9663SMark.Logan@Sun.COM d->__nextchar = NULL;
1029*9663SMark.Logan@Sun.COM }
1030*9663SMark.Logan@Sun.COM else
1031*9663SMark.Logan@Sun.COM {
1032*9663SMark.Logan@Sun.COM /* This is an option that requires an argument. */
1033*9663SMark.Logan@Sun.COM if (*d->__nextchar != '\0')
1034*9663SMark.Logan@Sun.COM {
1035*9663SMark.Logan@Sun.COM d->optarg = d->__nextchar;
1036*9663SMark.Logan@Sun.COM /* If we end this ARGV-element by taking the rest as an arg,
1037*9663SMark.Logan@Sun.COM we must advance to the next element now. */
1038*9663SMark.Logan@Sun.COM d->optind++;
1039*9663SMark.Logan@Sun.COM }
1040*9663SMark.Logan@Sun.COM else if (d->optind == argc)
1041*9663SMark.Logan@Sun.COM {
1042*9663SMark.Logan@Sun.COM if (print_errors)
1043*9663SMark.Logan@Sun.COM {
1044*9663SMark.Logan@Sun.COM /* 1003.2 specifies the format of this message. */
1045*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO
1046*9663SMark.Logan@Sun.COM char *buf;
1047*9663SMark.Logan@Sun.COM
1048*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\
1049*9663SMark.Logan@Sun.COM %s: option requires an argument -- %c\n"),
1050*9663SMark.Logan@Sun.COM argv[0], c) >= 0)
1051*9663SMark.Logan@Sun.COM {
1052*9663SMark.Logan@Sun.COM _IO_flockfile (stderr);
1053*9663SMark.Logan@Sun.COM
1054*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
1055*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
1056*9663SMark.Logan@Sun.COM
1057*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf);
1058*9663SMark.Logan@Sun.COM
1059*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2;
1060*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr);
1061*9663SMark.Logan@Sun.COM
1062*9663SMark.Logan@Sun.COM free (buf);
1063*9663SMark.Logan@Sun.COM }
1064*9663SMark.Logan@Sun.COM #else
1065*9663SMark.Logan@Sun.COM fprintf (stderr,
1066*9663SMark.Logan@Sun.COM _("%s: option requires an argument -- %c\n"),
1067*9663SMark.Logan@Sun.COM argv[0], c);
1068*9663SMark.Logan@Sun.COM #endif
1069*9663SMark.Logan@Sun.COM }
1070*9663SMark.Logan@Sun.COM d->optopt = c;
1071*9663SMark.Logan@Sun.COM if (optstring[0] == ':')
1072*9663SMark.Logan@Sun.COM c = ':';
1073*9663SMark.Logan@Sun.COM else
1074*9663SMark.Logan@Sun.COM c = '?';
1075*9663SMark.Logan@Sun.COM }
1076*9663SMark.Logan@Sun.COM else
1077*9663SMark.Logan@Sun.COM /* We already incremented `optind' once;
1078*9663SMark.Logan@Sun.COM increment it again when taking next ARGV-elt as argument. */
1079*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++];
1080*9663SMark.Logan@Sun.COM d->__nextchar = NULL;
1081*9663SMark.Logan@Sun.COM }
1082*9663SMark.Logan@Sun.COM }
1083*9663SMark.Logan@Sun.COM return c;
1084*9663SMark.Logan@Sun.COM }
1085*9663SMark.Logan@Sun.COM }
1086*9663SMark.Logan@Sun.COM
1087*9663SMark.Logan@Sun.COM int
_getopt_internal(int argc,char ** argv,const char * optstring,const struct option * longopts,int * longind,int long_only,int posixly_correct)1088*9663SMark.Logan@Sun.COM _getopt_internal (int argc, char **argv, const char *optstring,
1089*9663SMark.Logan@Sun.COM const struct option *longopts, int *longind,
1090*9663SMark.Logan@Sun.COM int long_only, int posixly_correct)
1091*9663SMark.Logan@Sun.COM {
1092*9663SMark.Logan@Sun.COM int result;
1093*9663SMark.Logan@Sun.COM
1094*9663SMark.Logan@Sun.COM getopt_data.optind = optind;
1095*9663SMark.Logan@Sun.COM getopt_data.opterr = opterr;
1096*9663SMark.Logan@Sun.COM
1097*9663SMark.Logan@Sun.COM result = _getopt_internal_r (argc, argv, optstring, longopts, longind,
1098*9663SMark.Logan@Sun.COM long_only, posixly_correct, &getopt_data);
1099*9663SMark.Logan@Sun.COM
1100*9663SMark.Logan@Sun.COM optind = getopt_data.optind;
1101*9663SMark.Logan@Sun.COM optarg = getopt_data.optarg;
1102*9663SMark.Logan@Sun.COM optopt = getopt_data.optopt;
1103*9663SMark.Logan@Sun.COM
1104*9663SMark.Logan@Sun.COM return result;
1105*9663SMark.Logan@Sun.COM }
1106*9663SMark.Logan@Sun.COM
1107*9663SMark.Logan@Sun.COM /* glibc gets a LSB-compliant getopt.
1108*9663SMark.Logan@Sun.COM Standalone applications get a POSIX-compliant getopt. */
1109*9663SMark.Logan@Sun.COM #if _LIBC
1110*9663SMark.Logan@Sun.COM enum { POSIXLY_CORRECT = 0 };
1111*9663SMark.Logan@Sun.COM #else
1112*9663SMark.Logan@Sun.COM enum { POSIXLY_CORRECT = 1 };
1113*9663SMark.Logan@Sun.COM #endif
1114*9663SMark.Logan@Sun.COM
1115*9663SMark.Logan@Sun.COM int
getopt(int argc,char * const * argv,const char * optstring)1116*9663SMark.Logan@Sun.COM getopt (int argc, char *const *argv, const char *optstring)
1117*9663SMark.Logan@Sun.COM {
1118*9663SMark.Logan@Sun.COM return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0,
1119*9663SMark.Logan@Sun.COM POSIXLY_CORRECT);
1120*9663SMark.Logan@Sun.COM }
1121*9663SMark.Logan@Sun.COM
1122*9663SMark.Logan@Sun.COM
1123*9663SMark.Logan@Sun.COM #ifdef TEST
1124*9663SMark.Logan@Sun.COM
1125*9663SMark.Logan@Sun.COM /* Compile with -DTEST to make an executable for use in testing
1126*9663SMark.Logan@Sun.COM the above definition of `getopt'. */
1127*9663SMark.Logan@Sun.COM
1128*9663SMark.Logan@Sun.COM int
main(int argc,char ** argv)1129*9663SMark.Logan@Sun.COM main (int argc, char **argv)
1130*9663SMark.Logan@Sun.COM {
1131*9663SMark.Logan@Sun.COM int c;
1132*9663SMark.Logan@Sun.COM int digit_optind = 0;
1133*9663SMark.Logan@Sun.COM
1134*9663SMark.Logan@Sun.COM while (1)
1135*9663SMark.Logan@Sun.COM {
1136*9663SMark.Logan@Sun.COM int this_option_optind = optind ? optind : 1;
1137*9663SMark.Logan@Sun.COM
1138*9663SMark.Logan@Sun.COM c = getopt (argc, argv, "abc:d:0123456789");
1139*9663SMark.Logan@Sun.COM if (c == -1)
1140*9663SMark.Logan@Sun.COM break;
1141*9663SMark.Logan@Sun.COM
1142*9663SMark.Logan@Sun.COM switch (c)
1143*9663SMark.Logan@Sun.COM {
1144*9663SMark.Logan@Sun.COM case '0':
1145*9663SMark.Logan@Sun.COM case '1':
1146*9663SMark.Logan@Sun.COM case '2':
1147*9663SMark.Logan@Sun.COM case '3':
1148*9663SMark.Logan@Sun.COM case '4':
1149*9663SMark.Logan@Sun.COM case '5':
1150*9663SMark.Logan@Sun.COM case '6':
1151*9663SMark.Logan@Sun.COM case '7':
1152*9663SMark.Logan@Sun.COM case '8':
1153*9663SMark.Logan@Sun.COM case '9':
1154*9663SMark.Logan@Sun.COM if (digit_optind != 0 && digit_optind != this_option_optind)
1155*9663SMark.Logan@Sun.COM printf ("digits occur in two different argv-elements.\n");
1156*9663SMark.Logan@Sun.COM digit_optind = this_option_optind;
1157*9663SMark.Logan@Sun.COM printf ("option %c\n", c);
1158*9663SMark.Logan@Sun.COM break;
1159*9663SMark.Logan@Sun.COM
1160*9663SMark.Logan@Sun.COM case 'a':
1161*9663SMark.Logan@Sun.COM printf ("option a\n");
1162*9663SMark.Logan@Sun.COM break;
1163*9663SMark.Logan@Sun.COM
1164*9663SMark.Logan@Sun.COM case 'b':
1165*9663SMark.Logan@Sun.COM printf ("option b\n");
1166*9663SMark.Logan@Sun.COM break;
1167*9663SMark.Logan@Sun.COM
1168*9663SMark.Logan@Sun.COM case 'c':
1169*9663SMark.Logan@Sun.COM printf ("option c with value `%s'\n", optarg);
1170*9663SMark.Logan@Sun.COM break;
1171*9663SMark.Logan@Sun.COM
1172*9663SMark.Logan@Sun.COM case '?':
1173*9663SMark.Logan@Sun.COM break;
1174*9663SMark.Logan@Sun.COM
1175*9663SMark.Logan@Sun.COM default:
1176*9663SMark.Logan@Sun.COM printf ("?? getopt returned character code 0%o ??\n", c);
1177*9663SMark.Logan@Sun.COM }
1178*9663SMark.Logan@Sun.COM }
1179*9663SMark.Logan@Sun.COM
1180*9663SMark.Logan@Sun.COM if (optind < argc)
1181*9663SMark.Logan@Sun.COM {
1182*9663SMark.Logan@Sun.COM printf ("non-option ARGV-elements: ");
1183*9663SMark.Logan@Sun.COM while (optind < argc)
1184*9663SMark.Logan@Sun.COM printf ("%s ", argv[optind++]);
1185*9663SMark.Logan@Sun.COM printf ("\n");
1186*9663SMark.Logan@Sun.COM }
1187*9663SMark.Logan@Sun.COM
1188*9663SMark.Logan@Sun.COM exit (0);
1189*9663SMark.Logan@Sun.COM }
1190*9663SMark.Logan@Sun.COM
1191*9663SMark.Logan@Sun.COM #endif /* TEST */
1192