1 #include "config.h"
2 #ifdef NO_GETOPT_LONG
3 
4 /* Added by JZ purely for warning suppression, because this getopt_long
5  * violates const.  *sigh*
6  */
remove_const_char_ptr_ptr(char * const * x)7 static char **remove_const_char_ptr_ptr(char * const* x)
8 {
9     union {
10         char * const* before;
11         char *      * after;
12     } pun;
13 
14     pun.before = x;
15     return pun.after;
16 }
17 
18 /* Getopt for GNU.
19    NOTE: getopt is now part of the C library, so if you don't know what
20    "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
21    before changing it!
22 
23    Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
24         Free Software Foundation, Inc.
25 
26    This program is free software; you can redistribute it and/or modify it
27    under the terms of the GNU General Public License as published by the
28    Free Software Foundation; either version 2, or (at your option) any
29    later version.
30 
31    This program is distributed in the hope that it will be useful,
32    but WITHOUT ANY WARRANTY; without even the implied warranty of
33    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34    GNU General Public License for more details.
35 
36    You should have received a copy of the GNU General Public License along
37    with this program; if not, write to the Free Software Foundation, Inc.,
38    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.  */
39 
40 #if !defined(__STDC__) && !defined(__cplusplus)
41 #  ifndef const
42 #    define const
43 #  endif
44 #endif
45 
46 #include <stdio.h>
47 
48 /* Comment out all this code if we are using the GNU C Library, and are not
49    actually compiling the library itself.  This code is part of the GNU C
50    Library, but also included in many other GNU distributions.  Compiling
51    and linking in this code is a waste when using the GNU C library
52    (especially if it is a shared library).  Rather than having every GNU
53    program understand `configure --with-gnu-libc' and omit the object files,
54    it is simpler to just do this in the source for each such file.  */
55 
56 #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
57 
58 
59 /* This needs to come after some library #include
60    to get __GNU_LIBRARY__ defined.  */
61 #ifdef  __GNU_LIBRARY__
62 /* Don't include stdlib.h for non-GNU C libraries because some of them
63    contain conflicting prototypes for getopt.  */
64 #include <stdlib.h>
65 #endif  /* GNU C library.  */
66 
67 /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
68    long-named option.  Because this is not POSIX.2 compliant, it is
69    being phased out.  */
70 /* #define GETOPT_COMPAT */
71 
72 /* This version of `getopt' appears to the caller like standard Unix `getopt'
73    but it behaves differently for the user, since it allows the user
74    to intersperse the options with the other arguments.
75 
76    As `getopt' works, it permutes the elements of ARGV so that,
77    when it is done, all the options precede everything else.  Thus
78    all application programs are extended to handle flexible argument order.
79 
80    Setting the environment variable POSIXLY_CORRECT disables permutation.
81    Then the behavior is completely standard.
82 
83    GNU application programs can use a third alternative mode in which
84    they can distinguish the relative order of options and other arguments.  */
85 
86 #include "plat/gnu_getopt.h"
87 
88 /* For communication from `getopt' to the caller.
89    When `getopt' finds an option that takes an argument,
90    the argument value is returned here.
91    Also, when `ordering' is RETURN_IN_ORDER,
92    each non-option ARGV-element is returned here.  */
93 
94 char *optarg = 0;
95 
96 /* Index in ARGV of the next element to be scanned.
97    This is used for communication to and from the caller
98    and for communication between successive calls to `getopt'.
99 
100    On entry to `getopt', zero means this is the first call; initialize.
101 
102    When `getopt' returns EOF, this is the index of the first of the
103    non-option elements that the caller should itself scan.
104 
105    Otherwise, `optind' communicates from one call to the next
106    how much of ARGV has been scanned so far.  */
107 
108 /* XXX 1003.2 says this must be 1 before any call.  */
109 int optind = 0;
110 
111 /* The next char to be scanned in the option-element
112    in which the last option character we returned was found.
113    This allows us to pick up the scan where we left off.
114 
115    If this is zero, or a null string, it means resume the scan
116    by advancing to the next ARGV-element.  */
117 
118 static char *nextchar;
119 
120 /* Callers store zero here to inhibit the error message
121    for unrecognized options.  */
122 
123 int opterr = 1;
124 
125 /* Set to an option character which was unrecognized.
126    This must be initialized on some systems to avoid linking in the
127    system's own getopt implementation.  */
128 
129 #define BAD_OPTION '\0'
130 int optopt = BAD_OPTION;
131 
132 /* Describe how to deal with options that follow non-option ARGV-elements.
133 
134    If the caller did not specify anything,
135    the default is REQUIRE_ORDER if the environment variable
136    POSIXLY_CORRECT is defined, PERMUTE otherwise.
137 
138    REQUIRE_ORDER means don't recognize them as options;
139    stop option processing when the first non-option is seen.
140    This is what Unix does.
141    This mode of operation is selected by either setting the environment
142    variable POSIXLY_CORRECT, or using `+' as the first character
143    of the list of option characters.
144 
145    PERMUTE is the default.  We permute the contents of ARGV as we scan,
146    so that eventually all the non-options are at the end.  This allows options
147    to be given in any order, even with programs that were not written to
148    expect this.
149 
150    RETURN_IN_ORDER is an option available to programs that were written
151    to expect options and other ARGV-elements in any order and that care about
152    the ordering of the two.  We describe each non-option ARGV-element
153    as if it were the argument of an option with character code 1.
154    Using `-' as the first character of the list of option characters
155    selects this mode of operation.
156 
157    The special argument `--' forces an end of option-scanning regardless
158    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
159    `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
160 
161 static enum
162 {
163   REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
164 } ordering;
165 
166 
167 #if 1 /* DISABLE THIS MAGIC TO WORK WITH MINGW32 */
168 #include <string.h>
169 #define my_index        strchr
170 #define my_strlen       strlen
171 #else
172 #ifdef  __GNU_LIBRARY__
173 /* We want to avoid inclusion of string.h with non-GNU libraries
174    because there are many ways it can cause trouble.
175    On some systems, it contains special magic macros that don't work
176    in GCC.  */
177 #include <string.h>
178 #define my_index        strchr
179 #define my_strlen       strlen
180 #else
181 
182 /* Avoid depending on library functions or files
183    whose names are inconsistent.  */
184 
185 #if __STDC__ || defined(PROTO) || defined(__cplusplus)
186 extern char *getenv(const char *name);
187 extern int  strcmp (const char *s1, const char *s2);
188 extern int  strncmp(const char *s1, const char *s2, int n);
189 
190 static int my_strlen(const char *s);
191 static char *my_index (const char *str, int chr);
192 #else
193 extern char *getenv ();
194 #endif
195 
196 static int
my_strlen(str)197 my_strlen (str)
198      const char *str;
199 {
200   int n = 0;
201   while (*str++)
202     n++;
203   return n;
204 }
205 
206 static char *
my_index(str,chr)207 my_index (str, chr)
208      const char *str;
209      int chr;
210 {
211   while (*str)
212     {
213       if (*str == chr)
214         return (char *) str;
215       str++;
216     }
217   return 0;
218 }
219 
220 #endif                          /* GNU C library.  */
221 #endif /* DISABLED MAGIC */
222 
223 /* Handle permutation of arguments.  */
224 
225 /* Describe the part of ARGV that contains non-options that have
226    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
227    `last_nonopt' is the index after the last of them.  */
228 
229 static int first_nonopt;
230 static int last_nonopt;
231 
232 /* Exchange two adjacent subsequences of ARGV.
233    One subsequence is elements [first_nonopt,last_nonopt)
234    which contains all the non-options that have been skipped so far.
235    The other is elements [last_nonopt,optind), which contains all
236    the options processed since those non-options were skipped.
237 
238    `first_nonopt' and `last_nonopt' are relocated so that they describe
239    the new indices of the non-options in ARGV after they are moved.
240 
241    To perform the swap, we first reverse the order of all elements. So
242    all options now come before all non options, but they are in the
243    wrong order. So we put back the options and non options in original
244    order by reversing them again. For example:
245        original input:      a b c -x -y
246        reverse all:         -y -x c b a
247        reverse options:     -x -y c b a
248        reverse non options: -x -y a b c
249 */
250 
251 #if __STDC__ || defined(PROTO) || defined(__cplusplus)
252 static void exchange (char **argv);
253 #endif
254 
exchange(char ** argv)255 static void exchange (char **argv)
256 {
257   char *temp, **first, **last;
258 
259   /* Reverse all the elements [first_nonopt, optind) */
260   first = &argv[first_nonopt];
261   last  = &argv[optind-1];
262   while (first < last) {
263     temp = *first; *first = *last; *last = temp; first++; last--;
264   }
265   /* Put back the options in order */
266   first = &argv[first_nonopt];
267   first_nonopt += (optind - last_nonopt);
268   last  = &argv[first_nonopt - 1];
269   while (first < last) {
270     temp = *first; *first = *last; *last = temp; first++; last--;
271   }
272 
273   /* Put back the non options in order */
274   first = &argv[first_nonopt];
275   last_nonopt = optind;
276   last  = &argv[last_nonopt-1];
277   while (first < last) {
278     temp = *first; *first = *last; *last = temp; first++; last--;
279   }
280 }
281 
282 /* Scan elements of ARGV (whose length is ARGC) for option characters
283    given in OPTSTRING.
284 
285    If an element of ARGV starts with '-', and is not exactly "-" or "--",
286    then it is an option element.  The characters of this element
287    (aside from the initial '-') are option characters.  If `getopt'
288    is called repeatedly, it returns successively each of the option characters
289    from each of the option elements.
290 
291    If `getopt' finds another option character, it returns that character,
292    updating `optind' and `nextchar' so that the next call to `getopt' can
293    resume the scan with the following option character or ARGV-element.
294 
295    If there are no more option characters, `getopt' returns `EOF'.
296    Then `optind' is the index in ARGV of the first ARGV-element
297    that is not an option.  (The ARGV-elements have been permuted
298    so that those that are not options now come last.)
299 
300    OPTSTRING is a string containing the legitimate option characters.
301    If an option character is seen that is not listed in OPTSTRING,
302    return BAD_OPTION after printing an error message.  If you set `opterr' to
303    zero, the error message is suppressed but we still return BAD_OPTION.
304 
305    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
306    so the following text in the same ARGV-element, or the text of the following
307    ARGV-element, is returned in `optarg'.  Two colons mean an option that
308    wants an optional arg; if there is text in the current ARGV-element,
309    it is returned in `optarg', otherwise `optarg' is set to zero.
310 
311    If OPTSTRING starts with `-' or `+', it requests different methods of
312    handling the non-option ARGV-elements.
313    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
314 
315    Long-named options begin with `--' instead of `-'.
316    Their names may be abbreviated as long as the abbreviation is unique
317    or is an exact match for some defined option.  If they have an
318    argument, it follows the option name in the same ARGV-element, separated
319    from the option name by a `=', or else the in next ARGV-element.
320    When `getopt' finds a long-named option, it returns 0 if that option's
321    `flag' field is nonzero, the value of the option's `val' field
322    if the `flag' field is zero.
323 
324    The elements of ARGV aren't really const, because we permute them.
325    But we pretend they're const in the prototype to be compatible
326    with other systems.
327 
328    LONGOPTS is a vector of `struct option' terminated by an
329    element containing a name which is zero.
330 
331    LONGIND returns the index in LONGOPT of the long-named option found.
332    It is only valid when a long-named option has been found by the most
333    recent call.
334 
335    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
336    long-named options.  */
337 
338 int
_getopt_internal(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,int long_only)339 _getopt_internal (int argc, char *const *argv, const char *optstring,
340                   const struct option *longopts, int *longind, int long_only)
341 {
342   int option_index;
343 
344   optarg = 0;
345 
346   /* Initialize the internal data when the first call is made.
347      Start processing options with ARGV-element 1 (since ARGV-element 0
348      is the program name); the sequence of previously skipped
349      non-option ARGV-elements is empty.  */
350 
351   if (optind == 0)
352     {
353       first_nonopt = last_nonopt = optind = 1;
354 
355       nextchar = NULL;
356 
357       /* Determine how to handle the ordering of options and nonoptions.  */
358 
359       if (optstring[0] == '-')
360         {
361           ordering = RETURN_IN_ORDER;
362           ++optstring;
363         }
364       else if (optstring[0] == '+')
365         {
366           ordering = REQUIRE_ORDER;
367           ++optstring;
368         }
369       else if (getenv ("POSIXLY_CORRECT") != NULL)
370         ordering = REQUIRE_ORDER;
371       else
372         ordering = PERMUTE;
373     }
374 
375   if (nextchar == NULL || *nextchar == '\0')
376     {
377       if (ordering == PERMUTE)
378         {
379           /* If we have just processed some options following some non-options,
380              exchange them so that the options come first.  */
381 
382           if (first_nonopt != last_nonopt && last_nonopt != optind)
383             exchange (remove_const_char_ptr_ptr(argv));
384           else if (last_nonopt != optind)
385             first_nonopt = optind;
386 
387           /* Now skip any additional non-options
388              and extend the range of non-options previously skipped.  */
389 
390           while (optind < argc
391                  && (argv[optind][0] != '-' || argv[optind][1] == '\0')
392 #ifdef GETOPT_COMPAT
393                  && (longopts == NULL
394                      || argv[optind][0] != '+' || argv[optind][1] == '\0')
395 #endif                          /* GETOPT_COMPAT */
396                  )
397             optind++;
398           last_nonopt = optind;
399         }
400 
401       /* Special ARGV-element `--' means premature end of options.
402          Skip it like a null option,
403          then exchange with previous non-options as if it were an option,
404          then skip everything else like a non-option.  */
405 
406       if (optind != argc && !strcmp (argv[optind], "--"))
407         {
408           optind++;
409 
410           if (first_nonopt != last_nonopt && last_nonopt != optind)
411             exchange (remove_const_char_ptr_ptr(argv));
412           else if (first_nonopt == last_nonopt)
413             first_nonopt = optind;
414           last_nonopt = argc;
415 
416           optind = argc;
417         }
418 
419       /* If we have done all the ARGV-elements, stop the scan
420          and back over any non-options that we skipped and permuted.  */
421 
422       if (optind == argc)
423         {
424           /* Set the next-arg-index to point at the non-options
425              that we previously skipped, so the caller will digest them.  */
426           if (first_nonopt != last_nonopt)
427             optind = first_nonopt;
428           return EOF;
429         }
430 
431       /* If we have come to a non-option and did not permute it,
432          either stop the scan or describe it to the caller and pass it by.  */
433 
434       if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
435 #ifdef GETOPT_COMPAT
436           && (longopts == NULL
437               || argv[optind][0] != '+' || argv[optind][1] == '\0')
438 #endif                          /* GETOPT_COMPAT */
439           )
440         {
441           if (ordering == REQUIRE_ORDER)
442             return EOF;
443           optarg = argv[optind++];
444           return 1;
445         }
446 
447       /* We have found another option-ARGV-element.
448          Start decoding its characters.  */
449 
450       nextchar = (argv[optind] + 1
451                   + (longopts != NULL && argv[optind][1] == '-'));
452     }
453 
454   if (longopts != NULL
455       && ((argv[optind][0] == '-'
456            && (argv[optind][1] == '-' || long_only))
457 #ifdef GETOPT_COMPAT
458           || argv[optind][0] == '+'
459 #endif                          /* GETOPT_COMPAT */
460           ))
461     {
462       const struct option *p;
463       char *s = nextchar;
464       int exact = 0;
465       int ambig = 0;
466       const struct option *pfound = NULL;
467       int indfound = 0;
468 
469       while (*s && *s != '=')
470         s++;
471 
472       /* Test all options for either exact match or abbreviated matches.  */
473       for (p = longopts, option_index = 0; p->name;
474            p++, option_index++)
475         if (!strncmp (p->name, nextchar, s - nextchar))
476           {
477             if (s - nextchar == (int)my_strlen (p->name))
478               {
479                 /* Exact match found.  */
480                 pfound = p;
481                 indfound = option_index;
482                 exact = 1;
483                 break;
484               }
485             else if (pfound == NULL)
486               {
487                 /* First nonexact match found.  */
488                 pfound = p;
489                 indfound = option_index;
490               }
491             else
492               /* Second nonexact match found.  */
493               ambig = 1;
494           }
495 
496       if (ambig && !exact)
497         {
498           if (opterr)
499             fprintf (stderr, "%s: option `%s' is ambiguous\n",
500                      argv[0], argv[optind]);
501           nextchar += my_strlen (nextchar);
502           optind++;
503           return BAD_OPTION;
504         }
505 
506       if (pfound != NULL)
507         {
508           option_index = indfound;
509           optind++;
510           if (*s)
511             {
512               /* Don't test has_arg with >, because some C compilers don't
513                  allow it to be used on enums.  */
514               if (pfound->has_arg)
515                 optarg = s + 1;
516               else
517                 {
518                   if (opterr)
519                     {
520                       if (argv[optind - 1][1] == '-')
521                         /* --option */
522                         fprintf (stderr,
523                                  "%s: option `--%s' doesn't allow an argument\n",
524                                  argv[0], pfound->name);
525                       else
526                         /* +option or -option */
527                         fprintf (stderr,
528                              "%s: option `%c%s' doesn't allow an argument\n",
529                              argv[0], argv[optind - 1][0], pfound->name);
530                     }
531                   nextchar += my_strlen (nextchar);
532                   return BAD_OPTION;
533                 }
534             }
535           else if (pfound->has_arg == 1)
536             {
537               if (optind < argc)
538                 optarg = argv[optind++];
539               else
540                 {
541                   if (opterr)
542                     fprintf (stderr, "%s: option `%s' requires an argument\n",
543                              argv[0], argv[optind - 1]);
544                   nextchar += my_strlen (nextchar);
545                   return optstring[0] == ':' ? ':' : BAD_OPTION;
546                 }
547             }
548           nextchar += my_strlen (nextchar);
549           if (longind != NULL)
550             *longind = option_index;
551           if (pfound->flag)
552             {
553               *(pfound->flag) = pfound->val;
554               return 0;
555             }
556           return pfound->val;
557         }
558       /* Can't find it as a long option.  If this is not getopt_long_only,
559          or the option starts with '--' or is not a valid short
560          option, then it's an error.
561          Otherwise interpret it as a short option.  */
562       if (!long_only || argv[optind][1] == '-'
563 #ifdef GETOPT_COMPAT
564           || argv[optind][0] == '+'
565 #endif                          /* GETOPT_COMPAT */
566           || my_index (optstring, *nextchar) == NULL)
567         {
568           if (opterr)
569             {
570               if (argv[optind][1] == '-')
571                 /* --option */
572                 fprintf (stderr, "%s: unrecognized option `--%s'\n",
573                          argv[0], nextchar);
574               else
575                 /* +option or -option */
576                 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
577                          argv[0], argv[optind][0], nextchar);
578             }
579           nextchar = (char *) "";
580           optind++;
581           return BAD_OPTION;
582         }
583     }
584 
585   /* Look at and handle the next option-character.  */
586 
587   {
588     char c = *nextchar++;
589     const char *temp = my_index (optstring, c);
590 
591     /* Increment `optind' when we start to process its last character.  */
592     if (*nextchar == '\0')
593       ++optind;
594 
595     if (temp == NULL || c == ':')
596       {
597         if (opterr)
598           {
599 #if 0
600             if (c < 040 || c >= 0177)
601               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
602                        argv[0], c);
603             else
604               fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
605 #else
606             /* 1003.2 specifies the format of this message.  */
607             fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
608 #endif
609           }
610         optopt = c;
611         return BAD_OPTION;
612       }
613     if (temp[1] == ':')
614       {
615         if (temp[2] == ':')
616           {
617             /* This is an option that accepts an argument optionally.  */
618             if (*nextchar != '\0')
619               {
620                 optarg = nextchar;
621                 optind++;
622               }
623             else
624               optarg = 0;
625             nextchar = NULL;
626           }
627         else
628           {
629             /* This is an option that requires an argument.  */
630             if (*nextchar != '\0')
631               {
632                 optarg = nextchar;
633                 /* If we end this ARGV-element by taking the rest as an arg,
634                    we must advance to the next element now.  */
635                 optind++;
636               }
637             else if (optind == argc)
638               {
639                 if (opterr)
640                   {
641 #if 0
642                     fprintf (stderr, "%s: option `-%c' requires an argument\n",
643                              argv[0], c);
644 #else
645                     /* 1003.2 specifies the format of this message.  */
646                     fprintf (stderr, "%s: option requires an argument -- %c\n",
647                              argv[0], c);
648 #endif
649                   }
650                 optopt = c;
651                 if (optstring[0] == ':')
652                   c = ':';
653                 else
654                   c = BAD_OPTION;
655               }
656             else
657               /* We already incremented `optind' once;
658                  increment it again when taking next ARGV-elt as argument.  */
659               optarg = argv[optind++];
660             nextchar = NULL;
661           }
662       }
663     return c;
664   }
665 }
666 
667 int
getopt(int argc,char * const * argv,const char * optstring)668 getopt (int argc, char *const *argv, const char *optstring)
669 {
670   return _getopt_internal (argc, argv, optstring,
671                            (const struct option *) 0,
672                            (int *) 0,
673                            0);
674 }
675 
676 int
getopt_long(int argc,char * const * argv,const char * options,const struct option * long_options,int * opt_index)677 getopt_long (int argc, char * const *argv, const char *options,
678              const struct option *long_options, int *opt_index)
679 {
680   return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
681 }
682 
683 #endif  /* _LIBC or not __GNU_LIBRARY__.  */
684 
685 #ifdef TEST
686 
687 /* Compile with -DTEST to make an executable for use in testing
688    the above definition of `getopt'.  */
689 
690 int
main(argc,argv)691 main (argc, argv)
692      int argc;
693      char **argv;
694 {
695   int c;
696   int digit_optind = 0;
697 
698   while (1)
699     {
700       int this_option_optind = optind ? optind : 1;
701 
702       c = getopt (argc, argv, "abc:d:0123456789");
703       if (c == EOF)
704         break;
705 
706       switch (c)
707         {
708         case '0':
709         case '1':
710         case '2':
711         case '3':
712         case '4':
713         case '5':
714         case '6':
715         case '7':
716         case '8':
717         case '9':
718           if (digit_optind != 0 && digit_optind != this_option_optind)
719             printf ("digits occur in two different argv-elements.\n");
720           digit_optind = this_option_optind;
721           printf ("option %c\n", c);
722           break;
723 
724         case 'a':
725           printf ("option a\n");
726           break;
727 
728         case 'b':
729           printf ("option b\n");
730           break;
731 
732         case 'c':
733           printf ("option c with value `%s'\n", optarg);
734           break;
735 
736         case BAD_OPTION:
737           break;
738 
739         default:
740           printf ("?? getopt returned character code 0%o ??\n", c);
741         }
742     }
743 
744   if (optind < argc)
745     {
746       printf ("non-option ARGV-elements: ");
747       while (optind < argc)
748         printf ("%s ", argv[optind++]);
749       printf ("\n");
750     }
751 
752   exit (0);
753 }
754 
755 #endif /* TEST */
756 
757 #else
758 
759 /* ======================================================================== */
760 /*  The following variable definition is present to keep certain over-anal  */
761 /*  compilers from complaining that the translation unit contained no       */
762 /*  actual definitions.                                                     */
763 /* ======================================================================== */
764 
765 int gnu_getopt_ = 0;
766 
767 #endif  /* NO_GETOPT_LONG */
768