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>
|
2011-05-24 Chris Sutcliffe <ir0nh34d@users.sourceforge.net>
|
||||||
|
|
||||||
* include/stdlib.h (strtod): Declare as extern to resolve compilation issues.
|
* 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;
|
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
|
static
|
||||||
#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring
|
#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring
|
||||||
int getopt_parse( int mode, getopt_std_args, ... )
|
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 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;
|
optopt = 0;
|
||||||
nextchar = NULL;
|
nextchar = NULL;
|
||||||
optind = argind + 1;
|
optind = argind + 1;
|
||||||
@ -634,11 +692,19 @@ int getopt_parse( int mode, getopt_std_args, ... )
|
|||||||
return getopt_resolved( mode, argc, argv, &argind,
|
return getopt_resolved( mode, argc, argv, &argind,
|
||||||
longopts, matched, optindex, optstring );
|
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,
|
/* When it cannot be matched, reset the parsing context to
|
||||||
* but it is unmatched; (perversely, `mode == getopt_mode_long_only'
|
* resume from the next argument, diagnose the failed match,
|
||||||
* allows us to still try to match it as a short form option).
|
* and bail out.
|
||||||
*/
|
*/
|
||||||
optopt = 0;
|
optopt = 0;
|
||||||
nextchar = NULL;
|
nextchar = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user