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