xref: /onnv-gate/usr/src/lib/libparted/common/lib/getopt.c (revision 9663:ace9a2ac3683)
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