VirtualBox

source: kBuild/trunk/src/kmk/kmkbuiltin/getopt_r.c@ 3213

Last change on this file since 3213 was 3213, checked in by bird, 6 years ago

kmk: Forked getopt and created a reentrant variant getopt_r.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use