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