3 Copyright (C) 1993, 1994
4 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include "../memalloc.h"
25 /* For communication from `sh_getopt' to the caller.
26 When `sh_getopt' finds an option that takes an argument,
27 the argument value is returned here. */
30 /* Index in ARGV of the next element to be scanned.
31 This is used for communication to and from the caller
32 and for communication between successive calls to `sh_getopt'.
34 On entry to `sh_getopt', zero means this is the first call; initialize.
36 When `sh_getopt' returns EOF, this is the index of the first of the
37 non-option elements that the caller should itself scan.
39 Otherwise, `sh_optind' communicates from one call to the next
40 how much of ARGV has been scanned so far. */
42 /* XXX 1003.2 says this must be 1 before any call. */
45 /* Index of the current argument. */
48 /* The next char to be scanned in the option-element
49 in which the last option character we returned was found.
50 This allows us to pick up the scan where we left off.
52 If this is zero, or a null string, it means resume the scan
53 by advancing to the next ARGV-element. */
55 static char *nextchar;
56 static int sh_charindex;
58 /* Callers store zero here to inhibit the error message
59 for unrecognized options. */
63 /* Set to an option character which was unrecognized.
64 This must be initialized on some systems to avoid linking in the
65 system's own getopt implementation. */
69 /* Scan elements of ARGV (whose length is ARGC) for option characters
72 If an element of ARGV starts with '-', and is not exactly "-" or "--",
73 then it is an option element. The characters of this element
74 (aside from the initial '-') are option characters. If `sh_getopt'
75 is called repeatedly, it returns successively each of the option characters
76 from each of the option elements.
78 If `sh_getopt' finds another option character, it returns that character,
79 updating `sh_optind' and `nextchar' so that the next call to `sh_getopt' can
80 resume the scan with the following option character or ARGV-element.
82 If there are no more option characters, `sh_getopt' returns `EOF'.
83 Then `sh_optind' is the index in ARGV of the first ARGV-element
84 that is not an option.
86 OPTSTRING is a string containing the legitimate option characters.
87 If an option character is seen that is not listed in OPTSTRING,
88 return '?' after printing an error message. If you set `sh_opterr' to
89 zero, the error message is suppressed but we still return '?'.
91 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
92 so the following text in the same ARGV-element, or the text of the following
93 ARGV-element, is returned in `sh_optarg'. */
95 /* 1003.2 specifies the format of this message. */
96 #define BADOPT(x) fprintf (stderr, "%s: illegal option -- %c\n", argv[0], x)
97 #define NEEDARG(x) fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], x)
100 sh_getopt (argc, argv, optstring)
103 const char *optstring;
110 if (sh_optind > argc || sh_optind < 0)
116 /* Initialize the internal data when the first call is made.
117 Start processing options with ARGV-element 1 (since ARGV-element 0
118 is the program name); the sequence of previously skipped
119 non-option ARGV-elements is empty. */
124 nextchar = (char *)NULL;
127 if (nextchar == 0 || *nextchar == '\0')
129 /* If we have done all the ARGV-elements, stop the scan
130 and back over any non-options that we skipped and permuted. */
131 if (sh_optind == argc)
134 temp = argv[sh_optind];
136 /* Special ARGV-element `--' means premature end of options.
137 Skip it like a null option, and return EOF. */
138 if (temp[0] == '-' && temp[1] == '-' && temp[2] == '\0')
144 /* If we have come to a non-option, either stop the scan or describe
145 it to the caller and pass it by. This makes the pseudo-option
146 `-' mean the end of options, but does not skip over it. */
147 if (temp[0] != '-' || temp[1] == '\0')
150 /* We have found another option-ARGV-element.
151 Start decoding its characters. */
152 nextchar = argv[sh_curopt = sh_optind] + 1;
156 /* Look at and handle the next option-character. */
158 c = *nextchar++; sh_charindex++;
159 temp = strchr (optstring, c);
161 /* Increment `sh_optind' when we start to process its last character. */
162 if (nextchar == 0 || *nextchar == '\0')
165 nextchar = (char *)NULL;
170 if (temp == NULL || c == ':')
180 if (nextchar && *nextchar)
182 /* This is an option that requires an argument. */
183 sh_optarg = nextchar;
184 /* If we end this ARGV-element by taking the rest as an arg,
185 we must advance to the next element now. */
188 else if (sh_optind == argc)
194 c = (optstring[0] == ':') ? ':' : '?';
197 /* We already incremented `sh_optind' once;
198 increment it again when taking next ARGV-elt as argument. */
199 sh_optarg = argv[sh_optind++];
200 nextchar = (char *)NULL;
206 sh_getopt_restore_state (argv)
210 nextchar = argv[sh_curopt] + sh_charindex;
215 /* Compile with -DTEST to make an executable for use in testing
216 the above definition of `sh_getopt'. */
224 int digit_sh_optind = 0;
228 int this_option_sh_optind = sh_optind ? sh_optind : 1;
230 c = sh_getopt (argc, argv, "abc:d:0123456789");
246 if (digit_sh_optind != 0 && digit_sh_optind != this_option_sh_optind)
247 printf ("digits occur in two different argv-elements.\n");
248 digit_sh_optind = this_option_sh_optind;
249 printf ("option %c\n", c);
253 printf ("option a\n");
257 printf ("option b\n");
261 printf ("option c with value `%s'\n", sh_optarg);
268 printf ("?? sh_getopt returned character code 0%o ??\n", c);
272 if (sh_optind < argc)
274 printf ("non-option ARGV-elements: ");
275 while (sh_optind < argc)
276 printf ("%s ", argv[sh_optind++]);