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

source code of glibc/posix/getopt.c