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