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