* mingwex/getopt.c: New file, copied from cygwin srcs.
* include/getopt.h: New file, copied from cygwin srcs. * include/unistd.h: Include getopt.h. * mingwex/Makefile.in ((DISTFILES): Add getopt.c. (POSIX_OBJS): Add getopt.o.
This commit is contained in:
		| @@ -1,3 +1,11 @@ | |||||||
|  | 2003-03-03  Danny Smith  <dannysmith@users.sourceforge.net> | ||||||
|  |  | ||||||
|  | 	* mingwex/getopt.c: New file, copied from cygwin srcs. | ||||||
|  | 	* include/getopt.h: New file, copied from cygwin srcs. | ||||||
|  | 	* include/unistd.h: Include getopt.h. | ||||||
|  | 	* mingwex/Makefile.in ((DISTFILES): Add getopt.c. | ||||||
|  | 	(POSIX_OBJS): Add getopt.o. | ||||||
|  |  | ||||||
| 2003-03-02  Danny Smith  <dannysmith@users.sourceforge.net> | 2003-03-02  Danny Smith  <dannysmith@users.sourceforge.net> | ||||||
|  |  | ||||||
| 	* include/stdio.h (vscanf): Add prototype. | 	* include/stdio.h (vscanf): Add prototype. | ||||||
|   | |||||||
							
								
								
									
										84
									
								
								winsup/mingw/include/getopt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								winsup/mingw/include/getopt.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright (c) 1987, 1993, 1994, 1996 | ||||||
|  |  *  The Regents of the University of California.  All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. All advertising materials mentioning features or use of this software | ||||||
|  |  *    must display the following acknowledgement: | ||||||
|  |  *  This product includes software developed by the University of | ||||||
|  |  *  California, Berkeley and its contributors. | ||||||
|  |  * 4. Neither the name of the University nor the names of its contributors | ||||||
|  |  *    may be used to endorse or promote products derived from this software | ||||||
|  |  *    without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||||||
|  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||||
|  |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||||
|  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||||
|  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||||
|  |  * SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef __GETOPT_H__ | ||||||
|  | #define __GETOPT_H__ | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | extern int   opterr;      /* if error message should be printed */ | ||||||
|  | extern int   optind;      /* index into parent argv vector */ | ||||||
|  | extern int   optopt;      /* character checked for validity */ | ||||||
|  | extern int   optreset;    /* reset getopt */ | ||||||
|  | extern char *optarg;      /* argument associated with option */ | ||||||
|  |  | ||||||
|  | int getopt (int, char * const *, const char *); | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* __GETOPT_H__ */ | ||||||
|  |  | ||||||
|  | #ifndef __UNISTD_GETOPT__ | ||||||
|  | #ifndef __GETOPT_LONG_H__ | ||||||
|  | #define __GETOPT_LONG_H__ | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | struct option { | ||||||
|  | 	const char *name; | ||||||
|  | 	int  has_arg; | ||||||
|  | 	int *flag; | ||||||
|  | 	int val; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | int getopt_long (int, char *const *, const char *, const struct option *, int *); | ||||||
|  | #ifndef HAVE_DECL_GETOPT | ||||||
|  | #define HAVE_DECL_GETOPT 1 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define no_argument             0 | ||||||
|  | #define required_argument       1 | ||||||
|  | #define optional_argument       2 | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* __GETOPT_LONG_H__ */ | ||||||
|  | #endif /* __UNISTD_GETOPT__ */ | ||||||
| @@ -5,7 +5,13 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #ifndef __STRICT_ANSI__ | #ifndef __STRICT_ANSI__ | ||||||
|  |  | ||||||
| #include <io.h> | #include <io.h> | ||||||
| #include <process.h> | #include <process.h> | ||||||
| #endif |  | ||||||
|  | #define __UNISTD_GETOPT__ | ||||||
|  | #include <getopt.h> | ||||||
|  | #undef __UNISTD_GETOPT__ | ||||||
|  |  | ||||||
|  | #endif  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,11 +29,10 @@ DISTFILES = Makefile.in configure configure.in \ | |||||||
| 	_Exit.c atoll.c dirent.c feclearexcept.c fegetenv.c \ | 	_Exit.c atoll.c dirent.c feclearexcept.c fegetenv.c \ | ||||||
| 	fegetexceptflag.c fegetround.c feholdexcept.c feraiseexcept.c \ | 	fegetexceptflag.c fegetround.c feholdexcept.c feraiseexcept.c \ | ||||||
| 	fesetenv.c fesetexceptflag.c fesetround.c fetestexcept.c \ | 	fesetenv.c fesetexceptflag.c fesetround.c fetestexcept.c \ | ||||||
| 	feupdateenv.c fwide.c imaxabs.c imaxdiv.c ldtoa.c lltoa.c lltow.c \ | 	feupdateenv.c fwide.c  getopt.c imaxabs.c imaxdiv.c ldtoa.c \ | ||||||
| 	mbsinit.c mingw-fseek.c sitest.c \ | 	lltoa.c lltow.c mbsinit.c mingw-fseek.c sitest.c strtof.c \ | ||||||
| 	strtof.c strtoimax.c strtold.c strtoumax.c testwmem.c \ | 	strtoimax.c strtold.c strtoumax.c testwmem.c ulltoa.c ulltow.c \ | ||||||
| 	ulltoa.c ulltow.c  wcstof.c \ | 	wcstof.c wcstoimax.c wcstold.c wcstoumax.c wdirent.c wmemchr.c \ | ||||||
| 	wcstoimax.c wcstold.c wcstoumax.c wdirent.c wmemchr.c \ |  | ||||||
| 	wmemcmp.c wmemcpy.c wmemmove.c wmemset.c wtoll.c | 	wmemcmp.c wmemcpy.c wmemmove.c wmemset.c wtoll.c | ||||||
| 	 | 	 | ||||||
| MATH_DISTFILES = \ | MATH_DISTFILES = \ | ||||||
| @@ -142,7 +141,7 @@ FENV_OBJS = fesetround.o  fegetround.o \ | |||||||
| 	feclearexcept.o feholdexcept.o fegetexceptflag.o \ | 	feclearexcept.o feholdexcept.o fegetexceptflag.o \ | ||||||
| 	feraiseexcept.o fetestexcept.o fesetexceptflag.o | 	feraiseexcept.o fetestexcept.o fesetexceptflag.o | ||||||
| POSIX_OBJS = \ | POSIX_OBJS = \ | ||||||
| 	dirent.o wdirent.o | 	dirent.o wdirent.o getopt.o | ||||||
| REPLACE_OBJS = \ | REPLACE_OBJS = \ | ||||||
| 	mingw-fseek.o | 	mingw-fseek.o | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										493
									
								
								winsup/mingw/mingwex/getopt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										493
									
								
								winsup/mingw/mingwex/getopt.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,493 @@ | |||||||
|  | /*	$NetBSD: getopt_long.c,v 1.12 2001/04/24 09:07:43 joda Exp $	*/ | ||||||
|  |  | ||||||
|  | /*- | ||||||
|  |  * Copyright (c) 2000 The NetBSD Foundation, Inc. | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * This code is derived from software contributed to The NetBSD Foundation | ||||||
|  |  * by Dieter Baron and Thomas Klausner. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. All advertising materials mentioning features or use of this software | ||||||
|  |  *    must display the following acknowledgement: | ||||||
|  |  *        This product includes software developed by the NetBSD | ||||||
|  |  *        Foundation, Inc. and its contributors. | ||||||
|  |  * 4. Neither the name of The NetBSD Foundation nor the names of its | ||||||
|  |  *    contributors may be used to endorse or promote products derived | ||||||
|  |  *    from this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | ||||||
|  |  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||||||
|  |  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||||
|  |  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | ||||||
|  |  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||||
|  |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||||
|  |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||||
|  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||||
|  |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||||
|  |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  |  * POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <assert.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <getopt.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #define REPLACE_GETOPT | ||||||
|  |  | ||||||
|  | #define _DIAGASSERT(x) do {} while (0) | ||||||
|  |  | ||||||
|  | #ifdef REPLACE_GETOPT | ||||||
|  | #ifdef __weak_alias | ||||||
|  | __weak_alias(getopt,_getopt) | ||||||
|  | #endif | ||||||
|  | int	opterr = 1;		/* if error message should be printed */ | ||||||
|  | int	optind = 1;		/* index into parent argv vector */ | ||||||
|  | int	optopt = '?';		/* character checked for validity */ | ||||||
|  | int	optreset;		/* reset getopt */ | ||||||
|  | char    *optarg;		/* argument associated with option */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef __weak_alias | ||||||
|  | __weak_alias(getopt_long,_getopt_long) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef __CYGWIN__ | ||||||
|  | #define __progname __argv[0] | ||||||
|  | #else | ||||||
|  | extern char __declspec(dllimport) *__progname; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define IGNORE_FIRST	(*options == '-' || *options == '+') | ||||||
|  | #define PRINT_ERROR	((opterr) && ((*options != ':') \ | ||||||
|  | 				      || (IGNORE_FIRST && options[1] != ':'))) | ||||||
|  |  | ||||||
|  | #define IS_POSIXLY_CORRECT (getenv("POSIXLY_INCORRECT_GETOPT") == NULL) | ||||||
|  |  | ||||||
|  | #define PERMUTE         (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) | ||||||
|  | /* XXX: GNU ignores PC if *options == '-' */ | ||||||
|  | #define IN_ORDER        (!IS_POSIXLY_CORRECT && *options == '-') | ||||||
|  |  | ||||||
|  | /* return values */ | ||||||
|  | #define	BADCH	(int)'?' | ||||||
|  | #define	BADARG		((IGNORE_FIRST && options[1] == ':') \ | ||||||
|  | 			 || (*options == ':') ? (int)':' : (int)'?') | ||||||
|  | #define INORDER (int)1 | ||||||
|  |  | ||||||
|  | #define	EMSG	"" | ||||||
|  |  | ||||||
|  | static int getopt_internal (int, char * const *, const char *); | ||||||
|  | static int gcd (int, int); | ||||||
|  | static void permute_args (int, int, int, char * const *); | ||||||
|  |  | ||||||
|  | static const char *place = EMSG; /* option letter processing */ | ||||||
|  |  | ||||||
|  | /* XXX: set optreset to 1 rather than these two */ | ||||||
|  | static int nonopt_start = -1; /* first non option argument (for permute) */ | ||||||
|  | static int nonopt_end = -1;   /* first option after non options (for permute) */ | ||||||
|  |  | ||||||
|  | /* Error messages */ | ||||||
|  | static const char recargchar[] = "option requires an argument -- %c"; | ||||||
|  | static const char recargstring[] = "option requires an argument -- %s"; | ||||||
|  | static const char ambig[] = "ambiguous option -- %.*s"; | ||||||
|  | static const char noarg[] = "option doesn't take an argument -- %.*s"; | ||||||
|  | static const char illoptchar[] = "unknown option -- %c"; | ||||||
|  | static const char illoptstring[] = "unknown option -- %s"; | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | _vwarnx(const char *fmt, va_list ap) | ||||||
|  | { | ||||||
|  |   (void)fprintf(stderr, "%s: ", __progname); | ||||||
|  |   if (fmt != NULL) | ||||||
|  |     (void)vfprintf(stderr, fmt, ap); | ||||||
|  |   (void)fprintf(stderr, "\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | warnx(const char *fmt, ...) | ||||||
|  | { | ||||||
|  |   va_list ap; | ||||||
|  |   va_start(ap, fmt); | ||||||
|  |   _vwarnx(fmt, ap); | ||||||
|  |   va_end(ap); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Compute the greatest common divisor of a and b. | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | gcd(a, b) | ||||||
|  | 	int a; | ||||||
|  | 	int b; | ||||||
|  | { | ||||||
|  | 	int c; | ||||||
|  |  | ||||||
|  | 	c = a % b; | ||||||
|  | 	while (c != 0) { | ||||||
|  | 		a = b; | ||||||
|  | 		b = c; | ||||||
|  | 		c = a % b; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return b; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Exchange the block from nonopt_start to nonopt_end with the block | ||||||
|  |  * from nonopt_end to opt_end (keeping the same order of arguments | ||||||
|  |  * in each block). | ||||||
|  |  */ | ||||||
|  | static void | ||||||
|  | permute_args(nonopt_start, nonopt_end, opt_end, nargv) | ||||||
|  | 	int nonopt_start; | ||||||
|  | 	int nonopt_end; | ||||||
|  | 	int opt_end; | ||||||
|  | 	char * const *nargv; | ||||||
|  | { | ||||||
|  | 	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; | ||||||
|  | 	char *swap; | ||||||
|  |  | ||||||
|  | 	_DIAGASSERT(nargv != NULL); | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * compute lengths of blocks and number and size of cycles | ||||||
|  | 	 */ | ||||||
|  | 	nnonopts = nonopt_end - nonopt_start; | ||||||
|  | 	nopts = opt_end - nonopt_end; | ||||||
|  | 	ncycle = gcd(nnonopts, nopts); | ||||||
|  | 	cyclelen = (opt_end - nonopt_start) / ncycle; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < ncycle; i++) { | ||||||
|  | 		cstart = nonopt_end+i; | ||||||
|  | 		pos = cstart; | ||||||
|  | 		for (j = 0; j < cyclelen; j++) { | ||||||
|  | 			if (pos >= nonopt_end) | ||||||
|  | 				pos -= nnonopts; | ||||||
|  | 			else | ||||||
|  | 				pos += nopts; | ||||||
|  | 			swap = nargv[pos]; | ||||||
|  | 			/* LINTED const cast */ | ||||||
|  | 			((char **) nargv)[pos] = nargv[cstart]; | ||||||
|  | 			/* LINTED const cast */ | ||||||
|  | 			((char **)nargv)[cstart] = swap; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * getopt_internal -- | ||||||
|  |  *	Parse argc/argv argument vector.  Called by user level routines. | ||||||
|  |  *  Returns -2 if -- is found (can be long option or end of options marker). | ||||||
|  |  */ | ||||||
|  | static int | ||||||
|  | getopt_internal(int nargc, char *const * nargv, const char *options) | ||||||
|  | { | ||||||
|  | 	char *oli;				/* option letter list index */ | ||||||
|  | 	int optchar; | ||||||
|  |  | ||||||
|  | 	_DIAGASSERT(nargv != NULL); | ||||||
|  | 	_DIAGASSERT(options != NULL); | ||||||
|  |  | ||||||
|  | 	optarg = NULL; | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * XXX Some programs (like rsyncd) expect to be able to | ||||||
|  | 	 * XXX re-initialize optind to 0 and have getopt_long(3) | ||||||
|  | 	 * XXX properly function again.  Work around this braindamage. | ||||||
|  | 	 */ | ||||||
|  | 	if (optind == 0 && optreset == 0) | ||||||
|  | 		optind = 1; | ||||||
|  |  | ||||||
|  | 	if (optreset) | ||||||
|  | 		nonopt_start = nonopt_end = -1; | ||||||
|  | start: | ||||||
|  | 	if (optreset || !*place) {		/* update scanning pointer */ | ||||||
|  | 		optreset = 0; | ||||||
|  | 		if (optind >= nargc) {          /* end of argument vector */ | ||||||
|  | 			place = EMSG; | ||||||
|  | 			if (nonopt_end != -1) { | ||||||
|  | 				/* do permutation, if we have to */ | ||||||
|  | 				permute_args(nonopt_start, nonopt_end, | ||||||
|  | 				    optind, nargv); | ||||||
|  | 				optind -= nonopt_end - nonopt_start; | ||||||
|  | 			} | ||||||
|  | 			else if (nonopt_start != -1) { | ||||||
|  | 				/* | ||||||
|  | 				 * If we skipped non-options, set optind | ||||||
|  | 				 * to the first of them. | ||||||
|  | 				 */ | ||||||
|  | 				optind = nonopt_start; | ||||||
|  | 			} | ||||||
|  | 			nonopt_start = nonopt_end = -1; | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 		if ((*(place = nargv[optind]) != '-') | ||||||
|  | 		    || (place[1] == '\0')) {    /* found non-option */ | ||||||
|  | 			place = EMSG; | ||||||
|  | 			if (IN_ORDER) { | ||||||
|  | 				/* | ||||||
|  | 				 * GNU extension: | ||||||
|  | 				 * return non-option as argument to option 1 | ||||||
|  | 				 */ | ||||||
|  | 				optarg = nargv[optind++]; | ||||||
|  | 				return INORDER; | ||||||
|  | 			} | ||||||
|  | 			if (!PERMUTE) { | ||||||
|  | 				/* | ||||||
|  | 				 * if no permutation wanted, stop parsing | ||||||
|  | 				 * at first non-option | ||||||
|  | 				 */ | ||||||
|  | 				return -1; | ||||||
|  | 			} | ||||||
|  | 			/* do permutation */ | ||||||
|  | 			if (nonopt_start == -1) | ||||||
|  | 				nonopt_start = optind; | ||||||
|  | 			else if (nonopt_end != -1) { | ||||||
|  | 				permute_args(nonopt_start, nonopt_end, | ||||||
|  | 				    optind, nargv); | ||||||
|  | 				nonopt_start = optind - | ||||||
|  | 				    (nonopt_end - nonopt_start); | ||||||
|  | 				nonopt_end = -1; | ||||||
|  | 			} | ||||||
|  | 			optind++; | ||||||
|  | 			/* process next argument */ | ||||||
|  | 			goto start; | ||||||
|  | 		} | ||||||
|  | 		if (nonopt_start != -1 && nonopt_end == -1) | ||||||
|  | 			nonopt_end = optind; | ||||||
|  | 		if (place[1] && *++place == '-') {	/* found "--" */ | ||||||
|  | 			place++; | ||||||
|  | 			return -2; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if ((optchar = (int)*place++) == (int)':' || | ||||||
|  | 	    (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { | ||||||
|  | 		/* option letter unknown or ':' */ | ||||||
|  | 		if (!*place) | ||||||
|  | 			++optind; | ||||||
|  | 		if (PRINT_ERROR) | ||||||
|  | 			warnx(illoptchar, optchar); | ||||||
|  | 		optopt = optchar; | ||||||
|  | 		return BADCH; | ||||||
|  | 	} | ||||||
|  | 	if (optchar == 'W' && oli[1] == ';') {		/* -W long-option */ | ||||||
|  | 		/* XXX: what if no long options provided (called by getopt)? */ | ||||||
|  | 		if (*place) | ||||||
|  | 			return -2; | ||||||
|  |  | ||||||
|  | 		if (++optind >= nargc) {	/* no arg */ | ||||||
|  | 			place = EMSG; | ||||||
|  | 			if (PRINT_ERROR) | ||||||
|  | 				warnx(recargchar, optchar); | ||||||
|  | 			optopt = optchar; | ||||||
|  | 			return BADARG; | ||||||
|  | 		} else				/* white space */ | ||||||
|  | 			place = nargv[optind]; | ||||||
|  | 		/* | ||||||
|  | 		 * Handle -W arg the same as --arg (which causes getopt to | ||||||
|  | 		 * stop parsing). | ||||||
|  | 		 */ | ||||||
|  | 		return -2; | ||||||
|  | 	} | ||||||
|  | 	if (*++oli != ':') {			/* doesn't take argument */ | ||||||
|  | 		if (!*place) | ||||||
|  | 			++optind; | ||||||
|  | 	} else {				/* takes (optional) argument */ | ||||||
|  | 		optarg = NULL; | ||||||
|  | 		if (*place)			/* no white space */ | ||||||
|  | 			optarg = (char *) place; | ||||||
|  | 		/* XXX: disable test for :: if PC? (GNU doesn't) */ | ||||||
|  | 		else if (oli[1] != ':') {	/* arg not optional */ | ||||||
|  | 			if (++optind >= nargc) {	/* no arg */ | ||||||
|  | 				place = EMSG; | ||||||
|  | 				if (PRINT_ERROR) | ||||||
|  | 					warnx(recargchar, optchar); | ||||||
|  | 				optopt = optchar; | ||||||
|  | 				return BADARG; | ||||||
|  | 			} else | ||||||
|  | 				optarg = nargv[optind]; | ||||||
|  | 		} | ||||||
|  | 		place = EMSG; | ||||||
|  | 		++optind; | ||||||
|  | 	} | ||||||
|  | 	/* dump back option letter */ | ||||||
|  | 	return optchar; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifdef REPLACE_GETOPT | ||||||
|  | /* | ||||||
|  |  * getopt -- | ||||||
|  |  *	Parse argc/argv argument vector. | ||||||
|  |  * | ||||||
|  |  * [eventually this will replace the real getopt] | ||||||
|  |  */ | ||||||
|  | int | ||||||
|  | getopt(int nargc, char * const *nargv, const char *options) | ||||||
|  | { | ||||||
|  | 	int retval; | ||||||
|  |  | ||||||
|  | 	_DIAGASSERT(nargv != NULL); | ||||||
|  | 	_DIAGASSERT(options != NULL); | ||||||
|  |  | ||||||
|  | 	if ((retval = getopt_internal(nargc, nargv, options)) == -2) { | ||||||
|  | 		++optind; | ||||||
|  | 		/* | ||||||
|  | 		 * We found an option (--), so if we skipped non-options, | ||||||
|  | 		 * we have to permute. | ||||||
|  | 		 */ | ||||||
|  | 		if (nonopt_end != -1) { | ||||||
|  | 			permute_args(nonopt_start, nonopt_end, optind, | ||||||
|  | 				       nargv); | ||||||
|  | 			optind -= nonopt_end - nonopt_start; | ||||||
|  | 		} | ||||||
|  | 		nonopt_start = nonopt_end = -1; | ||||||
|  | 		retval = -1; | ||||||
|  | 	} | ||||||
|  | 	return retval; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * getopt_long -- | ||||||
|  |  *	Parse argc/argv argument vector. | ||||||
|  |  */ | ||||||
|  | int | ||||||
|  | getopt_long(int nargc, char * const *nargv, const char *options, | ||||||
|  | 	    const struct option *long_options, int *idx) | ||||||
|  | { | ||||||
|  | 	int retval; | ||||||
|  |  | ||||||
|  | 	_DIAGASSERT(nargv != NULL); | ||||||
|  | 	_DIAGASSERT(options != NULL); | ||||||
|  | 	_DIAGASSERT(long_options != NULL); | ||||||
|  | 	/* idx may be NULL */ | ||||||
|  |  | ||||||
|  | 	if ((retval = getopt_internal(nargc, nargv, options)) == -2) { | ||||||
|  | 		char *current_argv, *has_equal; | ||||||
|  | 		size_t current_argv_len; | ||||||
|  | 		int i, match; | ||||||
|  |  | ||||||
|  | 		current_argv = (char *) place; | ||||||
|  | 		match = -1; | ||||||
|  |  | ||||||
|  | 		optind++; | ||||||
|  | 		place = EMSG; | ||||||
|  |  | ||||||
|  | 		if (*current_argv == '\0') {		/* found "--" */ | ||||||
|  | 			/* | ||||||
|  | 			 * We found an option (--), so if we skipped | ||||||
|  | 			 * non-options, we have to permute. | ||||||
|  | 			 */ | ||||||
|  | 			if (nonopt_end != -1) { | ||||||
|  | 				permute_args(nonopt_start, nonopt_end, | ||||||
|  | 				    optind, nargv); | ||||||
|  | 				optind -= nonopt_end - nonopt_start; | ||||||
|  | 			} | ||||||
|  | 			nonopt_start = nonopt_end = -1; | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 		if ((has_equal = strchr(current_argv, '=')) != NULL) { | ||||||
|  | 			/* argument found (--option=arg) */ | ||||||
|  | 			current_argv_len = has_equal - current_argv; | ||||||
|  | 			has_equal++; | ||||||
|  | 		} else | ||||||
|  | 			current_argv_len = strlen(current_argv); | ||||||
|  |  | ||||||
|  | 		for (i = 0; long_options[i].name; i++) { | ||||||
|  | 			/* find matching long option */ | ||||||
|  | 			if (strncmp(current_argv, long_options[i].name, | ||||||
|  | 			    current_argv_len)) | ||||||
|  | 				continue; | ||||||
|  |  | ||||||
|  | 			if (strlen(long_options[i].name) == | ||||||
|  | 			    (unsigned)current_argv_len) { | ||||||
|  | 				/* exact match */ | ||||||
|  | 				match = i; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			if (match == -1)		/* partial match */ | ||||||
|  | 				match = i; | ||||||
|  | 			else { | ||||||
|  | 				/* ambiguous abbreviation */ | ||||||
|  | 				if (PRINT_ERROR) | ||||||
|  | 					warnx(ambig, (int)current_argv_len, | ||||||
|  | 					     current_argv); | ||||||
|  | 				optopt = 0; | ||||||
|  | 				return BADCH; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (match != -1) {			/* option found */ | ||||||
|  | 			if (long_options[match].has_arg == no_argument | ||||||
|  | 			    && has_equal) { | ||||||
|  | 				if (PRINT_ERROR) | ||||||
|  | 					warnx(noarg, (int)current_argv_len, | ||||||
|  | 					     current_argv); | ||||||
|  | 				/* | ||||||
|  | 				 * XXX: GNU sets optopt to val regardless of | ||||||
|  | 				 * flag | ||||||
|  | 				 */ | ||||||
|  | 				if (long_options[match].flag == NULL) | ||||||
|  | 					optopt = long_options[match].val; | ||||||
|  | 				else | ||||||
|  | 					optopt = 0; | ||||||
|  | 				return BADARG; | ||||||
|  | 			} | ||||||
|  | 			if (long_options[match].has_arg == required_argument || | ||||||
|  | 			    long_options[match].has_arg == optional_argument) { | ||||||
|  | 				if (has_equal) | ||||||
|  | 					optarg = has_equal; | ||||||
|  | 				else if (long_options[match].has_arg == | ||||||
|  | 				    required_argument) { | ||||||
|  | 					/* | ||||||
|  | 					 * optional argument doesn't use | ||||||
|  | 					 * next nargv | ||||||
|  | 					 */ | ||||||
|  | 					optarg = nargv[optind++]; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if ((long_options[match].has_arg == required_argument) | ||||||
|  | 			    && (optarg == NULL)) { | ||||||
|  | 				/* | ||||||
|  | 				 * Missing argument; leading ':' | ||||||
|  | 				 * indicates no error should be generated | ||||||
|  | 				 */ | ||||||
|  | 				if (PRINT_ERROR) | ||||||
|  | 					warnx(recargstring, current_argv); | ||||||
|  | 				/* | ||||||
|  | 				 * XXX: GNU sets optopt to val regardless | ||||||
|  | 				 * of flag | ||||||
|  | 				 */ | ||||||
|  | 				if (long_options[match].flag == NULL) | ||||||
|  | 					optopt = long_options[match].val; | ||||||
|  | 				else | ||||||
|  | 					optopt = 0; | ||||||
|  | 				--optind; | ||||||
|  | 				return BADARG; | ||||||
|  | 			} | ||||||
|  | 		} else {			/* unknown option */ | ||||||
|  | 			if (PRINT_ERROR) | ||||||
|  | 				warnx(illoptstring, current_argv); | ||||||
|  | 			optopt = 0; | ||||||
|  | 			return BADCH; | ||||||
|  | 		} | ||||||
|  | 		if (long_options[match].flag) { | ||||||
|  | 			*long_options[match].flag = long_options[match].val; | ||||||
|  | 			retval = 0; | ||||||
|  | 		} else | ||||||
|  | 			retval = long_options[match].val; | ||||||
|  | 		if (idx) | ||||||
|  | 			*idx = match; | ||||||
|  | 	} | ||||||
|  | 	return retval; | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user