parse-options: add precision handling for OPTION_BIT

Similar to 09705696f7 (parse-options: introduce precision handling for `OPTION_INTEGER`, 2025-04-17) support value variables of different sizes for OPTION_BIT. Do that by requiring their "precision" to be set, casting their "value" pointer accordingly and checking whether the value fits. Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Jul 9, 2025 at 11:45 UTC 5228211c4b92052c0a38f2ab67cd0b87a7baec30
3 files changed +17 -4
builtin/write-tree.c
+1
@@ -35,6 +35,7 @@ int cmd_write_tree(int argc,
35 .type = OPTION_BIT,
36 .long_name = "ignore-cache-tree",
37 .value = &flags,
38 + .precision = sizeof(flags),
39 .help = N_("only useful for debugging"),
40 .flags = PARSE_OPT_HIDDEN | PARSE_OPT_NOARG,
41 .defval = WRITE_TREE_IGNORE_CACHE_TREE,
parse-options.c
+15 -4
@@ -88,6 +88,14 @@ static int do_get_int_value(const void *value, size_t precision, intmax_t *ret)
88 }
89 }
90
91 +static intmax_t get_int_value(const struct option *opt, enum opt_parsed flags)
92 +{
93 + intmax_t ret;
94 + if (do_get_int_value(opt->value, opt->precision, &ret))
95 + BUG("invalid precision for option %s", optname(opt, flags));
96 + return ret;
97 +}
98 +
99 static enum parse_opt_result set_int_value(const struct option *opt,
100 enum opt_parsed flags,
101 intmax_t value)
@@ -139,11 +147,14 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
147 return opt->ll_callback(p, opt, NULL, unset);
148
149 case OPTION_BIT:
150 + {
151 + intmax_t value = get_int_value(opt, flags);
152 if (unset)
143 - *(int *)opt->value &= ~opt->defval;
153 + value &= ~opt->defval;
154 else
145 - *(int *)opt->value |= opt->defval;
146 - return 0;
155 + value |= opt->defval;
156 + return set_int_value(opt, flags, value);
157 + }
158
159 case OPTION_NEGBIT:
160 if (unset)
@@ -631,11 +642,11 @@ static void parse_options_check(const struct option *opts)
642 optbug(opts, "OPTION_SET_INT 0 should not be negatable");
643 switch (opts->type) {
644 case OPTION_SET_INT:
645 + case OPTION_BIT:
646 if (!signed_int_fits(opts->defval, opts->precision))
647 optbug(opts, "has invalid defval");
648 /* fallthru */
649 case OPTION_COUNTUP:
638 - case OPTION_BIT:
650 case OPTION_NEGBIT:
651 case OPTION_NUMBER:
652 case OPTION_BITOP:
parse-options.h
+1
@@ -172,6 +172,7 @@ struct option {
172 .short_name = (s), \
173 .long_name = (l), \
174 .value = (v), \
175 + .precision = sizeof(*v), \
176 .help = (h), \
177 .flags = PARSE_OPT_NOARG|(f), \
178 .callback = NULL, \