Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Marshall <keithmarshall@@users.sf.net>2011-06-01 00:24:51 +0400
committerKeith Marshall <keithmarshall@@users.sf.net>2011-06-01 00:24:51 +0400
commit2ec2d00e1bf5d50f4d29f4d4d9681bd5641aa221 (patch)
tree00a75b1b67be1e00860b606522bc6be836ac3595 /winsup/mingw/mingwex
parente60d84e840f2666fe99b6c6abac3bcfc10bc38e6 (diff)
Correct checking for short option matches in getopt_long_only().
Diffstat (limited to 'winsup/mingw/mingwex')
-rw-r--r--winsup/mingw/mingwex/getopt.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/winsup/mingw/mingwex/getopt.c b/winsup/mingw/mingwex/getopt.c
index 4f081d18d..b26e97c43 100644
--- a/winsup/mingw/mingwex/getopt.c
+++ b/winsup/mingw/mingwex/getopt.c
@@ -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;