diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt index e66ca9f70c705841c864196a3a651e04d8156e01..794194bad6614af220f310612e937a716d06e532 100644 --- a/Documentation/technical/api-parse-options.txt +++ b/Documentation/technical/api-parse-options.txt @@ -137,6 +137,10 @@ There are some macros to easily define options: Introduce a boolean option. If used, `int_var` is bitwise-ored with `mask`. +`OPT_NEGBIT(short, long, &int_var, description, mask)`:: + Introduce a boolean option. + If used, `int_var` is bitwise-anded with the inverted `mask`. + `OPT_SET_INT(short, long, &int_var, description, integer)`:: Introduce a boolean option. If used, set `int_var` to `integer`. diff --git a/parse-options.c b/parse-options.c index cf71bcffd2e1e9aeacb44df488b0825f09d54255..a8c05e3dc21f83b906003cbe6a1151e98bad4c55 100644 --- a/parse-options.c +++ b/parse-options.c @@ -50,6 +50,7 @@ static int get_value(struct parse_opt_ctx_t *p, /* FALLTHROUGH */ case OPTION_BOOLEAN: case OPTION_BIT: + case OPTION_NEGBIT: case OPTION_SET_INT: case OPTION_SET_PTR: return opterror(opt, "takes no value", flags); @@ -66,6 +67,13 @@ static int get_value(struct parse_opt_ctx_t *p, *(int *)opt->value |= opt->defval; return 0; + case OPTION_NEGBIT: + if (unset) + *(int *)opt->value |= opt->defval; + else + *(int *)opt->value &= ~opt->defval; + return 0; + case OPTION_BOOLEAN: *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; return 0; diff --git a/parse-options.h b/parse-options.h index b54eec128bcda1a8b4c4a2c33f2ce799c506ac23..f1e2452f69756d9d3c4fc444d37dbdd224194809 100644 --- a/parse-options.h +++ b/parse-options.h @@ -8,6 +8,7 @@ enum parse_opt_type { OPTION_GROUP, /* options with no arguments */ OPTION_BIT, + OPTION_NEGBIT, OPTION_BOOLEAN, /* _INCR would have been a better name */ OPTION_SET_INT, OPTION_SET_PTR, @@ -93,6 +94,7 @@ struct option { #define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) } #define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } #define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) } +#define OPT_NEGBIT(s, l, v, h, b) { OPTION_NEGBIT, (s), (l), (v), NULL, (h), 0, NULL, (b) } #define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) } #define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) } #define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) } diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index e38241c80a6625c9b5b89340b9d0c5a2667bf345..9054ed6030b35ca3745f666539735139e1dc8720 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -12,6 +12,7 @@ usage: test-parse-options -b, --boolean get a boolean -4, --or4 bitwise-or boolean with ...0100 + --neg-or4 same as --no-or4 -i, --integer get a integer -j get a integer, too @@ -245,7 +246,33 @@ test_expect_success 'OPT_BIT() and OPT_SET_INT() work' ' test_cmp expect output ' -# --or4 -# --no-or4 +test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' ' + test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +cat > expect < output 2> output.err && + test ! -s output.err && + test_cmp expect output +' + +test_expect_success 'OPT_NEGBIT() works' ' + test-parse-options -bb --no-neg-or4 > output 2> output.err && + test ! -s output.err && + test_cmp expect output +' test_done diff --git a/test-parse-options.c b/test-parse-options.c index 61d2c39814529bd0264e4c9e40241131d51d819c..eddc0267a27323e40a41849f777df4dc4fed45a8 100644 --- a/test-parse-options.c +++ b/test-parse-options.c @@ -29,6 +29,7 @@ int main(int argc, const char **argv) OPT_BOOLEAN('b', "boolean", &boolean, "get a boolean"), OPT_BIT('4', "or4", &boolean, "bitwise-or boolean with ...0100", 4), + OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4), OPT_GROUP(""), OPT_INTEGER('i', "integer", &integer, "get a integer"), OPT_INTEGER('j', NULL, &integer, "get a integer, too"),