libsubcmd automatically generates for every option --opt an equivalent
negated option, --no-opt, to unset the option. Vice versa, for every
option declared as --no-opt, a shorthand --opt is declared for
convenience.

Add a flag, PARSE_OPT_NOAUTONEG, to disable this behavior. This new flag
behaves similarly to the already existing PARSE_OPT_NONEG, only it does
not reject the --no-opt variant, but leaves it undefined. That is useful
when there is a conflicting distinct --no-opt option in the syntax of
the tool.

PARSE_OPT_NOAUTONEG is enabled per-option, allowing to unset other
options that do not have this conflict.

Signed-off-by: Tomas Glozar <[email protected]>
---
 tools/lib/subcmd/parse-options.c | 10 ++++++----
 tools/lib/subcmd/parse-options.h |  3 +++
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c
index 664b2053bb77..e83200e9f56a 100644
--- a/tools/lib/subcmd/parse-options.c
+++ b/tools/lib/subcmd/parse-options.c
@@ -427,7 +427,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const 
char *arg,
                        return 0;
                }
                if (!rest) {
-                       if (strstarts(options->long_name, "no-")) {
+                       if (strstarts(options->long_name, "no-") &&
+                           !(options->flags & PARSE_OPT_NOAUTONEG)) {
                                /*
                                 * The long name itself starts with "no-", so
                                 * accept the option without "no-" so that users
@@ -465,12 +466,12 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, 
const char *arg,
                                continue;
                        }
                        /* negated and abbreviated very much? */
-                       if (strstarts("no-", arg)) {
+                       if (strstarts("no-", arg) && !(options->flags & 
PARSE_OPT_NOAUTONEG)) {
                                flags |= OPT_UNSET;
                                goto is_abbreviated;
                        }
                        /* negated? */
-                       if (strncmp(arg, "no-", 3))
+                       if (strncmp(arg, "no-", 3) || (options->flags & 
PARSE_OPT_NOAUTONEG))
                                continue;
                        flags |= OPT_UNSET;
                        rest = skip_prefix(arg + 3, options->long_name);
@@ -1019,7 +1020,8 @@ int parse_options_usage(const char * const *usagestr,
                if (strstarts(opts->long_name, optstr))
                        print_option_help(opts, 0);
                if (strstarts("no-", optstr) &&
-                   strstarts(opts->long_name, optstr + 3))
+                   strstarts(opts->long_name, optstr + 3) &&
+                       !(opts->flags & PARSE_OPT_NOAUTONEG))
                        print_option_help(opts, 0);
        }
 
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h
index c573a0ca5ca6..38df5fd21963 100644
--- a/tools/lib/subcmd/parse-options.h
+++ b/tools/lib/subcmd/parse-options.h
@@ -47,6 +47,7 @@ enum parse_opt_option_flags {
        PARSE_OPT_NOEMPTY  = 128,
        PARSE_OPT_NOBUILD  = 256,
        PARSE_OPT_CANSKIP  = 512,
+       PARSE_OPT_NOAUTONEG = 1024,
 };
 
 struct option;
@@ -149,6 +150,8 @@ struct option {
        { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value 
= (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
        { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value 
= (v), .argh = (a), .help = (h), .callback = (f) }
+#define OPT_CALLBACK_FLAG(s, l, v, a, h, f, fl) \
+       { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value 
= (v), .argh = (a), .help = (h), .callback = (f), .flags = (fl) }
 #define OPT_CALLBACK_SET(s, l, v, os, a, h, f) \
        { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value 
= (v), .argh = (a), .help = (h), .callback = (f), .set = check_vtype(os, bool 
*)}
 #define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
-- 
2.54.0


Reply via email to