Skip to content

Commit a194e2a

Browse files
committed
die_for_incompatible_opts(): unbounded number of options
We have die_for_incompatible_optN() (for 2 <= N <= 4) to check and complain when two or more among N mutually incompatible options are used. What should a developer do if there are more than four options that cannot be used at once? Introduce die_for_incompatible_opts(), which can handle an arbitrary number of mutually exclusive options, and rewrite existing variants using it. The new function takes N pairs of <bool optN, const char *nameN>, followed by EOF. Note that even if the caller passes bool, it is promoted to platform-natural int when calling this variadic function. Thus, the implementation uses va_arg(ap, int) to extract the value, which allows it to distinguish between bool and EOF serving as the sentinel. Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent f78ce2f commit a194e2a

2 files changed

Lines changed: 43 additions & 24 deletions

File tree

parse-options.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,26 +1535,31 @@ void NORETURN usage_msg_optf(const char * const fmt,
15351535
usage_msg_opt(msg.buf, usagestr, options);
15361536
}
15371537

1538-
void die_for_incompatible_opt4(int opt1, const char *opt1_name,
1539-
int opt2, const char *opt2_name,
1540-
int opt3, const char *opt3_name,
1541-
int opt4, const char *opt4_name)
1538+
void die_for_incompatible_opts(bool opt1, const char *opt1_name, ...)
15421539
{
1543-
int count = 0;
1540+
unsigned count = 0;
15441541
const char *options[4];
1542+
va_list ap;
15451543

15461544
if (opt1)
15471545
options[count++] = opt1_name;
1548-
if (opt2)
1549-
options[count++] = opt2_name;
1550-
if (opt3)
1551-
options[count++] = opt3_name;
1552-
if (opt4)
1553-
options[count++] = opt4_name;
1546+
va_start(ap, opt1_name);
1547+
while (count < ARRAY_SIZE(options)) {
1548+
int opt_set = va_arg(ap, int);
1549+
const char *opt_name;
1550+
1551+
if (opt_set == EOF)
1552+
break;
1553+
opt_name = va_arg(ap, const char *);
1554+
if (opt_set)
1555+
options[count++] = opt_name;
1556+
}
1557+
va_end(ap);
1558+
15541559
switch (count) {
15551560
case 4:
15561561
die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
1557-
opt1_name, opt2_name, opt3_name, opt4_name);
1562+
options[0], options[1], options[2], options[3]);
15581563
break;
15591564
case 3:
15601565
die(_("options '%s', '%s', and '%s' cannot be used together"),

parse-options.h

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -441,29 +441,43 @@ void NORETURN usage_msg_optf(const char *fmt,
441441
const char * const *usagestr,
442442
const struct option *options, ...);
443443

444-
void die_for_incompatible_opt4(int opt1, const char *opt1_name,
445-
int opt2, const char *opt2_name,
446-
int opt3, const char *opt3_name,
447-
int opt4, const char *opt4_name);
444+
/*
445+
* Take N pairs of <bool optN, const char *opt_nameN> as parameters,
446+
* followed by EOF. The caller declares "The options opt_name1 through
447+
* opt_nameN exist and the command line has options whose optN is set."
448+
* and asks that an error be raised if two or more of these options are
449+
* set at the same time.
450+
*/
451+
void die_for_incompatible_opts(bool opt1, const char *opt1_name, ...);
448452

453+
static inline void die_for_incompatible_opt4(int opt1, const char *opt1_name,
454+
int opt2, const char *opt2_name,
455+
int opt3, const char *opt3_name,
456+
int opt4, const char *opt4_name)
457+
{
458+
die_for_incompatible_opts(!!opt1, opt1_name,
459+
!!opt2, opt2_name,
460+
!!opt3, opt3_name,
461+
!!opt4, opt4_name,
462+
EOF);
463+
}
449464

450465
static inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
451466
int opt2, const char *opt2_name,
452467
int opt3, const char *opt3_name)
453468
{
454-
die_for_incompatible_opt4(opt1, opt1_name,
455-
opt2, opt2_name,
456-
opt3, opt3_name,
457-
0, "");
469+
die_for_incompatible_opts(!!opt1, opt1_name,
470+
!!opt2, opt2_name,
471+
!!opt3, opt3_name,
472+
EOF);
458473
}
459474

460475
static inline void die_for_incompatible_opt2(int opt1, const char *opt1_name,
461476
int opt2, const char *opt2_name)
462477
{
463-
die_for_incompatible_opt4(opt1, opt1_name,
464-
opt2, opt2_name,
465-
0, "",
466-
0, "");
478+
die_for_incompatible_opts(!!opt1, opt1_name,
479+
!!opt2, opt2_name,
480+
EOF);
467481
}
468482

469483
/*

0 commit comments

Comments
 (0)