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