VirtualBox

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

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

kmk: build fixes

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

© 2023 Oracle
ContactPrivacy policyTerms of Use