Browse Source

For getopt_long_only() we *do* want to match single-character options

as shortcuts for long ones, but only if this would not conflict with
a short option in optstring.  Now binutils gas works.
OPENBSD_3_3
millert 22 years ago
parent
commit
03be658a41
1 changed files with 36 additions and 41 deletions
  1. +36
    -41
      src/lib/libc/stdlib/getopt_long.c

+ 36
- 41
src/lib/libc/stdlib/getopt_long.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $ */
/* $OpenBSD: getopt_long.c,v 1.6 2002/12/07 19:15:59 millert Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
@ -64,7 +64,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $";
static char *rcsid = "$OpenBSD: getopt_long.c,v 1.6 2002/12/07 19:15:59 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <err.h>
@ -173,12 +173,11 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if long_only is set and the current option could be a short
* (single character) option instead.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int long_only)
const struct option *long_options, int *idx, int short_too)
{
char *current_argv, *has_equal;
size_t current_argv_len;
@ -208,11 +207,10 @@ parse_long_options(char * const *nargv, const char *options,
break;
}
/*
* Don't try a partial match of a short option when in
* long_only mode. Otherwise there is a potential conflict
* between partial matches and short options.
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (long_only && current_argv_len == 1)
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
@ -273,7 +271,7 @@ parse_long_options(char * const *nargv, const char *options,
return (BADARG);
}
} else { /* unknown option */
if (long_only) {
if (short_too) {
--optind;
return (-1);
}
@ -300,8 +298,7 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
int optchar;
int long_only;
int optchar, short_too;
static int posixly_correct = -1;
optarg = NULL;
@ -320,12 +317,13 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
options++;
/*
* 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.
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
if (optind == 0) {
optind = 1;
optreset = 1;
}
if (optreset)
nonopt_start = nonopt_end = -1;
@ -384,7 +382,10 @@ start:
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
if (strcmp(place, "--") == 0) {
/* check for "--" or "--foo" with no long options */
if (*++place == '-' &&
(place[1] == '\0' || long_options == NULL)) {
optind++;
place = EMSG;
/*
@ -399,38 +400,32 @@ start:
nonopt_start = nonopt_end = -1;
return (-1);
}
place++;
}
/* Check long options if we have any */
long_only = 0;
if (long_options != NULL) {
if (*place == '-' ||
(long_only = (flags & FLAG_LONGONLY))) {
if (!long_only)
place++;
optchar = parse_long_options(nargv, options,
long_options, idx, long_only);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
/* check long options if we have any */
if (long_options != NULL &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, optchar) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(oli = strchr(options, optchar)) == NULL) {
/* option letter unknown or ':' */
if (PRINT_ERROR) {
if (long_only)
warnx(illoptstring, place - 1);
else
warnx(illoptchar, optchar);
}
if (!*place || long_only) {
if (!*place)
++optind;
if (*place)
place = EMSG;
}
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}


Loading…
Cancel
Save