Correct checking for short option matches in getopt_long_only().
This commit is contained in:
parent
e60d84e840
commit
2ec2d00e1b
@ -1,3 +1,12 @@
|
||||
2011-05-31 Keith Marshall <keithmarshall@users.sourceforge.net>
|
||||
|
||||
Correct checking for short option matches in getopt_long_only().
|
||||
|
||||
* mingwex/getopt.c (getopt_verify): New static inline function.
|
||||
(getopt_parse) [getopt_mode_long_only]: Use it, to validate as a
|
||||
possible short option match after failing to match, or ambiguously
|
||||
matching as a long option.
|
||||
|
||||
2011-05-24 Chris Sutcliffe <ir0nh34d@users.sourceforge.net>
|
||||
|
||||
* include/stdlib.h (strtod): Declare as extern to resolve compilation issues.
|
||||
|
@ -310,6 +310,48 @@ struct option *opt, int index, int *retindex, const CHAR *optstring )
|
||||
return opt[index].val;
|
||||
}
|
||||
|
||||
static __inline__
|
||||
int getopt_verify( const CHAR *nextchar, const CHAR *optstring )
|
||||
{
|
||||
/* Helper function, called by getopt_parse() when invoked
|
||||
* by getopt_long_only(), to verify when an unmatched or an
|
||||
* ambiguously matched long form option string is valid as
|
||||
* a short form option specification.
|
||||
*/
|
||||
if( ! (nextchar && *nextchar && optstring && *optstring) )
|
||||
/*
|
||||
* There are no characters to be matched, or there are no
|
||||
* valid short form option characters to which they can be
|
||||
* matched, so this can never be valid.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
while( *nextchar )
|
||||
{
|
||||
/* For each command line character in turn ...
|
||||
*/
|
||||
const CHAR *test;
|
||||
if( (test = getopt_match( *nextchar++, optstring )) == NULL )
|
||||
/*
|
||||
* ... there is no short form option to match the current
|
||||
* candidate, so the entire argument fails.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
if( test[1] == getopt_takes_argument )
|
||||
/*
|
||||
* The current candidate is valid, and it matches an option
|
||||
* which takes an argument, so this command line argument is
|
||||
* a valid short form option specification; accept it.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
/* If we get to here, then every character in the command line
|
||||
* argument was valid as a short form option; accept it.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring
|
||||
int getopt_parse( int mode, getopt_std_args, ... )
|
||||
@ -614,6 +656,22 @@ int getopt_parse( int mode, getopt_std_args, ... )
|
||||
{
|
||||
/* if this is not the first, then we have an ambiguity ...
|
||||
*/
|
||||
if( (mode == getopt_mode_long_only)
|
||||
/*
|
||||
* However, in the case of getopt_long_only(), if
|
||||
* the entire ambiguously matched string represents
|
||||
* a valid short option specification, then we may
|
||||
* proceed to interpret it as such.
|
||||
*/
|
||||
&& getopt_verify( nextchar, optstring ) )
|
||||
return getopt_parse( mode, argc, argv, optstring );
|
||||
|
||||
/* If we get to here, then the ambiguously matched
|
||||
* partial long option isn't valid for short option
|
||||
* evaluation; reset parser context to resume with
|
||||
* the following command line argument, diagnose
|
||||
* ambiguity, and bail out.
|
||||
*/
|
||||
optopt = 0;
|
||||
nextchar = NULL;
|
||||
optind = argind + 1;
|
||||
@ -634,11 +692,19 @@ int getopt_parse( int mode, getopt_std_args, ... )
|
||||
return getopt_resolved( mode, argc, argv, &argind,
|
||||
longopts, matched, optindex, optstring );
|
||||
}
|
||||
if( mode < getopt_mode_long_only )
|
||||
/* if here, then we had what SHOULD have been a long form option,
|
||||
* but it is unmatched ...
|
||||
*/
|
||||
if( (mode < getopt_mode_long_only)
|
||||
/*
|
||||
* ... although paradoxically, `mode == getopt_mode_long_only'
|
||||
* allows us to still try to match it as a short form option.
|
||||
*/
|
||||
|| (getopt_verify( nextchar, optstring ) == 0) )
|
||||
{
|
||||
/* if here, then we had what SHOULD have been a long form option,
|
||||
* but it is unmatched; (perversely, `mode == getopt_mode_long_only'
|
||||
* allows us to still try to match it as a short form option).
|
||||
/* When it cannot be matched, reset the parsing context to
|
||||
* resume from the next argument, diagnose the failed match,
|
||||
* and bail out.
|
||||
*/
|
||||
optopt = 0;
|
||||
nextchar = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user