The GNU version allows short matches, if they are unique. Our version
does not, since it's weird, but let's at least make them have the
same behavior. Otherwise users will have different behavior for
command line parsing for edge cases, on different platforms.
Signed-off-by: Jens Axboe <axboe@fb.com>
} pvt;
static inline const char *option_matches(const char *arg_str,
} pvt;
static inline const char *option_matches(const char *arg_str,
+ const char *opt_name, int smatch)
{
while (*arg_str != '\0' && *arg_str != '=') {
if (*arg_str++ != *opt_name++)
return NULL;
}
{
while (*arg_str != '\0' && *arg_str != '=') {
if (*arg_str++ != *opt_name++)
return NULL;
}
+ if (*opt_name && !smatch)
return NULL;
return arg_str;
return NULL;
return arg_str;
}
for (lo = longopts; lo->name; lo++) {
}
for (lo = longopts; lo->name; lo++) {
- if ((opt_end = option_matches(carg+2, lo->name)))
+ opt_end = option_matches(carg+2, lo->name, 0);
+ if (opt_end)
- if (!opt_end)
- return '?';
+ /*
+ * The GNU getopt_long_only() apparently allows a short match,
+ * if it's unique and if we don't have a full match. Let's
+ * do the same here, search and see if there is one (and only
+ * one) short match.
+ */
+ if (!opt_end) {
+ const struct option *lo_match = NULL;
+
+ for (lo = longopts; lo->name; lo++) {
+ const char *ret;
+
+ ret = option_matches(carg+2, lo->name, 1);
+ if (!ret)
+ continue;
+ if (!opt_end) {
+ opt_end = ret;
+ lo_match = lo;
+ } else {
+ opt_end = NULL;
+ break;
+ }
+ }
+ if (!opt_end)
+ return '?';
+ lo = lo_match;
+ }
if (longindex)
*longindex = lo-longopts;
if (longindex)
*longindex = lo-longopts;