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