]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/getopts.def
Imported from ../bash-2.05.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
4Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
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
42this mode, no error messages are printed. If an illegal option is
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
46silent mode, and an illegal option is seen, getopts places '?' into
47NAME and unsets OPTARG. If a required option is not found, a '?'
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
JA
77#define G_EOF -1
78#define G_ILLEGAL_OPT -2
79#define G_ARG_MISSING -3
726f6388
JA
80
81extern char *this_command_name;
82extern 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. */
86void
87getopts_reset (newind)
88 int newind;
89{
90 sh_optind = newind;
ccc6cda3
JA
91 sh_badopt = 0;
92}
93
94static int
95getopts_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
139static int
140dogetopts (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. */
293int
294getopts_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}