Line data Source code
1 : /* getopt.c - getopt for Bash. Used by the getopt builtin. */
2 :
3 : /* Copyright (C) 1993-2009 Free Software Foundation, Inc.
4 :
5 : This file is part of GNU Bash, the Bourne Again SHell.
6 :
7 : Bash is free software: you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation, either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : Bash is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 :
23 : #if defined (HAVE_UNISTD_H)
24 : # ifdef _MINIX
25 : # include <sys/types.h>
26 : # endif
27 : # include <unistd.h>
28 : #endif
29 :
30 : #include <stdio.h>
31 : #include "memalloc.h"
32 : #include "../bashintl.h"
33 : #include "../shell.h"
34 : #include "getopt.h"
35 :
36 : /* For communication from `sh_getopt' to the caller.
37 : When `sh_getopt' finds an option that takes an argument,
38 : the argument value is returned here. */
39 : char *sh_optarg = 0;
40 :
41 : /* Index in ARGV of the next element to be scanned.
42 : This is used for communication to and from the caller
43 : and for communication between successive calls to `sh_getopt'.
44 :
45 : On entry to `sh_getopt', zero means this is the first call; initialize.
46 :
47 : When `sh_getopt' returns EOF, this is the index of the first of the
48 : non-option elements that the caller should itself scan.
49 :
50 : Otherwise, `sh_optind' communicates from one call to the next
51 : how much of ARGV has been scanned so far. */
52 :
53 : /* XXX 1003.2 says this must be 1 before any call. */
54 : int sh_optind = 0;
55 :
56 : /* Index of the current argument. */
57 : static int sh_curopt;
58 :
59 : /* The next char to be scanned in the option-element
60 : in which the last option character we returned was found.
61 : This allows us to pick up the scan where we left off.
62 :
63 : If this is zero, or a null string, it means resume the scan
64 : by advancing to the next ARGV-element. */
65 :
66 : static char *nextchar;
67 : static int sh_charindex;
68 :
69 : /* Callers store zero here to inhibit the error message
70 : for unrecognized options. */
71 :
72 : int sh_opterr = 1;
73 :
74 : /* Set to an option character which was unrecognized.
75 : This must be initialized on some systems to avoid linking in the
76 : system's own getopt implementation. */
77 :
78 : int sh_optopt = '?';
79 :
80 : /* Set to 1 when we see an invalid option; public so getopts can reset it. */
81 : int sh_badopt = 0;
82 :
83 : /* Scan elements of ARGV (whose length is ARGC) for option characters
84 : given in OPTSTRING.
85 :
86 : If an element of ARGV starts with '-', and is not exactly "-" or "--",
87 : then it is an option element. The characters of this element
88 : (aside from the initial '-') are option characters. If `sh_getopt'
89 : is called repeatedly, it returns successively each of the option characters
90 : from each of the option elements.
91 :
92 : If `sh_getopt' finds another option character, it returns that character,
93 : updating `sh_optind' and `nextchar' so that the next call to `sh_getopt' can
94 : resume the scan with the following option character or ARGV-element.
95 :
96 : If there are no more option characters, `sh_getopt' returns `EOF'.
97 : Then `sh_optind' is the index in ARGV of the first ARGV-element
98 : that is not an option.
99 :
100 : OPTSTRING is a string containing the legitimate option characters.
101 : If an option character is seen that is not listed in OPTSTRING,
102 : return '?' after printing an error message. If you set `sh_opterr' to
103 : zero, the error message is suppressed but we still return '?'.
104 :
105 : If a char in OPTSTRING is followed by a colon, that means it wants an arg,
106 : so the following text in the same ARGV-element, or the text of the following
107 : ARGV-element, is returned in `sh_optarg'. */
108 :
109 : /* 1003.2 specifies the format of this message. */
110 : #define BADOPT(x) fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], x)
111 : #define NEEDARG(x) fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], x)
112 :
113 : int
114 0 : sh_getopt (argc, argv, optstring)
115 : int argc;
116 : char *const *argv;
117 : const char *optstring;
118 : {
119 0 : char c, *temp;
120 :
121 0 : sh_optarg = 0;
122 :
123 0 : if (sh_optind >= argc || sh_optind < 0) /* XXX was sh_optind > argc */
124 : {
125 0 : sh_optind = argc;
126 0 : return (EOF);
127 : }
128 :
129 : /* Initialize the internal data when the first call is made.
130 : Start processing options with ARGV-element 1 (since ARGV-element 0
131 : is the program name); the sequence of previously skipped
132 : non-option ARGV-elements is empty. */
133 :
134 0 : if (sh_optind == 0)
135 : {
136 0 : sh_optind = 1;
137 0 : nextchar = (char *)NULL;
138 : }
139 :
140 0 : if (nextchar == 0 || *nextchar == '\0')
141 : {
142 : /* If we have done all the ARGV-elements, stop the scan. */
143 0 : if (sh_optind >= argc)
144 : return EOF;
145 :
146 0 : temp = argv[sh_optind];
147 :
148 : /* Special ARGV-element `--' means premature end of options.
149 : Skip it like a null option, and return EOF. */
150 0 : if (temp[0] == '-' && temp[1] == '-' && temp[2] == '\0')
151 : {
152 0 : sh_optind++;
153 0 : return EOF;
154 : }
155 :
156 : /* If we have come to a non-option, either stop the scan or describe
157 : it to the caller and pass it by. This makes the pseudo-option
158 : `-' mean the end of options, but does not skip over it. */
159 0 : if (temp[0] != '-' || temp[1] == '\0')
160 : return EOF;
161 :
162 : /* We have found another option-ARGV-element.
163 : Start decoding its characters. */
164 0 : nextchar = argv[sh_curopt = sh_optind] + 1;
165 0 : sh_charindex = 1;
166 : }
167 :
168 : /* Look at and handle the next option-character. */
169 :
170 0 : c = *nextchar++; sh_charindex++;
171 0 : temp = strchr (optstring, c);
172 :
173 0 : sh_optopt = c;
174 :
175 : /* Increment `sh_optind' when we start to process its last character. */
176 0 : if (nextchar == 0 || *nextchar == '\0')
177 : {
178 0 : sh_optind++;
179 0 : nextchar = (char *)NULL;
180 : }
181 :
182 0 : if (sh_badopt = (temp == NULL || c == ':'))
183 : {
184 0 : if (sh_opterr)
185 0 : BADOPT (c);
186 :
187 0 : return '?';
188 : }
189 :
190 0 : if (temp[1] == ':')
191 : {
192 0 : if (nextchar && *nextchar)
193 : {
194 : /* This is an option that requires an argument. */
195 0 : sh_optarg = nextchar;
196 : /* If we end this ARGV-element by taking the rest as an arg,
197 : we must advance to the next element now. */
198 0 : sh_optind++;
199 : }
200 0 : else if (sh_optind == argc)
201 : {
202 0 : if (sh_opterr)
203 0 : NEEDARG (c);
204 :
205 0 : sh_optopt = c;
206 0 : sh_optarg = ""; /* Needed by getopts. */
207 0 : c = (optstring[0] == ':') ? ':' : '?';
208 : }
209 : else
210 : /* We already incremented `sh_optind' once;
211 : increment it again when taking next ARGV-elt as argument. */
212 0 : sh_optarg = argv[sh_optind++];
213 0 : nextchar = (char *)NULL;
214 : }
215 0 : return c;
216 : }
217 :
218 : void
219 0 : sh_getopt_restore_state (argv)
220 : char **argv;
221 : {
222 0 : if (nextchar)
223 0 : nextchar = argv[sh_curopt] + sh_charindex;
224 0 : }
225 :
226 : sh_getopt_state_t *
227 0 : sh_getopt_alloc_istate ()
228 : {
229 7489 : sh_getopt_state_t *ret;
230 :
231 0 : ret = (sh_getopt_state_t *)xmalloc (sizeof (sh_getopt_state_t));
232 7489 : return ret;
233 : }
234 :
235 : void
236 0 : sh_getopt_dispose_istate (gs)
237 : sh_getopt_state_t *gs;
238 : {
239 0 : free (gs);
240 0 : }
241 :
242 : sh_getopt_state_t *
243 7489 : sh_getopt_save_istate ()
244 : {
245 7489 : sh_getopt_state_t *ret;
246 :
247 7489 : ret = sh_getopt_alloc_istate ();
248 :
249 7489 : ret->gs_optarg = sh_optarg;
250 7489 : ret->gs_optind = sh_optind;
251 7489 : ret->gs_curopt = sh_curopt;
252 7489 : ret->gs_nextchar = nextchar; /* XXX */
253 7489 : ret->gs_charindex = sh_charindex;
254 7489 : ret->gs_flags = 0; /* XXX for later use */
255 :
256 7489 : return ret;
257 : }
258 :
259 : void
260 0 : sh_getopt_restore_istate (state)
261 : sh_getopt_state_t *state;
262 : {
263 0 : sh_optarg = state->gs_optarg;
264 0 : sh_optind = state->gs_optind;
265 0 : sh_curopt = state->gs_curopt;
266 0 : nextchar = state->gs_nextchar; /* XXX - probably not usable */
267 0 : sh_charindex = state->gs_charindex;
268 :
269 0 : sh_getopt_dispose_istate (state);
270 0 : }
271 :
272 : #if 0
273 : void
274 : sh_getopt_debug_restore_state (argv)
275 : char **argv;
276 : {
277 : if (nextchar && nextchar != argv[sh_curopt] + sh_charindex)
278 : {
279 : itrace("sh_getopt_debug_restore_state: resetting nextchar");
280 : nextchar = argv[sh_curopt] + sh_charindex;
281 : }
282 : }
283 : #endif
284 :
285 : #ifdef TEST
286 :
287 : /* Compile with -DTEST to make an executable for use in testing
288 : the above definition of `sh_getopt'. */
289 :
290 : int
291 : main (argc, argv)
292 : int argc;
293 : char **argv;
294 : {
295 : int c;
296 : int digit_sh_optind = 0;
297 :
298 : while (1)
299 : {
300 : int this_option_sh_optind = sh_optind ? sh_optind : 1;
301 :
302 : c = sh_getopt (argc, argv, "abc:d:0123456789");
303 : if (c == EOF)
304 : break;
305 :
306 : switch (c)
307 : {
308 : case '0':
309 : case '1':
310 : case '2':
311 : case '3':
312 : case '4':
313 : case '5':
314 : case '6':
315 : case '7':
316 : case '8':
317 : case '9':
318 : if (digit_sh_optind != 0 && digit_sh_optind != this_option_sh_optind)
319 : printf ("digits occur in two different argv-elements.\n");
320 : digit_sh_optind = this_option_sh_optind;
321 : printf ("option %c\n", c);
322 : break;
323 :
324 : case 'a':
325 : printf ("option a\n");
326 : break;
327 :
328 : case 'b':
329 : printf ("option b\n");
330 : break;
331 :
332 : case 'c':
333 : printf ("option c with value `%s'\n", sh_optarg);
334 : break;
335 :
336 : case '?':
337 : break;
338 :
339 : default:
340 : printf ("?? sh_getopt returned character code 0%o ??\n", c);
341 : }
342 : }
343 :
344 : if (sh_optind < argc)
345 : {
346 : printf ("non-option ARGV-elements: ");
347 : while (sh_optind < argc)
348 : printf ("%s ", argv[sh_optind++]);
349 : printf ("\n");
350 : }
351 :
352 : exit (0);
353 : }
354 :
355 : #endif /* TEST */
|