1 /* Declarations for getopt.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License
6 as published by the Free Software Foundation; either version 2, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18 // This file is part of the GNU Binutils package. Obviously, it's under
19 // the GPL. It's included for the benefit of people with extremely broken
20 // compilers, such as MSVC++, who otherwise could not compile this code.
21
22 #define _LIBC
23
24 #ifndef _NO_PROTO
25 #define _NO_PROTO
26 #endif
27
28 #ifdef HAVE_CONFIG_H
29 #if defined (emacs) || defined (CONFIG_BROKETS)
30 /* We use <config.h> instead of "config.h" so that a compilation
31 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
32 (which it would do because it found this file in $srcdir). */
33 #include <config.h>
34 #else
35 #include "config.h"
36 #endif
37 #endif
38
39 #ifndef __STDC__
40 #ifndef const
41 #define const
42 #endif
43 #endif
44
45 #include <stdio.h>
46 #include <string.h>
47
48 #if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
49 #ifdef __GNU_LIBRARY__
50 #include <stdlib.h>
51 #endif /* GNU C library. */
52
53 #include "getopt.h"
54
55 char *optarg = NULL;
56
57 int optind = 0;
58
59 static char *nextchar;
60
61 int opterr = 1;
62
63 int optopt = '?';
64
65 static enum
66 {
67 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
68 } ordering;
69
70 #ifdef __GNU_LIBRARY__
71 #include <string.h>
72 #define my_index strchr
73 #else
74
75 char *getenv ();
76
77 static char *
my_index(str,chr)78 my_index (str, chr)
79 const char *str;
80 int chr;
81 {
82 while (*str)
83 {
84 if (*str == chr)
85 return (char *) str;
86 str++;
87 }
88 return 0;
89 }
90
91 #ifdef __GNUC__
92 #ifndef __STDC__
93 extern int strlen (const char *);
94 #endif /* not __STDC__ */
95 #endif /* __GNUC__ */
96
97 #endif /* not __GNU_LIBRARY__ */
98
99 static int first_nonopt;
100 static int last_nonopt;
101
102 static void
exchange(argv)103 exchange (argv)
104 char **argv;
105 {
106 int bottom = first_nonopt;
107 int middle = last_nonopt;
108 int top = optind;
109 char *tem;
110
111 while (top > middle && middle > bottom)
112 {
113 if (top - middle > middle - bottom)
114 {
115 int len = middle - bottom;
116 register int i;
117
118 for (i = 0; i < len; i++)
119 {
120 tem = argv[bottom + i];
121 argv[bottom + i] = argv[top - (middle - bottom) + i];
122 argv[top - (middle - bottom) + i] = tem;
123 }
124 /* Exclude the moved bottom segment from further swapping. */
125 top -= len;
126 }
127 else
128 {
129 /* Top segment is the short one. */
130 int len = top - middle;
131 register int i;
132
133 /* Swap it with the bottom part of the bottom segment. */
134 for (i = 0; i < len; i++)
135 {
136 tem = argv[bottom + i];
137 argv[bottom + i] = argv[middle + i];
138 argv[middle + i] = tem;
139 }
140 /* Exclude the moved top segment from further swapping. */
141 bottom += len;
142 }
143 }
144
145 /* Update records for the slots the non-options now occupy. */
146
147 first_nonopt += (optind - last_nonopt);
148 last_nonopt = optind;
149 }
150
151 /* Initialize the internal data when the first call is made. */
152
153 static const char *
_getopt_initialize(optstring)154 _getopt_initialize (optstring)
155 const char *optstring;
156 {
157 first_nonopt = last_nonopt = optind = 1;
158
159 nextchar = NULL;
160
161 if (optstring[0] == '-')
162 {
163 ordering = RETURN_IN_ORDER;
164 ++optstring;
165 }
166 else if (optstring[0] == '+')
167 {
168 ordering = REQUIRE_ORDER;
169 ++optstring;
170 }
171 else if (getenv ("POSIXLY_CORRECT") != NULL)
172 ordering = REQUIRE_ORDER;
173 else
174 ordering = PERMUTE;
175
176 return optstring;
177 }
178
179 int
_getopt_internal(argc,argv,optstring,longopts,longind,long_only)180 _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
181 int argc;
182 char *const *argv;
183 const char *optstring;
184 const struct option *longopts;
185 int *longind;
186 int long_only;
187 {
188 optarg = NULL;
189
190 if (optind == 0)
191 optstring = _getopt_initialize (optstring);
192
193 if (argc == 0)
194 return EOF;
195
196 if (nextchar == NULL || *nextchar == '\0')
197 {
198 /* Advance to the next ARGV-element. */
199
200 if (ordering == PERMUTE)
201 {
202 /* If we have just processed some options following some non-options,
203 exchange them so that the options come first. */
204
205 if (first_nonopt != last_nonopt && last_nonopt != optind)
206 exchange ((char **) argv);
207 else if (last_nonopt != optind)
208 first_nonopt = optind;
209
210 /* Skip any additional non-options
211 and extend the range of non-options previously skipped. */
212
213 while (optind < argc
214 && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
215 optind++;
216 last_nonopt = optind;
217 }
218
219 if (optind != argc && !strcmp (argv[optind], "--"))
220 {
221 optind++;
222
223 if (first_nonopt != last_nonopt && last_nonopt != optind)
224 exchange ((char **) argv);
225 else if (first_nonopt == last_nonopt)
226 first_nonopt = optind;
227 last_nonopt = argc;
228
229 optind = argc;
230 }
231
232 /* If we have done all the ARGV-elements, stop the scan
233 and back over any non-options that we skipped and permuted. */
234
235 if (optind == argc)
236 {
237 /* Set the next-arg-index to point at the non-options
238 that we previously skipped, so the caller will digest them. */
239 if (first_nonopt != last_nonopt)
240 optind = first_nonopt;
241 return EOF;
242 }
243
244 /* If we have come to a non-option and did not permute it,
245 either stop the scan or describe it to the caller and pass it by. */
246
247 if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
248 {
249 if (ordering == REQUIRE_ORDER)
250 return EOF;
251 optarg = argv[optind++];
252 return 1;
253 }
254
255 /* We have found another option-ARGV-element.
256 Skip the initial punctuation. */
257
258 nextchar = (argv[optind] + 1
259 + (longopts != NULL && argv[optind][1] == '-'));
260 }
261
262 if (longopts != NULL
263 && (argv[optind][1] == '-'
264 || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
265 {
266 char *nameend;
267 const struct option *p;
268 const struct option *pfound = NULL;
269 int exact = 0;
270 int ambig = 0;
271 int indfound;
272 int option_index;
273
274 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
275 /* Do nothing. */ ;
276
277 /* Test all long options for either exact match
278 or abbreviated matches. */
279 for (p = longopts, option_index = 0; p->name; p++, option_index++)
280 if (!strncmp (p->name, nextchar, nameend - nextchar))
281 {
282 if (nameend - nextchar == strlen (p->name))
283 {
284 /* Exact match found. */
285 pfound = p;
286 indfound = option_index;
287 exact = 1;
288 break;
289 }
290 else if (pfound == NULL)
291 {
292 /* First nonexact match found. */
293 pfound = p;
294 indfound = option_index;
295 }
296 else
297 /* Second or later nonexact match found. */
298 ambig = 1;
299 }
300
301 if (ambig && !exact)
302 {
303 if (opterr)
304 fprintf (stderr, "%s: option `%s' is ambiguous\n",
305 argv[0], argv[optind]);
306 nextchar += strlen (nextchar);
307 optind++;
308 return '?';
309 }
310
311 if (pfound != NULL)
312 {
313 option_index = indfound;
314 optind++;
315 if (*nameend)
316 {
317 /* Don't test has_arg with >, because some C compilers don't
318 allow it to be used on enums. */
319 if (pfound->has_arg)
320 optarg = nameend + 1;
321 else
322 {
323 if (opterr)
324 {
325 if (argv[optind - 1][1] == '-')
326 /* --option */
327 fprintf (stderr,
328 "%s: option `--%s' doesn't allow an argument\n",
329 argv[0], pfound->name);
330 else
331 /* +option or -option */
332 fprintf (stderr,
333 "%s: option `%c%s' doesn't allow an argument\n",
334 argv[0], argv[optind - 1][0], pfound->name);
335 }
336 nextchar += strlen (nextchar);
337 return '?';
338 }
339 }
340 else if (pfound->has_arg == 1)
341 {
342 if (optind < argc)
343 optarg = argv[optind++];
344 else
345 {
346 if (opterr)
347 fprintf (stderr, "%s: option `%s' requires an argument\n",
348 argv[0], argv[optind - 1]);
349 nextchar += strlen (nextchar);
350 return optstring[0] == ':' ? ':' : '?';
351 }
352 }
353 nextchar += strlen (nextchar);
354 if (longind != NULL)
355 *longind = option_index;
356 if (pfound->flag)
357 {
358 *(pfound->flag) = pfound->val;
359 return 0;
360 }
361 return pfound->val;
362 }
363
364 if (!long_only || argv[optind][1] == '-'
365 || my_index (optstring, *nextchar) == NULL)
366 {
367 if (opterr)
368 {
369 if (argv[optind][1] == '-')
370 /* --option */
371 fprintf (stderr, "%s: unrecognized option `--%s'\n",
372 argv[0], nextchar);
373 else
374 /* +option or -option */
375 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
376 argv[0], argv[optind][0], nextchar);
377 }
378 nextchar = (char *) "";
379 optind++;
380 return '?';
381 }
382 }
383
384 /* Look at and handle the next short option-character. */
385
386 {
387 char c = *nextchar++;
388 char *temp = my_index (optstring, c);
389
390 /* Increment `optind' when we start to process its last character. */
391 if (*nextchar == '\0')
392 ++optind;
393
394 if (temp == NULL || c == ':')
395 {
396 if (opterr)
397 {
398 /* 1003.2 specifies the format of this message. */
399 fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
400 }
401 optopt = c;
402 return '?';
403 }
404 if (temp[1] == ':')
405 {
406 if (temp[2] == ':')
407 {
408 /* This is an option that accepts an argument optionally. */
409 if (*nextchar != '\0')
410 {
411 optarg = nextchar;
412 optind++;
413 }
414 else
415 optarg = NULL;
416 nextchar = NULL;
417 }
418 else
419 {
420 /* This is an option that requires an argument. */
421 if (*nextchar != '\0')
422 {
423 optarg = nextchar;
424 /* If we end this ARGV-element by taking the rest as an arg,
425 we must advance to the next element now. */
426 optind++;
427 }
428 else if (optind == argc)
429 {
430 if (opterr)
431 {
432 /* 1003.2 specifies the format of this message. */
433 fprintf (stderr, "%s: option requires an argument -- %c\n",
434 argv[0], c);
435 }
436 optopt = c;
437 if (optstring[0] == ':')
438 c = ':';
439 else
440 c = '?';
441 }
442 else
443 /* We already incremented `optind' once;
444 increment it again when taking next ARGV-elt as argument. */
445 optarg = argv[optind++];
446 nextchar = NULL;
447 }
448 }
449 return c;
450 }
451 }
452
453 int
getopt(argc,argv,optstring)454 getopt (argc, argv, optstring)
455 int argc;
456 char *const *argv;
457 const char *optstring;
458 {
459 return _getopt_internal (argc, argv, optstring,
460 (const struct option *) 0,
461 (int *) 0,
462 0);
463 }
464
465 #endif /* _LIBC or not __GNU_LIBRARY__. */
466
467