Skip to content

Commit 0d3e045

Browse files
rscharfegitster
authored andcommitted
parse-options: add precision handling for PARSE_OPT_CMDMODE
Build on 0970569 (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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 369e6d9 commit 0d3e045

File tree

4 files changed

+48
-8
lines changed

4 files changed

+48
-8
lines changed

builtin/am.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,6 +2406,7 @@ int cmd_am(int argc,
24062406
.type = OPTION_CALLBACK,
24072407
.long_name = "show-current-patch",
24082408
.value = &resume_mode,
2409+
.precision = sizeof(resume_mode),
24092410
.argh = "(diff|raw)",
24102411
.help = N_("show the patch being applied"),
24112412
.flags = PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,

parse-options.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,26 @@ static char *fix_filename(const char *prefix, const char *file)
6868
return prefix_filename_except_for_dash(prefix, file);
6969
}
7070

71+
static int do_get_int_value(const void *value, size_t precision, intmax_t *ret)
72+
{
73+
switch (precision) {
74+
case sizeof(int8_t):
75+
*ret = *(int8_t *)value;
76+
return 0;
77+
case sizeof(int16_t):
78+
*ret = *(int16_t *)value;
79+
return 0;
80+
case sizeof(int32_t):
81+
*ret = *(int32_t *)value;
82+
return 0;
83+
case sizeof(int64_t):
84+
*ret = *(int64_t *)value;
85+
return 0;
86+
default:
87+
return -1;
88+
}
89+
}
90+
7191
static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
7292
const struct option *opt,
7393
enum opt_parsed flags,
@@ -266,7 +286,9 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
266286
}
267287

268288
struct parse_opt_cmdmode_list {
269-
int value, *value_ptr;
289+
intmax_t value;
290+
void *value_ptr;
291+
size_t precision;
270292
const struct option *opt;
271293
const char *arg;
272294
enum opt_parsed flags;
@@ -280,7 +302,7 @@ static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,
280302

281303
for (; opts->type != OPTION_END; opts++) {
282304
struct parse_opt_cmdmode_list *elem = ctx->cmdmode_list;
283-
int *value_ptr = opts->value;
305+
void *value_ptr = opts->value;
284306

285307
if (!(opts->flags & PARSE_OPT_CMDMODE) || !value_ptr)
286308
continue;
@@ -292,10 +314,13 @@ static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,
292314

293315
CALLOC_ARRAY(elem, 1);
294316
elem->value_ptr = value_ptr;
295-
elem->value = *value_ptr;
317+
elem->precision = opts->precision;
318+
if (do_get_int_value(value_ptr, opts->precision, &elem->value))
319+
optbug(opts, "has invalid precision");
296320
elem->next = ctx->cmdmode_list;
297321
ctx->cmdmode_list = elem;
298322
}
323+
BUG_if_bug("invalid 'struct option'");
299324
}
300325

301326
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,
317342
char *opt_name, *other_opt_name;
318343

319344
for (; elem; elem = elem->next) {
320-
if (*elem->value_ptr == elem->value)
345+
intmax_t new_value;
346+
347+
if (do_get_int_value(elem->value_ptr, elem->precision,
348+
&new_value))
349+
BUG("impossible: invalid precision");
350+
351+
if (new_value == elem->value)
321352
continue;
322353

323354
if (elem->opt &&
@@ -327,7 +358,7 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
327358
elem->opt = opt;
328359
elem->arg = arg;
329360
elem->flags = flags;
330-
elem->value = *elem->value_ptr;
361+
elem->value = new_value;
331362
}
332363

333364
if (result || !elem)

parse-options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ struct option {
269269
.short_name = (s), \
270270
.long_name = (l), \
271271
.value = (v), \
272+
.precision = sizeof(*v), \
272273
.help = (h), \
273274
.flags = PARSE_OPT_CMDMODE|PARSE_OPT_NOARG|PARSE_OPT_NONEG | (f), \
274275
.defval = (i), \

t/helper/test-parse-options.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,16 @@ int cmd__parse_options(int argc, const char **argv)
148148
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
149149
OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
150150
OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
151-
OPT_CALLBACK_F(0, "mode34", &integer, "(3|4)",
152-
"set integer to 3 or 4 (cmdmode option)",
153-
PARSE_OPT_CMDMODE, mode34_callback),
151+
{
152+
.type = OPTION_CALLBACK,
153+
.long_name = "mode34",
154+
.value = &integer,
155+
.precision = sizeof(integer),
156+
.argh = "(3|4)",
157+
.help = "set integer to 3 or 4 (cmdmode option)",
158+
.flags = PARSE_OPT_CMDMODE,
159+
.callback = mode34_callback,
160+
},
154161
OPT_CALLBACK('L', "length", &integer, "str",
155162
"get length of <str>", length_callback),
156163
OPT_FILENAME('F', "file", &file, "set file to <file>"),

0 commit comments

Comments
 (0)