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
