remove some compiler warning due to unused pinfo parameter
[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 #include <string.h>
32
33 #ifndef __STDC__
34 /* This is a separate conditional since some stdc systems
35    reject `defined (const)'.  */
36 #ifndef const
37 #define const
38 #endif
39 #endif
40
41 /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.  */
42 #ifndef _NO_PROTO
43 #define _NO_PROTO
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 "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 int optopt = '?';
130
131 /* Describe how to deal with options that follow non-option ARGV-elements.
132
133    If the caller did not specify anything,
134    the default is REQUIRE_ORDER if the environment variable
135    POSIXLY_CORRECT is defined, PERMUTE otherwise.
136
137    REQUIRE_ORDER means don't recognize them as options;
138    stop option processing when the first non-option is seen.
139    This is what Unix does.
140    This mode of operation is selected by either setting the environment
141    variable POSIXLY_CORRECT, or using `+' as the first character
142    of the list of option characters.
143
144    PERMUTE is the default.  We permute the contents of ARGV as we scan,
145    so that eventually all the non-options are at the end.  This allows options
146    to be given in any order, even with programs that were not written to
147    expect this.
148
149    RETURN_IN_ORDER is an option available to programs that were written
150    to expect options and other ARGV-elements in any order and that care about
151    the ordering of the two.  We describe each non-option ARGV-element
152    as if it were the argument of an option with character code 1.
153    Using `-' as the first character of the list of option characters
154    selects this mode of operation.
155
156    The special argument `--' forces an end of option-scanning regardless
157    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
158    `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
159
160 static enum
161 {
162   REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
163 } ordering;
164
165 #ifdef  __GNU_LIBRARY__
166 /* We want to avoid inclusion of string.h with non-GNU libraries
167    because there are many ways it can cause trouble.
168    On some systems, it contains special magic macros that don't work
169    in GCC.  */
170 #define my_index        strchr
171 #else
172
173 /* Avoid depending on library functions or files
174    whose names are inconsistent.  */
175
176 char *getenv ();
177
178 static char *
179 my_index (str, chr)
180      const char *str;
181      int chr;
182 {
183   while (*str)
184     {
185       if (*str == chr)
186         return (char *) str;
187       str++;
188     }
189   return 0;
190 }
191
192 /* If using GCC, we can safely declare strlen this way.
193    If not using GCC, it is ok not to declare it.
194    (Supposedly there are some machines where it might get a warning,
195    but changing this conditional to __STDC__ is too risky.)  */
196 #ifdef __GNUC__
197 #ifdef IN_GCC
198 #include "gstddef.h"
199 #else
200 #include <stddef.h>
201 #endif
202 extern size_t strlen (const char *);
203 #endif
204
205 #endif                          /* GNU C library.  */
206
207 /* Handle permutation of arguments.  */
208
209 /* Describe the part of ARGV that contains non-options that have
210    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
211    `last_nonopt' is the index after the last of them.  */
212
213 static int first_nonopt;
214 static int last_nonopt;
215
216 /* Exchange two adjacent subsequences of ARGV.
217    One subsequence is elements [first_nonopt,last_nonopt)
218    which contains all the non-options that have been skipped so far.
219    The other is elements [last_nonopt,optind), which contains all
220    the options processed since those non-options were skipped.
221
222    `first_nonopt' and `last_nonopt' are relocated so that they describe
223    the new indices of the non-options in ARGV after they are moved.  */
224
225 static void
226 exchange (argv)
227      char **argv;
228 {
229   int bottom = first_nonopt;
230   int middle = last_nonopt;
231   int top = optind;
232   char *tem;
233
234   /* Exchange the shorter segment with the far end of the longer segment.
235      That puts the shorter segment into the right place.
236      It leaves the longer segment in the right place overall,
237      but it consists of two parts that need to be swapped next.  */
238
239   while (top > middle && middle > bottom)
240     {
241       if (top - middle > middle - bottom)
242         {
243           /* Bottom segment is the short one.  */
244           int len = middle - bottom;
245           register int i;
246
247           /* Swap it with the top part of the top segment.  */
248           for (i = 0; i < len; i++)
249             {
250               tem = argv[bottom + i];
251               argv[bottom + i] = argv[top - (middle - bottom) + i];
252               argv[top - (middle - bottom) + i] = tem;
253             }
254           /* Exclude the moved bottom segment from further swapping.  */
255           top -= len;
256         }
257       else
258         {
259           /* Top segment is the short one.  */
260           int len = top - middle;
261           register int i;
262
263           /* Swap it with the bottom part of the bottom segment.  */
264           for (i = 0; i < len; i++)
265             {
266               tem = argv[bottom + i];
267               argv[bottom + i] = argv[middle + i];
268               argv[middle + i] = tem;
269             }
270           /* Exclude the moved top segment from further swapping.  */
271           bottom += len;
272         }
273     }
274
275   /* Update records for the slots the non-options now occupy.  */
276
277   first_nonopt += (optind - last_nonopt);
278   last_nonopt = optind;
279 }
280
281 /* Scan elements of ARGV (whose length is ARGC) for option characters
282    given in OPTSTRING.
283
284    If an element of ARGV starts with '-', and is not exactly "-" or "--",
285    then it is an option element.  The characters of this element
286    (aside from the initial '-') are option characters.  If `getopt'
287    is called repeatedly, it returns successively each of the option characters
288    from each of the option elements.
289
290    If `getopt' finds another option character, it returns that character,
291    updating `optind' and `nextchar' so that the next call to `getopt' can
292    resume the scan with the following option character or ARGV-element.
293
294    If there are no more option characters, `getopt' returns `EOF'.
295    Then `optind' is the index in ARGV of the first ARGV-element
296    that is not an option.  (The ARGV-elements have been permuted
297    so that those that are not options now come last.)
298
299    OPTSTRING is a string containing the legitimate option characters.
300    If an option character is seen that is not listed in OPTSTRING,
301    return '?' after printing an error message.  If you set `opterr' to
302    zero, the error message is suppressed but we still return '?'.
303
304    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
305    so the following text in the same ARGV-element, or the text of the following
306    ARGV-element, is returned in `optarg'.  Two colons mean an option that
307    wants an optional arg; if there is text in the current ARGV-element,
308    it is returned in `optarg', otherwise `optarg' is set to zero.
309
310    If OPTSTRING starts with `-' or `+', it requests different methods of
311    handling the non-option ARGV-elements.
312    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
313
314    Long-named options begin with `--' instead of `-'.
315    Their names may be abbreviated as long as the abbreviation is unique
316    or is an exact match for some defined option.  If they have an
317    argument, it follows the option name in the same ARGV-element, separated
318    from the option name by a `=', or else the in next ARGV-element.
319    When `getopt' finds a long-named option, it returns 0 if that option's
320    `flag' field is nonzero, the value of the option's `val' field
321    if the `flag' field is zero.
322
323    The elements of ARGV aren't really const, because we permute them.
324    But we pretend they're const in the prototype to be compatible
325    with other systems.
326
327    LONGOPTS is a vector of `struct option' terminated by an
328    element containing a name which is zero.
329
330    LONGIND returns the index in LONGOPT of the long-named option found.
331    It is only valid when a long-named option has been found by the most
332    recent call.
333
334    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
335    long-named options.  */
336
337 int
338 _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
339      int argc;
340      char *const *argv;
341      const char *optstring;
342      const struct option *longopts;
343      int *longind;
344      int long_only;
345 {
346   int option_index;
347
348   optarg = 0;
349
350   /* Initialize the internal data when the first call is made.
351      Start processing options with ARGV-element 1 (since ARGV-element 0
352      is the program name); the sequence of previously skipped
353      non-option ARGV-elements is empty.  */
354
355   if (optind == 0)
356     {
357       first_nonopt = last_nonopt = optind = 1;
358
359       nextchar = NULL;
360
361       /* Determine how to handle the ordering of options and nonoptions.  */
362
363       if (optstring[0] == '-')
364         {
365           ordering = RETURN_IN_ORDER;
366           ++optstring;
367         }
368       else if (optstring[0] == '+')
369         {
370           ordering = REQUIRE_ORDER;
371           ++optstring;
372         }
373       else if (getenv ("POSIXLY_CORRECT") != NULL)
374         ordering = REQUIRE_ORDER;
375       else
376         ordering = PERMUTE;
377     }
378
379   if (nextchar == NULL || *nextchar == '\0')
380     {
381       if (ordering == PERMUTE)
382         {
383           /* If we have just processed some options following some non-options,
384              exchange them so that the options come first.  */
385
386           if (first_nonopt != last_nonopt && last_nonopt != optind)
387             exchange ((char **) argv);
388           else if (last_nonopt != optind)
389             first_nonopt = optind;
390
391           /* Now skip any additional non-options
392              and extend the range of non-options previously skipped.  */
393
394           while (optind < argc
395                  && (argv[optind][0] != '-' || argv[optind][1] == '\0')
396 #ifdef GETOPT_COMPAT
397                  && (longopts == NULL
398                      || argv[optind][0] != '+' || argv[optind][1] == '\0')
399 #endif                          /* GETOPT_COMPAT */
400                  )
401             optind++;
402           last_nonopt = optind;
403         }
404
405       /* Special ARGV-element `--' means premature end of options.
406          Skip it like a null option,
407          then exchange with previous non-options as if it were an option,
408          then skip everything else like a non-option.  */
409
410       if (optind != argc && !strcmp (argv[optind], "--"))
411         {
412           optind++;
413
414           if (first_nonopt != last_nonopt && last_nonopt != optind)
415             exchange ((char **) argv);
416           else if (first_nonopt == last_nonopt)
417             first_nonopt = optind;
418           last_nonopt = argc;
419
420           optind = argc;
421         }
422
423       /* If we have done all the ARGV-elements, stop the scan
424          and back over any non-options that we skipped and permuted.  */
425
426       if (optind == argc)
427         {
428           /* Set the next-arg-index to point at the non-options
429              that we previously skipped, so the caller will digest them.  */
430           if (first_nonopt != last_nonopt)
431             optind = first_nonopt;
432           return EOF;
433         }
434
435       /* If we have come to a non-option and did not permute it,
436          either stop the scan or describe it to the caller and pass it by.  */
437
438       if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
439 #ifdef GETOPT_COMPAT
440           && (longopts == NULL
441               || argv[optind][0] != '+' || argv[optind][1] == '\0')
442 #endif                          /* GETOPT_COMPAT */
443           )
444         {
445           if (ordering == REQUIRE_ORDER)
446             return EOF;
447           optarg = argv[optind++];
448           return 1;
449         }
450
451       /* We have found another option-ARGV-element.
452          Start decoding its characters.  */
453
454       nextchar = (argv[optind] + 1
455                   + (longopts != NULL && argv[optind][1] == '-'));
456     }
457
458   if (longopts != NULL
459       && ((argv[optind][0] == '-'
460            && (argv[optind][1] == '-' || long_only))
461 #ifdef GETOPT_COMPAT
462           || argv[optind][0] == '+'
463 #endif                          /* GETOPT_COMPAT */
464           ))
465     {
466       const struct option *p;
467       char *s = nextchar;
468       int exact = 0;
469       int ambig = 0;
470       const struct option *pfound = NULL;
471       int indfound;
472
473       while (*s && *s != '=')
474         s++;
475
476       /* Test all options for either exact match or abbreviated matches.  */
477       for (p = longopts, option_index = 0; p->name;
478            p++, option_index++)
479         if (!strncmp (p->name, nextchar, s - nextchar))
480           {
481             if ((size_t)(s - nextchar) == strlen (p->name))
482               {
483                 /* Exact match found.  */
484                 pfound = p;
485                 indfound = option_index;
486                 exact = 1;
487                 break;
488               }
489             else if (pfound == NULL)
490               {
491                 /* First nonexact match found.  */
492                 pfound = p;
493                 indfound = option_index;
494               }
495             else
496               /* Second nonexact match found.  */
497               ambig = 1;
498           }
499
500       if (ambig && !exact)
501         {
502           if (opterr)
503             fprintf (stderr, "%s: option `%s' is ambiguous\n",
504                      argv[0], argv[optind]);
505           nextchar += strlen (nextchar);
506           optind++;
507           return '?';
508         }
509
510       if (pfound != NULL)
511         {
512           option_index = indfound;
513           optind++;
514           if (*s)
515             {
516               /* Don't test has_arg with >, because some C compilers don't
517                  allow it to be used on enums.  */
518               if (pfound->has_arg)
519                 optarg = s + 1;
520               else
521                 {
522                   if (opterr)
523                     {
524                       if (argv[optind - 1][1] == '-')
525                         /* --option */
526                         fprintf (stderr,
527                                  "%s: option `--%s' doesn't allow an argument\n",
528                                  argv[0], pfound->name);
529                       else
530                         /* +option or -option */
531                         fprintf (stderr,
532                              "%s: option `%c%s' doesn't allow an argument\n",
533                              argv[0], argv[optind - 1][0], pfound->name);
534                     }
535                   nextchar += strlen (nextchar);
536                   return '?';
537                 }
538             }
539           else if (pfound->has_arg == 1)
540             {
541               if (optind < argc)
542                 optarg = argv[optind++];
543               else
544                 {
545                   if (opterr)
546                     fprintf (stderr, "%s: option `%s' requires an argument\n",
547                              argv[0], argv[optind - 1]);
548                   nextchar += strlen (nextchar);
549                   return optstring[0] == ':' ? ':' : '?';
550                 }
551             }
552           nextchar += strlen (nextchar);
553           if (longind != NULL)
554             *longind = option_index;
555           if (pfound->flag)
556             {
557               *(pfound->flag) = pfound->val;
558               return 0;
559             }
560           return pfound->val;
561         }
562       /* Can't find it as a long option.  If this is not getopt_long_only,
563          or the option starts with '--' or is not a valid short
564          option, then it's an error.
565          Otherwise interpret it as a short option.  */
566       if (!long_only || argv[optind][1] == '-'
567 #ifdef GETOPT_COMPAT
568           || argv[optind][0] == '+'
569 #endif                          /* GETOPT_COMPAT */
570           || my_index (optstring, *nextchar) == NULL)
571         {
572           if (opterr)
573             {
574               if (argv[optind][1] == '-')
575                 /* --option */
576                 fprintf (stderr, "%s: unrecognized option `--%s'\n",
577                          argv[0], nextchar);
578               else
579                 /* +option or -option */
580                 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
581                          argv[0], argv[optind][0], nextchar);
582             }
583           nextchar = (char *) "";
584           optind++;
585           return '?';
586         }
587     }
588
589   /* Look at and handle the next option-character.  */
590
591   {
592     char c = *nextchar++;
593     char *temp = my_index (optstring, c);
594
595     /* Increment `optind' when we start to process its last character.  */
596     if (*nextchar == '\0')
597       ++optind;
598
599     if (temp == NULL || c == ':')
600       {
601         if (opterr)
602           {
603 #if 0
604             if (c < 040 || c >= 0177)
605               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
606                        argv[0], c);
607             else
608               fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
609 #else
610             /* 1003.2 specifies the format of this message.  */
611             fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
612 #endif
613           }
614         optopt = c;
615         return '?';
616       }
617     if (temp[1] == ':')
618       {
619         if (temp[2] == ':')
620           {
621             /* This is an option that accepts an argument optionally.  */
622             if (*nextchar != '\0')
623               {
624                 optarg = nextchar;
625                 optind++;
626               }
627             else
628               optarg = 0;
629             nextchar = NULL;
630           }
631         else
632           {
633             /* This is an option that requires an argument.  */
634             if (*nextchar != '\0')
635               {
636                 optarg = nextchar;
637                 /* If we end this ARGV-element by taking the rest as an arg,
638                    we must advance to the next element now.  */
639                 optind++;
640               }
641             else if (optind == argc)
642               {
643                 if (opterr)
644                   {
645 #if 0
646                     fprintf (stderr, "%s: option `-%c' requires an argument\n",
647                              argv[0], c);
648 #else
649                     /* 1003.2 specifies the format of this message.  */
650                     fprintf (stderr, "%s: option requires an argument -- %c\n",
651                              argv[0], c);
652 #endif
653                   }
654                 optopt = c;
655                 if (optstring[0] == ':')
656                   c = ':';
657                 else
658                   c = '?';
659               }
660             else
661               /* We already incremented `optind' once;
662                  increment it again when taking next ARGV-elt as argument.  */
663               optarg = argv[optind++];
664             nextchar = NULL;
665           }
666       }
667     return c;
668   }
669 }
670
671 int
672 getopt (argc, argv, optstring)
673      int argc;
674      char *const *argv;
675      const char *optstring;
676 {
677   return _getopt_internal (argc, argv, optstring,
678                            (const struct option *) 0,
679                            (int *) 0,
680                            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
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 '?':
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 */