diff options
| -rw-r--r-- | src/deps.mk | 2 | ||||
| -rw-r--r-- | src/getopt.c | 949 | ||||
| -rw-r--r-- | src/getopt1.c | 173 | 
3 files changed, 1124 insertions, 0 deletions
| diff --git a/src/deps.mk b/src/deps.mk index 8d8358d..5cd4fdf 100644 --- a/src/deps.mk +++ b/src/deps.mk @@ -6,6 +6,8 @@ feh_png.o: feh_png.c feh_png.h feh.h structs.h menu.h ipc.h utils.h \    getopt.h debug.h  filelist.o: filelist.c feh.h structs.h menu.h ipc.h utils.h getopt.h \    debug.h filelist.h options.h +getopt.o: getopt.c +getopt1.o: getopt1.c getopt.h  imlib.o: imlib.c feh.h structs.h menu.h ipc.h utils.h getopt.h debug.h \    filelist.h winwidget.h options.h  index.o: index.c feh.h structs.h menu.h ipc.h utils.h getopt.h debug.h \ diff --git a/src/getopt.c b/src/getopt.c new file mode 100644 index 0000000..d212b3a --- /dev/null +++ b/src/getopt.c @@ -0,0 +1,949 @@ +/* Getopt for GNU. +   NOTE: getopt is now part of the C library, so if you don't know what +   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu +   before changing it! + +   Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 +   	Free Software Foundation, Inc. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Library General Public License as +   published by the Free Software Foundation; either version 2 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. +   Ditto for AIX 3.2 and <stdlib.h>.  */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems +   reject `defined (const)'.  */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not +   actually compiling the library itself.  This code is part of the GNU C +   Library, but also included in many other GNU distributions.  Compiling +   and linking in this code is a waste when using the GNU C library +   (especially if it is a shared library).  Rather than having every GNU +   program understand `configure --with-gnu-libc' and omit the object files, +   it is simpler to just do this in the source for each such file.  */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + +/* This needs to come after some library #include +   to get __GNU_LIBRARY__ defined.  */ +#ifdef	__GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them +   contain conflicting prototypes for getopt.  */ +#include <stdlib.h> +#include <unistd.h> +#endif				/* GNU C library.  */ + +#ifdef VMS +#include <unixlib.h> +#if HAVE_STRING_H - 0 +#include <string.h> +#endif +#endif + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. +   When compiling libc, the _ macro is predefined.  */ +#ifdef HAVE_LIBINTL_H +# include <libintl.h> +# define _(msgid)	gettext (msgid) +#else +# define _(msgid)	(msgid) +#endif +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' +   but it behaves differently for the user, since it allows the user +   to intersperse the options with the other arguments. + +   As `getopt' works, it permutes the elements of ARGV so that, +   when it is done, all the options precede everything else.  Thus +   all application programs are extended to handle flexible argument order. + +   Setting the environment variable POSIXLY_CORRECT disables permutation. +   Then the behavior is completely standard. + +   GNU application programs can use a third alternative mode in which +   they can distinguish the relative order of options and other arguments.  */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. +   When `getopt' finds an option that takes an argument, +   the argument value is returned here. +   Also, when `ordering' is RETURN_IN_ORDER, +   each non-option ARGV-element is returned here.  */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. +   This is used for communication to and from the caller +   and for communication between successive calls to `getopt'. + +   On entry to `getopt', zero means this is the first call; initialize. + +   When `getopt' returns -1, this is the index of the first of the +   non-option elements that the caller should itself scan. + +   Otherwise, `optind' communicates from one call to the next +   how much of ARGV has been scanned so far.  */ + +/* 1003.2 says this must be 1 before any call.  */ +int optind = 1; + +/* Formerly, initialization of getopt depended on optind==0, which +   causes problems with re-calling getopt as programs generally don't +   know that. */ + +int __getopt_initialized = 0; + +/* The next char to be scanned in the option-element +   in which the last option character we returned was found. +   This allows us to pick up the scan where we left off. + +   If this is zero, or a null string, it means resume the scan +   by advancing to the next ARGV-element.  */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message +   for unrecognized options.  */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. +   This must be initialized on some systems to avoid linking in the +   system's own getopt implementation.  */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + +   If the caller did not specify anything, +   the default is REQUIRE_ORDER if the environment variable +   POSIXLY_CORRECT is defined, PERMUTE otherwise. + +   REQUIRE_ORDER means don't recognize them as options; +   stop option processing when the first non-option is seen. +   This is what Unix does. +   This mode of operation is selected by either setting the environment +   variable POSIXLY_CORRECT, or using `+' as the first character +   of the list of option characters. + +   PERMUTE is the default.  We permute the contents of ARGV as we scan, +   so that eventually all the non-options are at the end.  This allows options +   to be given in any order, even with programs that were not written to +   expect this. + +   RETURN_IN_ORDER is an option available to programs that were written +   to expect options and other ARGV-elements in any order and that care about +   the ordering of the two.  We describe each non-option ARGV-element +   as if it were the argument of an option with character code 1. +   Using `-' as the first character of the list of option characters +   selects this mode of operation. + +   The special argument `--' forces an end of option-scanning regardless +   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only +   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */ + +static enum { +	REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable.  */ +static char *posixly_correct; + +#ifdef	__GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries +   because there are many ways it can cause trouble. +   On some systems, it contains special magic macros that don't work +   in GCC.  */ +#include <string.h> +#define	my_index	strchr +#else + +/* Avoid depending on library functions or files +   whose names are inconsistent.  */ + +char *getenv(); + +static char *my_index(str, chr) +const char *str; +int chr; +{ +	while (*str) { +		if (*str == chr) +			return (char *) str; +		str++; +	} +	return 0; +} + +/* If using GCC, we can safely declare strlen this way. +   If not using GCC, it is ok not to declare it.  */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. +   That was relevant to code that was here before.  */ +#if !defined (__STDC__) || !__STDC__ +/* gcc with -traditional declares the built-in strlen to return int, +   and has done so at least since version 2.4.5. -- rms.  */ +extern int strlen(const char *); +#endif				/* not __STDC__ */ +#endif				/* __GNUC__ */ + +#endif				/* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments.  */ + +/* Describe the part of ARGV that contains non-options that have +   been skipped.  `first_nonopt' is the index in ARGV of the first of them; +   `last_nonopt' is the index after the last of them.  */ + +static int first_nonopt; +static int last_nonopt; + +#ifdef _LIBC +/* Bash 2.0 gives us an environment variable containing flags +   indicating ARGV elements that should not be considered arguments.  */ + +/* Defined in getopt_init.c  */ +extern char *__getopt_nonoption_flags; + +static int nonoption_flags_max_len; +static int nonoption_flags_len; + +static int original_argc; +static char *const *original_argv; + +/* Make sure the environment variable bash 2.0 puts in the environment +   is valid for the getopt call we must make sure that the ARGV passed +   to getopt is that one passed to the process.  */ +static void +    __attribute__ ((unused)) store_args_and_env(int argc, char *const *argv) +{ +	/* XXX This is no good solution.  We should rather copy the args so that +	   we can compare them later.  But we must not use malloc(3).  */ +	original_argc = argc; +	original_argv = argv; +} + +# ifdef text_set_element +text_set_element(__libc_subinit, store_args_and_env); +# endif				/* text_set_element */ + +# define SWAP_FLAGS(ch1, ch2) \ +  if (nonoption_flags_len > 0)						      \ +    {									      \ +      char __tmp = __getopt_nonoption_flags[ch1];			      \ +      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \ +      __getopt_nonoption_flags[ch2] = __tmp;				      \ +    } +#else				/* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif				/* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. +   One subsequence is elements [first_nonopt,last_nonopt) +   which contains all the non-options that have been skipped so far. +   The other is elements [last_nonopt,optind), which contains all +   the options processed since those non-options were skipped. + +   `first_nonopt' and `last_nonopt' are relocated so that they describe +   the new indices of the non-options in ARGV after they are moved.  */ + +#if defined (__STDC__) && __STDC__ +static void exchange(char **); +#endif + +static void exchange(argv) +char **argv; +{ +	int bottom = first_nonopt; +	int middle = last_nonopt; +	int top = optind; +	char *tem; + +	/* Exchange the shorter segment with the far end of the longer segment. +	   That puts the shorter segment into the right place. It leaves the +	   longer segment in the right place overall, but it consists of two parts  +	   that need to be swapped next.  */ + +#ifdef _LIBC +	/* First make sure the handling of the `__getopt_nonoption_flags' string +	   can work normally.  Our top argument must be in the range of the +	   string.  */ +	if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { +		/* We must extend the array.  The user plays games with us and presents  +		   new arguments.  */ +		char *new_str = malloc(top + 1); + +		if (new_str == NULL) +			nonoption_flags_len = nonoption_flags_max_len = 0; +		else { +			memset(__mempcpy +			       (new_str, __getopt_nonoption_flags, +				nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); +			nonoption_flags_max_len = top + 1; +			__getopt_nonoption_flags = new_str; +		} +	} +#endif + +	while (top > middle && middle > bottom) { +		if (top - middle > middle - bottom) { +			/* Bottom segment is the short one.  */ +			int len = middle - bottom; +			register int i; + +			/* Swap it with the top part of the top segment.  */ +			for (i = 0; i < len; i++) { +				tem = argv[bottom + i]; +				argv[bottom + i] = argv[top - (middle - bottom) + i]; +				argv[top - (middle - bottom) + i] = tem; +				SWAP_FLAGS(bottom + i, top - (middle - bottom) + i); +			} +			/* Exclude the moved bottom segment from further swapping.  */ +			top -= len; +		} else { +			/* Top segment is the short one.  */ +			int len = top - middle; +			register int i; + +			/* Swap it with the bottom part of the bottom segment.  */ +			for (i = 0; i < len; i++) { +				tem = argv[bottom + i]; +				argv[bottom + i] = argv[middle + i]; +				argv[middle + i] = tem; +				SWAP_FLAGS(bottom + i, middle + i); +			} +			/* Exclude the moved top segment from further swapping.  */ +			bottom += len; +		} +	} + +	/* Update records for the slots the non-options now occupy.  */ + +	first_nonopt += (optind - last_nonopt); +	last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made.  */ + +#if defined (__STDC__) && __STDC__ +static const char *_getopt_initialize(int, char *const *, const char *); +#endif +static const char *_getopt_initialize(argc, argv, optstring) +int argc; +char *const *argv; +const char *optstring; +{ +	/* Start processing options with ARGV-element 1 (since ARGV-element 0 is +	   the program name); the sequence of previously skipped non-option +	   ARGV-elements is empty.  */ + +	first_nonopt = last_nonopt = optind; + +	nextchar = NULL; + +	posixly_correct = getenv("POSIXLY_CORRECT"); + +	/* Determine how to handle the ordering of options and nonoptions.  */ + +	if (optstring[0] == '-') { +		ordering = RETURN_IN_ORDER; +		++optstring; +	} else if (optstring[0] == '+') { +		ordering = REQUIRE_ORDER; +		++optstring; +	} else if (posixly_correct != NULL) +		ordering = REQUIRE_ORDER; +	else +		ordering = PERMUTE; + +#ifdef _LIBC +	if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { +		if (nonoption_flags_max_len == 0) { +			if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') +				nonoption_flags_max_len = -1; +			else { +				const char *orig_str = __getopt_nonoption_flags; +				int len = nonoption_flags_max_len = strlen(orig_str); + +				if (nonoption_flags_max_len < argc) +					nonoption_flags_max_len = argc; +				__getopt_nonoption_flags = (char *) +				    malloc(nonoption_flags_max_len); +				if (__getopt_nonoption_flags == NULL) +					nonoption_flags_max_len = -1; +				else +					memset(__mempcpy +					       (__getopt_nonoption_flags, +						orig_str, len), '\0', nonoption_flags_max_len - len); +			} +		} +		nonoption_flags_len = nonoption_flags_max_len; +	} else +		nonoption_flags_len = 0; +#endif + +	return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters +   given in OPTSTRING. + +   If an element of ARGV starts with '-', and is not exactly "-" or "--", +   then it is an option element.  The characters of this element +   (aside from the initial '-') are option characters.  If `getopt' +   is called repeatedly, it returns successively each of the option characters +   from each of the option elements. + +   If `getopt' finds another option character, it returns that character, +   updating `optind' and `nextchar' so that the next call to `getopt' can +   resume the scan with the following option character or ARGV-element. + +   If there are no more option characters, `getopt' returns -1. +   Then `optind' is the index in ARGV of the first ARGV-element +   that is not an option.  (The ARGV-elements have been permuted +   so that those that are not options now come last.) + +   OPTSTRING is a string containing the legitimate option characters. +   If an option character is seen that is not listed in OPTSTRING, +   return '?' after printing an error message.  If you set `opterr' to +   zero, the error message is suppressed but we still return '?'. + +   If a char in OPTSTRING is followed by a colon, that means it wants an arg, +   so the following text in the same ARGV-element, or the text of the following +   ARGV-element, is returned in `optarg'.  Two colons mean an option that +   wants an optional arg; if there is text in the current ARGV-element, +   it is returned in `optarg', otherwise `optarg' is set to zero. + +   If OPTSTRING starts with `-' or `+', it requests different methods of +   handling the non-option ARGV-elements. +   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + +   Long-named options begin with `--' instead of `-'. +   Their names may be abbreviated as long as the abbreviation is unique +   or is an exact match for some defined option.  If they have an +   argument, it follows the option name in the same ARGV-element, separated +   from the option name by a `=', or else the in next ARGV-element. +   When `getopt' finds a long-named option, it returns 0 if that option's +   `flag' field is nonzero, the value of the option's `val' field +   if the `flag' field is zero. + +   The elements of ARGV aren't really const, because we permute them. +   But we pretend they're const in the prototype to be compatible +   with other systems. + +   LONGOPTS is a vector of `struct option' terminated by an +   element containing a name which is zero. + +   LONGIND returns the index in LONGOPT of the long-named option found. +   It is only valid when a long-named option has been found by the most +   recent call. + +   If LONG_ONLY is nonzero, '-' as well as '--' can introduce +   long-named options.  */ + +int _getopt_internal(argc, argv, optstring, longopts, longind, long_only) +int argc; +char *const *argv; +const char *optstring; +const struct option *longopts; +int *longind; +int long_only; +{ +	optarg = NULL; + +	if (optind == 0 || !__getopt_initialized) { +		if (optind == 0) +			optind = 1;	/* Don't scan ARGV[0], the +					   program name.  */ +		optstring = _getopt_initialize(argc, argv, optstring); +		__getopt_initialized = 1; +	} + +	/* Test whether ARGV[optind] points to a non-option argument. Either it +	   does not have option syntax, or there is an environment flag from the +	   shell indicating it is not an option.  The later information is only +	   used when the used in the GNU libc.  */ +#ifdef _LIBC +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'	      \ +		     || (optind < nonoption_flags_len			      \ +			 && __getopt_nonoption_flags[optind] == '1')) +#else +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#endif + +	if (nextchar == NULL || *nextchar == '\0') { +		/* Advance to the next ARGV-element.  */ + +		/* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been +		   moved back by the user (who may also have changed the arguments).  */ +		if (last_nonopt > optind) +			last_nonopt = optind; +		if (first_nonopt > optind) +			first_nonopt = optind; + +		if (ordering == PERMUTE) { +			/* If we have just processed some options following some +			   non-options, exchange them so that the options come first.  */ + +			if (first_nonopt != last_nonopt && last_nonopt != optind) +				exchange((char **) argv); +			else if (last_nonopt != optind) +				first_nonopt = optind; + +			/* Skip any additional non-options and extend the range of +			   non-options previously skipped.  */ + +			while (optind < argc && NONOPTION_P) +				optind++; +			last_nonopt = optind; +		} + +		/* The special ARGV-element `--' means premature end of options. Skip +		   it like a null option, then exchange with previous non-options as if  +		   it were an option, then skip everything else like a non-option.  */ + +		if (optind != argc && !strcmp(argv[optind], "--")) { +			optind++; + +			if (first_nonopt != last_nonopt && last_nonopt != optind) +				exchange((char **) argv); +			else if (first_nonopt == last_nonopt) +				first_nonopt = optind; +			last_nonopt = argc; + +			optind = argc; +		} + +		/* If we have done all the ARGV-elements, stop the scan and back over +		   any non-options that we skipped and permuted.  */ + +		if (optind == argc) { +			/* Set the next-arg-index to point at the non-options that we +			   previously skipped, so the caller will digest them.  */ +			if (first_nonopt != last_nonopt) +				optind = first_nonopt; +			return -1; +		} + +		/* If we have come to a non-option and did not permute it, either stop +		   the scan or describe it to the caller and pass it by.  */ + +		if (NONOPTION_P) { +			if (ordering == REQUIRE_ORDER) +				return -1; +			optarg = argv[optind++]; +			return 1; +		} + +		/* We have found another option-ARGV-element. Skip the initial +		   punctuation.  */ + +		nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); +	} + +	/* Decode the current option-ARGV-element.  */ + +	/* Check whether the ARGV-element is a long option. + +	   If long_only and the ARGV-element has the form "-f", where f is a valid  +	   short option, don't consider it an abbreviated form of a long option +	   that starts with f.  Otherwise there would be no way to give the -f +	   short option. + +	   On the other hand, if there's a long option "fubar" and the +	   ARGV-element is "-fu", do consider that an abbreviation of the long +	   option, just like "--fu", and not "-f" with arg "u". + +	   This distinction seems to be the most useful approach.  */ + +	if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] +									  || !my_index(optstring, argv[optind] +										       [1]))))) { +		char *nameend; +		const struct option *p; +		const struct option *pfound = NULL; +		int exact = 0; +		int ambig = 0; +		int indfound = -1; +		int option_index; + +		for (nameend = nextchar; *nameend && *nameend != '='; nameend++) +			/* Do nothing.  */ ; + +		/* Test all long options for either exact match or abbreviated matches.  +		 */ +		for (p = longopts, option_index = 0; p->name; p++, option_index++) +			if (!strncmp(p->name, nextchar, nameend - nextchar)) { +				if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen(p->name)) { +					/* Exact match found.  */ +					pfound = p; +					indfound = option_index; +					exact = 1; +					break; +				} else if (pfound == NULL) { +					/* First nonexact match found.  */ +					pfound = p; +					indfound = option_index; +				} else +					/* Second or later nonexact match found.  */ +					ambig = 1; +			} + +		if (ambig && !exact) { +			if (opterr) +				fprintf(stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); +			nextchar += strlen(nextchar); +			optind++; +			optopt = 0; +			return '?'; +		} + +		if (pfound != NULL) { +			option_index = indfound; +			optind++; +			if (*nameend) { +				/* Don't test has_arg with >, because some C compilers don't +				   allow it to be used on enums.  */ +				if (pfound->has_arg) +					optarg = nameend + 1; +				else { +					if (opterr) { +						if (argv[optind - 1][1] == '-') +							/* --option */ +							fprintf(stderr, +								_ +								("%s: option `--%s' doesn't allow an argument\n"), +								argv[0], pfound->name); +						else +							/* +option or -option */ +							fprintf(stderr, +								_ +								("%s: option `%c%s' doesn't allow an argument\n"), +								argv[0], argv[optind - 1][0], pfound->name); +					} + +					nextchar += strlen(nextchar); + +					optopt = pfound->val; +					return '?'; +				} +			} else if (pfound->has_arg == 1) { +				if (optind < argc) +					optarg = argv[optind++]; +				else { +					if (opterr) +						fprintf(stderr, +							_ +							("%s: option `%s' requires an argument\n"), +							argv[0], argv[optind - 1]); +					nextchar += strlen(nextchar); +					optopt = pfound->val; +					return optstring[0] == ':' ? ':' : '?'; +				} +			} +			nextchar += strlen(nextchar); +			if (longind != NULL) +				*longind = option_index; +			if (pfound->flag) { +				*(pfound->flag) = pfound->val; +				return 0; +			} +			return pfound->val; +		} + +		/* Can't find it as a long option.  If this is not getopt_long_only, or  +		   the option starts with '--' or is not a valid short option, then +		   it's an error. Otherwise interpret it as a short option.  */ +		if (!long_only || argv[optind][1] == '-' || my_index(optstring, *nextchar) == NULL) { +			if (opterr) { +				if (argv[optind][1] == '-') +					/* --option */ +					fprintf(stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); +				else +					/* +option or -option */ +					fprintf(stderr, +						_ +						("%s: unrecognized option `%c%s'\n"), +						argv[0], argv[optind][0], nextchar); +			} +			nextchar = (char *) ""; +			optind++; +			optopt = 0; +			return '?'; +		} +	} + +	/* Look at and handle the next short option-character.  */ + +	{ +		char c = *nextchar++; +		char *temp = my_index(optstring, c); + +		/* Increment `optind' when we start to process its last character.  */ +		if (*nextchar == '\0') +			++optind; + +		if (temp == NULL || c == ':') { +			if (opterr) { +				if (posixly_correct) +					/* 1003.2 specifies the format of this message.  */ +					fprintf(stderr, _("%s: illegal option -- %c\n"), argv[0], c); +				else +					fprintf(stderr, _("%s: invalid option -- %c\n"), argv[0], c); +			} +			optopt = c; +			return '?'; +		} +		/* Convenience. Treat POSIX -W foo same as long option --foo */ +		if (temp[0] == 'W' && temp[1] == ';') { +			char *nameend; +			const struct option *p; +			const struct option *pfound = NULL; +			int exact = 0; +			int ambig = 0; +			int indfound = 0; +			int option_index; + +			/* This is an option that requires an argument.  */ +			if (*nextchar != '\0') { +				optarg = nextchar; +				/* If we end this ARGV-element by taking the rest as an arg, we +				   must advance to the next element now.  */ +				optind++; +			} else if (optind == argc) { +				if (opterr) { +					/* 1003.2 specifies the format of this message.  */ +					fprintf(stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); +				} +				optopt = c; +				if (optstring[0] == ':') +					c = ':'; +				else +					c = '?'; +				return c; +			} else +				/* We already incremented `optind' once; increment it again when +				   taking next ARGV-elt as argument.  */ +				optarg = argv[optind++]; + +			/* optarg is now the argument, see if it's in the table of longopts.  +			 */ + +			for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) +				/* Do nothing.  */ ; + +			/* Test all long options for either exact match or abbreviated +			   matches.  */ +			for (p = longopts, option_index = 0; p->name; p++, option_index++) +				if (!strncmp(p->name, nextchar, nameend - nextchar)) { +					if ((unsigned int) (nameend - nextchar) == strlen(p->name)) { +						/* Exact match found.  */ +						pfound = p; +						indfound = option_index; +						exact = 1; +						break; +					} else if (pfound == NULL) { +						/* First nonexact match found.  */ +						pfound = p; +						indfound = option_index; +					} else +						/* Second or later nonexact match found.  */ +						ambig = 1; +				} +			if (ambig && !exact) { +				if (opterr) +					fprintf(stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); +				nextchar += strlen(nextchar); +				optind++; +				return '?'; +			} +			if (pfound != NULL) { +				option_index = indfound; +				if (*nameend) { +					/* Don't test has_arg with >, because some C compilers don't +					   allow it to be used on enums.  */ +					if (pfound->has_arg) +						optarg = nameend + 1; +					else { +						if (opterr) +							fprintf(stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); + +						nextchar += strlen(nextchar); +						return '?'; +					} +				} else if (pfound->has_arg == 1) { +					if (optind < argc) +						optarg = argv[optind++]; +					else { +						if (opterr) +							fprintf(stderr, +								_ +								("%s: option `%s' requires an argument\n"), +								argv[0], argv[optind - 1]); +						nextchar += strlen(nextchar); +						return optstring[0] == ':' ? ':' : '?'; +					} +				} +				nextchar += strlen(nextchar); +				if (longind != NULL) +					*longind = option_index; +				if (pfound->flag) { +					*(pfound->flag) = pfound->val; +					return 0; +				} +				return pfound->val; +			} +			nextchar = NULL; +			return 'W';	/* Let the application handle it.  +					 */ +		} +		if (temp[1] == ':') { +			if (temp[2] == ':') { +				/* This is an option that accepts an argument optionally.  */ +				if (*nextchar != '\0') { +					optarg = nextchar; +					optind++; +				} else +					optarg = NULL; +				nextchar = NULL; +			} else { +				/* This is an option that requires an argument.  */ +				if (*nextchar != '\0') { +					optarg = nextchar; +					/* If we end this ARGV-element by taking the rest as an arg, +					   we must advance to the next element now.  */ +					optind++; +				} else if (optind == argc) { +					if (opterr) { +						/* 1003.2 specifies the format of this message.  */ +						fprintf(stderr, +							_("%s: option requires an argument -- %c\n"), argv[0], c); +					} +					optopt = c; +					if (optstring[0] == ':') +						c = ':'; +					else +						c = '?'; +				} else +					/* We already incremented `optind' once; increment it again +					   when taking next ARGV-elt as argument.  */ +					optarg = argv[optind++]; +				nextchar = NULL; +			} +		} +		return c; +	} +} + +int getopt(argc, argv, optstring) +int argc; +char *const *argv; +const char *optstring; +{ +	return _getopt_internal(argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); +} + +#endif				/* Not ELIDE_CODE.  */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing +   the above definition of `getopt'.  */ + +int main(argc, argv) +int argc; +char **argv; +{ +	int c; +	int digit_optind = 0; + +	while (1) { +		int this_option_optind = optind ? optind : 1; + +		c = getopt(argc, argv, "abc:d:0123456789"); +		if (c == -1) +			break; + +		switch (c) { +		case '0': +		case '1': +		case '2': +		case '3': +		case '4': +		case '5': +		case '6': +		case '7': +		case '8': +		case '9': +			if (digit_optind != 0 && digit_optind != this_option_optind) +				printf("digits occur in two different argv-elements.\n"); +			digit_optind = this_option_optind; +			printf("option %c\n", c); +			break; + +		case 'a': +			printf("option a\n"); +			break; + +		case 'b': +			printf("option b\n"); +			break; + +		case 'c': +			printf("option c with value `%s'\n", optarg); +			break; + +		case '?': +			break; + +		default: +			printf("?? getopt returned character code 0%o ??\n", c); +		} +	} + +	if (optind < argc) { +		printf("non-option ARGV-elements: "); +		while (optind < argc) +			printf("%s ", argv[optind++]); +		printf("\n"); +	} + +	exit(0); +} + +#endif				/* TEST */ diff --git a/src/getopt1.c b/src/getopt1.c new file mode 100644 index 0000000..5a5c483 --- /dev/null +++ b/src/getopt1.c @@ -0,0 +1,173 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. +   Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Library General Public License as +   published by the Free Software Foundation; either version 2 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include "getopt.h" + +#if !defined (__STDC__) || !__STDC__ +/* This is a separate conditional since some stdc systems +   reject `defined (const)'.  */ +#ifndef const +#define const +#endif +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not +   actually compiling the library itself.  This code is part of the GNU C +   Library, but also included in many other GNU distributions.  Compiling +   and linking in this code is a waste when using the GNU C library +   (especially if it is a shared library).  Rather than having every GNU +   program understand `configure --with-gnu-libc' and omit the object files, +   it is simpler to just do this in the source for each such file.  */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + +#ifndef ELIDE_CODE + +/* This needs to come after some library #include +   to get __GNU_LIBRARY__ defined.  */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#endif + +#ifndef	NULL +#define NULL 0 +#endif + +int getopt_long(argc, argv, options, long_options, opt_index) +int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; +{ +	return _getopt_internal(argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. +   If an option that starts with '-' (not '--') doesn't match a long option, +   but does match a short option, it is parsed as a short option +   instead.  */ + +int getopt_long_only(argc, argv, options, long_options, opt_index) +int argc; +char *const *argv; +const char *options; +const struct option *long_options; +int *opt_index; +{ +	return _getopt_internal(argc, argv, options, long_options, opt_index, 1); +} + +#endif				/* Not ELIDE_CODE.  */ + +#ifdef TEST + +#include <stdio.h> + +int main(argc, argv) +int argc; +char **argv; +{ +	int c; +	int digit_optind = 0; + +	while (1) { +		int this_option_optind = optind ? optind : 1; +		int option_index = 0; +		static struct option long_options[] = { +			{"add", 1, 0, 0}, +			{"append", 0, 0, 0}, +			{"delete", 1, 0, 0}, +			{"verbose", 0, 0, 0}, +			{"create", 0, 0, 0}, +			{"file", 1, 0, 0}, +			{0, 0, 0, 0} +		}; + +		c = getopt_long(argc, argv, "abc:d:0123456789", long_options, &option_index); +		if (c == -1) +			break; + +		switch (c) { +		case 0: +			printf("option %s", long_options[option_index].name); +			if (optarg) +				printf(" with arg %s", optarg); +			printf("\n"); +			break; + +		case '0': +		case '1': +		case '2': +		case '3': +		case '4': +		case '5': +		case '6': +		case '7': +		case '8': +		case '9': +			if (digit_optind != 0 && digit_optind != this_option_optind) +				printf("digits occur in two different argv-elements.\n"); +			digit_optind = this_option_optind; +			printf("option %c\n", c); +			break; + +		case 'a': +			printf("option a\n"); +			break; + +		case 'b': +			printf("option b\n"); +			break; + +		case 'c': +			printf("option c with value `%s'\n", optarg); +			break; + +		case 'd': +			printf("option d with value `%s'\n", optarg); +			break; + +		case '?': +			break; + +		default: +			printf("?? getopt returned character code 0%o ??\n", c); +		} +	} + +	if (optind < argc) { +		printf("non-option ARGV-elements: "); +		while (optind < argc) +			printf("%s ", argv[optind++]); +		printf("\n"); +	} + +	exit(0); +} + +#endif				/* TEST */ | 
