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