0e881d24f3f2573776ed4690940c5fa02ac8b261
[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, 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 }