]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/getopts.def
Imported from ../bash-2.05.tar.gz.
[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, 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
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 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
59 #include <config.h>
60
61 #include <stdio.h>
62
63 #if defined (HAVE_UNISTD_H)
64 # ifdef _MINIX
65 # include <sys/types.h>
66 # endif
67 # include <unistd.h>
68 #endif
69
70 #include "../bashansi.h"
71
72 #include "../shell.h"
73 #include "common.h"
74 #include "bashgetopt.h"
75 #include "getopt.h"
76
77 #define G_EOF -1
78 #define G_ILLEGAL_OPT -2
79 #define G_ARG_MISSING -3
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;
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 }
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 {
144 int ret, special_error, old_opterr, i, n;
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 {
152 builtin_usage ();
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 {
182 for (i = 0; i < 10 && dollar_vars[i]; i++)
183 ;
184
185 sh_getopt_restore_state (dollar_vars);
186 ret = sh_getopt (i, dollar_vars, optstr);
187 }
188 else
189 {
190 register WORD_LIST *words;
191 char **v;
192
193 for (i = 0; i < 10 && dollar_vars[i]; i++)
194 ;
195 for (words = rest_of_args; words; words = words->next, i++)
196 ;
197 v = alloc_array (i + 1);
198 for (i = 0; i < 10 && dollar_vars[i]; i++)
199 v[i] = dollar_vars[i];
200 for (words = rest_of_args; words; words = words->next, i++)
201 v[i] = words->word->word;
202 v[i] = (char *)NULL;
203 sh_getopt_restore_state (v);
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
232 is in OPTOPT. If an illegal option was encountered, OPTARG is
233 NULL. If a required option argument was missing, OPTARG points
234 to a NULL string (that is, sh_optarg[0] == 0). */
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 {
245 getopts_bind_variable (name, "?");
246 return (EXECUTION_FAILURE);
247 }
248
249 if (ret == G_ILLEGAL_OPT)
250 {
251 /* Illegal option encountered. */
252 ret = getopts_bind_variable (name, "?");
253
254 if (special_error)
255 {
256 strval[0] = (char)sh_optopt;
257 strval[1] = '\0';
258 bind_variable ("OPTARG", strval);
259 }
260 else
261 makunbound ("OPTARG", shell_variables);
262
263 return (ret);
264 }
265
266 if (ret == G_ARG_MISSING)
267 {
268 /* Required argument missing. */
269 if (special_error)
270 {
271 ret = getopts_bind_variable (name, ":");
272
273 strval[0] = (char)sh_optopt;
274 strval[1] = '\0';
275 bind_variable ("OPTARG", strval);
276 }
277 else
278 {
279 ret = getopts_bind_variable (name, "?");
280 makunbound ("OPTARG", shell_variables);
281 }
282 return (ret);
283 }
284
285 bind_variable ("OPTARG", sh_optarg);
286
287 strval[0] = (char) ret;
288 strval[1] = '\0';
289 return (getopts_bind_variable (name, strval));
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 {
297 char **av;
298 int ac, ret;
299
300 if (list == 0)
301 {
302 builtin_usage ();
303 return EX_USAGE;
304 }
305
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;
317
318 av = make_builtin_argv (list, &ac);
319 ret = dogetopts (ac, av);
320 free ((char *)av);
321
322 return (ret);
323 }