Update shipped getopt version to include the new optional_argument option

directional-lights
Sven Eberhardt 2016-10-08 20:51:22 -04:00
parent 45718ee44d
commit 64cfe42827
3 changed files with 298 additions and 262 deletions

View File

@ -1,3 +1,5 @@
/* $NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $ */
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
@ -6,133 +8,145 @@
* 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.
* 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. 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.
* 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
* 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
#endif
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
/*
* On some versions of Solaris, opterr and friends are defined in core libc
* rather than in a separate getopt module. Define these variables only
* if configure found they aren't there by default. (We assume that testing
* opterr is sufficient for all of these except optreset.)
*/
#ifndef HAVE_INT_OPTERR
#define __P(x) x
#define _DIAGASSERT(x) assert(x)
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt; /* character checked for validity */
char *optarg; /* argument associated with option */
#else
extern int opterr;
extern int optind;
extern int optopt;
extern char *optarg;
#ifdef __weak_alias
__weak_alias(getopt,_getopt);
#endif
#ifndef HAVE_INT_OPTRESET
int optreset; /* reset getopt */
#else
extern int optreset;
#endif
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
static char * _progname __P((char *));
int getopt_internal __P((int, char * const *, const char *));
static char *
_progname(nargv0)
char * nargv0;
{
char * tmp;
_DIAGASSERT(nargv0 != NULL);
tmp = strrchr(nargv0, '/');
if (tmp)
tmp++;
else
tmp = nargv0;
return(tmp);
}
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char *const * nargv;
const char *ostr;
int nargc;
char * const nargv[];
const char *ostr;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
static char *__progname = 0;
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
__progname = __progname?__progname:_progname(*nargv);
if (optreset || !*place)
{ /* update scanning pointer */
_DIAGASSERT(nargv != NULL);
_DIAGASSERT(ostr != NULL);
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-')
{
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return -1;
return (-1);
}
if (place[1] && *++place == '-' && place[1] == '\0')
{ /* found "--" */
if (place[1] && *++place == '-' /* found "--" */
&& place[1] == '\0') {
++optind;
place = EMSG;
return -1;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int) *place++) == (int) ':' ||
!(oli = strchr(ostr, optopt)))
{
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option, assume it means -1.
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int) '-')
return -1;
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void) fprintf(stderr,
"illegal option -- %c\n", optopt);
return BADCH;
(void)fprintf(stderr,
"%s: illegal option -- %c\n", __progname, optopt);
return (BADCH);
}
if (*++oli != ':')
{ /* don't need argument */
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else
{ /* need an argument */
if (*place) /* no white space */
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind)
{ /* no arg */
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return BADARG;
return (BADARG);
if (opterr)
(void) fprintf(stderr,
"option requires an argument -- %c\n",
optopt);
return BADCH;
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
__progname, optopt);
return (BADCH);
}
else
/* white space */
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return optopt; /* dump back option letter */
return (optopt); /* dump back option letter */
}

View File

@ -1,49 +1,33 @@
/*
* Portions Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Portions Copyright (c) 2003-2010, PostgreSQL Global Development Group
*/
#ifndef GETOPT_H
#define GETOPT_H
#ifndef __GETOPT_H__
#define __GETOPT_H__
#ifdef __cplusplus
extern "C" {
#endif
extern int getopt(int argc, char * const argv[],
const char *optstring);
/* These are picked up from the system's getopt() facility. */
extern int opterr;
extern int optind;
extern int optopt;
extern char *optarg;
extern int optreset;
#ifndef HAVE_STRUCT_OPTION
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 */
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
const char *name;
int has_arg;
int *flag;
int val;
};
#define no_argument 0
#define no_argument 0
#define required_argument 1
#endif
#define optional_argument 2
#ifndef HAVE_GETOPT_LONG
extern int getopt_long(int argc, char *const argv[],
const char *optstring,
const struct option * longopts, int *longindex);
#endif
int getopt(int, char**, char*);
int getopt_long(int, char**, const char*, struct option*, int*);
#ifdef __cplusplus
}
#endif
#endif /* GETOPT_H */
#endif /* __GETOPT_H__ */

View File

@ -1,28 +1,27 @@
/*
* getopt_long() -- long options parser
*
* Portions Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Portions Copyright (c) 2003
* PostgreSQL Global Development Group
* 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.
* 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. 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.
* 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
* 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)
@ -31,168 +30,207 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
#ifndef HAVE_INT_OPTRESET
int optreset;
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 */
/* else the "extern" was provided by getopt_long.h */
#endif
#define __P(x) x
#define _DIAGASSERT(x) assert(x)
#define BADCH '?'
#define BADARG ':'
#define EMSG ""
static char * __progname __P((char *));
int getopt_internal __P((int, char * const *, const char *));
#include <string.h>
#include <stdio.h>
int
getopt_long(int argc, char *const argv[],
const char *optstring,
const struct option * longopts, int *longindex)
static char *
__progname(nargv0)
char * nargv0;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
char * tmp;
if (optreset || !*place)
{ /* update scanning pointer */
_DIAGASSERT(nargv0 != NULL);
tmp = strrchr(nargv0, '/');
if (tmp)
tmp++;
else
tmp = nargv0;
return(tmp);
}
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt_internal(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
_DIAGASSERT(nargv != NULL);
_DIAGASSERT(ostr != NULL);
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= argc)
{
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return -1;
return (-1);
}
place = argv[optind];
if (place[0] != '-')
{
if (place[1] && *++place == '-') { /* found "--" */
/* ++optind; */
place = EMSG;
return -1;
return (-2);
}
place++;
if (place[0] && place[0] == '-' && place[1] == '\0')
{ /* found "--" */
++optind;
place = EMSG;
return -1;
}
if (place[0] && place[0] == '-' && place[1])
{
/* long option */
size_t namelen;
int i;
place++;
namelen = strcspn(place, "=");
for (i = 0; longopts[i].name != NULL; i++)
{
if (strlen(longopts[i].name) == namelen
&& strncmp(place, longopts[i].name, namelen) == 0)
{
if (longopts[i].has_arg)
{
if (place[namelen] == '=')
optarg = place + namelen + 1;
else if (optind < argc - 1)
{
optind++;
optarg = argv[optind];
}
else
{
if (optstring[0] == ':')
return BADARG;
if (opterr)
fprintf(stderr,
"%s: option requires an argument -- %s\n",
argv[0], place);
place = EMSG;
optind++;
return BADCH;
}
}
else
{
optarg = NULL;
if (place[namelen] != 0)
{
/* XXX error? */
}
}
optind++;
if (longindex)
*longindex = i;
place = EMSG;
if (longopts[i].flag == NULL)
return longopts[i].val;
else
{
*longopts[i].flag = longopts[i].val;
return 0;
}
}
}
if (opterr && optstring[0] != ':')
fprintf(stderr,
"%s: illegal option -- %s\n", argv[0], place);
place = EMSG;
optind++;
return BADCH;
}
}
/* short option */
optopt = (int) *place++;
oli = strchr(optstring, optopt);
if (!oli)
{
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
if (opterr && *optstring != ':')
fprintf(stderr,
"%s: illegal option -- %c\n", argv[0], optopt);
return BADCH;
if (opterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
return (BADCH);
}
if (oli[1] != ':')
{ /* don't need argument */
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else
{ /* need an argument */
if (*place) /* no white space */
} else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (argc <= ++optind)
{ /* no arg */
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*optstring == ':')
return BADARG;
if (opterr)
fprintf(stderr,
"%s: option requires an argument -- %c\n",
argv[0], optopt);
return BADCH;
}
else
/* white space */
optarg = argv[optind];
if ((opterr) && (*ostr != ':'))
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
__progname(nargv[0]), optopt);
return (BADARG);
} else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return optopt;
return (optopt); /* dump back option letter */
}
#if 0
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt2(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
int retval;
if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
retval = -1;
++optind;
}
return(retval);
}
#endif
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(nargc, nargv, options, long_options, index)
int nargc;
char ** nargv;
const char * options;
struct option * long_options;
int * index;
{
int retval;
_DIAGASSERT(nargv != NULL);
_DIAGASSERT(options != NULL);
_DIAGASSERT(long_options != NULL);
/* index may be NULL */
if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
char *current_argv = nargv[optind++] + 2, *has_equal;
int i, current_argv_len, match = -1;
if (*current_argv == '\0') {
return(-1);
}
if ((has_equal = strchr(current_argv, '=')) != NULL) {
current_argv_len = (int) (has_equal - current_argv);
has_equal++;
} else
current_argv_len = (int) (strlen(current_argv));
for (i = 0; long_options[i].name; i++) {
if (strncmp(current_argv, long_options[i].name, current_argv_len))
continue;
if (strlen(long_options[i].name) == (unsigned)current_argv_len) {
match = i;
break;
}
if (match == -1)
match = i;
}
if (match != -1) {
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else
optarg = nargv[optind++];
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument, leading :
* indicates no error should be generated
*/
if ((opterr) && (*options != ':'))
(void)fprintf(stderr,
"%s: option requires an argument -- %s\n",
__progname(nargv[0]), current_argv);
return (BADARG);
}
} else { /* No matching argument */
if ((opterr) && (*options != ':'))
(void)fprintf(stderr,
"%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
return (BADCH);
}
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
retval = 0;
} else
retval = long_options[match].val;
if (index)
*index = match;
}
return(retval);
}