source: vendor/bash/3.1/builtins/getopt.c

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 8.0 KB
Line 
1/* getopt for BASH.
2
3 Copyright (C) 1993, 1994
4 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
19
20#include <config.h>
21
22#if defined (HAVE_UNISTD_H)
23# ifdef _MINIX
24# include <sys/types.h>
25# endif
26# include <unistd.h>
27#endif
28
29#include <stdio.h>
30#include "memalloc.h"
31#include "../bashintl.h"
32#include "../shell.h"
33#include "getopt.h"
34
35/* For communication from `sh_getopt' to the caller.
36 When `sh_getopt' finds an option that takes an argument,
37 the argument value is returned here. */
38char *sh_optarg = 0;
39
40/* Index in ARGV of the next element to be scanned.
41 This is used for communication to and from the caller
42 and for communication between successive calls to `sh_getopt'.
43
44 On entry to `sh_getopt', zero means this is the first call; initialize.
45
46 When `sh_getopt' returns EOF, this is the index of the first of the
47 non-option elements that the caller should itself scan.
48
49 Otherwise, `sh_optind' communicates from one call to the next
50 how much of ARGV has been scanned so far. */
51
52/* XXX 1003.2 says this must be 1 before any call. */
53int sh_optind = 0;
54
55/* Index of the current argument. */
56static int sh_curopt;
57
58/* The next char to be scanned in the option-element
59 in which the last option character we returned was found.
60 This allows us to pick up the scan where we left off.
61
62 If this is zero, or a null string, it means resume the scan
63 by advancing to the next ARGV-element. */
64
65static char *nextchar;
66static int sh_charindex;
67
68/* Callers store zero here to inhibit the error message
69 for unrecognized options. */
70
71int sh_opterr = 1;
72
73/* Set to an option character which was unrecognized.
74 This must be initialized on some systems to avoid linking in the
75 system's own getopt implementation. */
76
77int sh_optopt = '?';
78
79/* Set to 1 when we see an invalid option; public so getopts can reset it. */
80int sh_badopt = 0;
81
82/* Scan elements of ARGV (whose length is ARGC) for option characters
83 given in OPTSTRING.
84
85 If an element of ARGV starts with '-', and is not exactly "-" or "--",
86 then it is an option element. The characters of this element
87 (aside from the initial '-') are option characters. If `sh_getopt'
88 is called repeatedly, it returns successively each of the option characters
89 from each of the option elements.
90
91 If `sh_getopt' finds another option character, it returns that character,
92 updating `sh_optind' and `nextchar' so that the next call to `sh_getopt' can
93 resume the scan with the following option character or ARGV-element.
94
95 If there are no more option characters, `sh_getopt' returns `EOF'.
96 Then `sh_optind' is the index in ARGV of the first ARGV-element
97 that is not an option.
98
99 OPTSTRING is a string containing the legitimate option characters.
100 If an option character is seen that is not listed in OPTSTRING,
101 return '?' after printing an error message. If you set `sh_opterr' to
102 zero, the error message is suppressed but we still return '?'.
103
104 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
105 so the following text in the same ARGV-element, or the text of the following
106 ARGV-element, is returned in `sh_optarg'. */
107
108/* 1003.2 specifies the format of this message. */
109#define BADOPT(x) fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], x)
110#define NEEDARG(x) fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], x)
111
112int
113sh_getopt (argc, argv, optstring)
114 int argc;
115 char *const *argv;
116 const char *optstring;
117{
118 char c, *temp;
119
120 sh_optarg = 0;
121
122 if (sh_optind >= argc || sh_optind < 0) /* XXX was sh_optind > argc */
123 {
124 sh_optind = argc;
125 return (EOF);
126 }
127
128 /* Initialize the internal data when the first call is made.
129 Start processing options with ARGV-element 1 (since ARGV-element 0
130 is the program name); the sequence of previously skipped
131 non-option ARGV-elements is empty. */
132
133 if (sh_optind == 0)
134 {
135 sh_optind = 1;
136 nextchar = (char *)NULL;
137 }
138
139 if (nextchar == 0 || *nextchar == '\0')
140 {
141 /* If we have done all the ARGV-elements, stop the scan. */
142 if (sh_optind >= argc)
143 return EOF;
144
145 temp = argv[sh_optind];
146
147 /* Special ARGV-element `--' means premature end of options.
148 Skip it like a null option, and return EOF. */
149 if (temp[0] == '-' && temp[1] == '-' && temp[2] == '\0')
150 {
151 sh_optind++;
152 return EOF;
153 }
154
155 /* If we have come to a non-option, either stop the scan or describe
156 it to the caller and pass it by. This makes the pseudo-option
157 `-' mean the end of options, but does not skip over it. */
158 if (temp[0] != '-' || temp[1] == '\0')
159 return EOF;
160
161 /* We have found another option-ARGV-element.
162 Start decoding its characters. */
163 nextchar = argv[sh_curopt = sh_optind] + 1;
164 sh_charindex = 1;
165 }
166
167 /* Look at and handle the next option-character. */
168
169 c = *nextchar++; sh_charindex++;
170 temp = strchr (optstring, c);
171
172 sh_optopt = c;
173
174 /* Increment `sh_optind' when we start to process its last character. */
175 if (nextchar == 0 || *nextchar == '\0')
176 {
177 sh_optind++;
178 nextchar = (char *)NULL;
179 }
180
181 if (sh_badopt = (temp == NULL || c == ':'))
182 {
183 if (sh_opterr)
184 BADOPT (c);
185
186 return '?';
187 }
188
189 if (temp[1] == ':')
190 {
191 if (nextchar && *nextchar)
192 {
193 /* This is an option that requires an argument. */
194 sh_optarg = nextchar;
195 /* If we end this ARGV-element by taking the rest as an arg,
196 we must advance to the next element now. */
197 sh_optind++;
198 }
199 else if (sh_optind == argc)
200 {
201 if (sh_opterr)
202 NEEDARG (c);
203
204 sh_optopt = c;
205 sh_optarg = ""; /* Needed by getopts. */
206 c = (optstring[0] == ':') ? ':' : '?';
207 }
208 else
209 /* We already incremented `sh_optind' once;
210 increment it again when taking next ARGV-elt as argument. */
211 sh_optarg = argv[sh_optind++];
212 nextchar = (char *)NULL;
213 }
214 return c;
215}
216
217void
218sh_getopt_restore_state (argv)
219 char **argv;
220{
221 if (nextchar)
222 nextchar = argv[sh_curopt] + sh_charindex;
223}
224
225#if 0
226void
227sh_getopt_debug_restore_state (argv)
228 char **argv;
229{
230 if (nextchar && nextchar != argv[sh_curopt] + sh_charindex)
231 {
232 itrace("sh_getopt_debug_restore_state: resetting nextchar");
233 nextchar = argv[sh_curopt] + sh_charindex;
234 }
235}
236#endif
237
238#ifdef TEST
239
240/* Compile with -DTEST to make an executable for use in testing
241 the above definition of `sh_getopt'. */
242
243int
244main (argc, argv)
245 int argc;
246 char **argv;
247{
248 int c;
249 int digit_sh_optind = 0;
250
251 while (1)
252 {
253 int this_option_sh_optind = sh_optind ? sh_optind : 1;
254
255 c = sh_getopt (argc, argv, "abc:d:0123456789");
256 if (c == EOF)
257 break;
258
259 switch (c)
260 {
261 case '0':
262 case '1':
263 case '2':
264 case '3':
265 case '4':
266 case '5':
267 case '6':
268 case '7':
269 case '8':
270 case '9':
271 if (digit_sh_optind != 0 && digit_sh_optind != this_option_sh_optind)
272 printf ("digits occur in two different argv-elements.\n");
273 digit_sh_optind = this_option_sh_optind;
274 printf ("option %c\n", c);
275 break;
276
277 case 'a':
278 printf ("option a\n");
279 break;
280
281 case 'b':
282 printf ("option b\n");
283 break;
284
285 case 'c':
286 printf ("option c with value `%s'\n", sh_optarg);
287 break;
288
289 case '?':
290 break;
291
292 default:
293 printf ("?? sh_getopt returned character code 0%o ??\n", c);
294 }
295 }
296
297 if (sh_optind < argc)
298 {
299 printf ("non-option ARGV-elements: ");
300 while (sh_optind < argc)
301 printf ("%s ", argv[sh_optind++]);
302 printf ("\n");
303 }
304
305 exit (0);
306}
307
308#endif /* TEST */
Note: See TracBrowser for help on using the repository browser.