Skip to content

Commit b3df3a5

Browse files
pks-tgitster
authored andcommitted
parse-options: introduce precision handling for OPTION_MAGNITUDE
This commit is the equivalent to the preceding commit, but instead of introducing precision handling for `OPTION_INTEGER` we introduce it for `OPTION_MAGNITUDE`. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 38bba07 commit b3df3a5

File tree

4 files changed

+55
-12
lines changed

4 files changed

+55
-12
lines changed

parse-options.c

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
202202

203203
if (value < lower_bound || value > upper_bound)
204204
return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
205-
arg, optname(opt, flags), lower_bound, upper_bound);
205+
arg, optname(opt, flags), (intmax_t)lower_bound, (intmax_t)upper_bound);
206206

207207
switch (opt->precision) {
208208
case 1:
@@ -223,21 +223,44 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
223223
}
224224
}
225225
case OPTION_MAGNITUDE:
226+
{
227+
uintmax_t upper_bound = UINTMAX_MAX >> (bitsizeof(uintmax_t) - CHAR_BIT * opt->precision);
228+
unsigned long value;
229+
226230
if (unset) {
227-
*(unsigned long *)opt->value = 0;
228-
return 0;
229-
}
230-
if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
231-
*(unsigned long *)opt->value = opt->defval;
232-
return 0;
233-
}
234-
if (get_arg(p, opt, flags, &arg))
231+
value = 0;
232+
} else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
233+
value = opt->defval;
234+
} else if (get_arg(p, opt, flags, &arg)) {
235235
return -1;
236-
if (!git_parse_ulong(arg, opt->value))
236+
} else if (!git_parse_ulong(arg, &value)) {
237237
return error(_("%s expects a non-negative integer value"
238238
" with an optional k/m/g suffix"),
239239
optname(opt, flags));
240-
return 0;
240+
}
241+
242+
if (value > upper_bound)
243+
return error(_("value %s for %s not in range [%"PRIuMAX",%"PRIuMAX"]"),
244+
arg, optname(opt, flags), (uintmax_t)0, (uintmax_t)upper_bound);
245+
246+
switch (opt->precision) {
247+
case 1:
248+
*(uint8_t *)opt->value = value;
249+
return 0;
250+
case 2:
251+
*(uint16_t *)opt->value = value;
252+
return 0;
253+
case 4:
254+
*(uint32_t *)opt->value = value;
255+
return 0;
256+
case 8:
257+
*(uint64_t *)opt->value = value;
258+
return 0;
259+
default:
260+
BUG("invalid precision for option %s",
261+
optname(opt, flags));
262+
}
263+
}
241264

242265
default:
243266
BUG("opt->type %d should not happen", opt->type);

parse-options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ struct option {
281281
.short_name = (s), \
282282
.long_name = (l), \
283283
.value = (v), \
284+
.precision = sizeof(*v), \
284285
.argh = N_("n"), \
285286
.help = (h), \
286287
.flags = PARSE_OPT_NONEG, \

t/helper/test-parse-options.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ int cmd__parse_options(int argc, const char **argv)
120120
};
121121
struct string_list expect = STRING_LIST_INIT_NODUP;
122122
struct string_list list = STRING_LIST_INIT_NODUP;
123+
uint16_t m16 = 0;
123124
int16_t i16 = 0;
124125

125126
struct option options[] = {
@@ -143,6 +144,7 @@ int cmd__parse_options(int argc, const char **argv)
143144
OPT_INTEGER(0, "i16", &i16, "get a 16 bit integer"),
144145
OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
145146
OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
147+
OPT_MAGNITUDE(0, "m16", &m16, "get a 16 bit magnitude"),
146148
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
147149
OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
148150
OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
@@ -214,6 +216,7 @@ int cmd__parse_options(int argc, const char **argv)
214216
show(&expect, &ret, "integer: %d", integer);
215217
show(&expect, &ret, "i16: %"PRIdMAX, (intmax_t) i16);
216218
show(&expect, &ret, "magnitude: %lu", magnitude);
219+
show(&expect, &ret, "m16: %"PRIuMAX, (uintmax_t) m16);
217220
show(&expect, &ret, "timestamp: %"PRItime, timestamp);
218221
show(&expect, &ret, "string: %s", string ? string : "(not set)");
219222
show(&expect, &ret, "abbrev: %d", abbrev);

t/t0040-parse-options.sh

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ usage: test-tool parse-options <options>
2525
--[no-]i16 <n> get a 16 bit integer
2626
-j <n> get a integer, too
2727
-m, --magnitude <n> get a magnitude
28+
--m16 <n> get a 16 bit magnitude
2829
--[no-]set23 set integer to 23
2930
--mode1 set integer to 1 (cmdmode option)
3031
--mode2 set integer to 2 (cmdmode option)
@@ -139,6 +140,7 @@ boolean: 2
139140
integer: 1729
140141
i16: 0
141142
magnitude: 16384
143+
m16: 0
142144
timestamp: 0
143145
string: 123
144146
abbrev: 7
@@ -160,6 +162,7 @@ boolean: 2
160162
integer: 1729
161163
i16: 9000
162164
magnitude: 16384
165+
m16: 32768
163166
timestamp: 0
164167
string: 321
165168
abbrev: 10
@@ -171,7 +174,7 @@ EOF
171174

172175
test_expect_success 'long options' '
173176
test-tool parse-options --boolean --integer 1729 --i16 9000 --magnitude 16k \
174-
--boolean --string2=321 --verbose --verbose --no-dry-run \
177+
--m16 32k --boolean --string2=321 --verbose --verbose --no-dry-run \
175178
--abbrev=10 --file fi.le --obsolete \
176179
>output 2>output.err &&
177180
test_must_be_empty output.err &&
@@ -184,6 +187,7 @@ test_expect_success 'abbreviate to something longer than SHA1 length' '
184187
integer: 0
185188
i16: 0
186189
magnitude: 0
190+
m16: 0
187191
timestamp: 0
188192
string: (not set)
189193
abbrev: 100
@@ -259,6 +263,7 @@ boolean: 1
259263
integer: 13
260264
i16: 0
261265
magnitude: 0
266+
m16: 0
262267
timestamp: 0
263268
string: 123
264269
abbrev: 7
@@ -283,6 +288,7 @@ boolean: 0
283288
integer: 2
284289
i16: 0
285290
magnitude: 0
291+
m16: 0
286292
timestamp: 0
287293
string: (not set)
288294
abbrev: 7
@@ -351,6 +357,7 @@ boolean: 5
351357
integer: 4
352358
i16: 0
353359
magnitude: 0
360+
m16: 0
354361
timestamp: 0
355362
string: (not set)
356363
abbrev: 7
@@ -377,6 +384,7 @@ boolean: 1
377384
integer: 23
378385
i16: 0
379386
magnitude: 0
387+
m16: 0
380388
timestamp: 0
381389
string: (not set)
382390
abbrev: 7
@@ -457,6 +465,7 @@ boolean: 0
457465
integer: 0
458466
i16: 0
459467
magnitude: 0
468+
m16: 0
460469
timestamp: 0
461470
string: (not set)
462471
abbrev: 7
@@ -810,4 +819,11 @@ test_expect_success 'i16 limits range' '
810819
test_grep "value -32769 for option .i16. not in range \[-32768,32767\]" err
811820
'
812821

822+
test_expect_success 'm16 limits range' '
823+
test-tool parse-options --m16 65535 >out &&
824+
test_grep "m16: 65535" out &&
825+
test_must_fail test-tool parse-options --m16 65536 2>err &&
826+
test_grep "value 65536 for option .m16. not in range \[0,65535\]" err
827+
'
828+
813829
test_done

0 commit comments

Comments
 (0)