1/* Getopt for GNU.
2 Copyright (C) 1987-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library and is also part of gnulib.
4 Patches to this file should be submitted to both projects.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
19
20#ifndef _LIBC
21# include <config.h>
22#endif
23
24#include "getopt.h"
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30
31#ifdef _LIBC
32/* When used as part of glibc, error printing must be done differently
33 for standards compliance. getopt is not a cancellation point, so
34 it must not call functions that are, and it is specified by an
35 older standard than stdio locking, so it must not refer to
36 functions in the "user namespace" related to stdio locking.
37 Finally, it must use glibc's internal message translation so that
38 the messages are looked up in the proper text domain. */
39# include <libintl.h>
40# define fprintf __fxprintf_nocancel
41# define flockfile(fp) _IO_flockfile (fp)
42# define funlockfile(fp) _IO_funlockfile (fp)
43#else
44# include "gettext.h"
45# define _(msgid) gettext (msgid)
46/* When used standalone, flockfile and funlockfile might not be
47 available. */
48# ifndef _POSIX_THREAD_SAFE_FUNCTIONS
49# define flockfile(fp) /* nop */
50# define funlockfile(fp) /* nop */
51# endif
52/* When used standalone, do not attempt to use alloca. */
53# define __libc_use_alloca(size) 0
54# undef alloca
55# define alloca(size) (abort (), (void *)0)
56#endif
57
58/* This implementation of 'getopt' has three modes for handling
59 options interspersed with non-option arguments. It can stop
60 scanning for options at the first non-option argument encountered,
61 as POSIX specifies. It can continue scanning for options after the
62 first non-option argument, but permute 'argv' as it goes so that,
63 after 'getopt' is done, all the options precede all the non-option
64 arguments and 'optind' points to the first non-option argument.
65 Or, it can report non-option arguments as if they were arguments to
66 the option character '\x01'.
67
68 The default behavior of 'getopt_long' is to permute the argument list.
69 When this implementation is used standalone, the default behavior of
70 'getopt' is to stop at the first non-option argument, but when it is
71 used as part of GNU libc it also permutes the argument list. In both
72 cases, setting the environment variable POSIXLY_CORRECT to any value
73 disables permutation.
74
75 If the first character of the OPTSTRING argument to 'getopt' or
76 'getopt_long' is '+', both functions will stop at the first
77 non-option argument. If it is '-', both functions will report
78 non-option arguments as arguments to the option character '\x01'. */
79
80#include "getopt_int.h"
81
82/* For communication from 'getopt' to the caller.
83 When 'getopt' finds an option that takes an argument,
84 the argument value is returned here.
85 Also, when 'ordering' is RETURN_IN_ORDER,
86 each non-option ARGV-element is returned here. */
87
88char *optarg;
89
90/* Index in ARGV of the next element to be scanned.
91 This is used for communication to and from the caller
92 and for communication between successive calls to 'getopt'.
93
94 On entry to 'getopt', zero means this is the first call; initialize.
95
96 When 'getopt' returns -1, this is the index of the first of the
97 non-option elements that the caller should itself scan.
98
99 Otherwise, 'optind' communicates from one call to the next
100 how much of ARGV has been scanned so far. */
101
102/* 1003.2 says this must be 1 before any call. */
103int optind = 1;
104
105/* Callers store zero here to inhibit the error message
106 for unrecognized options. */
107
108int opterr = 1;
109
110/* Set to an option character which was unrecognized.
111 This must be initialized on some systems to avoid linking in the
112 system's own getopt implementation. */
113
114int optopt = '?';
115
116/* Keep a global copy of all internal members of getopt_data. */
117
118static struct _getopt_data getopt_data;
119
120/* Exchange two adjacent subsequences of ARGV.
121 One subsequence is elements [first_nonopt,last_nonopt)
122 which contains all the non-options that have been skipped so far.
123 The other is elements [last_nonopt,optind), which contains all
124 the options processed since those non-options were skipped.
125
126 'first_nonopt' and 'last_nonopt' are relocated so that they describe
127 the new indices of the non-options in ARGV after they are moved. */
128
129static void
130exchange (char **argv, struct _getopt_data *d)
131{
132 int bottom = d->__first_nonopt;
133 int middle = d->__last_nonopt;
134 int top = d->optind;
135 char *tem;
136
137 /* Exchange the shorter segment with the far end of the longer segment.
138 That puts the shorter segment into the right place.
139 It leaves the longer segment in the right place overall,
140 but it consists of two parts that need to be swapped next. */
141
142 while (top > middle && middle > bottom)
143 {
144 if (top - middle > middle - bottom)
145 {
146 /* Bottom segment is the short one. */
147 int len = middle - bottom;
148 int i;
149
150 /* Swap it with the top part of the top segment. */
151 for (i = 0; i < len; i++)
152 {
153 tem = argv[bottom + i];
154 argv[bottom + i] = argv[top - (middle - bottom) + i];
155 argv[top - (middle - bottom) + i] = tem;
156 }
157 /* Exclude the moved bottom segment from further swapping. */
158 top -= len;
159 }
160 else
161 {
162 /* Top segment is the short one. */
163 int len = top - middle;
164 int i;
165
166 /* Swap it with the bottom part of the bottom segment. */
167 for (i = 0; i < len; i++)
168 {
169 tem = argv[bottom + i];
170 argv[bottom + i] = argv[middle + i];
171 argv[middle + i] = tem;
172 }
173 /* Exclude the moved top segment from further swapping. */
174 bottom += len;
175 }
176 }
177
178 /* Update records for the slots the non-options now occupy. */
179
180 d->__first_nonopt += (d->optind - d->__last_nonopt);
181 d->__last_nonopt = d->optind;
182}
183
184/* Process the argument starting with d->__nextchar as a long option.
185 d->optind should *not* have been advanced over this argument.
186
187 If the value returned is -1, it was not actually a long option, the
188 state is unchanged, and the argument should be processed as a set
189 of short options (this can only happen when long_only is true).
190 Otherwise, the option (and its argument, if any) have been consumed
191 and the return value is the value to return from _getopt_internal_r. */
192static int
193process_long_option (int argc, char **argv, const char *optstring,
194 const struct option *longopts, int *longind,
195 int long_only, struct _getopt_data *d,
196 int print_errors, const char *prefix)
197{
198 char *nameend;
199 size_t namelen;
200 const struct option *p;
201 const struct option *pfound = NULL;
202 int n_options;
203 int option_index;
204
205 for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
206 /* Do nothing. */ ;
207 namelen = nameend - d->__nextchar;
208
209 /* First look for an exact match, counting the options as a side
210 effect. */
211 for (p = longopts, n_options = 0; p->name; p++, n_options++)
212 if (!strncmp (p->name, d->__nextchar, namelen)
213 && namelen == strlen (p->name))
214 {
215 /* Exact match found. */
216 pfound = p;
217 option_index = n_options;
218 break;
219 }
220
221 if (pfound == NULL)
222 {
223 /* Didn't find an exact match, so look for abbreviations. */
224 unsigned char *ambig_set = NULL;
225 int ambig_malloced = 0;
226 int ambig_fallback = 0;
227 int indfound = -1;
228
229 for (p = longopts, option_index = 0; p->name; p++, option_index++)
230 if (!strncmp (p->name, d->__nextchar, namelen))
231 {
232 if (pfound == NULL)
233 {
234 /* First nonexact match found. */
235 pfound = p;
236 indfound = option_index;
237 }
238 else if (long_only
239 || pfound->has_arg != p->has_arg
240 || pfound->flag != p->flag
241 || pfound->val != p->val)
242 {
243 /* Second or later nonexact match found. */
244 if (!ambig_fallback)
245 {
246 if (!print_errors)
247 /* Don't waste effort tracking the ambig set if
248 we're not going to print it anyway. */
249 ambig_fallback = 1;
250 else if (!ambig_set)
251 {
252 if (__libc_use_alloca (size: n_options))
253 ambig_set = alloca (n_options);
254 else if ((ambig_set = malloc (size: n_options)) == NULL)
255 /* Fall back to simpler error message. */
256 ambig_fallback = 1;
257 else
258 ambig_malloced = 1;
259
260 if (ambig_set)
261 {
262 memset (ambig_set, 0, n_options);
263 ambig_set[indfound] = 1;
264 }
265 }
266 if (ambig_set)
267 ambig_set[option_index] = 1;
268 }
269 }
270 }
271
272 if (ambig_set || ambig_fallback)
273 {
274 if (print_errors)
275 {
276 if (ambig_fallback)
277 fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"),
278 argv[0], prefix, d->__nextchar);
279 else
280 {
281 flockfile (stderr);
282 fprintf (stderr,
283 _("%s: option '%s%s' is ambiguous; possibilities:"),
284 argv[0], prefix, d->__nextchar);
285
286 for (option_index = 0; option_index < n_options; option_index++)
287 if (ambig_set[option_index])
288 fprintf (stderr, fmt: " '%s%s'",
289 prefix, longopts[option_index].name);
290
291 /* This must use 'fprintf' even though it's only
292 printing a single character, so that it goes through
293 __fxprintf_nocancel when compiled as part of glibc. */
294 fprintf (stderr, fmt: "\n");
295 funlockfile (stderr);
296 }
297 }
298 if (ambig_malloced)
299 free (ptr: ambig_set);
300 d->__nextchar += strlen (d->__nextchar);
301 d->optind++;
302 d->optopt = 0;
303 return '?';
304 }
305
306 option_index = indfound;
307 }
308
309 if (pfound == NULL)
310 {
311 /* Can't find it as a long option. If this is not getopt_long_only,
312 or the option starts with '--' or is not a valid short option,
313 then it's an error. */
314 if (!long_only || argv[d->optind][1] == '-'
315 || strchr (optstring, *d->__nextchar) == NULL)
316 {
317 if (print_errors)
318 fprintf (stderr, _("%s: unrecognized option '%s%s'\n"),
319 argv[0], prefix, d->__nextchar);
320
321 d->__nextchar = NULL;
322 d->optind++;
323 d->optopt = 0;
324 return '?';
325 }
326
327 /* Otherwise interpret it as a short option. */
328 return -1;
329 }
330
331 /* We have found a matching long option. Consume it. */
332 d->optind++;
333 d->__nextchar = NULL;
334 if (*nameend)
335 {
336 /* Don't test has_arg with >, because some C compilers don't
337 allow it to be used on enums. */
338 if (pfound->has_arg)
339 d->optarg = nameend + 1;
340 else
341 {
342 if (print_errors)
343 fprintf (stderr,
344 _("%s: option '%s%s' doesn't allow an argument\n"),
345 argv[0], prefix, pfound->name);
346
347 d->optopt = pfound->val;
348 return '?';
349 }
350 }
351 else if (pfound->has_arg == 1)
352 {
353 if (d->optind < argc)
354 d->optarg = argv[d->optind++];
355 else
356 {
357 if (print_errors)
358 fprintf (stderr,
359 _("%s: option '%s%s' requires an argument\n"),
360 argv[0], prefix, pfound->name);
361
362 d->optopt = pfound->val;
363 return optstring[0] == ':' ? ':' : '?';
364 }
365 }
366
367 if (longind != NULL)
368 *longind = option_index;
369 if (pfound->flag)
370 {
371 *(pfound->flag) = pfound->val;
372 return 0;
373 }
374 return pfound->val;
375}
376
377/* Initialize internal data upon the first call to getopt. */
378
379static const char *
380_getopt_initialize (int argc _GL_UNUSED,
381 char **argv _GL_UNUSED, const char *optstring,
382 struct _getopt_data *d, int posixly_correct)
383{
384 /* Start processing options with ARGV-element 1 (since ARGV-element 0
385 is the program name); the sequence of previously skipped
386 non-option ARGV-elements is empty. */
387 if (d->optind == 0)
388 d->optind = 1;
389
390 d->__first_nonopt = d->__last_nonopt = d->optind;
391 d->__nextchar = NULL;
392
393 /* Determine how to handle the ordering of options and nonoptions. */
394 if (optstring[0] == '-')
395 {
396 d->__ordering = RETURN_IN_ORDER;
397 ++optstring;
398 }
399 else if (optstring[0] == '+')
400 {
401 d->__ordering = REQUIRE_ORDER;
402 ++optstring;
403 }
404 else if (posixly_correct || !!getenv ("POSIXLY_CORRECT"))
405 d->__ordering = REQUIRE_ORDER;
406 else
407 d->__ordering = PERMUTE;
408
409 d->__initialized = 1;
410 return optstring;
411}
412
413/* Scan elements of ARGV (whose length is ARGC) for option characters
414 given in OPTSTRING.
415
416 If an element of ARGV starts with '-', and is not exactly "-" or "--",
417 then it is an option element. The characters of this element
418 (aside from the initial '-') are option characters. If 'getopt'
419 is called repeatedly, it returns successively each of the option characters
420 from each of the option elements.
421
422 If 'getopt' finds another option character, it returns that character,
423 updating 'optind' and 'nextchar' so that the next call to 'getopt' can
424 resume the scan with the following option character or ARGV-element.
425
426 If there are no more option characters, 'getopt' returns -1.
427 Then 'optind' is the index in ARGV of the first ARGV-element
428 that is not an option. (The ARGV-elements have been permuted
429 so that those that are not options now come last.)
430
431 OPTSTRING is a string containing the legitimate option characters.
432 If an option character is seen that is not listed in OPTSTRING,
433 return '?' after printing an error message. If you set 'opterr' to
434 zero, the error message is suppressed but we still return '?'.
435
436 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
437 so the following text in the same ARGV-element, or the text of the following
438 ARGV-element, is returned in 'optarg'. Two colons mean an option that
439 wants an optional arg; if there is text in the current ARGV-element,
440 it is returned in 'optarg', otherwise 'optarg' is set to zero.
441
442 If OPTSTRING starts with '-' or '+', it requests different methods of
443 handling the non-option ARGV-elements.
444 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
445
446 Long-named options begin with '--' instead of '-'.
447 Their names may be abbreviated as long as the abbreviation is unique
448 or is an exact match for some defined option. If they have an
449 argument, it follows the option name in the same ARGV-element, separated
450 from the option name by a '=', or else the in next ARGV-element.
451 When 'getopt' finds a long-named option, it returns 0 if that option's
452 'flag' field is nonzero, the value of the option's 'val' field
453 if the 'flag' field is zero.
454
455 The elements of ARGV aren't really const, because we permute them.
456 But we pretend they're const in the prototype to be compatible
457 with other systems.
458
459 LONGOPTS is a vector of 'struct option' terminated by an
460 element containing a name which is zero.
461
462 LONGIND returns the index in LONGOPT of the long-named option found.
463 It is only valid when a long-named option has been found by the most
464 recent call.
465
466 If LONG_ONLY is nonzero, '-' as well as '--' can introduce
467 long-named options. */
468
469int
470_getopt_internal_r (int argc, char **argv, const char *optstring,
471 const struct option *longopts, int *longind,
472 int long_only, struct _getopt_data *d, int posixly_correct)
473{
474 int print_errors = d->opterr;
475
476 if (argc < 1)
477 return -1;
478
479 d->optarg = NULL;
480
481 if (d->optind == 0 || !d->__initialized)
482 optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct);
483 else if (optstring[0] == '-' || optstring[0] == '+')
484 optstring++;
485
486 if (optstring[0] == ':')
487 print_errors = 0;
488
489 /* Test whether ARGV[optind] points to a non-option argument. */
490#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
491
492 if (d->__nextchar == NULL || *d->__nextchar == '\0')
493 {
494 /* Advance to the next ARGV-element. */
495
496 /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
497 moved back by the user (who may also have changed the arguments). */
498 if (d->__last_nonopt > d->optind)
499 d->__last_nonopt = d->optind;
500 if (d->__first_nonopt > d->optind)
501 d->__first_nonopt = d->optind;
502
503 if (d->__ordering == PERMUTE)
504 {
505 /* If we have just processed some options following some non-options,
506 exchange them so that the options come first. */
507
508 if (d->__first_nonopt != d->__last_nonopt
509 && d->__last_nonopt != d->optind)
510 exchange (argv, d);
511 else if (d->__last_nonopt != d->optind)
512 d->__first_nonopt = d->optind;
513
514 /* Skip any additional non-options
515 and extend the range of non-options previously skipped. */
516
517 while (d->optind < argc && NONOPTION_P)
518 d->optind++;
519 d->__last_nonopt = d->optind;
520 }
521
522 /* The special ARGV-element '--' means premature end of options.
523 Skip it like a null option,
524 then exchange with previous non-options as if it were an option,
525 then skip everything else like a non-option. */
526
527 if (d->optind != argc && !strcmp (argv[d->optind], "--"))
528 {
529 d->optind++;
530
531 if (d->__first_nonopt != d->__last_nonopt
532 && d->__last_nonopt != d->optind)
533 exchange (argv, d);
534 else if (d->__first_nonopt == d->__last_nonopt)
535 d->__first_nonopt = d->optind;
536 d->__last_nonopt = argc;
537
538 d->optind = argc;
539 }
540
541 /* If we have done all the ARGV-elements, stop the scan
542 and back over any non-options that we skipped and permuted. */
543
544 if (d->optind == argc)
545 {
546 /* Set the next-arg-index to point at the non-options
547 that we previously skipped, so the caller will digest them. */
548 if (d->__first_nonopt != d->__last_nonopt)
549 d->optind = d->__first_nonopt;
550 return -1;
551 }
552
553 /* If we have come to a non-option and did not permute it,
554 either stop the scan or describe it to the caller and pass it by. */
555
556 if (NONOPTION_P)
557 {
558 if (d->__ordering == REQUIRE_ORDER)
559 return -1;
560 d->optarg = argv[d->optind++];
561 return 1;
562 }
563
564 /* We have found another option-ARGV-element.
565 Check whether it might be a long option. */
566 if (longopts)
567 {
568 if (argv[d->optind][1] == '-')
569 {
570 /* "--foo" is always a long option. The special option
571 "--" was handled above. */
572 d->__nextchar = argv[d->optind] + 2;
573 return process_long_option (argc, argv, optstring, longopts,
574 longind, long_only, d,
575 print_errors, prefix: "--");
576 }
577
578 /* If long_only and the ARGV-element has the form "-f",
579 where f is a valid short option, don't consider it an
580 abbreviated form of a long option that starts with f.
581 Otherwise there would be no way to give the -f short
582 option.
583
584 On the other hand, if there's a long option "fubar" and
585 the ARGV-element is "-fu", do consider that an
586 abbreviation of the long option, just like "--fu", and
587 not "-f" with arg "u".
588
589 This distinction seems to be the most useful approach. */
590 if (long_only && (argv[d->optind][2]
591 || !strchr (optstring, argv[d->optind][1])))
592 {
593 int code;
594 d->__nextchar = argv[d->optind] + 1;
595 code = process_long_option (argc, argv, optstring, longopts,
596 longind, long_only, d,
597 print_errors, prefix: "-");
598 if (code != -1)
599 return code;
600 }
601 }
602
603 /* It is not a long option. Skip the initial punctuation. */
604 d->__nextchar = argv[d->optind] + 1;
605 }
606
607 /* Look at and handle the next short option-character. */
608
609 {
610 char c = *d->__nextchar++;
611 const char *temp = strchr (optstring, c);
612
613 /* Increment 'optind' when we start to process its last character. */
614 if (*d->__nextchar == '\0')
615 ++d->optind;
616
617 if (temp == NULL || c == ':' || c == ';')
618 {
619 if (print_errors)
620 fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
621 d->optopt = c;
622 return '?';
623 }
624
625 /* Convenience. Treat POSIX -W foo same as long option --foo */
626 if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL)
627 {
628 /* This is an option that requires an argument. */
629 if (*d->__nextchar != '\0')
630 d->optarg = d->__nextchar;
631 else if (d->optind == argc)
632 {
633 if (print_errors)
634 fprintf (stderr,
635 _("%s: option requires an argument -- '%c'\n"),
636 argv[0], c);
637
638 d->optopt = c;
639 if (optstring[0] == ':')
640 c = ':';
641 else
642 c = '?';
643 return c;
644 }
645 else
646 d->optarg = argv[d->optind];
647
648 d->__nextchar = d->optarg;
649 d->optarg = NULL;
650 return process_long_option (argc, argv, optstring, longopts, longind,
651 long_only: 0 /* long_only */, d, print_errors, prefix: "-W ");
652 }
653 if (temp[1] == ':')
654 {
655 if (temp[2] == ':')
656 {
657 /* This is an option that accepts an argument optionally. */
658 if (*d->__nextchar != '\0')
659 {
660 d->optarg = d->__nextchar;
661 d->optind++;
662 }
663 else
664 d->optarg = NULL;
665 d->__nextchar = NULL;
666 }
667 else
668 {
669 /* This is an option that requires an argument. */
670 if (*d->__nextchar != '\0')
671 {
672 d->optarg = d->__nextchar;
673 /* If we end this ARGV-element by taking the rest as an arg,
674 we must advance to the next element now. */
675 d->optind++;
676 }
677 else if (d->optind == argc)
678 {
679 if (print_errors)
680 fprintf (stderr,
681 _("%s: option requires an argument -- '%c'\n"),
682 argv[0], c);
683
684 d->optopt = c;
685 if (optstring[0] == ':')
686 c = ':';
687 else
688 c = '?';
689 }
690 else
691 /* We already incremented 'optind' once;
692 increment it again when taking next ARGV-elt as argument. */
693 d->optarg = argv[d->optind++];
694 d->__nextchar = NULL;
695 }
696 }
697 return c;
698 }
699}
700
701int
702_getopt_internal (int argc, char **argv, const char *optstring,
703 const struct option *longopts, int *longind, int long_only,
704 int posixly_correct)
705{
706 int result;
707
708 getopt_data.optind = optind;
709 getopt_data.opterr = opterr;
710
711 result = _getopt_internal_r (argc, argv, optstring, longopts,
712 longind, long_only, d: &getopt_data,
713 posixly_correct);
714
715 optind = getopt_data.optind;
716 optarg = getopt_data.optarg;
717 optopt = getopt_data.optopt;
718
719 return result;
720}
721
722/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt.
723 Standalone applications just get a POSIX-compliant getopt.
724 POSIX and LSB both require these functions to take 'char *const *argv'
725 even though this is incorrect (because of the permutation). */
726#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \
727 int \
728 NAME (int argc, char *const *argv, const char *optstring) \
729 { \
730 return _getopt_internal (argc, (char **)argv, optstring, \
731 0, 0, 0, POSIXLY_CORRECT); \
732 }
733
734#ifdef _LIBC
735GETOPT_ENTRY(getopt, 0)
736GETOPT_ENTRY(__posix_getopt, 1)
737#else
738GETOPT_ENTRY(getopt, 1)
739#endif
740
741
742#ifdef TEST
743
744/* Compile with -DTEST to make an executable for use in testing
745 the above definition of 'getopt'. */
746
747int
748main (int argc, char **argv)
749{
750 int c;
751 int digit_optind = 0;
752
753 while (1)
754 {
755 int this_option_optind = optind ? optind : 1;
756
757 c = getopt (argc, argv, "abc:d:0123456789");
758 if (c == -1)
759 break;
760
761 switch (c)
762 {
763 case '0':
764 case '1':
765 case '2':
766 case '3':
767 case '4':
768 case '5':
769 case '6':
770 case '7':
771 case '8':
772 case '9':
773 if (digit_optind != 0 && digit_optind != this_option_optind)
774 printf ("digits occur in two different argv-elements.\n");
775 digit_optind = this_option_optind;
776 printf ("option %c\n", c);
777 break;
778
779 case 'a':
780 printf ("option a\n");
781 break;
782
783 case 'b':
784 printf ("option b\n");
785 break;
786
787 case 'c':
788 printf ("option c with value '%s'\n", optarg);
789 break;
790
791 case '?':
792 break;
793
794 default:
795 printf ("?? getopt returned character code 0%o ??\n", c);
796 }
797 }
798
799 if (optind < argc)
800 {
801 printf ("non-option ARGV-elements: ");
802 while (optind < argc)
803 printf ("%s ", argv[optind++]);
804 printf ("\n");
805 }
806
807 exit (0);
808}
809
810#endif /* TEST */
811

source code of glibc/posix/getopt.c