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