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