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