|
|
@ -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); |
|
|
|
} |
|
|
|