source: trunk/indexers/mgpp/lib/getopt_old.c@ 3365

Last change on this file since 3365 was 3365, checked in by kjdon, 22 years ago

Initial revision

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