From 603e604eb6d9b3ba9f201a6bff0a18da1a6c0967 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 22 Apr 2016 18:14:24 -0400 Subject: [PATCH] oslib/getopt_long: allow (unique) short match 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 --- oslib/getopt_long.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/oslib/getopt_long.c b/oslib/getopt_long.c index 11d879ad..8ec77413 100644 --- a/oslib/getopt_long.c +++ b/oslib/getopt_long.c @@ -26,14 +26,14 @@ static struct getopt_private_state { } pvt; static inline const char *option_matches(const char *arg_str, - const char *opt_name) + const char *opt_name, int smatch) { while (*arg_str != '\0' && *arg_str != '=') { if (*arg_str++ != *opt_name++) return NULL; } - if (*opt_name) + if (*opt_name && !smatch) return NULL; return arg_str; @@ -84,11 +84,37 @@ int getopt_long_only(int argc, char *const *argv, const char *optstring, } 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) break; } - 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; -- 2.25.1