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