1 | /*****
2 | ** ** Module Header ******************************************************* **
3 | ** **
4 | ** Modules Revision 3.0 **
5 | ** Providing a flexible user environment **
6 | ** **
7 | ** File: getopt.c **
8 | ** First Edition: 1995/12/20 **
9 | ** **
10 | ** Authors: Jens Hamisch, jens@Strawberry.COM **
11 | ** **
12 | ** Description: getopt procedure for the Modules package **
13 | ** **
14 | ** Exports: getopt Recognition of commadn line options **
15 | ** **
16 | ** Notes: This is based on the 'Getopt for GNU' from the gcc-2.7.2 **
17 | ** compiler. It is preferred to the libc version, because it **
18 | ** provides 'long-options'. **
19 | ** **
20 | ** ************************************************************************ **
21 | ****/
22 | /** **/
23 | /** Getopt for GNU. **/
24 | /** NOTE: getopt is now part of the C library, so if you don't know what **/
25 | /** "Keep this file name-space clean" means, talk to roland"@gnu.ai.mit.edu **/
26 | /** before changing it! **/
27 | /** **/
28 | /** Copyright( C) 1987, 88, 89, 90, 91, 92, 93, 94, 95 **/
29 | /** Free Software Foundation, Inc. **/
30 | /** **/
31 | /** This program is free software; you can redistribute it and/or modify **/
32 | /** it under the terms of the GNU General Public License as published by **/
33 | /** the Free Software Foundation; either version 2, or( at your option) **/
34 | /** any later version. **/
35 | /** **/
36 | /** This program is distributed in the hope that it will be useful, **/
37 | /** but WITHOUT ANY WARRANTY; without even the implied warranty of **/
38 | /** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the **/
39 | /** GNU General Public License for more details. **/
40 | /** **/
41 | /** You should have received a copy of the GNU General Public License **/
42 | /** along with this program; if not, write to the Free Software **/
43 | /** Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. **/
44 | /** **/
45 | /** ************************************************************************ **/
46 |
47 | /** ** Copyright *********************************************************** **
48 | ** **
49 | ** Copyright 1991-1994 by John L. Furlan. **
50 | ** see LICENSE.GPL, which must be provided, for details **
51 | ** **
52 | ** ************************************************************************ **/
53 |
54 | static char Id[] = "@(#)$Id: getopt.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
55 | static void *UseId[] = { &UseId, Id };
56 |
57 | /** ************************************************************************ **/
58 | /** CONFIGURATION **/
59 | /** ************************************************************************ **/
60 |
61 | /**
62 | ** This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
63 | ** Ditto for AIX 3.2 and <stdlib.h>.
64 | **/
65 |
66 | #ifndef _NO_PROTO
67 | # define _NO_PROTO
68 | #endif
69 |
70 | #ifdef HAVE_CONFIG_H
71 | # include <config.h>
72 | #endif
73 |
74 | /**
75 | ** This is a separate conditional since some stdc systems
76 | ** reject `defined( const)'.
77 | **/
78 |
79 | #if !defined( __STDC__) || !__STDC__
80 | # ifndef const
81 | # define const
82 | # endif
83 | #endif
84 |
85 | /** ************************************************************************ **/
86 | /** HEADERS **/
87 | /** ************************************************************************ **/
88 |
89 | #include <stdio.h>
90 |
91 | /**
92 | ** Comment out all this code if we are using the GNU C Library, and are not
93 | ** actually compiling the library itself. This code is part of the GNU C
94 | ** Library, but also included in many other GNU distributions. Compiling
95 | ** and linking in this code is a waste when using the GNU C library
96 | ** ( especially if it is a shared library). Rather than having every GNU
97 | ** program understand `configure --with-gnu-libc' and omit the object files,
98 | ** it is simpler to just do this in the source for each such file.
99 | **
100 | ** All this conditional nonsense has been commented out, because this
101 | ** version of getopt has some module specific error handling that gets
102 | ** tested during the check. It's a nice sentiment, but it doesn't buy
103 | ** you much to not include this code in.
104 | **/
105 |
106 | /**
107 | ** This needs to come after some library #include
108 | ** to get __GNU_LIBRARY__ defined.
109 | **/
110 |
111 | /* #if defined( _LIBC) || !defined (__GNU_LIBRARY__) */
112 |
113 | /**
114 | ** Don't include stdlib.h for non-GNU C libraries because some of them
115 | ** contain conflicting prototypes for getopt.
116 | **/
117 |
118 | # ifdef __GNU_LIBRARY__
119 | # include <stdlib.h>
120 | # endif /* GNU C library. */
121 |
122 | /**
123 | ** This is for other GNU distributions with internationalized messages.
124 | ** When compiling libc, the _ macro is predefined.
125 | **/
126 |
127 | # ifndef _
128 | # ifdef HAVE_LIBINTL_H
129 | # include <libintl.h>
130 | # define _(msgid) gettext( msgid)
131 | # else
132 | # define _(msgid) (msgid)
133 | # endif
134 | # endif
135 |
136 | /**
137 | ** This version of `getopt' appears to the caller like standard Unix `getopt'
138 | ** but it behaves differently for the user, since it allows the user
139 | ** to intersperse the options with the other arguments.
140 | **
141 | ** As `getopt' works, it permutes the elements of ARGV so that,
142 | ** when it is done, all the options precede everything else. Thus
143 | ** all application programs are extended to handle flexible argument order.
144 | **
145 | ** Setting the environment variable POSIXLY_CORRECT disables permutation.
146 | ** Then the behavior is completely standard.
147 | **
148 | ** GNU application programs can use a third alternative mode in which
149 | ** they can distinguish the relative order of options and other arguments.
150 | **/
151 |
152 | # include "getopt.h"
153 |
154 | /**
155 | ** We want to avoid inclusion of string.h with non-GNU libraries
156 | ** because there are many ways it can cause trouble.
157 | ** On some systems, it contains special magic macros that don't work
158 | ** in GCC.
159 | **/
160 |
161 | # ifdef __GNU_LIBRARY__
162 | # include <string.h>
163 | # define my_index strchr
164 | # else
165 |
166 | /**
167 | ** Avoid depending on library functions or files whose names are
168 | ** inconsistent.
169 | **/
170 |
171 | char *getenv();
172 |
173 | static char *my_index( const char *str, int chr)
174 | {
175 | while( *str) {
176 | if( *str == chr)
177 | return( char *) str;
178 | str++;
179 | }
180 | return( 0);
181 | }
182 |
183 | /**
184 | ** If using GCC, we can safely declare strlen this way.
185 | ** If not using GCC, it is ok not to declare it.
186 | **
187 | ** Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
188 | ** That was relevant to code that was here before.
189 | **/
190 |
191 | # ifdef __GNUC__
192 | # if !defined( __STDC__) || !__STDC__
193 |
194 | /**
195 | ** gcc with -traditional declares the built-in strlen to return int,
196 | ** and has done so at least since version 2.4.5. -- rms.
197 | **/
198 |
199 | extern int strlen( const char *);
200 | # endif /* not __STDC__ */
201 | # endif /* __GNUC__ */
202 |
203 | # endif /* not __GNU_LIBRARY__ */
204 |
205 | /**
206 | ** Include the modules header in order to get all error messages
207 | **/
208 |
209 | #include "modules_def.h"
210 |
211 | /** ************************************************************************ **/
212 | /** LOCAL DATATYPES **/
213 | /** ************************************************************************ **/
214 |
215 | /** not applicable **/
216 |
217 | /** ************************************************************************ **/
218 | /** CONSTANTS **/
219 | /** ************************************************************************ **/
220 |
221 | /** not applicable **/
222 |
223 | /** ************************************************************************ **/
224 | /** MACROS **/
225 | /** ************************************************************************ **/
226 |
227 | /** not applicable **/
228 |
229 | /** ************************************************************************ **/
230 | /** GLOBAL DATA **/
231 | /** ************************************************************************ **/
232 |
233 | /**
234 | ** The following is required for compiling the TEST environment for the
235 | ** modules package
236 | **/
237 |
238 | #ifdef _MODULES_DEF_H
239 | # ifdef TEST
240 | char *g_current_module = "getopt";
241 | int linenum = 0;
242 | # endif
243 | #endif /** _MODULES_DEF_H **/
244 |
245 | /**
246 | ** For communication from `getopt' to the caller. When `getopt' finds an
247 | ** option that takes an argument, the argument value is returned here.
248 | ** Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element
249 | ** is returned here.
250 | **/
251 |
252 | char *optarg = NULL;
253 |
254 | /**
255 | ** Index in ARGV of the next element to be scanned. This is used for
256 | ** communication to and from the caller and for communication between
257 | ** successive calls to `getopt'.
258 | **
259 | ** On entry to `getopt', zero means this is the first call; initialize.
260 | **
261 | ** When `getopt' returns EOF, this is the index of the first of the
262 | ** non-option elements that the caller should itself scan.
263 | **
264 | ** Otherwise, `optind' communicates from one call to the next
265 | ** how much of ARGV has been scanned so far.
266 | **/
267 |
268 | /**
269 | ** XXX 1003.2 says this must be 1 before any call.
270 | **/
271 |
272 | int optind = 0;
273 |
274 | /**
275 | ** Callers store zero here to inhibit the error message for unrecognized
276 | ** options.
277 | **/
278 |
279 | int opterr = 1;
280 |
281 | /**
282 | ** Set to an option character which was unrecognized.
283 | ** This must be initialized on some systems to avoid linking in the
284 | ** system's own getopt implementation.
285 | **/
286 |
287 | int optopt = '?';
288 |
289 | /** ************************************************************************ **/
290 | /** LOCAL DATA **/
291 | /** ************************************************************************ **/
292 |
293 | #ifdef _MODULES_DEF_H
294 |
295 | /**
296 | ** Runtime information for the modules package
297 | **/
298 |
299 | static char module_name[] = "getopt.c"; /** File name of this module **/
300 |
301 | #ifdef _MODULES_DEF_H
302 | # if WITH_DEBUGGING_INIT
303 | static char _proc_exchange[] = "exchange";
304 | static char _proc_getopt_initialize[] = "_getopt_initialize";
305 | static char _proc_getopt_internal[] = " _getopt_internal";
306 | static char _proc_getopt[] = "getopt";
307 | static char _proc_getopt_long[] = "getopt_long";
308 | static char _proc_getopt_long_only[] = "getopt_long_only";
309 | # endif
310 | #endif
311 |
312 | # ifdef TEST
313 | static char _proc_main[] = "main";
314 | # endif
315 |
316 | #endif /** _MODULES_DEF_H **/
317 |
318 | /**
319 | ** The next char to be scanned in the option-element in which the last
320 | ** option character we returned was found. This allows us to pick up
321 | ** the scan where we left off.
322 | **
323 | ** If this is zero, or a null string, it means resume the scan by advan-
324 | ** cing to the next ARGV-element.
325 | **/
326 |
327 | static char *nextchar;
328 |
329 | /**
330 | ** Describe how to deal with options that follow non-option ARGV-elements.
331 | **
332 | ** If the caller did not specify anything, the default is REQUIRE_ORDER if
333 | ** the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise.
334 | **
335 | ** REQUIRE_ORDER means don't recognize them as options;
336 | ** stop option processing when the first non-option is seen.
337 | ** This is what Unix does.
338 | ** This mode of operation is selected by either setting the environment
339 | ** variable POSIXLY_CORRECT, or using `+' as the first character
340 | ** of the list of option characters.
341 | **
342 | ** PERMUTE is the default. We permute the contents of ARGV as we scan,
343 | ** so that eventually all the non-options are at the end. This allows options
344 | ** to be given in any order, even with programs that were not written to
345 | ** expect this.
346 | **
347 | ** RETURN_IN_ORDER is an option available to programs that were written
348 | ** to expect options and other ARGV-elements in any order and that care about
349 | ** the ordering of the two. We describe each non-option ARGV-element
350 | ** as if it were the argument of an option with character code 1.
351 | ** Using `-' as the first character of the list of option characters
352 | ** selects this mode of operation.
353 | **
354 | ** The special argument `--' forces an end of option-scanning regardless
355 | ** of the value of `ordering'. In the case of RETURN_IN_ORDER, only
356 | ** `--' can cause `getopt' to return EOF with `optind' != ARGC.
357 | **/
358 |
359 | static enum {
360 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
361 | } ordering;
362 |
363 | /**
364 | ** Value of POSIXLY_CORRECT environment variable.
365 | **/
366 |
367 | static char *posixly_correct;
368 |
369 | /**
370 | ** Handle permutation of arguments.
371 | **/
372 |
373 | /**
374 | ** Describe the part of ARGV that contains non-options that have
375 | ** been skipped. `first_nonopt' is the index in ARGV of the first of them;
376 | ** `last_nonopt' is the index after the last of them.
377 | **/
378 |
379 | static int first_nonopt;
380 | static int last_nonopt;
381 |
382 | /** ************************************************************************ **/
383 | /** PROTOTYPES **/
384 | /** ************************************************************************ **/
385 |
386 | static void exchange( char **argv);
387 | static const char *_getopt_initialize( const char *optstring);
388 | static int _getopt_internal( int argc,
389 | char *const *argv,
390 | const char *optstring,
391 | const struct option *longopts,
392 | int *longind,
393 | int long_only);
394 |
395 | /*++++
396 | ** ** Function-Header ***************************************************** **
397 | ** **
398 | ** Function: exchange **
399 | ** **
400 | ** Description: Exchange two adjacent subsequences of ARGV. **
401 | ** One subsequence is elements( first_nonopt, **
402 | ** last_nonopt) which contains all the non-options that **
403 | ** have been skipped so far. The other is elements **
404 | ** (last_nonopt,optind), which contains all the options **
405 | ** processed since those non-options were skipped. **
406 | ** **
407 | ** `first_nonopt' and `last_nonopt' are relocated so **
408 | ** that they describe the new indices of the non-options**
409 | ** in ARGV after they are moved. **
410 | ** **
411 | ** First Edition: 1995/12/20 **
412 | ** **
413 | ** Parameters: char **argv Command line arguments **
414 | ** **
415 | ** Result: argv ARGV array with exchanged sequences **
416 | ** **
417 | ** Attached Globals: first_nonopt first and last non option argument **
418 | ** last_nonopt on the stream before and after the **
419 | ** change.( I/O parameter) **
420 | ** **
421 | ** ************************************************************************ **
422 | ++++*/
423 |
424 | static void exchange( char **argv)
425 | {
426 | int bottom = first_nonopt;
427 | int middle = last_nonopt;
428 | int top = optind;
429 | char *tem;
430 |
431 | #ifdef _MODULES_DEF_H
432 | # if WITH_DEBUGGING_INIT
433 | ErrorLogger( NO_ERR_START, LOC, _proc_exchange, NULL);
434 | # endif
435 | #endif
436 |
437 | /**
438 | ** Exchange the shorter segment with the far end of the longer segment.
439 | ** That puts the shorter segment into the right place.
440 | ** It leaves the longer segment in the right place overall,
441 | ** but it consists of two parts that need to be swapped next.
442 | **/
443 |
444 | while( top > middle && middle > bottom) {
445 | if( top - middle > middle - bottom) {
446 |
447 | /**
448 | ** Bottom segment is the short one.
449 | **/
450 |
451 | int len = middle - bottom;
452 | register int i;
453 |
454 | /**
455 | ** Swap it with the top part of the top segment.
456 | **/
457 |
458 | for( i = 0; i < len; i++) {
459 | tem = argv[bottom + i];
460 | argv[bottom + i] = argv[top -( middle - bottom) + i];
461 | argv[top -( middle - bottom) + i] = tem;
462 | }
463 |
464 | /**
465 | ** Exclude the moved bottom segment from further swapping.
466 | **/
467 |
468 | top -= len;
469 |
470 | } else {
471 |
472 | /**
473 | ** Top segment is the short one.
474 | **/
475 |
476 | int len = top - middle;
477 | register int i;
478 |
479 | /**
480 | ** Swap it with the bottom part of the bottom segment.
481 | **/
482 |
483 | for( i = 0; i < len; i++) {
484 | tem = argv[bottom + i];
485 | argv[bottom + i] = argv[middle + i];
486 | argv[middle + i] = tem;
487 | }
488 |
489 | /**
490 | ** Exclude the moved top segment from further swapping.
491 | **/
492 |
493 | bottom += len;
494 | }
495 |
496 | } /** while **/
497 |
498 | /**
499 | ** Update records for the slots the non-options now occupy.
500 | **/
501 |
502 | first_nonopt +=( optind - last_nonopt);
503 | last_nonopt = optind;
504 |
505 | #ifdef _MODULES_DEF_H
506 | # if WITH_DEBUGGING_INIT
507 | ErrorLogger( NO_ERR_END, LOC, _proc_exchange, NULL);
508 | # endif
509 | #endif
510 |
511 | } /** end of 'exchange' **/
512 |
513 | /*++++
514 | ** ** Function-Header ***************************************************** **
515 | ** **
516 | ** Function: _getopt_initialize **
517 | ** **
518 | ** Description: Initialize the internal data when the first call is **
519 | ** made **
520 | ** This defines how to proceed if options and non-op- **
521 | ** tions are mixed up. See definition of the enum **
522 | ** 'ordering' for further explanation. **
523 | ** **
524 | ** First Edition: 1995/12/20 **
525 | ** **
526 | ** Parameters: char *optstring Options string **
527 | ** **
528 | ** Result: argv ARGV array with exchanged sequences **
529 | ** **
530 | ** Attached globals: first_nonopt, First an las position of **
531 | ** last_nonopt non-option arguments **
532 | ** optind Option scan index **
533 | ** nextchar Next character to scan **
534 | ** posixly_correct Value of the environment **
535 | ** variable 'POSIXLY_CORRECT' **
536 | ** ordering Ordering method ... **
537 | ** **
538 | ** ************************************************************************ **
539 | ++++*/
540 |
541 | static const char *_getopt_initialize( const char *optstring)
542 | {
543 |
544 | #ifdef _MODULES_DEF_H
545 | # if WITH_DEBUGGING_INIT
546 | ErrorLogger( NO_ERR_START, LOC, _proc_getopt_initialize, NULL);
547 | # endif
548 | #endif
549 |
550 | /**
551 | ** Start processing options with ARGV-element 1( since ARGV-element 0
552 | ** is the program name); the sequence of previously skipped
553 | ** non-option ARGV-elements is empty.
554 | **/
555 |
556 | first_nonopt = last_nonopt = optind = 1;
557 | nextchar = NULL;
558 | posixly_correct = getenv( "POSIXLY_CORRECT");
559 |
560 | /**
561 | ** Determine how to handle the ordering of options and nonoptions.
562 | **/
563 |
564 | if( optstring[0] == '-') {
565 | ordering = RETURN_IN_ORDER;
566 | ++optstring;
567 |
568 | } else if( optstring[0] == '+') {
569 | ordering = REQUIRE_ORDER;
570 | ++optstring;
571 |
572 | } else if( posixly_correct != NULL)
573 | ordering = REQUIRE_ORDER;
574 |
575 | else
576 | ordering = PERMUTE;
577 |
578 | #ifdef _MODULES_DEF_H
579 | # if WITH_DEBUGGING_INIT
580 | ErrorLogger( NO_ERR_END, LOC, _proc_getopt_initialize, NULL);
581 | # endif
582 | #endif
583 |
584 | return( optstring);
585 |
586 | } /** End of '_getopt_initialize' **/
587 |
588 | /*++++
589 | ** ** Function-Header ***************************************************** **
590 | ** **
591 | ** Function: _getopt_internal **
592 | ** **
593 | ** Description: Scan elements of ARGV( whose length is ARGC) for **
594 | ** option characters given in OPTSTRING. **
595 | ** or long-options specified in the longopt array **
596 | ** **
597 | ** First Edition: 1995/12/20 **
598 | ** **
599 | ** Parameters: int argc, # of arguments **
600 | ** char **argv, ARGV array **
601 | ** char *optstring, String of valid **
602 | ** short options **
603 | ** struct option *longopts, Table of valid long **
604 | ** options **
605 | ** int *longind, Returns the index of **
606 | ** the found long opt. **
607 | ** int long_only Search long options **
608 | ** only **
609 | ** **
610 | ** Result: int '?' Parse error **
611 | ** 0 Long option w/o argument found **
612 | ** else short option that has been found **
613 | ** or the value of a long option **
614 | ** EOF no more arguments on ARGV **
615 | ** **
616 | ** Attached globals: optind Index of the current option in the **
617 | ** ARGV array **
618 | ** optarg Argument of an option with value **
619 | ** **
620 | ** ************************************************************************ **
621 | ++++*/
622 | /** **/
623 | /** If an element of ARGV starts with '-', and is not exactly "-" or "--", **/
624 | /** then it is an option element. The characters of this element **/
625 | /** ( aside from the initial '-') are option characters. If `getopt' **/
626 | /** is called repeatedly, it returns successively each of the option **/
627 | /** characters from each of the option elements. **/
628 | /** **/
629 | /** If `getopt' finds another option character, it returns that character, **/
630 | /** updating `optind' and `nextchar' so that the next call to `getopt' can **/
631 | /** resume the scan with the following option character or ARGV-element. **/
632 | /** **/
633 | /** If there are no more option characters, `getopt' returns `EOF'. **/
634 | /** Then `optind' is the index in ARGV of the first ARGV-element **/
635 | /** that is not an option. ( The ARGV-elements have been permuted **/
636 | /** so that those that are not options now come last.) **/
637 | /** **/
638 | /** OPTSTRING is a string containing the legitimate option characters. **/
639 | /** If an option character is seen that is not listed in OPTSTRING, **/
640 | /** return '?' after printing an error message. If you set `opterr' to **/
641 | /** zero, the error message is suppressed but we still return '?'. **/
642 | /** **/
643 | /** If a char in OPTSTRING is followed by a colon, that means it wants an **/
644 | /** arg, so the following text in the same ARGV-element, or the text of **/
645 | /** the following ARGV-element, is returned in `optarg'. Two colons mean **/
646 | /** an option that wants an optional arg; if there is text in the current **/
647 | /** ARGV-element, it is returned in `optarg', otherwise `optarg' is set to **/
648 | /** zero. **/
649 | /** **/
650 | /** If OPTSTRING starts with `-' or `+', it requests different methods of **/
651 | /** handling the non-option ARGV-elements. **/
652 | /** See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. **/
653 | /** **/
654 | /** Long-named options begin with `--' instead of `-'. **/
655 | /** Their names may be abbreviated as long as the abbreviation is unique **/
656 | /** or is an exact match for some defined option. If they have an **/
657 | /** argument, it follows the option name in the same ARGV-element, **/
658 | /** separated from the option name by a `=', or else the in next ARGV- **/
659 | /** element. When `getopt' finds a long-named option, it returns 0 if **/
660 | /** that option's `flag' field is nonzero, the value of the option's `val' **/
661 | /** field if the `flag' field is zero. **/
662 | /** **/
663 | /** The elements of ARGV aren't really const, because we permute them. **/
664 | /** But we pretend they're const in the prototype to be compatible **/
665 | /** with other systems. **/
666 | /** **/
667 | /** LONGOPTS is a vector of `struct option' terminated by an **/
668 | /** element containing a name which is zero. **/
669 | /** **/
670 | /** LONGIND returns the index in LONGOPT of the long-named option found. **/
671 | /** It is only valid when a long-named option has been found by the most **/
672 | /** recent call. **/
673 | /** **/
674 | /** If LONG_ONLY is nonzero, '-' as well as '--' can introduce **/
675 | /** long-named options. **/
676 | /** **/
677 | /** ************************************************************************ **/
678 |
679 | static int _getopt_internal( int argc,
680 | char *const *argv,
681 | const char *optstring,
682 | const struct option *longopts,
683 | int *longind,
684 | int long_only)
685 | {
686 | optarg = NULL;
687 |
688 | #ifdef _MODULES_DEF_H
689 | # if WITH_DEBUGGING_INIT
690 | ErrorLogger( NO_ERR_START, LOC, _proc_getopt_internal, NULL);
691 | # endif
692 | #endif
693 |
694 | /**
695 | ** Initialization
696 | **/
697 |
698 | if( optind == 0) {
699 | optstring = _getopt_initialize( optstring);
700 | optind = 1; /** Don't scan ARGV[0], the program name. **/
701 | }
702 |
703 | if( nextchar == NULL || *nextchar == '\0') {
704 |
705 | /**
706 | ** Advance to the next ARGV-element.
707 | **/
708 |
709 | if( ordering == PERMUTE) {
710 |
711 | /**
712 | ** If we have just processed some options following some non-
713 | ** options, exchange them so that the options come first.
714 | **/
715 |
716 | if( first_nonopt != last_nonopt && last_nonopt != optind)
717 | exchange( (char **) argv);
718 | else if( last_nonopt != optind)
719 | first_nonopt = optind;
720 |
721 | /**
722 | ** Skip any additional non-options and extend the range of
723 | ** non-options previously skipped.
724 | **/
725 |
726 | while( optind < argc &&
727 | ( argv[optind][0] != '-' || argv[optind][1] == '\0'))
728 | optind++;
729 |
730 | last_nonopt = optind;
731 | }
732 |
733 | /**
734 | ** The special ARGV-element `--' means premature end of options.
735 | ** Skip it like a null option, then exchange with previous non-
736 | ** options ** as if it were an option, then skip everything else
737 | ** like a non-option.
738 | **/
739 |
740 | if( optind != argc && !strcmp( argv[optind], "--")) {
741 |
742 | optind++;
743 |
744 | if( first_nonopt != last_nonopt && last_nonopt != optind)
745 | exchange((char **) argv);
746 | else if( first_nonopt == last_nonopt)
747 | first_nonopt = optind;
748 |
749 | last_nonopt = argc;
750 |
751 | optind = argc;
752 | }
753 |
754 | /**
755 | ** If we have done all the ARGV-elements, stop the scan and back
756 | ** over any non-options that we skipped and permuted.
757 | **/
758 |
759 | if( optind == argc) {
760 |
761 | /**
762 | ** Set the next-arg-index to point at the non-options that we
763 | ** previously skipped, so the caller will digest them.
764 | **/
765 |
766 | if( first_nonopt != last_nonopt)
767 | optind = first_nonopt;
768 |
769 | return( EOF);
770 | }
771 |
772 | /**
773 | ** If we have come to a non-option and did not permute it,
774 | ** either stop the scan or describe it to the caller and pass it by.
775 | **/
776 |
777 | if( argv[optind][0] != '-' || argv[optind][1] == '\0') {
778 |
779 | if( ordering == REQUIRE_ORDER)
780 | return EOF;
781 | optarg = argv[optind++];
782 |
783 | return( 1);
784 | }
785 |
786 | /**
787 | ** We have found another option-ARGV-element.
788 | ** Skip the initial punctuation.
789 | **/
790 |
791 | nextchar =( argv[optind] + 1 +
792 | ( longopts != NULL && argv[optind][1] == '-'));
793 | }
794 |
795 | /**
796 | ** Decode the current option-ARGV-element.
797 | **/
798 |
799 | /**
800 | ** Check whether the ARGV-element is a long option.
801 | **
802 | ** If long_only and the ARGV-element has the form "-f", where f is
803 | ** a valid short option, don't consider it an abbreviated form of
804 | ** a long option that starts with f. Otherwise there would be no
805 | ** way to give the -f short option.
806 | **
807 | ** On the other hand, if there's a long option "fubar" and
808 | ** the ARGV-element is "-fu", do consider that an abbreviation of
809 | ** the long option, just like "--fu", and not "-f" with arg "u".
810 | **
811 | ** This distinction seems to be the most useful approach.
812 | **/
813 |
814 | if( longopts != NULL &&( argv[optind][1] == '-' ||
815 | ( long_only &&
816 | ( argv[optind][2] || !my_index (optstring, argv[optind][1]))))) {
817 |
818 | char *nameend;
819 | const struct option *p;
820 | const struct option *pfound = NULL;
821 | int exact = 0;
822 | int ambig = 0;
823 | int indfound;
824 | int option_index;
825 |
826 | /**
827 | ** Skip the remaining characters of the long option upt to its
828 | ** names end( End of the option itsself or the '=' sign)
829 | **/
830 |
831 | for( nameend = nextchar; *nameend && *nameend != '='; nameend++);
832 |
833 | /**
834 | ** Test all long options for either exact match or abbreviated
835 | ** matches.
836 | **/
837 |
838 | for( p = longopts, option_index = 0; p->name; p++, option_index++) {
839 | if( !strncmp( p->name, nextchar, nameend - nextchar)) {
840 |
841 | if( nameend - nextchar == strlen( p->name)) {
842 |
843 | /**
844 | ** Exact match found.
845 | **/
846 |
847 | pfound = p;
848 | indfound = option_index;
849 | exact = 1;
850 | break;
851 |
852 | } else if( pfound == NULL) {
853 |
854 | /**
855 | ** First nonexact match found.
856 | **/
857 |
858 | pfound = p;
859 | indfound = option_index;
860 |
861 | } else
862 |
863 | /**
864 | ** Second or later nonexact match found.
865 | **/
866 |
867 | ambig = 1;
868 |
869 | } /** if( !strncmp) **/
870 | } /** for **/
871 |
872 | /**
873 | ** Print an error message for ambigious abbreviations and exit
874 | ** on error
875 | **/
876 |
877 | if( ambig && !exact) {
878 |
879 | if( opterr)
880 | #ifdef _MODULES_DEF_H
881 | ErrorLogger( ERR_OPT_AMBIG, LOC, argv[optind], NULL);
882 | #else
883 | fprintf( stderr, _("%s: option `%s' is ambiguous\n"),
884 | argv[0], argv[optind]);
885 | #endif
886 |
887 | nextchar += strlen( nextchar);
888 | optind++;
889 | return( '?');
890 | }
891 |
892 | /**
893 | ** Longname found ?
894 | **/
895 |
896 | if( pfound != NULL) {
897 |
898 | option_index = indfound;
899 | optind++;
900 |
901 | /**
902 | ** *nameend is != NULL if there is a value specified for
903 | ** the option: '--option=value' -> *nameend = '='
904 | **/
905 |
906 | if( *nameend) {
907 |
908 | /**
909 | ** Don't test has_arg with >, because some C compilers don't
910 | ** allow it to be used on enums.
911 | **/
912 |
913 | if( pfound->has_arg)
914 | optarg = nameend + 1;
915 |
916 | else {
917 |
918 | if( opterr)
919 |
920 | /**
921 | ** ERROR: --option w/o argument
922 | **/
923 |
924 | if( argv[optind - 1][1] == '-')
925 | #ifdef _MODULES_DEF_H
926 | ErrorLogger( ERR_OPT_NOARG, LOC, pfound->name, NULL);
927 | #else
928 | fprintf( stderr,
929 | _("%s: option `--%s' doesn't allow an argument\n"),
930 | argv[0], pfound->name);
931 | #endif
932 |
933 | /**
934 | ** ERROR: +option or -option w/o argument
935 | **/
936 |
937 | else {
938 | #ifdef _MODULES_DEF_H
939 | char buffer[ BUFSIZ];
940 | sprintf( buffer, "%c%s", argv[optind - 1][0], pfound->name);
941 | ErrorLogger( ERR_OPT_NOARG, LOC, buffer, NULL);
942 | #else
943 | fprintf( stderr,
944 | _("%s: option `%c%s' doesn't allow an argument\n"),
945 | argv[0], argv[optind - 1][0], pfound->name);
946 | #endif
947 | }
948 |
949 | nextchar += strlen( nextchar);
950 | return( '?');
951 | }
952 |
953 | /**
954 | ** Options with arguments
955 | **/
956 |
957 | } else if( pfound->has_arg == 1) {
958 |
959 | if( optind < argc)
960 | optarg = argv[optind++];
961 |
962 | else {
963 |
964 | /**
965 | ** ERROR: Option without argument where one is required
966 | **/
967 |
968 | if( opterr)
969 | #ifdef _MODULES_DEF_H
970 | ErrorLogger( ERR_OPT_REQARG, LOC, argv[optind-1], NULL);
971 | #else
972 | fprintf( stderr,
973 | _("%s: option `%s' requires an argument\n"),
974 | argv[0], argv[optind - 1]);
975 | #endif
976 |
977 | nextchar += strlen( nextchar);
978 | return((optstring[0] == ':') ? ':' : '?');
979 | }
980 | }
981 |
982 | /**
983 | ** Return the indication, that a long vlaue has been found
984 | ** and set up pointers for the next option expansion
985 | **/
986 |
987 | nextchar += strlen( nextchar);
988 |
989 | if( longind != NULL)
990 | *longind = option_index;
991 |
992 | if( pfound->flag) {
993 | *(pfound->flag) = pfound->val;
994 | return( 0);
995 | }
996 | return( pfound->val);
997 | }
998 |
999 | /**
1000 | ** Can't find it as a long option. If this is not getopt_long_only,
1001 | ** or the option starts with '--' or is not a valid short
1002 | ** option, then it's an error.
1003 | ** Otherwise interpret it as a short option.
1004 | **/
1005 |
1006 | if( !long_only || argv[optind][1] == '-' ||
1007 | my_index( optstring, *nextchar) == NULL) {
1008 |
1009 | if( opterr) {
1010 |
1011 | /**
1012 | ** ERROR: unrecognized --option
1013 | **/
1014 |
1015 | if( argv[optind][1] == '-') {
1016 | #ifdef _MODULES_DEF_H
1017 | ErrorLogger( ERR_OPT_UNKNOWN, LOC, nextchar, NULL);
1018 | #else
1019 | fprintf( stderr, _("%s: unrecognized option `--%s'\n"),
1020 | argv[0], nextchar);
1021 | #endif
1022 |
1023 | /**
1024 | ** ERROR: unrecognized +option or -option
1025 | **/
1026 |
1027 | } else {
1028 | #ifdef _MODULES_DEF_H
1029 | char buffer[ BUFSIZ];
1030 | sprintf( buffer, "%c%s", argv[optind][0], nextchar);
1031 | ErrorLogger( ERR_OPT_AMBIG, LOC, buffer, NULL);
1032 | #else
1033 | fprintf( stderr, _("%s: unrecognized option `%c%s'\n"),
1034 | argv[0], argv[optind][0], nextchar);
1035 | #endif
1036 | }
1037 | }
1038 |
1039 | nextchar =( char *) "";
1040 | optind++;
1041 | return( '?');
1042 | }
1043 | } /** if( long option) **/
1044 |
1045 | /**
1046 | ** Look at and handle the next short option-character.
1047 | **/
1048 |
1049 | {
1050 | char c = *nextchar++;
1051 | char *temp = my_index( optstring, c);
1052 |
1053 | /**
1054 | ** Increment `optind' when we start to process its last character.
1055 | **/
1056 |
1057 | if( *nextchar == '\0')
1058 | ++optind;
1059 |
1060 | /**
1061 | ** Unrecognized options
1062 | **/
1063 |
1064 | if( temp == NULL || c == ':') {
1065 | if( opterr) {
1066 |
1067 | #ifdef _MODULES_DEF_H
1068 | char buffer[ 2];
1069 | buffer[ 0] = c;
1070 | buffer[ 1] = '\0';
1071 | #endif
1072 |
1073 | if( posixly_correct) {
1074 |
1075 | /**
1076 | ** 1003.2 specifies the format of this message.
1077 | **/
1078 |
1079 | #ifdef _MODULES_DEF_H
1080 | ErrorLogger( ERR_OPT_ILL, LOC, buffer, NULL);
1081 | #else
1082 | fprintf( stderr, _("%s: illegal option -- %c\n"),
1083 | argv[0], c);
1084 | #endif
1085 | } else {
1086 | #ifdef _MODULES_DEF_H
1087 | ErrorLogger( ERR_OPT_INV, LOC, buffer, NULL);
1088 | #else
1089 | fprintf( stderr, _("%s: invalid option -- %c\n"),
1090 | argv[0], c);
1091 | #endif
1092 | }
1093 | }
1094 | optopt = c;
1095 | return( '?');
1096 | }
1097 |
1098 | /**
1099 | **
1100 | **/
1101 |
1102 | if( temp[1] == ':') {
1103 | if( temp[2] == ':') {
1104 |
1105 | /**
1106 | ** This is an option that accepts an argument optionally.
1107 | **/
1108 |
1109 | if( *nextchar != '\0') {
1110 | optarg = nextchar;
1111 | optind++;
1112 | } else
1113 | optarg = NULL;
1114 |
1115 | nextchar = NULL;
1116 |
1117 | } else { /** optional argument **/
1118 |
1119 | /**
1120 | ** This is an option that requires an argument.
1121 | **/
1122 |
1123 | if( *nextchar != '\0') {
1124 | optarg = nextchar;
1125 |
1126 | /**
1127 | ** If we end this ARGV-element by taking the rest as an arg,
1128 | ** we must advance to the next element now.
1129 | **/
1130 |
1131 | optind++;
1132 |
1133 | } else if( optind == argc) {
1134 |
1135 | if( opterr) {
1136 |
1137 | /**
1138 | ** 1003.2 specifies the format of this message. *
1139 | **/
1140 |
1141 | #ifdef _MODULES_DEF_H
1142 | char buffer[ 2];
1143 | buffer[ 0] = c;
1144 | buffer[ 1] = '\0';
1145 | ErrorLogger( ERR_OPT_REQARG, LOC, buffer, NULL);
1146 | #else
1147 | fprintf( stderr,
1148 | _("%s: option requires an argument -- %c\n"),
1149 | argv[0], c);
1150 | #endif
1151 | }
1152 |
1153 | optopt = c;
1154 | if( optstring[0] == ':')
1155 | c = ':';
1156 | else
1157 | c = '?';
1158 |
1159 | } else
1160 |
1161 | /**
1162 | ** We already incremented `optind' once;
1163 | ** increment it again when taking next ARGV-elt as argument.
1164 | **/
1165 |
1166 | optarg = argv[optind++];
1167 | nextchar = NULL;
1168 | }
1169 | }
1170 |
1171 | /**
1172 | ** Now c contains the found character in case of success of '?' in case
1173 | ** of failure
1174 | **/
1175 |
1176 | #ifdef _MODULES_DEF_H
1177 | # if WITH_DEBUGGING_INIT
1178 | ErrorLogger( NO_ERR_END, LOC, _proc_getopt_internal, NULL);
1179 | # endif
1180 | #endif
1181 | return( c);
1182 |
1183 | } /** block **/
1184 |
1185 | } /** End of '_getopt_internal' **/
1186 |
1187 | /*++++
1188 | ** ** Function-Header ***************************************************** **
1189 | ** **
1190 | ** Function: getopt, getopt_long, getopt_long_only **
1191 | ** **
1192 | ** Description: Calls _getopt_internal in order to provide a normal **
1193 | ** getopt call. **
1194 | ** **
1195 | ** First Edition: 1995/12/20 **
1196 | ** **
1197 | ** Parameters: int argc, # of arguments **
1198 | ** char **argv, ARGV array **
1199 | ** char *optstring, String of valid short opt. **
1200 | ** **
1201 | ** Result: int '?' Parse error **
1202 | ** 0 Long option w/o argument found **
1203 | ** else short option that has been found **
1204 | ** or the value of a long option **
1205 | ** EOF no more arguments on ARGV **
1206 | ** **
1207 | ** Attached globals: optind Index of the current option in the **
1208 | ** ARGV array **
1209 | ** optarg Argument of an option with value **
1210 | ** opterr Set in case of parse errors **
1211 | ** **
1212 | ** ************************************************************************ **
1213 | ++++*/
1214 |
1215 | int getopt( int argc, char *const *argv, const char *optstring)
1216 | {
1217 |
1218 | #ifdef _MODULES_DEF_H
1219 | # if WITH_DEBUGGING_INIT
1220 | ErrorLogger( NO_ERR_START, LOC, _proc_getopt, NULL);
1221 | # endif
1222 | #endif
1223 |
1224 | return _getopt_internal( argc, argv, optstring,
1225 | ( const struct option *) 0,
1226 | ( int *) 0,
1227 | 0);
1228 | } /** End of 'getopt' **/
1229 |
1230 | int getopt_long( int argc, char *const *argv, const char *optstring,
1231 | const struct option *longopts, int *longind)
1232 | {
1233 |
1234 | #ifdef _MODULES_DEF_H
1235 | # if WITH_DEBUGGING_INIT
1236 | ErrorLogger( NO_ERR_START, LOC, _proc_getopt_long, NULL);
1237 | # endif
1238 | #endif
1239 |
1240 | return _getopt_internal( argc, argv, optstring, longopts, longind, 0);
1241 |
1242 | } /** End of 'getopt' **/
1243 |
1244 | int getopt_long_only( int argc, char *const *argv, const char *optstring,
1245 | const struct option *longopts, int *longind)
1246 | {
1247 |
1248 | #ifdef _MODULES_DEF_H
1249 | # if WITH_DEBUGGING_INIT
1250 | ErrorLogger( NO_ERR_START, LOC, _proc_getopt_long_only, NULL);
1251 | # endif
1252 | #endif
1253 |
1254 | return _getopt_internal( argc, argv, optstring, longopts, longind, 1);
1255 |
1256 | } /** End of 'getopt' **/
1257 |
1258 | /* #endif */ /* _LIBC or not __GNU_LIBRARY__. */
1259 |
1260 | #ifdef TEST
1261 |
1262 | /*++++
1263 | ** ** Function-Header ***************************************************** **
1264 | ** **
1265 | ** Function: main **
1266 | ** **
1267 | ** Description: Test procedure for getopt **
1268 | ** Compile with -DTEST to make an executable for use in **
1269 | ** testing the above definition of `getopt' **
1270 | ** **
1271 | ** First Edition: 1995/12/20 **
1272 | ** **
1273 | ** Parameters: int argc, # of arguments **
1274 | ** char **argv, ARGV array **
1275 | ** **
1276 | ** Result: - **
1277 | ** **
1278 | ** ************************************************************************ **
1279 | ++++*/
1280 |
1281 | int main( int argc, char **argv)
1282 | {
1283 |
1284 | # ifdef _MODULES_DEF_H
1285 | # if WITH_DEBUGGING_INIT
1286 | ErrorLogger( NO_ERR_START, LOC, _proc_main, NULL);
1287 | # endif
1288 | # endif
1289 |
1290 | int c;
1291 | int digit_optind = 0;
1292 | int longind;
1293 | int option, verbose;
1294 | char *value;
1295 |
1296 | const struct option longopts[] = {
1297 | { "test", no_argument, NULL, 0 },
1298 | { "option", optional_argument, &option, 1 },
1299 | { "verbose", optional_argument, NULL, 'v' },
1300 | { "value", required_argument, NULL, 'x'},
1301 | { NULL, no_argument, NULL, 0 }
1302 | };
1303 |
1304 | /**
1305 | ** Print all options ...
1306 | **/
1307 |
1308 | while( 1) {
1309 |
1310 | int this_option_optind = optind ? optind : 1;
1311 |
1312 | c = getopt_long( argc, argv, "abc:d:0123456789", longopts, &longind);
1313 | if( c == EOF)
1314 | break; /** while( 1) **/
1315 |
1316 | switch( c) {
1317 |
1318 | case 0:
1319 | printf( "option --test or --option\n");
1320 | if( optarg)
1321 | printf( "with argument '%s'", optarg);
1322 | printf( "\n option is set to %d\n", option);
1323 | break;
1324 |
1325 | case '0':
1326 | case '1':
1327 | case '2':
1328 | case '3':
1329 | case '4':
1330 | case '5':
1331 | case '6':
1332 | case '7':
1333 | case '8':
1334 | case '9':
1335 | if( digit_optind != 0 && digit_optind != this_option_optind)
1336 | printf( "digits occur in two different argv-elements.\n");
1337 | digit_optind = this_option_optind;
1338 | printf( "option %c\n", c);
1339 | break;
1340 |
1341 | case 'a':
1342 | printf( "option a\n");
1343 | break;
1344 |
1345 | case 'b':
1346 | printf( "option b\n");
1347 | break;
1348 |
1349 | case 'c':
1350 | printf( "option c with value `%s'\n", optarg);
1351 | break;
1352 |
1353 | case 'v':
1354 | case 'x':
1355 | printf( "option %c ", c);
1356 | if( optarg)
1357 | printf( "with argument '%s'", optarg);
1358 | printf( "\n");
1359 | break;
1360 |
1361 | case '?':
1362 | break;
1363 |
1364 | default:
1365 | printf( "?? getopt returned character code 0%o ??\n", c);
1366 | }
1367 | } /** while( 1) **/
1368 |
1369 | /**
1370 | ** Finally print all remaining arguments
1371 | **/
1372 |
1373 | if( optind < argc) {
1374 | printf( "non-option ARGV-elements: ");
1375 | while( optind < argc)
1376 | printf( "%s ", argv[optind++]);
1377 | printf( "\n");
1378 | }
1379 |
1380 | /**
1381 | ** Exit on success
1382 | **/
1383 |
1384 | # ifdef _MODULES_DEF_H
1385 | # if WITH_DEBUGGING_INIT
1386 | ErrorLogger( NO_ERR_END, LOC, _proc_main, NULL);
1387 | # endif
1388 | # endif
1389 |
1390 | exit( 0);
1391 |
1392 | } /** End of 'main' **/
1393 |
1394 | #endif /* TEST */