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