]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/getopts.def
Imported from ../bash-2.05a.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
83 /* getopts_reset is magic code for when OPTIND is reset. N is the
84 value that has just been assigned to OPTIND. */
85 void
86 getopts_reset (newind)
87 int newind;
88 {
89 sh_optind = newind;
90 sh_badopt = 0;
91 }
92
93 static int
94 getopts_bind_variable (name, value)
95 char *name, *value;
96 {
97 SHELL_VAR *v;
98
99 if (legal_identifier (name))
100 {
101 v = bind_variable (name, value);
102 return (v && (readonly_p (v) == 0)) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
103 }
104 else
105 {
106 builtin_error ("`%s': not a valid identifier", name);
107 return (EXECUTION_FAILURE);
108 }
109 }
110
111 /* Error handling is now performed as specified by Posix.2, draft 11
112 (identical to that of ksh-88). The special handling is enabled if
113 the first character of the option string is a colon; this handling
114 disables diagnostic messages concerning missing option arguments
115 and illegal option characters. The handling is as follows.
116
117 ILLEGAL OPTIONS:
118 name -> "?"
119 if (special_error) then
120 OPTARG = option character found
121 no error output
122 else
123 OPTARG unset
124 diagnostic message
125 fi
126
127 MISSING OPTION ARGUMENT;
128 if (special_error) then
129 name -> ":"
130 OPTARG = option character found
131 else
132 name -> "?"
133 OPTARG unset
134 diagnostic message
135 fi
136 */
137
138 static int
139 dogetopts (argc, argv)
140 int argc;
141 char **argv;
142 {
143 int ret, special_error, old_opterr, i, n;
144 char strval[2], numval[16];
145 char *optstr; /* list of options */
146 char *name; /* variable to get flag val */
147 char *t;
148
149 if (argc < 3)
150 {
151 builtin_usage ();
152 return (EX_USAGE);
153 }
154
155 /* argv[0] is "getopts". */
156
157 optstr = argv[1];
158 name = argv[2];
159 argc -= 2;
160 argv += 2;
161
162 special_error = optstr[0] == ':';
163
164 if (special_error)
165 {
166 old_opterr = sh_opterr;
167 optstr++;
168 sh_opterr = 0; /* suppress diagnostic messages */
169 }
170
171 if (argc > 1)
172 {
173 sh_getopt_restore_state (argv);
174 t = argv[0];
175 argv[0] = dollar_vars[0];
176 ret = sh_getopt (argc, argv, optstr);
177 argv[0] = t;
178 }
179 else if (rest_of_args == (WORD_LIST *)NULL)
180 {
181 for (i = 0; i < 10 && dollar_vars[i]; i++)
182 ;
183
184 sh_getopt_restore_state (dollar_vars);
185 ret = sh_getopt (i, dollar_vars, optstr);
186 }
187 else
188 {
189 register WORD_LIST *words;
190 char **v;
191
192 for (i = 0; i < 10 && dollar_vars[i]; i++)
193 ;
194 for (words = rest_of_args; words; words = words->next, i++)
195 ;
196 v = alloc_array (i + 1);
197 for (i = 0; i < 10 && dollar_vars[i]; i++)
198 v[i] = dollar_vars[i];
199 for (words = rest_of_args; words; words = words->next, i++)
200 v[i] = words->word->word;
201 v[i] = (char *)NULL;
202 sh_getopt_restore_state (v);
203 ret = sh_getopt (i, v, optstr);
204 free (v);
205 }
206
207 if (special_error)
208 sh_opterr = old_opterr;
209
210 /* Set the OPTIND variable in any case, to handle "--" skipping. */
211 if (sh_optind < 10)
212 {
213 numval[14] = sh_optind + '0';
214 numval[15] = '\0';
215 i = 14;
216 }
217 else
218 {
219 numval[i = 15] = '\0';
220 n = sh_optind;
221 do
222 {
223 numval[--i] = (n % 10) + '0';
224 }
225 while (n /= 10);
226 }
227 bind_variable ("OPTIND", numval + i);
228
229 /* If an error occurred, decide which one it is and set the return
230 code appropriately. In all cases, the option character in error
231 is in OPTOPT. If an illegal option was encountered, OPTARG is
232 NULL. If a required option argument was missing, OPTARG points
233 to a NULL string (that is, sh_optarg[0] == 0). */
234 if (ret == '?')
235 {
236 if (sh_optarg == NULL)
237 ret = G_ILLEGAL_OPT;
238 else if (sh_optarg[0] == '\0')
239 ret = G_ARG_MISSING;
240 }
241
242 if (ret == G_EOF)
243 {
244 getopts_bind_variable (name, "?");
245 return (EXECUTION_FAILURE);
246 }
247
248 if (ret == G_ILLEGAL_OPT)
249 {
250 /* Illegal option encountered. */
251 ret = getopts_bind_variable (name, "?");
252
253 if (special_error)
254 {
255 strval[0] = (char)sh_optopt;
256 strval[1] = '\0';
257 bind_variable ("OPTARG", strval);
258 }
259 else
260 makunbound ("OPTARG", shell_variables);
261
262 return (ret);
263 }
264
265 if (ret == G_ARG_MISSING)
266 {
267 /* Required argument missing. */
268 if (special_error)
269 {
270 ret = getopts_bind_variable (name, ":");
271
272 strval[0] = (char)sh_optopt;
273 strval[1] = '\0';
274 bind_variable ("OPTARG", strval);
275 }
276 else
277 {
278 ret = getopts_bind_variable (name, "?");
279 makunbound ("OPTARG", shell_variables);
280 }
281 return (ret);
282 }
283
284 bind_variable ("OPTARG", sh_optarg);
285
286 strval[0] = (char) ret;
287 strval[1] = '\0';
288 return (getopts_bind_variable (name, strval));
289 }
290
291 /* The getopts builtin. Build an argv, and call dogetopts with it. */
292 int
293 getopts_builtin (list)
294 WORD_LIST *list;
295 {
296 char **av;
297 int ac, ret;
298
299 if (list == 0)
300 {
301 builtin_usage ();
302 return EX_USAGE;
303 }
304
305 reset_internal_getopt ();
306 if (internal_getopt (list, "") != -1)
307 {
308 builtin_usage ();
309 return (EX_USAGE);
310 }
311 list = loptend;
312
313 av = make_builtin_argv (list, &ac);
314 ret = dogetopts (ac, av);
315 free ((char *)av);
316
317 return (ret);
318 }