replace *a lot* of file related calls by their GLib counterparts. This is necessary...
[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 #include <string.h>
171 #define my_index        strchr
172 #else
173
174 /* Avoid depending on library functions or files
175    whose names are inconsistent.  */
176
177 char *getenv ();
178
179 static char *
180 my_index (str, chr)
181      const char *str;
182      int chr;
183 {
184   while (*str)
185     {
186       if (*str == chr)
187         return (char *) str;
188       str++;
189     }
190   return 0;
191 }
192
193 /* If using GCC, we can safely declare strlen this way.
194    If not using GCC, it is ok not to declare it.
195    (Supposedly there are some machines where it might get a warning,
196    but changing this conditional to __STDC__ is too risky.)  */
197 #ifdef __GNUC__
198 #ifdef IN_GCC
199 #include "gstddef.h"
200 #else
201 #include <stddef.h>
202 #endif
203 extern size_t strlen (const char *);
204 #endif
205
206 #endif                          /* GNU C library.  */
207
208 /* Handle permutation of arguments.  */
209
210 /* Describe the part of ARGV that contains non-options that have
211    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
212    `last_nonopt' is the index after the last of them.  */
213
214 static int first_nonopt;
215 static int last_nonopt;
216
217 /* Exchange two adjacent subsequences of ARGV.
218    One subsequence is elements [first_nonopt,last_nonopt)
219    which contains all the non-options that have been skipped so far.
220    The other is elements [last_nonopt,optind), which contains all
221    the options processed since those non-options were skipped.
222
223    `first_nonopt' and `last_nonopt' are relocated so that they describe
224    the new indices of the non-options in ARGV after they are moved.  */
225
226 static void
227 exchange (argv)
228      char **argv;
229 {
230   int bottom = first_nonopt;
231   int middle = last_nonopt;
232   int top = optind;
233   char *tem;
234
235   /* Exchange the shorter segment with the far end of the longer segment.
236      That puts the shorter segment into the right place.
237      It leaves the longer segment in the right place overall,
238      but it consists of two parts that need to be swapped next.  */
239
240   while (top > middle && middle > bottom)
241     {
242       if (top - middle > middle - bottom)
243         {
244           /* Bottom segment is the short one.  */
245           int len = middle - bottom;
246           register int i;
247
248           /* Swap it with the top part of the top segment.  */
249           for (i = 0; i < len; i++)
250             {
251               tem = argv[bottom + i];
252               argv[bottom + i] = argv[top - (middle - bottom) + i];
253               argv[top - (middle - bottom) + i] = tem;
254             }
255           /* Exclude the moved bottom segment from further swapping.  */
256           top -= len;
257         }
258       else
259         {
260           /* Top segment is the short one.  */
261           int len = top - middle;
262           register int i;
263
264           /* Swap it with the bottom part of the bottom segment.  */
265           for (i = 0; i < len; i++)
266             {
267               tem = argv[bottom + i];
268               argv[bottom + i] = argv[middle + i];
269               argv[middle + i] = tem;
270             }
271           /* Exclude the moved top segment from further swapping.  */
272           bottom += len;
273         }
274     }
275
276   /* Update records for the slots the non-options now occupy.  */
277
278   first_nonopt += (optind - last_nonopt);
279   last_nonopt = optind;
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 '?' after printing an error message.  If you set `opterr' to
303    zero, the error message is suppressed but we still return '?'.
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
339 _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
340      int argc;
341      char *const *argv;
342      const char *optstring;
343      const struct option *longopts;
344      int *longind;
345      int long_only;
346 {
347   int option_index;
348
349   optarg = 0;
350
351   /* Initialize the internal data when the first call is made.
352      Start processing options with ARGV-element 1 (since ARGV-element 0
353      is the program name); the sequence of previously skipped
354      non-option ARGV-elements is empty.  */
355
356   if (optind == 0)
357     {
358       first_nonopt = last_nonopt = optind = 1;
359
360       nextchar = NULL;
361
362       /* Determine how to handle the ordering of options and nonoptions.  */
363
364       if (optstring[0] == '-')
365         {
366           ordering = RETURN_IN_ORDER;
367           ++optstring;
368         }
369       else if (optstring[0] == '+')
370         {
371           ordering = REQUIRE_ORDER;
372           ++optstring;
373         }
374       else if (getenv ("POSIXLY_CORRECT") != NULL)
375         ordering = REQUIRE_ORDER;
376       else
377         ordering = PERMUTE;
378     }
379
380   if (nextchar == NULL || *nextchar == '\0')
381     {
382       if (ordering == PERMUTE)
383         {
384           /* If we have just processed some options following some non-options,
385              exchange them so that the options come first.  */
386
387           if (first_nonopt != last_nonopt && last_nonopt != optind)
388             exchange ((char **) argv);
389           else if (last_nonopt != optind)
390             first_nonopt = optind;
391
392           /* Now skip any additional non-options
393              and extend the range of non-options previously skipped.  */
394
395           while (optind < argc
396                  && (argv[optind][0] != '-' || argv[optind][1] == '\0')
397 #ifdef GETOPT_COMPAT
398                  && (longopts == NULL
399                      || argv[optind][0] != '+' || argv[optind][1] == '\0')
400 #endif                          /* GETOPT_COMPAT */
401                  )
402             optind++;
403           last_nonopt = optind;
404         }
405
406       /* Special ARGV-element `--' means premature end of options.
407          Skip it like a null option,
408          then exchange with previous non-options as if it were an option,
409          then skip everything else like a non-option.  */
410
411       if (optind != argc && !strcmp (argv[optind], "--"))
412         {
413           optind++;
414
415           if (first_nonopt != last_nonopt && last_nonopt != optind)
416             exchange ((char **) argv);
417           else if (first_nonopt == last_nonopt)
418             first_nonopt = optind;
419           last_nonopt = argc;
420
421           optind = argc;
422         }
423
424       /* If we have done all the ARGV-elements, stop the scan
425          and back over any non-options that we skipped and permuted.  */
426
427       if (optind == argc)
428         {
429           /* Set the next-arg-index to point at the non-options
430              that we previously skipped, so the caller will digest them.  */
431           if (first_nonopt != last_nonopt)
432             optind = first_nonopt;
433           return EOF;
434         }
435
436       /* If we have come to a non-option and did not permute it,
437          either stop the scan or describe it to the caller and pass it by.  */
438
439       if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
440 #ifdef GETOPT_COMPAT
441           && (longopts == NULL
442               || argv[optind][0] != '+' || argv[optind][1] == '\0')
443 #endif                          /* GETOPT_COMPAT */
444           )
445         {
446           if (ordering == REQUIRE_ORDER)
447             return EOF;
448           optarg = argv[optind++];
449           return 1;
450         }
451
452       /* We have found another option-ARGV-element.
453          Start decoding its characters.  */
454
455       nextchar = (argv[optind] + 1
456                   + (longopts != NULL && argv[optind][1] == '-'));
457     }
458
459   if (longopts != NULL
460       && ((argv[optind][0] == '-'
461            && (argv[optind][1] == '-' || long_only))
462 #ifdef GETOPT_COMPAT
463           || argv[optind][0] == '+'
464 #endif                          /* GETOPT_COMPAT */
465           ))
466     {
467       const struct option *p;
468       char *s = nextchar;
469       int exact = 0;
470       int ambig = 0;
471       const struct option *pfound = NULL;
472       int indfound;
473
474       while (*s && *s != '=')
475         s++;
476
477       /* Test all options for either exact match or abbreviated matches.  */
478       for (p = longopts, option_index = 0; p->name;
479            p++, option_index++)
480         if (!strncmp (p->name, nextchar, s - nextchar))
481           {
482             if ((size_t)(s - nextchar) == strlen (p->name))
483               {
484                 /* Exact match found.  */
485                 pfound = p;
486                 indfound = option_index;
487                 exact = 1;
488                 break;
489               }
490             else if (pfound == NULL)
491               {
492                 /* First nonexact match found.  */
493                 pfound = p;
494                 indfound = option_index;
495               }
496             else
497               /* Second nonexact match found.  */
498               ambig = 1;
499           }
500
501       if (ambig && !exact)
502         {
503           if (opterr)
504             fprintf (stderr, "%s: option `%s' is ambiguous\n",
505                      argv[0], argv[optind]);
506           nextchar += strlen (nextchar);
507           optind++;
508           return '?';
509         }
510
511       if (pfound != NULL)
512         {
513           option_index = indfound;
514           optind++;
515           if (*s)
516             {
517               /* Don't test has_arg with >, because some C compilers don't
518                  allow it to be used on enums.  */
519               if (pfound->has_arg)
520                 optarg = s + 1;
521               else
522                 {
523                   if (opterr)
524                     {
525                       if (argv[optind - 1][1] == '-')
526                         /* --option */
527                         fprintf (stderr,
528                                  "%s: option `--%s' doesn't allow an argument\n",
529                                  argv[0], pfound->name);
530                       else
531                         /* +option or -option */
532                         fprintf (stderr,
533                              "%s: option `%c%s' doesn't allow an argument\n",
534                              argv[0], argv[optind - 1][0], pfound->name);
535                     }
536                   nextchar += strlen (nextchar);
537                   return '?';
538                 }
539             }
540           else if (pfound->has_arg == 1)
541             {
542               if (optind < argc)
543                 optarg = argv[optind++];
544               else
545                 {
546                   if (opterr)
547                     fprintf (stderr, "%s: option `%s' requires an argument\n",
548                              argv[0], argv[optind - 1]);
549                   nextchar += strlen (nextchar);
550                   return optstring[0] == ':' ? ':' : '?';
551                 }
552             }
553           nextchar += strlen (nextchar);
554           if (longind != NULL)
555             *longind = option_index;
556           if (pfound->flag)
557             {
558               *(pfound->flag) = pfound->val;
559               return 0;
560             }
561           return pfound->val;
562         }
563       /* Can't find it as a long option.  If this is not getopt_long_only,
564          or the option starts with '--' or is not a valid short
565          option, then it's an error.
566          Otherwise interpret it as a short option.  */
567       if (!long_only || argv[optind][1] == '-'
568 #ifdef GETOPT_COMPAT
569           || argv[optind][0] == '+'
570 #endif                          /* GETOPT_COMPAT */
571           || my_index (optstring, *nextchar) == NULL)
572         {
573           if (opterr)
574             {
575               if (argv[optind][1] == '-')
576                 /* --option */
577                 fprintf (stderr, "%s: unrecognized option `--%s'\n",
578                          argv[0], nextchar);
579               else
580                 /* +option or -option */
581                 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
582                          argv[0], argv[optind][0], nextchar);
583             }
584           nextchar = (char *) "";
585           optind++;
586           return '?';
587         }
588     }
589
590   /* Look at and handle the next option-character.  */
591
592   {
593     char c = *nextchar++;
594     char *temp = my_index (optstring, c);
595
596     /* Increment `optind' when we start to process its last character.  */
597     if (*nextchar == '\0')
598       ++optind;
599
600     if (temp == NULL || c == ':')
601       {
602         if (opterr)
603           {
604 #if 0
605             if (c < 040 || c >= 0177)
606               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
607                        argv[0], c);
608             else
609               fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
610 #else
611             /* 1003.2 specifies the format of this message.  */
612             fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
613 #endif
614           }
615         optopt = c;
616         return '?';
617       }
618     if (temp[1] == ':')
619       {
620         if (temp[2] == ':')
621           {
622             /* This is an option that accepts an argument optionally.  */
623             if (*nextchar != '\0')
624               {
625                 optarg = nextchar;
626                 optind++;
627               }
628             else
629               optarg = 0;
630             nextchar = NULL;
631           }
632         else
633           {
634             /* This is an option that requires an argument.  */
635             if (*nextchar != '\0')
636               {
637                 optarg = nextchar;
638                 /* If we end this ARGV-element by taking the rest as an arg,
639                    we must advance to the next element now.  */
640                 optind++;
641               }
642             else if (optind == argc)
643               {
644                 if (opterr)
645                   {
646 #if 0
647                     fprintf (stderr, "%s: option `-%c' requires an argument\n",
648                              argv[0], c);
649 #else
650                     /* 1003.2 specifies the format of this message.  */
651                     fprintf (stderr, "%s: option requires an argument -- %c\n",
652                              argv[0], c);
653 #endif
654                   }
655                 optopt = c;
656                 if (optstring[0] == ':')
657                   c = ':';
658                 else
659                   c = '?';
660               }
661             else
662               /* We already incremented `optind' once;
663                  increment it again when taking next ARGV-elt as argument.  */
664               optarg = argv[optind++];
665             nextchar = NULL;
666           }
667       }
668     return c;
669   }
670 }
671
672 int
673 getopt (argc, argv, optstring)
674      int argc;
675      char *const *argv;
676      const char *optstring;
677 {
678   return _getopt_internal (argc, argv, optstring,
679                            (const struct option *) 0,
680                            (int *) 0,
681                            0);
682 }
683
684 #endif  /* _LIBC or not __GNU_LIBRARY__.  */
685
686 #ifdef TEST
687
688 /* Compile with -DTEST to make an executable for use in testing
689    the above definition of `getopt'.  */
690
691 int
692 main (argc, argv)
693      int argc;
694      char **argv;
695 {
696   int c;
697   int digit_optind = 0;
698
699   while (1)
700     {
701       int this_option_optind = optind ? optind : 1;
702
703       c = getopt (argc, argv, "abc:d:0123456789");
704       if (c == EOF)
705         break;
706
707       switch (c)
708         {
709         case '0':
710         case '1':
711         case '2':
712         case '3':
713         case '4':
714         case '5':
715         case '6':
716         case '7':
717         case '8':
718         case '9':
719           if (digit_optind != 0 && digit_optind != this_option_optind)
720             printf ("digits occur in two different argv-elements.\n");
721           digit_optind = this_option_optind;
722           printf ("option %c\n", c);
723           break;
724
725         case 'a':
726           printf ("option a\n");
727           break;
728
729         case 'b':
730           printf ("option b\n");
731           break;
732
733         case 'c':
734           printf ("option c with value `%s'\n", optarg);
735           break;
736
737         case '?':
738           break;
739
740         default:
741           printf ("?? getopt returned character code 0%o ??\n", c);
742         }
743     }
744
745   if (optind < argc)
746     {
747       printf ("non-option ARGV-elements: ");
748       while (optind < argc)
749         printf ("%s ", argv[optind++]);
750       printf ("\n");
751     }
752
753   exit (0);
754 }
755
756 #endif /* TEST */