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