e13fac3bf08d06264a5c9a3eb0e4fa4dfc9ac955
[mes.git] / mlibc / 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, 1992 Free Software Foundation, Inc.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2, or (at your option)
11    any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21 \f
22 /* AIX requires this to be the first thing in the file. */
23 #ifdef __GNUC__
24 #define alloca __builtin_alloca
25 #else /* not __GNUC__ */
26 #ifdef sparc
27 #include <alloca.h>
28 #else
29 #ifdef _AIX
30  #pragma alloca
31 #else
32 char *alloca ();
33 #endif
34 #endif /* sparc */
35 #endif /* not __GNUC__ */
36
37 #ifdef  LIBC
38 /* For when compiled as part of the GNU C library.  */
39 #include <ansidecl.h>
40 #endif
41
42 #include <stdio.h>
43
44 /* This needs to come after some library #include
45    to get __GNU_LIBRARY__ defined.  */
46 #ifdef  __GNU_LIBRARY__
47 #undef  alloca
48 #include <stdlib.h>
49 #else   /* Not GNU C library.  */
50 #define __alloca        alloca
51 #endif  /* GNU C library.  */
52
53
54 #ifndef __STDC__
55 #define const
56 #endif
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 int optind = 0;
100
101 /* The next char to be scanned in the option-element
102    in which the last option character we returned was found.
103    This allows us to pick up the scan where we left off.
104
105    If this is zero, or a null string, it means resume the scan
106    by advancing to the next ARGV-element.  */
107
108 static char *nextchar;
109
110 /* Callers store zero here to inhibit the error message
111    for unrecognized options.  */
112
113 int opterr = 1;
114
115 /* Describe how to deal with options that follow non-option ARGV-elements.
116
117    If the caller did not specify anything,
118    the default is REQUIRE_ORDER if the environment variable
119    POSIXLY_CORRECT is defined, PERMUTE otherwise.
120
121    REQUIRE_ORDER means don't recognize them as options;
122    stop option processing when the first non-option is seen.
123    This is what Unix does.
124    This mode of operation is selected by either setting the environment
125    variable POSIXLY_CORRECT, or using `+' as the first character
126    of the list of option characters.
127
128    PERMUTE is the default.  We permute the contents of ARGV as we scan,
129    so that eventually all the non-options are at the end.  This allows options
130    to be given in any order, even with programs that were not written to
131    expect this.
132
133    RETURN_IN_ORDER is an option available to programs that were written
134    to expect options and other ARGV-elements in any order and that care about
135    the ordering of the two.  We describe each non-option ARGV-element
136    as if it were the argument of an option with character code 1.
137    Using `-' as the first character of the list of option characters
138    selects this mode of operation.
139
140    The special argument `--' forces an end of option-scanning regardless
141    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
142    `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
143
144 static enum
145 {
146   REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
147 } ordering;
148 \f
149 #ifdef  __GNU_LIBRARY__
150 #include <string.h>
151 #define my_index        strchr
152 #define my_bcopy(src, dst, n)   memcpy ((dst), (src), (n))
153 #else
154
155 /* Avoid depending on library functions or files
156    whose names are inconsistent.  */
157
158 char *getenv ();
159
160 static char *
161 my_index (string, chr)
162      char *string;
163      int chr;
164 {
165   while (*string)
166     {
167       if (*string == chr)
168         return string;
169       string++;
170     }
171   return 0;
172 }
173
174 static void
175 my_bcopy (from, to, size)
176      char *from, *to;
177      int size;
178 {
179   int i;
180   for (i = 0; i < size; i++)
181     to[i] = from[i];
182 }
183 #endif                          /* GNU C library.  */
184 \f
185 /* Handle permutation of arguments.  */
186
187 /* Describe the part of ARGV that contains non-options that have
188    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
189    `last_nonopt' is the index after the last of them.  */
190
191 static int first_nonopt;
192 static int last_nonopt;
193
194 /* Exchange two adjacent subsequences of ARGV.
195    One subsequence is elements [first_nonopt,last_nonopt)
196    which contains all the non-options that have been skipped so far.
197    The other is elements [last_nonopt,optind), which contains all
198    the options processed since those non-options were skipped.
199
200    `first_nonopt' and `last_nonopt' are relocated so that they describe
201    the new indices of the non-options in ARGV after they are moved.  */
202
203 static void
204 exchange (argv)
205      char **argv;
206 {
207   int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
208   char **temp = (char **) __alloca (nonopts_size);
209
210   /* Interchange the two blocks of data in ARGV.  */
211
212   my_bcopy (&argv[first_nonopt], temp, nonopts_size);
213   my_bcopy (&argv[last_nonopt], &argv[first_nonopt],
214             (optind - last_nonopt) * sizeof (char *));
215   my_bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size);
216
217   /* Update records for the slots the non-options now occupy.  */
218
219   first_nonopt += (optind - last_nonopt);
220   last_nonopt = optind;
221 }
222 \f
223 /* Scan elements of ARGV (whose length is ARGC) for option characters
224    given in OPTSTRING.
225
226    If an element of ARGV starts with '-', and is not exactly "-" or "--",
227    then it is an option element.  The characters of this element
228    (aside from the initial '-') are option characters.  If `getopt'
229    is called repeatedly, it returns successively each of the option characters
230    from each of the option elements.
231
232    If `getopt' finds another option character, it returns that character,
233    updating `optind' and `nextchar' so that the next call to `getopt' can
234    resume the scan with the following option character or ARGV-element.
235
236    If there are no more option characters, `getopt' returns `EOF'.
237    Then `optind' is the index in ARGV of the first ARGV-element
238    that is not an option.  (The ARGV-elements have been permuted
239    so that those that are not options now come last.)
240
241    OPTSTRING is a string containing the legitimate option characters.
242    If an option character is seen that is not listed in OPTSTRING,
243    return '?' after printing an error message.  If you set `opterr' to
244    zero, the error message is suppressed but we still return '?'.
245
246    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
247    so the following text in the same ARGV-element, or the text of the following
248    ARGV-element, is returned in `optarg'.  Two colons mean an option that
249    wants an optional arg; if there is text in the current ARGV-element,
250    it is returned in `optarg', otherwise `optarg' is set to zero.
251
252    If OPTSTRING starts with `-' or `+', it requests different methods of
253    handling the non-option ARGV-elements.
254    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
255
256    Long-named options begin with `--' instead of `-'.
257    Their names may be abbreviated as long as the abbreviation is unique
258    or is an exact match for some defined option.  If they have an
259    argument, it follows the option name in the same ARGV-element, separated
260    from the option name by a `=', or else the in next ARGV-element.
261    When `getopt' finds a long-named option, it returns 0 if that option's
262    `flag' field is nonzero, the value of the option's `val' field
263    if the `flag' field is zero.
264
265    The elements of ARGV aren't really const, because we permute them.
266    But we pretend they're const in the prototype to be compatible
267    with other systems.
268
269    LONGOPTS is a vector of `struct option' terminated by an
270    element containing a name which is zero.
271
272    LONGIND returns the index in LONGOPT of the long-named option found.
273    It is only valid when a long-named option has been found by the most
274    recent call.
275
276    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
277    long-named options.  */
278
279 int
280 _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
281      int argc;
282      char *const *argv;
283      const char *optstring;
284      const struct option *longopts;
285      int *longind;
286      int long_only;
287 {
288   int option_index;
289
290   optarg = 0;
291
292   /* Initialize the internal data when the first call is made.
293      Start processing options with ARGV-element 1 (since ARGV-element 0
294      is the program name); the sequence of previously skipped
295      non-option ARGV-elements is empty.  */
296
297   if (optind == 0)
298     {
299       first_nonopt = last_nonopt = optind = 1;
300
301       nextchar = NULL;
302
303       /* Determine how to handle the ordering of options and nonoptions.  */
304
305       if (optstring[0] == '-')
306         {
307           ordering = RETURN_IN_ORDER;
308           ++optstring;
309         }
310       else if (optstring[0] == '+')
311         {
312           ordering = REQUIRE_ORDER;
313           ++optstring;
314         }
315       else if (getenv ("POSIXLY_CORRECT") != NULL)
316         ordering = REQUIRE_ORDER;
317       else
318         ordering = PERMUTE;
319     }
320
321   if (nextchar == NULL || *nextchar == '\0')
322     {
323       if (ordering == PERMUTE)
324         {
325           /* If we have just processed some options following some non-options,
326              exchange them so that the options come first.  */
327
328           if (first_nonopt != last_nonopt && last_nonopt != optind)
329             exchange ((char **) argv);
330           else if (last_nonopt != optind)
331             first_nonopt = optind;
332
333           /* Now skip any additional non-options
334              and extend the range of non-options previously skipped.  */
335
336           while (optind < argc
337                  && (argv[optind][0] != '-' || argv[optind][1] == '\0')
338 #ifdef GETOPT_COMPAT
339                  && (longopts == NULL
340                      || argv[optind][0] != '+' || argv[optind][1] == '\0')
341 #endif                          /* GETOPT_COMPAT */
342                  )
343             optind++;
344           last_nonopt = optind;
345         }
346
347       /* Special ARGV-element `--' means premature end of options.
348          Skip it like a null option,
349          then exchange with previous non-options as if it were an option,
350          then skip everything else like a non-option.  */
351
352       if (optind != argc && !strcmp (argv[optind], "--"))
353         {
354           optind++;
355
356           if (first_nonopt != last_nonopt && last_nonopt != optind)
357             exchange ((char **) argv);
358           else if (first_nonopt == last_nonopt)
359             first_nonopt = optind;
360           last_nonopt = argc;
361
362           optind = argc;
363         }
364
365       /* If we have done all the ARGV-elements, stop the scan
366          and back over any non-options that we skipped and permuted.  */
367
368       if (optind == argc)
369         {
370           /* Set the next-arg-index to point at the non-options
371              that we previously skipped, so the caller will digest them.  */
372           if (first_nonopt != last_nonopt)
373             optind = first_nonopt;
374           return EOF;
375         }
376
377       /* If we have come to a non-option and did not permute it,
378          either stop the scan or describe it to the caller and pass it by.  */
379
380       if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
381 #ifdef GETOPT_COMPAT
382           && (longopts == NULL
383               || argv[optind][0] != '+' || argv[optind][1] == '\0')
384 #endif                          /* GETOPT_COMPAT */
385           )
386         {
387           if (ordering == REQUIRE_ORDER)
388             return EOF;
389           optarg = argv[optind++];
390           return 1;
391         }
392
393       /* We have found another option-ARGV-element.
394          Start decoding its characters.  */
395
396       nextchar = (argv[optind] + 1
397                   + (longopts != NULL && argv[optind][1] == '-'));
398     }
399
400   if (longopts != NULL
401       && ((argv[optind][0] == '-'
402            && (argv[optind][1] == '-' || long_only))
403 #ifdef GETOPT_COMPAT
404           || argv[optind][0] == '+'
405 #endif                          /* GETOPT_COMPAT */
406           ))
407     {
408       const struct option *p;
409       char *s = nextchar;
410       int exact = 0;
411       int ambig = 0;
412       const struct option *pfound = NULL;
413       int indfound;
414
415       while (*s && *s != '=')
416         s++;
417
418       /* Test all options for either exact match or abbreviated matches.  */
419       for (p = longopts, option_index = 0; p->name;
420            p++, option_index++)
421         if (!strncmp (p->name, nextchar, s - nextchar))
422           {
423             if (s - nextchar == strlen (p->name))
424               {
425                 /* Exact match found.  */
426                 pfound = p;
427                 indfound = option_index;
428                 exact = 1;
429                 break;
430               }
431             else if (pfound == NULL)
432               {
433                 /* First nonexact match found.  */
434                 pfound = p;
435                 indfound = option_index;
436               }
437             else
438               /* Second nonexact match found.  */
439               ambig = 1;
440           }
441
442       if (ambig && !exact)
443         {
444           if (opterr)
445             fprintf (stderr, "%s: option `%s' is ambiguous\n",
446                      argv[0], argv[optind]);
447           nextchar += strlen (nextchar);
448           optind++;
449           return '?';
450         }
451
452       if (pfound != NULL)
453         {
454           option_index = indfound;
455           optind++;
456           if (*s)
457             {
458               /* Don't test has_arg with >, because some C compilers don't
459                  allow it to be used on enums. */
460               if (pfound->has_arg)
461                 optarg = s + 1;
462               else
463                 {
464                   if (opterr)
465                     {
466                       if (argv[optind - 1][1] == '-')
467                         /* --option */
468                         fprintf (stderr,
469                                  "%s: option `--%s' doesn't allow an argument\n",
470                                  argv[0], pfound->name);
471                       else
472                         /* +option or -option */
473                         fprintf (stderr,
474                              "%s: option `%c%s' doesn't allow an argument\n",
475                              argv[0], argv[optind - 1][0], pfound->name);
476                     }
477                   nextchar += strlen (nextchar);
478                   return '?';
479                 }
480             }
481           else if (pfound->has_arg == 1)
482             {
483               if (optind < argc)
484                 optarg = argv[optind++];
485               else
486                 {
487                   if (opterr)
488                     fprintf (stderr, "%s: option `%s' requires an argument\n",
489                              argv[0], argv[optind - 1]);
490                   nextchar += strlen (nextchar);
491                   return '?';
492                 }
493             }
494           nextchar += strlen (nextchar);
495           if (longind != NULL)
496             *longind = option_index;
497           if (pfound->flag)
498             {
499               *(pfound->flag) = pfound->val;
500               return 0;
501             }
502           return pfound->val;
503         }
504       /* Can't find it as a long option.  If this is not getopt_long_only,
505          or the option starts with '--' or is not a valid short
506          option, then it's an error.
507          Otherwise interpret it as a short option. */
508       if (!long_only || argv[optind][1] == '-'
509 #ifdef GETOPT_COMPAT
510           || argv[optind][0] == '+'
511 #endif                          /* GETOPT_COMPAT */
512           || my_index (optstring, *nextchar) == NULL)
513         {
514           if (opterr)
515             {
516               if (argv[optind][1] == '-')
517                 /* --option */
518                 fprintf (stderr, "%s: unrecognized option `--%s'\n",
519                          argv[0], nextchar);
520               else
521                 /* +option or -option */
522                 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
523                          argv[0], argv[optind][0], nextchar);
524             }
525           nextchar += strlen (nextchar);
526           optind++;
527           return '?';
528         }
529     }
530
531   /* Look at and handle the next option-character.  */
532
533   {
534     char c = *nextchar++;
535     char *temp = my_index (optstring, c);
536
537     /* Increment `optind' when we start to process its last character.  */
538     if (*nextchar == '\0')
539       optind++;
540
541     if (temp == NULL || c == ':')
542       {
543         if (opterr)
544           {
545             if (c < 040 || c >= 0177)
546               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
547                        argv[0], c);
548             else
549               fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
550           }
551         return '?';
552       }
553     if (temp[1] == ':')
554       {
555         if (temp[2] == ':')
556           {
557             /* This is an option that accepts an argument optionally.  */
558             if (*nextchar != '\0')
559               {
560                 optarg = nextchar;
561                 optind++;
562               }
563             else
564               optarg = 0;
565             nextchar = NULL;
566           }
567         else
568           {
569             /* This is an option that requires an argument.  */
570             if (*nextchar != 0)
571               {
572                 optarg = nextchar;
573                 /* If we end this ARGV-element by taking the rest as an arg,
574                    we must advance to the next element now.  */
575                 optind++;
576               }
577             else if (optind == argc)
578               {
579                 if (opterr)
580                   fprintf (stderr, "%s: option `-%c' requires an argument\n",
581                            argv[0], c);
582                 c = '?';
583               }
584             else
585               /* We already incremented `optind' once;
586                  increment it again when taking next ARGV-elt as argument.  */
587               optarg = argv[optind++];
588             nextchar = NULL;
589           }
590       }
591     return c;
592   }
593 }
594
595 int
596 getopt (argc, argv, optstring)
597      int argc;
598      char *const *argv;
599      const char *optstring;
600 {
601   return _getopt_internal (argc, argv, optstring,
602                            (const struct option *) 0,
603                            (int *) 0,
604                            0);
605 }
606 \f
607 #ifdef TEST
608
609 /* Compile with -DTEST to make an executable for use in testing
610    the above definition of `getopt'.  */
611
612 int
613 main (argc, argv)
614      int argc;
615      char **argv;
616 {
617   int c;
618   int digit_optind = 0;
619
620   while (1)
621     {
622       int this_option_optind = optind ? optind : 1;
623
624       c = getopt (argc, argv, "abc:d:0123456789");
625       if (c == EOF)
626         break;
627
628       switch (c)
629         {
630         case '0':
631         case '1':
632         case '2':
633         case '3':
634         case '4':
635         case '5':
636         case '6':
637         case '7':
638         case '8':
639         case '9':
640           if (digit_optind != 0 && digit_optind != this_option_optind)
641             printf ("digits occur in two different argv-elements.\n");
642           digit_optind = this_option_optind;
643           printf ("option %c\n", c);
644           break;
645
646         case 'a':
647           printf ("option a\n");
648           break;
649
650         case 'b':
651           printf ("option b\n");
652           break;
653
654         case 'c':
655           printf ("option c with value `%s'\n", optarg);
656           break;
657
658         case '?':
659           break;
660
661         default:
662           printf ("?? getopt returned character code 0%o ??\n", c);
663         }
664     }
665
666   if (optind < argc)
667     {
668       printf ("non-option ARGV-elements: ");
669       while (optind < argc)
670         printf ("%s ", argv[optind++]);
671       printf ("\n");
672     }
673
674   exit (0);
675 }
676
677 #endif /* TEST */