]> git.ipfire.org Git - thirdparty/git.git/commitdiff
parse-options: add precision handling for PARSE_OPT_CMDMODE
authorRené Scharfe <l.s.r@web.de>
Wed, 9 Jul 2025 09:45:14 +0000 (11:45 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 9 Jul 2025 15:39:10 +0000 (08:39 -0700)
Build on 09705696f7 (parse-options: introduce precision handling for
`OPTION_INTEGER`, 2025-04-17) to support value variables of different
sizes for PARSE_OPT_CMDMODE options.  Do that by requiring their
"precision" to be set and casting their "value" pointer accordingly.

Call the function that does the raw casting do_get_int_value() to
reserve the name get_int_value() for a more friendly wrapper we're
going to introduce in one of the next patches.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/am.c
parse-options.c
parse-options.h
t/helper/test-parse-options.c

index e32a3b4c973a42bae72b6aafa9cc5efeaa5a32f1..ce58abf2a2e8ba7bbe6ad334ee14dc9c6dbcfd8c 100644 (file)
@@ -2406,6 +2406,7 @@ int cmd_am(int argc,
                        .type = OPTION_CALLBACK,
                        .long_name = "show-current-patch",
                        .value = &resume_mode,
+                       .precision = sizeof(resume_mode),
                        .argh = "(diff|raw)",
                        .help = N_("show the patch being applied"),
                        .flags = PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
index 68ff4944925c6123b1a3d57a0bec32bc8a084b5c..ddac008a5ea7a77c4f66b0497c426f7f29379a89 100644 (file)
@@ -68,6 +68,26 @@ static char *fix_filename(const char *prefix, const char *file)
                return prefix_filename_except_for_dash(prefix, file);
 }
 
+static int do_get_int_value(const void *value, size_t precision, intmax_t *ret)
+{
+       switch (precision) {
+       case sizeof(int8_t):
+               *ret = *(int8_t *)value;
+               return 0;
+       case sizeof(int16_t):
+               *ret = *(int16_t *)value;
+               return 0;
+       case sizeof(int32_t):
+               *ret = *(int32_t *)value;
+               return 0;
+       case sizeof(int64_t):
+               *ret = *(int64_t *)value;
+               return 0;
+       default:
+               return -1;
+       }
+}
+
 static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
                                          const struct option *opt,
                                          enum opt_parsed flags,
@@ -266,7 +286,9 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
 }
 
 struct parse_opt_cmdmode_list {
-       int value, *value_ptr;
+       intmax_t value;
+       void *value_ptr;
+       size_t precision;
        const struct option *opt;
        const char *arg;
        enum opt_parsed flags;
@@ -280,7 +302,7 @@ static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,
 
        for (; opts->type != OPTION_END; opts++) {
                struct parse_opt_cmdmode_list *elem = ctx->cmdmode_list;
-               int *value_ptr = opts->value;
+               void *value_ptr = opts->value;
 
                if (!(opts->flags & PARSE_OPT_CMDMODE) || !value_ptr)
                        continue;
@@ -292,10 +314,13 @@ static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,
 
                CALLOC_ARRAY(elem, 1);
                elem->value_ptr = value_ptr;
-               elem->value = *value_ptr;
+               elem->precision = opts->precision;
+               if (do_get_int_value(value_ptr, opts->precision, &elem->value))
+                       optbug(opts, "has invalid precision");
                elem->next = ctx->cmdmode_list;
                ctx->cmdmode_list = elem;
        }
+       BUG_if_bug("invalid 'struct option'");
 }
 
 static char *optnamearg(const struct option *opt, const char *arg,
@@ -317,7 +342,13 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
        char *opt_name, *other_opt_name;
 
        for (; elem; elem = elem->next) {
-               if (*elem->value_ptr == elem->value)
+               intmax_t new_value;
+
+               if (do_get_int_value(elem->value_ptr, elem->precision,
+                                    &new_value))
+                       BUG("impossible: invalid precision");
+
+               if (new_value == elem->value)
                        continue;
 
                if (elem->opt &&
@@ -327,7 +358,7 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
                elem->opt = opt;
                elem->arg = arg;
                elem->flags = flags;
-               elem->value = *elem->value_ptr;
+               elem->value = new_value;
        }
 
        if (result || !elem)
index 91c3e3c29b3dda1f679ae4c77e250180ed6f9639..c75a473c9ecdfc0848e8d4dcc89607c117e90fbe 100644 (file)
@@ -269,6 +269,7 @@ struct option {
        .short_name = (s), \
        .long_name = (l), \
        .value = (v), \
+       .precision = sizeof(*v), \
        .help = (h), \
        .flags = PARSE_OPT_CMDMODE|PARSE_OPT_NOARG|PARSE_OPT_NONEG | (f), \
        .defval = (i), \
index f2663dd0c07279b26a1f10a966170239c0f34583..1e03ff88f6ff89f23455f4ebb8f547598e148323 100644 (file)
@@ -148,9 +148,16 @@ int cmd__parse_options(int argc, const char **argv)
                OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
                OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
                OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
-               OPT_CALLBACK_F(0, "mode34", &integer, "(3|4)",
-                       "set integer to 3 or 4 (cmdmode option)",
-                       PARSE_OPT_CMDMODE, mode34_callback),
+               {
+                       .type = OPTION_CALLBACK,
+                       .long_name = "mode34",
+                       .value = &integer,
+                       .precision = sizeof(integer),
+                       .argh = "(3|4)",
+                       .help = "set integer to 3 or 4 (cmdmode option)",
+                       .flags = PARSE_OPT_CMDMODE,
+                       .callback = mode34_callback,
+               },
                OPT_CALLBACK('L', "length", &integer, "str",
                        "get length of <str>", length_callback),
                OPT_FILENAME('F', "file", &file, "set file to <file>"),