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