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