source: main/trunk/greenstone2/common-src/packages/gdbm/gdbm-1.8.3/getopt.c@ 21356

Last change on this file since 21356 was 18019, checked in by mdewsnip, 15 years ago

Added gdbm-1.8.3 (downloaded as gdbm-1.8.3.tar.gz and unpacked), in preparation for adding code for reading both little and big endian databases.

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