Browse Source

Fix parsing of ambiguous options, the whole loop must be processed.

From FreeBSD.  OK miod@
OPENBSD_5_4
millert 11 years ago
parent
commit
e8e815fedd
1 changed files with 22 additions and 15 deletions
  1. +22
    -15
      src/lib/libc/stdlib/getopt_long.c

+ 22
- 15
src/lib/libc/stdlib/getopt_long.c View File

@ -1,4 +1,4 @@
/* $OpenBSD: getopt_long.c,v 1.25 2011/03/05 22:10:11 guenther Exp $ */
/* $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
@ -77,7 +77,7 @@ char *optarg; /* argument associated with option */
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
const struct option *, int *, int, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
@ -157,14 +157,16 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
const struct option *long_options, int *idx, int short_too, int flags)
{
char *current_argv, *has_equal;
size_t current_argv_len;
int i, match;
int i, match, exact_match, second_partial_match;
current_argv = place;
match = -1;
exact_match = 0;
second_partial_match = 0;
optind++;
@ -184,6 +186,7 @@ parse_long_options(char * const *nargv, const char *options,
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
exact_match = 1;
break;
}
/*
@ -193,16 +196,20 @@ parse_long_options(char * const *nargv, const char *options,
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
if (match == -1) /* first partial match */
match = i;
else {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
else if ((flags & FLAG_LONGONLY) ||
long_options[i].has_arg != long_options[match].has_arg ||
long_options[i].flag != long_options[match].flag ||
long_options[i].val != long_options[match].val)
second_partial_match = 1;
}
if (!exact_match && second_partial_match) {
/* 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
@ -398,7 +405,7 @@ start:
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
idx, short_too, flags);
if (optchar != -1) {
place = EMSG;
return (optchar);
@ -435,7 +442,7 @@ start:
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
idx, 0, flags);
place = EMSG;
return (optchar);
}


Loading…
Cancel
Save