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: 70c17cc67df8607445a45be72dde339b54581948 $";
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 
my_index(const char * str,int chr)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 
exchange(char ** argv)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 
_getopt_initialize(const char * optstring)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 
_getopt_internal(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,int long_only)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 
getopt(int argc,char * const * argv,const char * optstring)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 
getopt_long(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind)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 
getopt_long_only(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind)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 
main(int argc,char ** argv)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 */
1395