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