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