xref: /openbsd-src/gnu/usr.bin/texinfo/lib/getopt.c (revision a1acfa9b69ad64eb720639240c8438f11107dc85)
1840175f0Skstailey /* Getopt for GNU.
2*a1acfa9bSespie    NOTE: getopt is now part of the C library, so if you don't know what
3*a1acfa9bSespie    "Keep this file name-space clean" means, talk to drepper@gnu.org
4*a1acfa9bSespie    before changing it!
5*a1acfa9bSespie    Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
6840175f0Skstailey    	Free Software Foundation, Inc.
7*a1acfa9bSespie    This file is part of the GNU C Library.
8840175f0Skstailey 
9*a1acfa9bSespie    This program is free software; you can redistribute it and/or modify
10*a1acfa9bSespie    it under the terms of the GNU General Public License as published by
11*a1acfa9bSespie    the Free Software Foundation; either version 2, or (at your option)
12*a1acfa9bSespie    any later version.
13840175f0Skstailey 
14840175f0Skstailey    This program is distributed in the hope that it will be useful,
15840175f0Skstailey    but WITHOUT ANY WARRANTY; without even the implied warranty of
16840175f0Skstailey    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17840175f0Skstailey    GNU General Public License for more details.
18840175f0Skstailey 
19*a1acfa9bSespie    You should have received a copy of the GNU General Public License along
20*a1acfa9bSespie    with this program; if not, write to the Free Software Foundation,
213fb98d4aSespie    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22840175f0Skstailey 
23840175f0Skstailey /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
24840175f0Skstailey    Ditto for AIX 3.2 and <stdlib.h>.  */
25840175f0Skstailey #ifndef _NO_PROTO
26840175f0Skstailey # define _NO_PROTO
27840175f0Skstailey #endif
28840175f0Skstailey 
29840175f0Skstailey #ifdef HAVE_CONFIG_H
30840175f0Skstailey # include <config.h>
313fb98d4aSespie #endif
32840175f0Skstailey 
33840175f0Skstailey #include <stdio.h>
34840175f0Skstailey 
35840175f0Skstailey /* This needs to come after some library #include
36840175f0Skstailey    to get __GNU_LIBRARY__ defined.  */
37840175f0Skstailey #ifdef	__GNU_LIBRARY__
38840175f0Skstailey /* Don't include stdlib.h for non-GNU C libraries because some of them
39840175f0Skstailey    contain conflicting prototypes for getopt.  */
40840175f0Skstailey # include <stdlib.h>
41840175f0Skstailey # include <unistd.h>
42840175f0Skstailey #endif	/* GNU C library.  */
43840175f0Skstailey 
44*a1acfa9bSespie #include <string.h>
45*a1acfa9bSespie 
46840175f0Skstailey #ifdef VMS
47840175f0Skstailey # include <unixlib.h>
48840175f0Skstailey #endif
49840175f0Skstailey 
50*a1acfa9bSespie #ifdef _LIBC
51840175f0Skstailey # include <libintl.h>
52840175f0Skstailey #else
53*a1acfa9bSespie # include "gettext.h"
54*a1acfa9bSespie # define _(msgid) gettext (msgid)
55840175f0Skstailey #endif
56*a1acfa9bSespie 
57*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
58*a1acfa9bSespie # include <wchar.h>
59*a1acfa9bSespie #endif
60*a1acfa9bSespie 
61*a1acfa9bSespie #ifndef attribute_hidden
62*a1acfa9bSespie # define attribute_hidden
63840175f0Skstailey #endif
64840175f0Skstailey 
65840175f0Skstailey /* This version of `getopt' appears to the caller like standard Unix `getopt'
66840175f0Skstailey    but it behaves differently for the user, since it allows the user
67840175f0Skstailey    to intersperse the options with the other arguments.
68840175f0Skstailey 
69840175f0Skstailey    As `getopt' works, it permutes the elements of ARGV so that,
70840175f0Skstailey    when it is done, all the options precede everything else.  Thus
71840175f0Skstailey    all application programs are extended to handle flexible argument order.
72840175f0Skstailey 
73840175f0Skstailey    Setting the environment variable POSIXLY_CORRECT disables permutation.
74840175f0Skstailey    Then the behavior is completely standard.
75840175f0Skstailey 
76840175f0Skstailey    GNU application programs can use a third alternative mode in which
77840175f0Skstailey    they can distinguish the relative order of options and other arguments.  */
78840175f0Skstailey 
79840175f0Skstailey #include "getopt.h"
80*a1acfa9bSespie #include "getopt_int.h"
81840175f0Skstailey 
82840175f0Skstailey /* For communication from `getopt' to the caller.
83840175f0Skstailey    When `getopt' finds an option that takes an argument,
84840175f0Skstailey    the argument value is returned here.
85840175f0Skstailey    Also, when `ordering' is RETURN_IN_ORDER,
86840175f0Skstailey    each non-option ARGV-element is returned here.  */
87840175f0Skstailey 
883fb98d4aSespie char *optarg;
89840175f0Skstailey 
90840175f0Skstailey /* Index in ARGV of the next element to be scanned.
91840175f0Skstailey    This is used for communication to and from the caller
92840175f0Skstailey    and for communication between successive calls to `getopt'.
93840175f0Skstailey 
94840175f0Skstailey    On entry to `getopt', zero means this is the first call; initialize.
95840175f0Skstailey 
96840175f0Skstailey    When `getopt' returns -1, this is the index of the first of the
97840175f0Skstailey    non-option elements that the caller should itself scan.
98840175f0Skstailey 
99840175f0Skstailey    Otherwise, `optind' communicates from one call to the next
100840175f0Skstailey    how much of ARGV has been scanned so far.  */
101840175f0Skstailey 
102840175f0Skstailey /* 1003.2 says this must be 1 before any call.  */
103840175f0Skstailey int optind = 1;
104840175f0Skstailey 
105840175f0Skstailey /* Callers store zero here to inhibit the error message
106840175f0Skstailey    for unrecognized options.  */
107840175f0Skstailey 
108840175f0Skstailey int opterr = 1;
109840175f0Skstailey 
110840175f0Skstailey /* Set to an option character which was unrecognized.
111840175f0Skstailey    This must be initialized on some systems to avoid linking in the
112840175f0Skstailey    system's own getopt implementation.  */
113840175f0Skstailey 
114840175f0Skstailey int optopt = '?';
115840175f0Skstailey 
116*a1acfa9bSespie /* Keep a global copy of all internal members of getopt_data.  */
117840175f0Skstailey 
118*a1acfa9bSespie static struct _getopt_data getopt_data;
119840175f0Skstailey 
120840175f0Skstailey 
121*a1acfa9bSespie #ifndef __GNU_LIBRARY__
1221cc83814Sespie 
123840175f0Skstailey /* Avoid depending on library functions or files
124840175f0Skstailey    whose names are inconsistent.  */
125840175f0Skstailey 
1261cc83814Sespie #ifndef getenv
1271cc83814Sespie extern char *getenv ();
1281cc83814Sespie #endif
129840175f0Skstailey 
130840175f0Skstailey #endif /* not __GNU_LIBRARY__ */
131840175f0Skstailey 
132840175f0Skstailey #ifdef _LIBC
133*a1acfa9bSespie /* Stored original parameters.
134*a1acfa9bSespie    XXX This is no good solution.  We should rather copy the args so
135*a1acfa9bSespie    that we can compare them later.  But we must not use malloc(3).  */
136*a1acfa9bSespie extern int __libc_argc;
137*a1acfa9bSespie extern char **__libc_argv;
138*a1acfa9bSespie 
139840175f0Skstailey /* Bash 2.0 gives us an environment variable containing flags
140840175f0Skstailey    indicating ARGV elements that should not be considered arguments.  */
141840175f0Skstailey 
142*a1acfa9bSespie # ifdef USE_NONOPTION_FLAGS
143840175f0Skstailey /* Defined in getopt_init.c  */
144840175f0Skstailey extern char *__getopt_nonoption_flags;
145*a1acfa9bSespie # endif
146840175f0Skstailey 
147*a1acfa9bSespie # ifdef USE_NONOPTION_FLAGS
148840175f0Skstailey #  define SWAP_FLAGS(ch1, ch2) \
149*a1acfa9bSespie   if (d->__nonoption_flags_len > 0)					      \
150840175f0Skstailey     {									      \
151840175f0Skstailey       char __tmp = __getopt_nonoption_flags[ch1];			      \
152840175f0Skstailey       __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
153840175f0Skstailey       __getopt_nonoption_flags[ch2] = __tmp;				      \
154840175f0Skstailey     }
155*a1acfa9bSespie # else
156*a1acfa9bSespie #  define SWAP_FLAGS(ch1, ch2)
157*a1acfa9bSespie # endif
158840175f0Skstailey #else	/* !_LIBC */
159840175f0Skstailey # define SWAP_FLAGS(ch1, ch2)
160840175f0Skstailey #endif	/* _LIBC */
161840175f0Skstailey 
162840175f0Skstailey /* Exchange two adjacent subsequences of ARGV.
163840175f0Skstailey    One subsequence is elements [first_nonopt,last_nonopt)
164840175f0Skstailey    which contains all the non-options that have been skipped so far.
165840175f0Skstailey    The other is elements [last_nonopt,optind), which contains all
166840175f0Skstailey    the options processed since those non-options were skipped.
167840175f0Skstailey 
168840175f0Skstailey    `first_nonopt' and `last_nonopt' are relocated so that they describe
169840175f0Skstailey    the new indices of the non-options in ARGV after they are moved.  */
170840175f0Skstailey 
171840175f0Skstailey static void
exchange(char ** argv,struct _getopt_data * d)172*a1acfa9bSespie exchange (char **argv, struct _getopt_data *d)
173840175f0Skstailey {
174*a1acfa9bSespie   int bottom = d->__first_nonopt;
175*a1acfa9bSespie   int middle = d->__last_nonopt;
176*a1acfa9bSespie   int top = d->optind;
177840175f0Skstailey   char *tem;
178840175f0Skstailey 
179840175f0Skstailey   /* Exchange the shorter segment with the far end of the longer segment.
180840175f0Skstailey      That puts the shorter segment into the right place.
181840175f0Skstailey      It leaves the longer segment in the right place overall,
182840175f0Skstailey      but it consists of two parts that need to be swapped next.  */
183840175f0Skstailey 
184*a1acfa9bSespie #if defined _LIBC && defined USE_NONOPTION_FLAGS
185840175f0Skstailey   /* First make sure the handling of the `__getopt_nonoption_flags'
186840175f0Skstailey      string can work normally.  Our top argument must be in the range
187840175f0Skstailey      of the string.  */
188*a1acfa9bSespie   if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
189840175f0Skstailey     {
190840175f0Skstailey       /* We must extend the array.  The user plays games with us and
191840175f0Skstailey 	 presents new arguments.  */
192840175f0Skstailey       char *new_str = malloc (top + 1);
193840175f0Skstailey       if (new_str == NULL)
194*a1acfa9bSespie 	d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
195840175f0Skstailey       else
196840175f0Skstailey 	{
19728ea187bSespie 	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
198*a1acfa9bSespie 			     d->__nonoption_flags_max_len),
199*a1acfa9bSespie 		  '\0', top + 1 - d->__nonoption_flags_max_len);
200*a1acfa9bSespie 	  d->__nonoption_flags_max_len = top + 1;
201840175f0Skstailey 	  __getopt_nonoption_flags = new_str;
202840175f0Skstailey 	}
203840175f0Skstailey     }
204840175f0Skstailey #endif
205840175f0Skstailey 
206840175f0Skstailey   while (top > middle && middle > bottom)
207840175f0Skstailey     {
208840175f0Skstailey       if (top - middle > middle - bottom)
209840175f0Skstailey 	{
210840175f0Skstailey 	  /* Bottom segment is the short one.  */
211840175f0Skstailey 	  int len = middle - bottom;
212840175f0Skstailey 	  register int i;
213840175f0Skstailey 
214840175f0Skstailey 	  /* Swap it with the top part of the top segment.  */
215840175f0Skstailey 	  for (i = 0; i < len; i++)
216840175f0Skstailey 	    {
217840175f0Skstailey 	      tem = argv[bottom + i];
218840175f0Skstailey 	      argv[bottom + i] = argv[top - (middle - bottom) + i];
219840175f0Skstailey 	      argv[top - (middle - bottom) + i] = tem;
220840175f0Skstailey 	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
221840175f0Skstailey 	    }
222840175f0Skstailey 	  /* Exclude the moved bottom segment from further swapping.  */
223840175f0Skstailey 	  top -= len;
224840175f0Skstailey 	}
225840175f0Skstailey       else
226840175f0Skstailey 	{
227840175f0Skstailey 	  /* Top segment is the short one.  */
228840175f0Skstailey 	  int len = top - middle;
229840175f0Skstailey 	  register int i;
230840175f0Skstailey 
231840175f0Skstailey 	  /* Swap it with the bottom part of the bottom segment.  */
232840175f0Skstailey 	  for (i = 0; i < len; i++)
233840175f0Skstailey 	    {
234840175f0Skstailey 	      tem = argv[bottom + i];
235840175f0Skstailey 	      argv[bottom + i] = argv[middle + i];
236840175f0Skstailey 	      argv[middle + i] = tem;
237840175f0Skstailey 	      SWAP_FLAGS (bottom + i, middle + i);
238840175f0Skstailey 	    }
239840175f0Skstailey 	  /* Exclude the moved top segment from further swapping.  */
240840175f0Skstailey 	  bottom += len;
241840175f0Skstailey 	}
242840175f0Skstailey     }
243840175f0Skstailey 
244840175f0Skstailey   /* Update records for the slots the non-options now occupy.  */
245840175f0Skstailey 
246*a1acfa9bSespie   d->__first_nonopt += (d->optind - d->__last_nonopt);
247*a1acfa9bSespie   d->__last_nonopt = d->optind;
248840175f0Skstailey }
249840175f0Skstailey 
250840175f0Skstailey /* Initialize the internal data when the first call is made.  */
251840175f0Skstailey 
252840175f0Skstailey static const char *
_getopt_initialize(int argc,char * const * argv,const char * optstring,struct _getopt_data * d)253*a1acfa9bSespie _getopt_initialize (int argc, char *const *argv, const char *optstring,
254*a1acfa9bSespie 		    struct _getopt_data *d)
255840175f0Skstailey {
256840175f0Skstailey   /* Start processing options with ARGV-element 1 (since ARGV-element 0
257840175f0Skstailey      is the program name); the sequence of previously skipped
258840175f0Skstailey      non-option ARGV-elements is empty.  */
259840175f0Skstailey 
260*a1acfa9bSespie   d->__first_nonopt = d->__last_nonopt = d->optind;
261840175f0Skstailey 
262*a1acfa9bSespie   d->__nextchar = NULL;
263840175f0Skstailey 
264*a1acfa9bSespie   d->__posixly_correct = !!getenv ("POSIXLY_CORRECT");
265840175f0Skstailey 
266840175f0Skstailey   /* Determine how to handle the ordering of options and nonoptions.  */
267840175f0Skstailey 
268840175f0Skstailey   if (optstring[0] == '-')
269840175f0Skstailey     {
270*a1acfa9bSespie       d->__ordering = RETURN_IN_ORDER;
271840175f0Skstailey       ++optstring;
272840175f0Skstailey     }
273840175f0Skstailey   else if (optstring[0] == '+')
274840175f0Skstailey     {
275*a1acfa9bSespie       d->__ordering = REQUIRE_ORDER;
276840175f0Skstailey       ++optstring;
277840175f0Skstailey     }
278*a1acfa9bSespie   else if (d->__posixly_correct)
279*a1acfa9bSespie     d->__ordering = REQUIRE_ORDER;
280840175f0Skstailey   else
281*a1acfa9bSespie     d->__ordering = PERMUTE;
282840175f0Skstailey 
283*a1acfa9bSespie #if defined _LIBC && defined USE_NONOPTION_FLAGS
284*a1acfa9bSespie   if (!d->__posixly_correct
285*a1acfa9bSespie       && argc == __libc_argc && argv == __libc_argv)
286840175f0Skstailey     {
287*a1acfa9bSespie       if (d->__nonoption_flags_max_len == 0)
288840175f0Skstailey 	{
289840175f0Skstailey 	  if (__getopt_nonoption_flags == NULL
290840175f0Skstailey 	      || __getopt_nonoption_flags[0] == '\0')
291*a1acfa9bSespie 	    d->__nonoption_flags_max_len = -1;
292840175f0Skstailey 	  else
293840175f0Skstailey 	    {
294840175f0Skstailey 	      const char *orig_str = __getopt_nonoption_flags;
295*a1acfa9bSespie 	      int len = d->__nonoption_flags_max_len = strlen (orig_str);
296*a1acfa9bSespie 	      if (d->__nonoption_flags_max_len < argc)
297*a1acfa9bSespie 		d->__nonoption_flags_max_len = argc;
298840175f0Skstailey 	      __getopt_nonoption_flags =
299*a1acfa9bSespie 		(char *) malloc (d->__nonoption_flags_max_len);
300840175f0Skstailey 	      if (__getopt_nonoption_flags == NULL)
301*a1acfa9bSespie 		d->__nonoption_flags_max_len = -1;
302840175f0Skstailey 	      else
30328ea187bSespie 		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
304*a1acfa9bSespie 			'\0', d->__nonoption_flags_max_len - len);
305840175f0Skstailey 	    }
306840175f0Skstailey 	}
307*a1acfa9bSespie       d->__nonoption_flags_len = d->__nonoption_flags_max_len;
308840175f0Skstailey     }
309840175f0Skstailey   else
310*a1acfa9bSespie     d->__nonoption_flags_len = 0;
311840175f0Skstailey #endif
312840175f0Skstailey 
313840175f0Skstailey   return optstring;
314840175f0Skstailey }
315840175f0Skstailey 
316840175f0Skstailey /* Scan elements of ARGV (whose length is ARGC) for option characters
317840175f0Skstailey    given in OPTSTRING.
318840175f0Skstailey 
319840175f0Skstailey    If an element of ARGV starts with '-', and is not exactly "-" or "--",
320840175f0Skstailey    then it is an option element.  The characters of this element
321840175f0Skstailey    (aside from the initial '-') are option characters.  If `getopt'
322840175f0Skstailey    is called repeatedly, it returns successively each of the option characters
323840175f0Skstailey    from each of the option elements.
324840175f0Skstailey 
325840175f0Skstailey    If `getopt' finds another option character, it returns that character,
326840175f0Skstailey    updating `optind' and `nextchar' so that the next call to `getopt' can
327840175f0Skstailey    resume the scan with the following option character or ARGV-element.
328840175f0Skstailey 
329840175f0Skstailey    If there are no more option characters, `getopt' returns -1.
330840175f0Skstailey    Then `optind' is the index in ARGV of the first ARGV-element
331840175f0Skstailey    that is not an option.  (The ARGV-elements have been permuted
332840175f0Skstailey    so that those that are not options now come last.)
333840175f0Skstailey 
334840175f0Skstailey    OPTSTRING is a string containing the legitimate option characters.
335840175f0Skstailey    If an option character is seen that is not listed in OPTSTRING,
336840175f0Skstailey    return '?' after printing an error message.  If you set `opterr' to
337840175f0Skstailey    zero, the error message is suppressed but we still return '?'.
338840175f0Skstailey 
339840175f0Skstailey    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
340840175f0Skstailey    so the following text in the same ARGV-element, or the text of the following
341840175f0Skstailey    ARGV-element, is returned in `optarg'.  Two colons mean an option that
342840175f0Skstailey    wants an optional arg; if there is text in the current ARGV-element,
343840175f0Skstailey    it is returned in `optarg', otherwise `optarg' is set to zero.
344840175f0Skstailey 
345840175f0Skstailey    If OPTSTRING starts with `-' or `+', it requests different methods of
346840175f0Skstailey    handling the non-option ARGV-elements.
347840175f0Skstailey    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
348840175f0Skstailey 
349840175f0Skstailey    Long-named options begin with `--' instead of `-'.
350840175f0Skstailey    Their names may be abbreviated as long as the abbreviation is unique
351840175f0Skstailey    or is an exact match for some defined option.  If they have an
352840175f0Skstailey    argument, it follows the option name in the same ARGV-element, separated
353840175f0Skstailey    from the option name by a `=', or else the in next ARGV-element.
354840175f0Skstailey    When `getopt' finds a long-named option, it returns 0 if that option's
355840175f0Skstailey    `flag' field is nonzero, the value of the option's `val' field
356840175f0Skstailey    if the `flag' field is zero.
357840175f0Skstailey 
358840175f0Skstailey    The elements of ARGV aren't really const, because we permute them.
359840175f0Skstailey    But we pretend they're const in the prototype to be compatible
360840175f0Skstailey    with other systems.
361840175f0Skstailey 
362840175f0Skstailey    LONGOPTS is a vector of `struct option' terminated by an
363840175f0Skstailey    element containing a name which is zero.
364840175f0Skstailey 
365840175f0Skstailey    LONGIND returns the index in LONGOPT of the long-named option found.
366840175f0Skstailey    It is only valid when a long-named option has been found by the most
367840175f0Skstailey    recent call.
368840175f0Skstailey 
369840175f0Skstailey    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
370840175f0Skstailey    long-named options.  */
371840175f0Skstailey 
372840175f0Skstailey int
_getopt_internal_r(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,int long_only,struct _getopt_data * d)373*a1acfa9bSespie _getopt_internal_r (int argc, char *const *argv, const char *optstring,
374*a1acfa9bSespie 		    const struct option *longopts, int *longind,
375*a1acfa9bSespie 		    int long_only, struct _getopt_data *d)
376840175f0Skstailey {
377*a1acfa9bSespie   int print_errors = d->opterr;
378*a1acfa9bSespie   if (optstring[0] == ':')
379*a1acfa9bSespie     print_errors = 0;
380840175f0Skstailey 
381*a1acfa9bSespie   if (argc < 1)
382*a1acfa9bSespie     return -1;
383*a1acfa9bSespie 
384*a1acfa9bSespie   d->optarg = NULL;
385*a1acfa9bSespie 
386*a1acfa9bSespie   if (d->optind == 0 || !d->__initialized)
387840175f0Skstailey     {
388*a1acfa9bSespie       if (d->optind == 0)
389*a1acfa9bSespie 	d->optind = 1;	/* Don't scan ARGV[0], the program name.  */
390*a1acfa9bSespie       optstring = _getopt_initialize (argc, argv, optstring, d);
391*a1acfa9bSespie       d->__initialized = 1;
392840175f0Skstailey     }
393840175f0Skstailey 
394840175f0Skstailey   /* Test whether ARGV[optind] points to a non-option argument.
395840175f0Skstailey      Either it does not have option syntax, or there is an environment flag
396840175f0Skstailey      from the shell indicating it is not an option.  The later information
397840175f0Skstailey      is only used when the used in the GNU libc.  */
398*a1acfa9bSespie #if defined _LIBC && defined USE_NONOPTION_FLAGS
399*a1acfa9bSespie # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
400*a1acfa9bSespie 		      || (d->optind < d->__nonoption_flags_len		      \
401*a1acfa9bSespie 			  && __getopt_nonoption_flags[d->optind] == '1'))
402840175f0Skstailey #else
403*a1acfa9bSespie # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
404840175f0Skstailey #endif
405840175f0Skstailey 
406*a1acfa9bSespie   if (d->__nextchar == NULL || *d->__nextchar == '\0')
407840175f0Skstailey     {
408840175f0Skstailey       /* Advance to the next ARGV-element.  */
409840175f0Skstailey 
410840175f0Skstailey       /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
411840175f0Skstailey 	 moved back by the user (who may also have changed the arguments).  */
412*a1acfa9bSespie       if (d->__last_nonopt > d->optind)
413*a1acfa9bSespie 	d->__last_nonopt = d->optind;
414*a1acfa9bSespie       if (d->__first_nonopt > d->optind)
415*a1acfa9bSespie 	d->__first_nonopt = d->optind;
416840175f0Skstailey 
417*a1acfa9bSespie       if (d->__ordering == PERMUTE)
418840175f0Skstailey 	{
419840175f0Skstailey 	  /* If we have just processed some options following some non-options,
420840175f0Skstailey 	     exchange them so that the options come first.  */
421840175f0Skstailey 
422*a1acfa9bSespie 	  if (d->__first_nonopt != d->__last_nonopt
423*a1acfa9bSespie 	      && d->__last_nonopt != d->optind)
424*a1acfa9bSespie 	    exchange ((char **) argv, d);
425*a1acfa9bSespie 	  else if (d->__last_nonopt != d->optind)
426*a1acfa9bSespie 	    d->__first_nonopt = d->optind;
427840175f0Skstailey 
428840175f0Skstailey 	  /* Skip any additional non-options
429840175f0Skstailey 	     and extend the range of non-options previously skipped.  */
430840175f0Skstailey 
431*a1acfa9bSespie 	  while (d->optind < argc && NONOPTION_P)
432*a1acfa9bSespie 	    d->optind++;
433*a1acfa9bSespie 	  d->__last_nonopt = d->optind;
434840175f0Skstailey 	}
435840175f0Skstailey 
436840175f0Skstailey       /* The special ARGV-element `--' means premature end of options.
437840175f0Skstailey 	 Skip it like a null option,
438840175f0Skstailey 	 then exchange with previous non-options as if it were an option,
439840175f0Skstailey 	 then skip everything else like a non-option.  */
440840175f0Skstailey 
441*a1acfa9bSespie       if (d->optind != argc && !strcmp (argv[d->optind], "--"))
442840175f0Skstailey 	{
443*a1acfa9bSespie 	  d->optind++;
444840175f0Skstailey 
445*a1acfa9bSespie 	  if (d->__first_nonopt != d->__last_nonopt
446*a1acfa9bSespie 	      && d->__last_nonopt != d->optind)
447*a1acfa9bSespie 	    exchange ((char **) argv, d);
448*a1acfa9bSespie 	  else if (d->__first_nonopt == d->__last_nonopt)
449*a1acfa9bSespie 	    d->__first_nonopt = d->optind;
450*a1acfa9bSespie 	  d->__last_nonopt = argc;
451840175f0Skstailey 
452*a1acfa9bSespie 	  d->optind = argc;
453840175f0Skstailey 	}
454840175f0Skstailey 
455840175f0Skstailey       /* If we have done all the ARGV-elements, stop the scan
456840175f0Skstailey 	 and back over any non-options that we skipped and permuted.  */
457840175f0Skstailey 
458*a1acfa9bSespie       if (d->optind == argc)
459840175f0Skstailey 	{
460840175f0Skstailey 	  /* Set the next-arg-index to point at the non-options
461840175f0Skstailey 	     that we previously skipped, so the caller will digest them.  */
462*a1acfa9bSespie 	  if (d->__first_nonopt != d->__last_nonopt)
463*a1acfa9bSespie 	    d->optind = d->__first_nonopt;
464840175f0Skstailey 	  return -1;
465840175f0Skstailey 	}
466840175f0Skstailey 
467840175f0Skstailey       /* If we have come to a non-option and did not permute it,
468840175f0Skstailey 	 either stop the scan or describe it to the caller and pass it by.  */
469840175f0Skstailey 
470840175f0Skstailey       if (NONOPTION_P)
471840175f0Skstailey 	{
472*a1acfa9bSespie 	  if (d->__ordering == REQUIRE_ORDER)
473840175f0Skstailey 	    return -1;
474*a1acfa9bSespie 	  d->optarg = argv[d->optind++];
475840175f0Skstailey 	  return 1;
476840175f0Skstailey 	}
477840175f0Skstailey 
478840175f0Skstailey       /* We have found another option-ARGV-element.
479840175f0Skstailey 	 Skip the initial punctuation.  */
480840175f0Skstailey 
481*a1acfa9bSespie       d->__nextchar = (argv[d->optind] + 1
482*a1acfa9bSespie 		  + (longopts != NULL && argv[d->optind][1] == '-'));
483840175f0Skstailey     }
484840175f0Skstailey 
485840175f0Skstailey   /* Decode the current option-ARGV-element.  */
486840175f0Skstailey 
487840175f0Skstailey   /* Check whether the ARGV-element is a long option.
488840175f0Skstailey 
489840175f0Skstailey      If long_only and the ARGV-element has the form "-f", where f is
490840175f0Skstailey      a valid short option, don't consider it an abbreviated form of
491840175f0Skstailey      a long option that starts with f.  Otherwise there would be no
492840175f0Skstailey      way to give the -f short option.
493840175f0Skstailey 
494840175f0Skstailey      On the other hand, if there's a long option "fubar" and
495840175f0Skstailey      the ARGV-element is "-fu", do consider that an abbreviation of
496840175f0Skstailey      the long option, just like "--fu", and not "-f" with arg "u".
497840175f0Skstailey 
498840175f0Skstailey      This distinction seems to be the most useful approach.  */
499840175f0Skstailey 
500840175f0Skstailey   if (longopts != NULL
501*a1acfa9bSespie       && (argv[d->optind][1] == '-'
502*a1acfa9bSespie 	  || (long_only && (argv[d->optind][2]
503*a1acfa9bSespie 			    || !strchr (optstring, argv[d->optind][1])))))
504840175f0Skstailey     {
505840175f0Skstailey       char *nameend;
506840175f0Skstailey       const struct option *p;
507840175f0Skstailey       const struct option *pfound = NULL;
508840175f0Skstailey       int exact = 0;
509840175f0Skstailey       int ambig = 0;
510840175f0Skstailey       int indfound = -1;
511840175f0Skstailey       int option_index;
512840175f0Skstailey 
513*a1acfa9bSespie       for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
514840175f0Skstailey 	/* Do nothing.  */ ;
515840175f0Skstailey 
516840175f0Skstailey       /* Test all long options for either exact match
517840175f0Skstailey 	 or abbreviated matches.  */
518840175f0Skstailey       for (p = longopts, option_index = 0; p->name; p++, option_index++)
519*a1acfa9bSespie 	if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
520840175f0Skstailey 	  {
521*a1acfa9bSespie 	    if ((unsigned int) (nameend - d->__nextchar)
522840175f0Skstailey 		== (unsigned int) strlen (p->name))
523840175f0Skstailey 	      {
524840175f0Skstailey 		/* Exact match found.  */
525840175f0Skstailey 		pfound = p;
526840175f0Skstailey 		indfound = option_index;
527840175f0Skstailey 		exact = 1;
528840175f0Skstailey 		break;
529840175f0Skstailey 	      }
530840175f0Skstailey 	    else if (pfound == NULL)
531840175f0Skstailey 	      {
532840175f0Skstailey 		/* First nonexact match found.  */
533840175f0Skstailey 		pfound = p;
534840175f0Skstailey 		indfound = option_index;
535840175f0Skstailey 	      }
536*a1acfa9bSespie 	    else if (long_only
537*a1acfa9bSespie 		     || pfound->has_arg != p->has_arg
538*a1acfa9bSespie 		     || pfound->flag != p->flag
539*a1acfa9bSespie 		     || pfound->val != p->val)
540840175f0Skstailey 	      /* Second or later nonexact match found.  */
541840175f0Skstailey 	      ambig = 1;
542840175f0Skstailey 	  }
543840175f0Skstailey 
544840175f0Skstailey       if (ambig && !exact)
545840175f0Skstailey 	{
546*a1acfa9bSespie 	  if (print_errors)
547*a1acfa9bSespie 	    {
548*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
549*a1acfa9bSespie 	      char *buf;
550*a1acfa9bSespie 
551*a1acfa9bSespie 	      if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
552*a1acfa9bSespie 			      argv[0], argv[d->optind]) >= 0)
553*a1acfa9bSespie 		{
554*a1acfa9bSespie 		  _IO_flockfile (stderr);
555*a1acfa9bSespie 
556*a1acfa9bSespie 		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
557*a1acfa9bSespie 		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
558*a1acfa9bSespie 
559*a1acfa9bSespie 		  if (_IO_fwide (stderr, 0) > 0)
560*a1acfa9bSespie 		    __fwprintf (stderr, L"%s", buf);
561*a1acfa9bSespie 		  else
562*a1acfa9bSespie 		    fputs (buf, stderr);
563*a1acfa9bSespie 
564*a1acfa9bSespie 		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
565*a1acfa9bSespie 		  _IO_funlockfile (stderr);
566*a1acfa9bSespie 
567*a1acfa9bSespie 		  free (buf);
568*a1acfa9bSespie 		}
569*a1acfa9bSespie #else
570840175f0Skstailey 	      fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
571*a1acfa9bSespie 		       argv[0], argv[d->optind]);
572*a1acfa9bSespie #endif
573*a1acfa9bSespie 	    }
574*a1acfa9bSespie 	  d->__nextchar += strlen (d->__nextchar);
575*a1acfa9bSespie 	  d->optind++;
576*a1acfa9bSespie 	  d->optopt = 0;
577840175f0Skstailey 	  return '?';
578840175f0Skstailey 	}
579840175f0Skstailey 
580840175f0Skstailey       if (pfound != NULL)
581840175f0Skstailey 	{
582840175f0Skstailey 	  option_index = indfound;
583*a1acfa9bSespie 	  d->optind++;
584840175f0Skstailey 	  if (*nameend)
585840175f0Skstailey 	    {
586840175f0Skstailey 	      /* Don't test has_arg with >, because some C compilers don't
587840175f0Skstailey 		 allow it to be used on enums.  */
588840175f0Skstailey 	      if (pfound->has_arg)
589*a1acfa9bSespie 		d->optarg = nameend + 1;
590840175f0Skstailey 	      else
591840175f0Skstailey 		{
592*a1acfa9bSespie 		  if (print_errors)
5933fb98d4aSespie 		    {
594*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
595*a1acfa9bSespie 		      char *buf;
596*a1acfa9bSespie 		      int n;
597*a1acfa9bSespie #endif
598*a1acfa9bSespie 
599*a1acfa9bSespie 		      if (argv[d->optind - 1][1] == '-')
600*a1acfa9bSespie 			{
601840175f0Skstailey 			  /* --option */
602*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
603*a1acfa9bSespie 			  n = __asprintf (&buf, _("\
604*a1acfa9bSespie %s: option `--%s' doesn't allow an argument\n"),
605840175f0Skstailey 					  argv[0], pfound->name);
606*a1acfa9bSespie #else
607*a1acfa9bSespie 			  fprintf (stderr, _("\
608*a1acfa9bSespie %s: option `--%s' doesn't allow an argument\n"),
609*a1acfa9bSespie 				   argv[0], pfound->name);
610*a1acfa9bSespie #endif
611*a1acfa9bSespie 			}
612840175f0Skstailey 		      else
613*a1acfa9bSespie 			{
614840175f0Skstailey 			  /* +option or -option */
615*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
616*a1acfa9bSespie 			  n = __asprintf (&buf, _("\
617*a1acfa9bSespie %s: option `%c%s' doesn't allow an argument\n"),
618*a1acfa9bSespie 					  argv[0], argv[d->optind - 1][0],
619*a1acfa9bSespie 					  pfound->name);
620*a1acfa9bSespie #else
621*a1acfa9bSespie 			  fprintf (stderr, _("\
622*a1acfa9bSespie %s: option `%c%s' doesn't allow an argument\n"),
623*a1acfa9bSespie 				   argv[0], argv[d->optind - 1][0],
624*a1acfa9bSespie 				   pfound->name);
625*a1acfa9bSespie #endif
6263fb98d4aSespie 			}
627840175f0Skstailey 
628*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
629*a1acfa9bSespie 		      if (n >= 0)
630*a1acfa9bSespie 			{
631*a1acfa9bSespie 			  _IO_flockfile (stderr);
632840175f0Skstailey 
633*a1acfa9bSespie 			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
634*a1acfa9bSespie 			  ((_IO_FILE *) stderr)->_flags2
635*a1acfa9bSespie 			    |= _IO_FLAGS2_NOTCANCEL;
636*a1acfa9bSespie 
637*a1acfa9bSespie 			  if (_IO_fwide (stderr, 0) > 0)
638*a1acfa9bSespie 			    __fwprintf (stderr, L"%s", buf);
639*a1acfa9bSespie 			  else
640*a1acfa9bSespie 			    fputs (buf, stderr);
641*a1acfa9bSespie 
642*a1acfa9bSespie 			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
643*a1acfa9bSespie 			  _IO_funlockfile (stderr);
644*a1acfa9bSespie 
645*a1acfa9bSespie 			  free (buf);
646*a1acfa9bSespie 			}
647*a1acfa9bSespie #endif
648*a1acfa9bSespie 		    }
649*a1acfa9bSespie 
650*a1acfa9bSespie 		  d->__nextchar += strlen (d->__nextchar);
651*a1acfa9bSespie 
652*a1acfa9bSespie 		  d->optopt = pfound->val;
653840175f0Skstailey 		  return '?';
654840175f0Skstailey 		}
655840175f0Skstailey 	    }
656840175f0Skstailey 	  else if (pfound->has_arg == 1)
657840175f0Skstailey 	    {
658*a1acfa9bSespie 	      if (d->optind < argc)
659*a1acfa9bSespie 		d->optarg = argv[d->optind++];
660840175f0Skstailey 	      else
661840175f0Skstailey 		{
662*a1acfa9bSespie 		  if (print_errors)
663*a1acfa9bSespie 		    {
664*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
665*a1acfa9bSespie 		      char *buf;
666*a1acfa9bSespie 
667*a1acfa9bSespie 		      if (__asprintf (&buf, _("\
668*a1acfa9bSespie %s: option `%s' requires an argument\n"),
669*a1acfa9bSespie 				      argv[0], argv[d->optind - 1]) >= 0)
670*a1acfa9bSespie 			{
671*a1acfa9bSespie 			  _IO_flockfile (stderr);
672*a1acfa9bSespie 
673*a1acfa9bSespie 			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
674*a1acfa9bSespie 			  ((_IO_FILE *) stderr)->_flags2
675*a1acfa9bSespie 			    |= _IO_FLAGS2_NOTCANCEL;
676*a1acfa9bSespie 
677*a1acfa9bSespie 			  if (_IO_fwide (stderr, 0) > 0)
678*a1acfa9bSespie 			    __fwprintf (stderr, L"%s", buf);
679*a1acfa9bSespie 			  else
680*a1acfa9bSespie 			    fputs (buf, stderr);
681*a1acfa9bSespie 
682*a1acfa9bSespie 			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
683*a1acfa9bSespie 			  _IO_funlockfile (stderr);
684*a1acfa9bSespie 
685*a1acfa9bSespie 			  free (buf);
686*a1acfa9bSespie 			}
687*a1acfa9bSespie #else
688840175f0Skstailey 		      fprintf (stderr,
689840175f0Skstailey 			       _("%s: option `%s' requires an argument\n"),
690*a1acfa9bSespie 			       argv[0], argv[d->optind - 1]);
691*a1acfa9bSespie #endif
692*a1acfa9bSespie 		    }
693*a1acfa9bSespie 		  d->__nextchar += strlen (d->__nextchar);
694*a1acfa9bSespie 		  d->optopt = pfound->val;
695840175f0Skstailey 		  return optstring[0] == ':' ? ':' : '?';
696840175f0Skstailey 		}
697840175f0Skstailey 	    }
698*a1acfa9bSespie 	  d->__nextchar += strlen (d->__nextchar);
699840175f0Skstailey 	  if (longind != NULL)
700840175f0Skstailey 	    *longind = option_index;
701840175f0Skstailey 	  if (pfound->flag)
702840175f0Skstailey 	    {
703840175f0Skstailey 	      *(pfound->flag) = pfound->val;
704840175f0Skstailey 	      return 0;
705840175f0Skstailey 	    }
706840175f0Skstailey 	  return pfound->val;
707840175f0Skstailey 	}
708840175f0Skstailey 
709840175f0Skstailey       /* Can't find it as a long option.  If this is not getopt_long_only,
710840175f0Skstailey 	 or the option starts with '--' or is not a valid short
711840175f0Skstailey 	 option, then it's an error.
712840175f0Skstailey 	 Otherwise interpret it as a short option.  */
713*a1acfa9bSespie       if (!long_only || argv[d->optind][1] == '-'
714*a1acfa9bSespie 	  || strchr (optstring, *d->__nextchar) == NULL)
715840175f0Skstailey 	{
716*a1acfa9bSespie 	  if (print_errors)
717840175f0Skstailey 	    {
718*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
719*a1acfa9bSespie 	      char *buf;
720*a1acfa9bSespie 	      int n;
721*a1acfa9bSespie #endif
722*a1acfa9bSespie 
723*a1acfa9bSespie 	      if (argv[d->optind][1] == '-')
724*a1acfa9bSespie 		{
725840175f0Skstailey 		  /* --option */
726*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
727*a1acfa9bSespie 		  n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
728*a1acfa9bSespie 				  argv[0], d->__nextchar);
729*a1acfa9bSespie #else
730840175f0Skstailey 		  fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
731*a1acfa9bSespie 			   argv[0], d->__nextchar);
732*a1acfa9bSespie #endif
733840175f0Skstailey 		}
734*a1acfa9bSespie 	      else
735*a1acfa9bSespie 		{
736*a1acfa9bSespie 		  /* +option or -option */
737*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
738*a1acfa9bSespie 		  n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
739*a1acfa9bSespie 				  argv[0], argv[d->optind][0], d->__nextchar);
740*a1acfa9bSespie #else
741*a1acfa9bSespie 		  fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
742*a1acfa9bSespie 			   argv[0], argv[d->optind][0], d->__nextchar);
743*a1acfa9bSespie #endif
744*a1acfa9bSespie 		}
745*a1acfa9bSespie 
746*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
747*a1acfa9bSespie 	      if (n >= 0)
748*a1acfa9bSespie 		{
749*a1acfa9bSespie 		  _IO_flockfile (stderr);
750*a1acfa9bSespie 
751*a1acfa9bSespie 		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
752*a1acfa9bSespie 		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
753*a1acfa9bSespie 
754*a1acfa9bSespie 		  if (_IO_fwide (stderr, 0) > 0)
755*a1acfa9bSespie 		    __fwprintf (stderr, L"%s", buf);
756*a1acfa9bSespie 		  else
757*a1acfa9bSespie 		    fputs (buf, stderr);
758*a1acfa9bSespie 
759*a1acfa9bSespie 		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
760*a1acfa9bSespie 		  _IO_funlockfile (stderr);
761*a1acfa9bSespie 
762*a1acfa9bSespie 		  free (buf);
763*a1acfa9bSespie 		}
764*a1acfa9bSespie #endif
765*a1acfa9bSespie 	    }
766*a1acfa9bSespie 	  d->__nextchar = (char *) "";
767*a1acfa9bSespie 	  d->optind++;
768*a1acfa9bSespie 	  d->optopt = 0;
769840175f0Skstailey 	  return '?';
770840175f0Skstailey 	}
771840175f0Skstailey     }
772840175f0Skstailey 
773840175f0Skstailey   /* Look at and handle the next short option-character.  */
774840175f0Skstailey 
775840175f0Skstailey   {
776*a1acfa9bSespie     char c = *d->__nextchar++;
777*a1acfa9bSespie     char *temp = strchr (optstring, c);
778840175f0Skstailey 
779840175f0Skstailey     /* Increment `optind' when we start to process its last character.  */
780*a1acfa9bSespie     if (*d->__nextchar == '\0')
781*a1acfa9bSespie       ++d->optind;
782840175f0Skstailey 
783840175f0Skstailey     if (temp == NULL || c == ':')
784840175f0Skstailey       {
785*a1acfa9bSespie 	if (print_errors)
786840175f0Skstailey 	  {
787*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
788*a1acfa9bSespie 	      char *buf;
789*a1acfa9bSespie 	      int n;
790*a1acfa9bSespie #endif
791*a1acfa9bSespie 
792*a1acfa9bSespie 	    if (d->__posixly_correct)
793*a1acfa9bSespie 	      {
794840175f0Skstailey 		/* 1003.2 specifies the format of this message.  */
795*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
796*a1acfa9bSespie 		n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
797840175f0Skstailey 				argv[0], c);
798*a1acfa9bSespie #else
799*a1acfa9bSespie 		fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
800*a1acfa9bSespie #endif
801840175f0Skstailey 	      }
802*a1acfa9bSespie 	    else
803*a1acfa9bSespie 	      {
804*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
805*a1acfa9bSespie 		n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
806*a1acfa9bSespie 				argv[0], c);
807*a1acfa9bSespie #else
808*a1acfa9bSespie 		fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
809*a1acfa9bSespie #endif
810*a1acfa9bSespie 	      }
811*a1acfa9bSespie 
812*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
813*a1acfa9bSespie 	    if (n >= 0)
814*a1acfa9bSespie 	      {
815*a1acfa9bSespie 		_IO_flockfile (stderr);
816*a1acfa9bSespie 
817*a1acfa9bSespie 		int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
818*a1acfa9bSespie 		((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
819*a1acfa9bSespie 
820*a1acfa9bSespie 		if (_IO_fwide (stderr, 0) > 0)
821*a1acfa9bSespie 		  __fwprintf (stderr, L"%s", buf);
822*a1acfa9bSespie 		else
823*a1acfa9bSespie 		  fputs (buf, stderr);
824*a1acfa9bSespie 
825*a1acfa9bSespie 		((_IO_FILE *) stderr)->_flags2 = old_flags2;
826*a1acfa9bSespie 		_IO_funlockfile (stderr);
827*a1acfa9bSespie 
828*a1acfa9bSespie 		free (buf);
829*a1acfa9bSespie 	      }
830*a1acfa9bSespie #endif
831*a1acfa9bSespie 	  }
832*a1acfa9bSespie 	d->optopt = c;
833840175f0Skstailey 	return '?';
834840175f0Skstailey       }
835840175f0Skstailey     /* Convenience. Treat POSIX -W foo same as long option --foo */
836840175f0Skstailey     if (temp[0] == 'W' && temp[1] == ';')
837840175f0Skstailey       {
838840175f0Skstailey 	char *nameend;
839840175f0Skstailey 	const struct option *p;
840840175f0Skstailey 	const struct option *pfound = NULL;
841840175f0Skstailey 	int exact = 0;
842840175f0Skstailey 	int ambig = 0;
843840175f0Skstailey 	int indfound = 0;
844840175f0Skstailey 	int option_index;
845840175f0Skstailey 
846840175f0Skstailey 	/* This is an option that requires an argument.  */
847*a1acfa9bSespie 	if (*d->__nextchar != '\0')
848840175f0Skstailey 	  {
849*a1acfa9bSespie 	    d->optarg = d->__nextchar;
850840175f0Skstailey 	    /* If we end this ARGV-element by taking the rest as an arg,
851840175f0Skstailey 	       we must advance to the next element now.  */
852*a1acfa9bSespie 	    d->optind++;
853840175f0Skstailey 	  }
854*a1acfa9bSespie 	else if (d->optind == argc)
855840175f0Skstailey 	  {
856*a1acfa9bSespie 	    if (print_errors)
857840175f0Skstailey 	      {
858840175f0Skstailey 		/* 1003.2 specifies the format of this message.  */
859*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
860*a1acfa9bSespie 		char *buf;
861*a1acfa9bSespie 
862*a1acfa9bSespie 		if (__asprintf (&buf,
863*a1acfa9bSespie 				_("%s: option requires an argument -- %c\n"),
864*a1acfa9bSespie 				argv[0], c) >= 0)
865*a1acfa9bSespie 		  {
866*a1acfa9bSespie 		    _IO_flockfile (stderr);
867*a1acfa9bSespie 
868*a1acfa9bSespie 		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
869*a1acfa9bSespie 		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
870*a1acfa9bSespie 
871*a1acfa9bSespie 		    if (_IO_fwide (stderr, 0) > 0)
872*a1acfa9bSespie 		      __fwprintf (stderr, L"%s", buf);
873*a1acfa9bSespie 		    else
874*a1acfa9bSespie 		      fputs (buf, stderr);
875*a1acfa9bSespie 
876*a1acfa9bSespie 		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
877*a1acfa9bSespie 		    _IO_funlockfile (stderr);
878*a1acfa9bSespie 
879*a1acfa9bSespie 		    free (buf);
880*a1acfa9bSespie 		  }
881*a1acfa9bSespie #else
882840175f0Skstailey 		fprintf (stderr, _("%s: option requires an argument -- %c\n"),
883840175f0Skstailey 			 argv[0], c);
884*a1acfa9bSespie #endif
885840175f0Skstailey 	      }
886*a1acfa9bSespie 	    d->optopt = c;
887840175f0Skstailey 	    if (optstring[0] == ':')
888840175f0Skstailey 	      c = ':';
889840175f0Skstailey 	    else
890840175f0Skstailey 	      c = '?';
891840175f0Skstailey 	    return c;
892840175f0Skstailey 	  }
893840175f0Skstailey 	else
894*a1acfa9bSespie 	  /* We already incremented `d->optind' once;
895840175f0Skstailey 	     increment it again when taking next ARGV-elt as argument.  */
896*a1acfa9bSespie 	  d->optarg = argv[d->optind++];
897840175f0Skstailey 
898840175f0Skstailey 	/* optarg is now the argument, see if it's in the
899840175f0Skstailey 	   table of longopts.  */
900840175f0Skstailey 
901*a1acfa9bSespie 	for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
902*a1acfa9bSespie 	     nameend++)
903840175f0Skstailey 	  /* Do nothing.  */ ;
904840175f0Skstailey 
905840175f0Skstailey 	/* Test all long options for either exact match
906840175f0Skstailey 	   or abbreviated matches.  */
907840175f0Skstailey 	for (p = longopts, option_index = 0; p->name; p++, option_index++)
908*a1acfa9bSespie 	  if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
909840175f0Skstailey 	    {
910*a1acfa9bSespie 	      if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
911840175f0Skstailey 		{
912840175f0Skstailey 		  /* Exact match found.  */
913840175f0Skstailey 		  pfound = p;
914840175f0Skstailey 		  indfound = option_index;
915840175f0Skstailey 		  exact = 1;
916840175f0Skstailey 		  break;
917840175f0Skstailey 		}
918840175f0Skstailey 	      else if (pfound == NULL)
919840175f0Skstailey 		{
920840175f0Skstailey 		  /* First nonexact match found.  */
921840175f0Skstailey 		  pfound = p;
922840175f0Skstailey 		  indfound = option_index;
923840175f0Skstailey 		}
924840175f0Skstailey 	      else
925840175f0Skstailey 		/* Second or later nonexact match found.  */
926840175f0Skstailey 		ambig = 1;
927840175f0Skstailey 	    }
928840175f0Skstailey 	if (ambig && !exact)
929840175f0Skstailey 	  {
930*a1acfa9bSespie 	    if (print_errors)
931*a1acfa9bSespie 	      {
932*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
933*a1acfa9bSespie 		char *buf;
934*a1acfa9bSespie 
935*a1acfa9bSespie 		if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
936*a1acfa9bSespie 				argv[0], argv[d->optind]) >= 0)
937*a1acfa9bSespie 		  {
938*a1acfa9bSespie 		    _IO_flockfile (stderr);
939*a1acfa9bSespie 
940*a1acfa9bSespie 		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
941*a1acfa9bSespie 		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
942*a1acfa9bSespie 
943*a1acfa9bSespie 		    if (_IO_fwide (stderr, 0) > 0)
944*a1acfa9bSespie 		      __fwprintf (stderr, L"%s", buf);
945*a1acfa9bSespie 		    else
946*a1acfa9bSespie 		      fputs (buf, stderr);
947*a1acfa9bSespie 
948*a1acfa9bSespie 		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
949*a1acfa9bSespie 		    _IO_funlockfile (stderr);
950*a1acfa9bSespie 
951*a1acfa9bSespie 		    free (buf);
952*a1acfa9bSespie 		  }
953*a1acfa9bSespie #else
954840175f0Skstailey 		fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
955*a1acfa9bSespie 			 argv[0], argv[d->optind]);
956*a1acfa9bSespie #endif
957*a1acfa9bSespie 	      }
958*a1acfa9bSespie 	    d->__nextchar += strlen (d->__nextchar);
959*a1acfa9bSespie 	    d->optind++;
960840175f0Skstailey 	    return '?';
961840175f0Skstailey 	  }
962840175f0Skstailey 	if (pfound != NULL)
963840175f0Skstailey 	  {
964840175f0Skstailey 	    option_index = indfound;
965840175f0Skstailey 	    if (*nameend)
966840175f0Skstailey 	      {
967840175f0Skstailey 		/* Don't test has_arg with >, because some C compilers don't
968840175f0Skstailey 		   allow it to be used on enums.  */
969840175f0Skstailey 		if (pfound->has_arg)
970*a1acfa9bSespie 		  d->optarg = nameend + 1;
971840175f0Skstailey 		else
972840175f0Skstailey 		  {
973*a1acfa9bSespie 		    if (print_errors)
974*a1acfa9bSespie 		      {
975*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
976*a1acfa9bSespie 			char *buf;
977*a1acfa9bSespie 
978*a1acfa9bSespie 			if (__asprintf (&buf, _("\
979*a1acfa9bSespie %s: option `-W %s' doesn't allow an argument\n"),
980*a1acfa9bSespie 					argv[0], pfound->name) >= 0)
981*a1acfa9bSespie 			  {
982*a1acfa9bSespie 			    _IO_flockfile (stderr);
983*a1acfa9bSespie 
984*a1acfa9bSespie 			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
985*a1acfa9bSespie 			    ((_IO_FILE *) stderr)->_flags2
986*a1acfa9bSespie 			      |= _IO_FLAGS2_NOTCANCEL;
987*a1acfa9bSespie 
988*a1acfa9bSespie 			    if (_IO_fwide (stderr, 0) > 0)
989*a1acfa9bSespie 			      __fwprintf (stderr, L"%s", buf);
990*a1acfa9bSespie 			    else
991*a1acfa9bSespie 			      fputs (buf, stderr);
992*a1acfa9bSespie 
993*a1acfa9bSespie 			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
994*a1acfa9bSespie 			    _IO_funlockfile (stderr);
995*a1acfa9bSespie 
996*a1acfa9bSespie 			    free (buf);
997*a1acfa9bSespie 			  }
998*a1acfa9bSespie #else
999840175f0Skstailey 			fprintf (stderr, _("\
1000840175f0Skstailey %s: option `-W %s' doesn't allow an argument\n"),
1001840175f0Skstailey 				 argv[0], pfound->name);
1002*a1acfa9bSespie #endif
1003*a1acfa9bSespie 		      }
1004840175f0Skstailey 
1005*a1acfa9bSespie 		    d->__nextchar += strlen (d->__nextchar);
1006840175f0Skstailey 		    return '?';
1007840175f0Skstailey 		  }
1008840175f0Skstailey 	      }
1009840175f0Skstailey 	    else if (pfound->has_arg == 1)
1010840175f0Skstailey 	      {
1011*a1acfa9bSespie 		if (d->optind < argc)
1012*a1acfa9bSespie 		  d->optarg = argv[d->optind++];
1013840175f0Skstailey 		else
1014840175f0Skstailey 		  {
1015*a1acfa9bSespie 		    if (print_errors)
1016*a1acfa9bSespie 		      {
1017*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
1018*a1acfa9bSespie 			char *buf;
1019*a1acfa9bSespie 
1020*a1acfa9bSespie 			if (__asprintf (&buf, _("\
1021*a1acfa9bSespie %s: option `%s' requires an argument\n"),
1022*a1acfa9bSespie 					argv[0], argv[d->optind - 1]) >= 0)
1023*a1acfa9bSespie 			  {
1024*a1acfa9bSespie 			    _IO_flockfile (stderr);
1025*a1acfa9bSespie 
1026*a1acfa9bSespie 			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
1027*a1acfa9bSespie 			    ((_IO_FILE *) stderr)->_flags2
1028*a1acfa9bSespie 			      |= _IO_FLAGS2_NOTCANCEL;
1029*a1acfa9bSespie 
1030*a1acfa9bSespie 			    if (_IO_fwide (stderr, 0) > 0)
1031*a1acfa9bSespie 			      __fwprintf (stderr, L"%s", buf);
1032*a1acfa9bSespie 			    else
1033*a1acfa9bSespie 			      fputs (buf, stderr);
1034*a1acfa9bSespie 
1035*a1acfa9bSespie 			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
1036*a1acfa9bSespie 			    _IO_funlockfile (stderr);
1037*a1acfa9bSespie 
1038*a1acfa9bSespie 			    free (buf);
1039*a1acfa9bSespie 			  }
1040*a1acfa9bSespie #else
1041840175f0Skstailey 			fprintf (stderr,
1042840175f0Skstailey 				 _("%s: option `%s' requires an argument\n"),
1043*a1acfa9bSespie 				 argv[0], argv[d->optind - 1]);
1044*a1acfa9bSespie #endif
1045*a1acfa9bSespie 		      }
1046*a1acfa9bSespie 		    d->__nextchar += strlen (d->__nextchar);
1047840175f0Skstailey 		    return optstring[0] == ':' ? ':' : '?';
1048840175f0Skstailey 		  }
1049840175f0Skstailey 	      }
1050*a1acfa9bSespie 	    d->__nextchar += strlen (d->__nextchar);
1051840175f0Skstailey 	    if (longind != NULL)
1052840175f0Skstailey 	      *longind = option_index;
1053840175f0Skstailey 	    if (pfound->flag)
1054840175f0Skstailey 	      {
1055840175f0Skstailey 		*(pfound->flag) = pfound->val;
1056840175f0Skstailey 		return 0;
1057840175f0Skstailey 	      }
1058840175f0Skstailey 	    return pfound->val;
1059840175f0Skstailey 	  }
1060*a1acfa9bSespie 	  d->__nextchar = NULL;
1061840175f0Skstailey 	  return 'W';	/* Let the application handle it.   */
1062840175f0Skstailey       }
1063840175f0Skstailey     if (temp[1] == ':')
1064840175f0Skstailey       {
1065840175f0Skstailey 	if (temp[2] == ':')
1066840175f0Skstailey 	  {
1067840175f0Skstailey 	    /* This is an option that accepts an argument optionally.  */
1068*a1acfa9bSespie 	    if (*d->__nextchar != '\0')
1069840175f0Skstailey 	      {
1070*a1acfa9bSespie 		d->optarg = d->__nextchar;
1071*a1acfa9bSespie 		d->optind++;
1072840175f0Skstailey 	      }
1073840175f0Skstailey 	    else
1074*a1acfa9bSespie 	      d->optarg = NULL;
1075*a1acfa9bSespie 	    d->__nextchar = NULL;
1076840175f0Skstailey 	  }
1077840175f0Skstailey 	else
1078840175f0Skstailey 	  {
1079840175f0Skstailey 	    /* This is an option that requires an argument.  */
1080*a1acfa9bSespie 	    if (*d->__nextchar != '\0')
1081840175f0Skstailey 	      {
1082*a1acfa9bSespie 		d->optarg = d->__nextchar;
1083840175f0Skstailey 		/* If we end this ARGV-element by taking the rest as an arg,
1084840175f0Skstailey 		   we must advance to the next element now.  */
1085*a1acfa9bSespie 		d->optind++;
1086840175f0Skstailey 	      }
1087*a1acfa9bSespie 	    else if (d->optind == argc)
1088840175f0Skstailey 	      {
1089*a1acfa9bSespie 		if (print_errors)
1090840175f0Skstailey 		  {
1091840175f0Skstailey 		    /* 1003.2 specifies the format of this message.  */
1092*a1acfa9bSespie #if defined _LIBC && defined USE_IN_LIBIO
1093*a1acfa9bSespie 		    char *buf;
1094*a1acfa9bSespie 
1095*a1acfa9bSespie 		    if (__asprintf (&buf, _("\
1096*a1acfa9bSespie %s: option requires an argument -- %c\n"),
1097*a1acfa9bSespie 				    argv[0], c) >= 0)
1098*a1acfa9bSespie 		      {
1099*a1acfa9bSespie 			_IO_flockfile (stderr);
1100*a1acfa9bSespie 
1101*a1acfa9bSespie 			int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
1102*a1acfa9bSespie 			((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
1103*a1acfa9bSespie 
1104*a1acfa9bSespie 			if (_IO_fwide (stderr, 0) > 0)
1105*a1acfa9bSespie 			  __fwprintf (stderr, L"%s", buf);
1106*a1acfa9bSespie 			else
1107*a1acfa9bSespie 			  fputs (buf, stderr);
1108*a1acfa9bSespie 
1109*a1acfa9bSespie 			((_IO_FILE *) stderr)->_flags2 = old_flags2;
1110*a1acfa9bSespie 			_IO_funlockfile (stderr);
1111*a1acfa9bSespie 
1112*a1acfa9bSespie 			free (buf);
1113*a1acfa9bSespie 		      }
1114*a1acfa9bSespie #else
1115840175f0Skstailey 		    fprintf (stderr,
1116840175f0Skstailey 			     _("%s: option requires an argument -- %c\n"),
1117840175f0Skstailey 			     argv[0], c);
1118*a1acfa9bSespie #endif
1119840175f0Skstailey 		  }
1120*a1acfa9bSespie 		d->optopt = c;
1121840175f0Skstailey 		if (optstring[0] == ':')
1122840175f0Skstailey 		  c = ':';
1123840175f0Skstailey 		else
1124840175f0Skstailey 		  c = '?';
1125840175f0Skstailey 	      }
1126840175f0Skstailey 	    else
1127840175f0Skstailey 	      /* We already incremented `optind' once;
1128840175f0Skstailey 		 increment it again when taking next ARGV-elt as argument.  */
1129*a1acfa9bSespie 	      d->optarg = argv[d->optind++];
1130*a1acfa9bSespie 	    d->__nextchar = NULL;
1131840175f0Skstailey 	  }
1132840175f0Skstailey       }
1133840175f0Skstailey     return c;
1134840175f0Skstailey   }
1135840175f0Skstailey }
1136840175f0Skstailey 
1137840175f0Skstailey int
_getopt_internal(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,int long_only)1138*a1acfa9bSespie _getopt_internal (int argc, char *const *argv, const char *optstring,
1139*a1acfa9bSespie 		  const struct option *longopts, int *longind, int long_only)
1140*a1acfa9bSespie {
1141*a1acfa9bSespie   int result;
1142*a1acfa9bSespie 
1143*a1acfa9bSespie   getopt_data.optind = optind;
1144*a1acfa9bSespie   getopt_data.opterr = opterr;
1145*a1acfa9bSespie 
1146*a1acfa9bSespie   result = _getopt_internal_r (argc, argv, optstring, longopts,
1147*a1acfa9bSespie 			       longind, long_only, &getopt_data);
1148*a1acfa9bSespie 
1149*a1acfa9bSespie   optind = getopt_data.optind;
1150*a1acfa9bSespie   optarg = getopt_data.optarg;
1151*a1acfa9bSespie   optopt = getopt_data.optopt;
1152*a1acfa9bSespie 
1153*a1acfa9bSespie   return result;
1154*a1acfa9bSespie }
1155*a1acfa9bSespie 
1156*a1acfa9bSespie int
getopt(int argc,char * const * argv,const char * optstring)1157*a1acfa9bSespie getopt (int argc, char *const *argv, const char *optstring)
1158840175f0Skstailey {
1159840175f0Skstailey   return _getopt_internal (argc, argv, optstring,
1160840175f0Skstailey 			   (const struct option *) 0,
1161840175f0Skstailey 			   (int *) 0,
1162840175f0Skstailey 			   0);
1163840175f0Skstailey }
1164840175f0Skstailey 
1165840175f0Skstailey 
1166840175f0Skstailey #ifdef TEST
1167840175f0Skstailey 
1168840175f0Skstailey /* Compile with -DTEST to make an executable for use in testing
1169840175f0Skstailey    the above definition of `getopt'.  */
1170840175f0Skstailey 
1171840175f0Skstailey int
main(int argc,char ** argv)1172*a1acfa9bSespie main (int argc, char **argv)
1173840175f0Skstailey {
1174840175f0Skstailey   int c;
1175840175f0Skstailey   int digit_optind = 0;
1176840175f0Skstailey 
1177840175f0Skstailey   while (1)
1178840175f0Skstailey     {
1179840175f0Skstailey       int this_option_optind = optind ? optind : 1;
1180840175f0Skstailey 
1181840175f0Skstailey       c = getopt (argc, argv, "abc:d:0123456789");
1182840175f0Skstailey       if (c == -1)
1183840175f0Skstailey 	break;
1184840175f0Skstailey 
1185840175f0Skstailey       switch (c)
1186840175f0Skstailey 	{
1187840175f0Skstailey 	case '0':
1188840175f0Skstailey 	case '1':
1189840175f0Skstailey 	case '2':
1190840175f0Skstailey 	case '3':
1191840175f0Skstailey 	case '4':
1192840175f0Skstailey 	case '5':
1193840175f0Skstailey 	case '6':
1194840175f0Skstailey 	case '7':
1195840175f0Skstailey 	case '8':
1196840175f0Skstailey 	case '9':
1197840175f0Skstailey 	  if (digit_optind != 0 && digit_optind != this_option_optind)
1198840175f0Skstailey 	    printf ("digits occur in two different argv-elements.\n");
1199840175f0Skstailey 	  digit_optind = this_option_optind;
1200840175f0Skstailey 	  printf ("option %c\n", c);
1201840175f0Skstailey 	  break;
1202840175f0Skstailey 
1203840175f0Skstailey 	case 'a':
1204840175f0Skstailey 	  printf ("option a\n");
1205840175f0Skstailey 	  break;
1206840175f0Skstailey 
1207840175f0Skstailey 	case 'b':
1208840175f0Skstailey 	  printf ("option b\n");
1209840175f0Skstailey 	  break;
1210840175f0Skstailey 
1211840175f0Skstailey 	case 'c':
1212840175f0Skstailey 	  printf ("option c with value `%s'\n", optarg);
1213840175f0Skstailey 	  break;
1214840175f0Skstailey 
1215840175f0Skstailey 	case '?':
1216840175f0Skstailey 	  break;
1217840175f0Skstailey 
1218840175f0Skstailey 	default:
1219840175f0Skstailey 	  printf ("?? getopt returned character code 0%o ??\n", c);
1220840175f0Skstailey 	}
1221840175f0Skstailey     }
1222840175f0Skstailey 
1223840175f0Skstailey   if (optind < argc)
1224840175f0Skstailey     {
1225840175f0Skstailey       printf ("non-option ARGV-elements: ");
1226840175f0Skstailey       while (optind < argc)
1227840175f0Skstailey 	printf ("%s ", argv[optind++]);
1228840175f0Skstailey       printf ("\n");
1229840175f0Skstailey     }
1230840175f0Skstailey 
1231840175f0Skstailey   exit (0);
1232840175f0Skstailey }
1233840175f0Skstailey 
1234840175f0Skstailey #endif /* TEST */
1235