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