]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is getopts.def, from which is created getopts.c. |
2 | It implements the builtin "getopts" in Bash. | |
3 | ||
4 | Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. | |
5 | ||
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
8 | Bash is free software; you can redistribute it and/or modify it under | |
9 | the terms of the GNU General Public License as published by the Free | |
bb70624e | 10 | Software Foundation; either version 2, or (at your option) any later |
726f6388 JA |
11 | version. |
12 | ||
13 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License along | |
19 | with Bash; see the file COPYING. If not, write to the Free Software | |
bb70624e | 20 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
726f6388 JA |
21 | |
22 | $PRODUCES getopts.c | |
23 | ||
24 | $BUILTIN getopts | |
726f6388 JA |
25 | $FUNCTION getopts_builtin |
26 | $SHORT_DOC getopts optstring name [arg] | |
27 | Getopts is used by shell procedures to parse positional parameters. | |
28 | ||
29 | OPTSTRING contains the option letters to be recognized; if a letter | |
30 | is followed by a colon, the option is expected to have an argument, | |
31 | which should be separated from it by white space. | |
32 | ||
33 | Each time it is invoked, getopts will place the next option in the | |
34 | shell variable $name, initializing name if it does not exist, and | |
35 | the index of the next argument to be processed into the shell | |
36 | variable OPTIND. OPTIND is initialized to 1 each time the shell or | |
37 | a shell script is invoked. When an option requires an argument, | |
38 | getopts places that argument into the shell variable OPTARG. | |
39 | ||
40 | getopts reports errors in one of two ways. If the first character | |
41 | of OPTSTRING is a colon, getopts uses silent error reporting. In | |
42 | this mode, no error messages are printed. If an illegal option is | |
43 | seen, getopts places the option character found into OPTARG. If a | |
44 | required argument is not found, getopts places a ':' into NAME and | |
45 | sets OPTARG to the option character found. If getopts is not in | |
46 | silent mode, and an illegal option is seen, getopts places '?' into | |
47 | NAME and unsets OPTARG. If a required option is not found, a '?' | |
48 | is placed in NAME, OPTARG is unset, and a diagnostic message is | |
49 | printed. | |
50 | ||
51 | If the shell variable OPTERR has the value 0, getopts disables the | |
52 | printing of error messages, even if the first character of | |
53 | OPTSTRING is not a colon. OPTERR has the value 1 by default. | |
54 | ||
55 | Getopts normally parses the positional parameters ($0 - $9), but if | |
56 | more arguments are given, they are parsed instead. | |
57 | $END | |
58 | ||
ccc6cda3 JA |
59 | #include <config.h> |
60 | ||
726f6388 JA |
61 | #include <stdio.h> |
62 | ||
ccc6cda3 | 63 | #if defined (HAVE_UNISTD_H) |
cce855bc JA |
64 | # ifdef _MINIX |
65 | # include <sys/types.h> | |
66 | # endif | |
ccc6cda3 JA |
67 | # include <unistd.h> |
68 | #endif | |
726f6388 | 69 | |
ccc6cda3 | 70 | #include "../bashansi.h" |
726f6388 | 71 | |
ccc6cda3 JA |
72 | #include "../shell.h" |
73 | #include "common.h" | |
74 | #include "bashgetopt.h" | |
726f6388 JA |
75 | #include "getopt.h" |
76 | ||
ccc6cda3 JA |
77 | #define G_EOF -1 |
78 | #define G_ILLEGAL_OPT -2 | |
79 | #define G_ARG_MISSING -3 | |
726f6388 JA |
80 | |
81 | extern char *this_command_name; | |
82 | extern WORD_LIST *rest_of_args; | |
83 | ||
84 | /* getopts_reset is magic code for when OPTIND is reset. N is the | |
85 | value that has just been assigned to OPTIND. */ | |
86 | void | |
87 | getopts_reset (newind) | |
88 | int newind; | |
89 | { | |
90 | sh_optind = newind; | |
ccc6cda3 JA |
91 | sh_badopt = 0; |
92 | } | |
93 | ||
94 | static int | |
95 | getopts_bind_variable (name, value) | |
96 | char *name, *value; | |
97 | { | |
98 | SHELL_VAR *v; | |
99 | ||
100 | if (legal_identifier (name)) | |
101 | { | |
102 | v = bind_variable (name, value); | |
103 | return (v && (readonly_p (v) == 0)) ? EXECUTION_SUCCESS : EXECUTION_FAILURE; | |
104 | } | |
105 | else | |
106 | { | |
107 | builtin_error ("`%s': not a valid identifier", name); | |
108 | return (EXECUTION_FAILURE); | |
109 | } | |
726f6388 JA |
110 | } |
111 | ||
112 | /* Error handling is now performed as specified by Posix.2, draft 11 | |
113 | (identical to that of ksh-88). The special handling is enabled if | |
114 | the first character of the option string is a colon; this handling | |
115 | disables diagnostic messages concerning missing option arguments | |
116 | and illegal option characters. The handling is as follows. | |
117 | ||
118 | ILLEGAL OPTIONS: | |
119 | name -> "?" | |
120 | if (special_error) then | |
121 | OPTARG = option character found | |
122 | no error output | |
123 | else | |
124 | OPTARG unset | |
125 | diagnostic message | |
126 | fi | |
127 | ||
128 | MISSING OPTION ARGUMENT; | |
129 | if (special_error) then | |
130 | name -> ":" | |
131 | OPTARG = option character found | |
132 | else | |
133 | name -> "?" | |
134 | OPTARG unset | |
135 | diagnostic message | |
136 | fi | |
137 | */ | |
138 | ||
139 | static int | |
140 | dogetopts (argc, argv) | |
141 | int argc; | |
142 | char **argv; | |
143 | { | |
ccc6cda3 | 144 | int ret, special_error, old_opterr, i, n; |
726f6388 JA |
145 | char strval[2], numval[16]; |
146 | char *optstr; /* list of options */ | |
147 | char *name; /* variable to get flag val */ | |
148 | char *t; | |
149 | ||
150 | if (argc < 3) | |
151 | { | |
ccc6cda3 | 152 | builtin_usage (); |
726f6388 JA |
153 | return (EX_USAGE); |
154 | } | |
155 | ||
156 | /* argv[0] is "getopts". */ | |
157 | ||
158 | optstr = argv[1]; | |
159 | name = argv[2]; | |
160 | argc -= 2; | |
161 | argv += 2; | |
162 | ||
163 | special_error = optstr[0] == ':'; | |
164 | ||
165 | if (special_error) | |
166 | { | |
167 | old_opterr = sh_opterr; | |
168 | optstr++; | |
169 | sh_opterr = 0; /* suppress diagnostic messages */ | |
170 | } | |
171 | ||
172 | if (argc > 1) | |
173 | { | |
174 | sh_getopt_restore_state (argv); | |
175 | t = argv[0]; | |
176 | argv[0] = dollar_vars[0]; | |
177 | ret = sh_getopt (argc, argv, optstr); | |
178 | argv[0] = t; | |
179 | } | |
180 | else if (rest_of_args == (WORD_LIST *)NULL) | |
181 | { | |
ccc6cda3 JA |
182 | for (i = 0; i < 10 && dollar_vars[i]; i++) |
183 | ; | |
b72432fd JA |
184 | |
185 | sh_getopt_restore_state (dollar_vars); | |
726f6388 JA |
186 | ret = sh_getopt (i, dollar_vars, optstr); |
187 | } | |
188 | else | |
189 | { | |
726f6388 JA |
190 | register WORD_LIST *words; |
191 | char **v; | |
192 | ||
ccc6cda3 JA |
193 | for (i = 0; i < 10 && dollar_vars[i]; i++) |
194 | ; | |
195 | for (words = rest_of_args; words; words = words->next, i++) | |
196 | ; | |
bb70624e | 197 | v = alloc_array (i + 1); |
726f6388 | 198 | for (i = 0; i < 10 && dollar_vars[i]; i++) |
28ef6c31 | 199 | v[i] = dollar_vars[i]; |
726f6388 | 200 | for (words = rest_of_args; words; words = words->next, i++) |
28ef6c31 | 201 | v[i] = words->word->word; |
726f6388 | 202 | v[i] = (char *)NULL; |
b72432fd | 203 | sh_getopt_restore_state (v); |
726f6388 JA |
204 | ret = sh_getopt (i, v, optstr); |
205 | free (v); | |
206 | } | |
207 | ||
208 | if (special_error) | |
209 | sh_opterr = old_opterr; | |
210 | ||
211 | /* Set the OPTIND variable in any case, to handle "--" skipping. */ | |
212 | if (sh_optind < 10) | |
213 | { | |
214 | numval[14] = sh_optind + '0'; | |
215 | numval[15] = '\0'; | |
216 | i = 14; | |
217 | } | |
218 | else | |
219 | { | |
220 | numval[i = 15] = '\0'; | |
221 | n = sh_optind; | |
222 | do | |
223 | { | |
224 | numval[--i] = (n % 10) + '0'; | |
225 | } | |
226 | while (n /= 10); | |
227 | } | |
228 | bind_variable ("OPTIND", numval + i); | |
229 | ||
230 | /* If an error occurred, decide which one it is and set the return | |
231 | code appropriately. In all cases, the option character in error | |
ccc6cda3 | 232 | is in OPTOPT. If an illegal option was encountered, OPTARG is |
726f6388 | 233 | NULL. If a required option argument was missing, OPTARG points |
ccc6cda3 | 234 | to a NULL string (that is, sh_optarg[0] == 0). */ |
726f6388 JA |
235 | if (ret == '?') |
236 | { | |
237 | if (sh_optarg == NULL) | |
238 | ret = G_ILLEGAL_OPT; | |
239 | else if (sh_optarg[0] == '\0') | |
240 | ret = G_ARG_MISSING; | |
241 | } | |
242 | ||
243 | if (ret == G_EOF) | |
244 | { | |
ccc6cda3 | 245 | getopts_bind_variable (name, "?"); |
726f6388 JA |
246 | return (EXECUTION_FAILURE); |
247 | } | |
248 | ||
249 | if (ret == G_ILLEGAL_OPT) | |
250 | { | |
251 | /* Illegal option encountered. */ | |
ccc6cda3 | 252 | ret = getopts_bind_variable (name, "?"); |
726f6388 JA |
253 | |
254 | if (special_error) | |
255 | { | |
ccc6cda3 | 256 | strval[0] = (char)sh_optopt; |
726f6388 JA |
257 | strval[1] = '\0'; |
258 | bind_variable ("OPTARG", strval); | |
259 | } | |
260 | else | |
261 | makunbound ("OPTARG", shell_variables); | |
ccc6cda3 JA |
262 | |
263 | return (ret); | |
726f6388 JA |
264 | } |
265 | ||
266 | if (ret == G_ARG_MISSING) | |
267 | { | |
268 | /* Required argument missing. */ | |
269 | if (special_error) | |
270 | { | |
ccc6cda3 | 271 | ret = getopts_bind_variable (name, ":"); |
726f6388 | 272 | |
ccc6cda3 | 273 | strval[0] = (char)sh_optopt; |
726f6388 JA |
274 | strval[1] = '\0'; |
275 | bind_variable ("OPTARG", strval); | |
276 | } | |
277 | else | |
278 | { | |
ccc6cda3 | 279 | ret = getopts_bind_variable (name, "?"); |
726f6388 JA |
280 | makunbound ("OPTARG", shell_variables); |
281 | } | |
ccc6cda3 | 282 | return (ret); |
726f6388 JA |
283 | } |
284 | ||
285 | bind_variable ("OPTARG", sh_optarg); | |
286 | ||
287 | strval[0] = (char) ret; | |
288 | strval[1] = '\0'; | |
ccc6cda3 | 289 | return (getopts_bind_variable (name, strval)); |
726f6388 JA |
290 | } |
291 | ||
292 | /* The getopts builtin. Build an argv, and call dogetopts with it. */ | |
293 | int | |
294 | getopts_builtin (list) | |
295 | WORD_LIST *list; | |
296 | { | |
726f6388 JA |
297 | char **av; |
298 | int ac, ret; | |
726f6388 JA |
299 | |
300 | if (list == 0) | |
d166f048 JA |
301 | { |
302 | builtin_usage (); | |
303 | return EX_USAGE; | |
304 | } | |
726f6388 | 305 | |
ccc6cda3 JA |
306 | reset_internal_getopt (); |
307 | while ((ret = internal_getopt (list, "")) != -1) | |
308 | { | |
309 | switch (ret) | |
310 | { | |
311 | default: | |
312 | builtin_usage (); | |
313 | return (EX_USAGE); | |
314 | } | |
315 | } | |
316 | list = loptend; | |
726f6388 | 317 | |
ccc6cda3 | 318 | av = make_builtin_argv (list, &ac); |
726f6388 JA |
319 | ret = dogetopts (ac, av); |
320 | free ((char *)av); | |
ccc6cda3 | 321 | |
726f6388 JA |
322 | return (ret); |
323 | } |