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