533775af60bddd478a42cd6232f681c2337767da
[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 1, 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, 675 Mass Ave, Cambridge, MA 02139, 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       ret = sh_getopt (i, dollar_vars, optstr);
185     }
186   else
187     {
188       register WORD_LIST *words;
189       char **v;
190
191       for (i = 0; i < 10 && dollar_vars[i]; i++)
192         ;
193       for (words = rest_of_args; words; words = words->next, i++)
194         ;
195       v = (char **)xmalloc ((i + 1) * sizeof (char *));
196       for (i = 0; i < 10 && dollar_vars[i]; i++)
197         v[i] = dollar_vars[i];
198       for (words = rest_of_args; words; words = words->next, i++)
199         v[i] = words->word->word;
200       v[i] = (char *)NULL;
201       ret = sh_getopt (i, v, optstr);
202       free (v);
203     }
204
205   if (special_error)
206     sh_opterr = old_opterr;
207
208   /* Set the OPTIND variable in any case, to handle "--" skipping. */
209   if (sh_optind < 10)
210     {
211       numval[14] = sh_optind + '0';
212       numval[15] = '\0';
213       i = 14;
214     }
215   else
216     {
217       numval[i = 15] = '\0';
218       n = sh_optind;
219       do
220         {
221           numval[--i] = (n % 10) + '0';
222         }
223       while (n /= 10);
224     }
225   bind_variable ("OPTIND", numval + i);
226
227   /* If an error occurred, decide which one it is and set the return
228      code appropriately.  In all cases, the option character in error
229      is in OPTOPT.  If an illegal option was encountered, OPTARG is
230      NULL.  If a required option argument was missing, OPTARG points
231      to a NULL string (that is, sh_optarg[0] == 0). */
232   if (ret == '?')
233     {
234       if (sh_optarg == NULL)
235         ret = G_ILLEGAL_OPT;
236       else if (sh_optarg[0] == '\0')
237         ret = G_ARG_MISSING;
238     }
239             
240   if (ret == G_EOF)
241     {
242       getopts_bind_variable (name, "?");
243       return (EXECUTION_FAILURE);
244     }
245
246   if (ret == G_ILLEGAL_OPT)
247     {
248       /* Illegal option encountered. */
249       ret = getopts_bind_variable (name, "?");
250
251       if (special_error)
252         {
253           strval[0] = (char)sh_optopt;
254           strval[1] = '\0';
255           bind_variable ("OPTARG", strval);
256         }
257       else
258         makunbound ("OPTARG", shell_variables);
259
260       return (ret);
261     }
262
263   if (ret == G_ARG_MISSING)
264     {
265       /* Required argument missing. */
266       if (special_error)
267         {
268           ret = getopts_bind_variable (name, ":");
269
270           strval[0] = (char)sh_optopt;
271           strval[1] = '\0';
272           bind_variable ("OPTARG", strval);
273         }
274       else
275         {
276           ret = getopts_bind_variable (name, "?");
277           makunbound ("OPTARG", shell_variables);
278         }
279       return (ret);
280     }                   
281
282   bind_variable ("OPTARG", sh_optarg);
283
284   strval[0] = (char) ret;
285   strval[1] = '\0';
286   return (getopts_bind_variable (name, strval));
287 }
288
289 /* The getopts builtin.  Build an argv, and call dogetopts with it. */
290 int
291 getopts_builtin (list)
292      WORD_LIST *list;
293 {
294   char **av;
295   int ac, ret;
296
297   if (list == 0)
298     {
299       builtin_usage ();
300       return EX_USAGE;
301     }
302
303   reset_internal_getopt ();
304   while ((ret = internal_getopt (list, "")) != -1)
305     {
306       switch (ret)
307         {
308         default:
309           builtin_usage ();
310           return (EX_USAGE);
311         }
312     }
313   list = loptend;
314
315   av = make_builtin_argv (list, &ac);
316   ret = dogetopts (ac, av);
317   free ((char *)av);
318
319   return (ret);
320 }