All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Subject: [PATCH v2] die_for_incompatible_opts(): unbounded number of options
Date: Thu, 27 Aug 2026 10:28:32 -0700	[thread overview]
Message-ID: <xmqqbjana2wv.fsf@gitster.g> (raw)
In-Reply-To: <20260826233152.1703497-1-gitster@pobox.com> (Junio C. Hamano's message of "Wed, 26 Aug 2026 16:31:50 -0700")

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>
---
 parse-options.c | 29 +++++++++++++++++------------
 parse-options.h | 38 ++++++++++++++++++++++++++------------
 2 files changed, 43 insertions(+), 24 deletions(-)

diff --git c/parse-options.c w/parse-options.c
index 4519ead9dc..0aad1e5373 100644
--- c/parse-options.c
+++ w/parse-options.c
@@ -1535,26 +1535,31 @@ void NORETURN usage_msg_optf(const char * const fmt,
 	usage_msg_opt(msg.buf, usagestr, options);
 }
 
-void die_for_incompatible_opt4(int opt1, const char *opt1_name,
-			       int opt2, const char *opt2_name,
-			       int opt3, const char *opt3_name,
-			       int opt4, const char *opt4_name)
+void die_for_incompatible_opts(bool opt1, const char *opt1_name, ...)
 {
-	int count = 0;
+	unsigned count = 0;
 	const char *options[4];
+	va_list ap;
 
 	if (opt1)
 		options[count++] = opt1_name;
-	if (opt2)
-		options[count++] = opt2_name;
-	if (opt3)
-		options[count++] = opt3_name;
-	if (opt4)
-		options[count++] = opt4_name;
+	va_start(ap, opt1_name);
+	while (count < ARRAY_SIZE(options)) {
+		int opt_set = va_arg(ap, int);
+		const char *opt_name;
+
+		if (opt_set == EOF)
+			break;
+		opt_name = va_arg(ap, const char *);
+		if (opt_set)
+			options[count++] = opt_name;
+	}
+	va_end(ap);
+
 	switch (count) {
 	case 4:
 		die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),
-		    opt1_name, opt2_name, opt3_name, opt4_name);
+		    options[0], options[1], options[2], options[3]);
 		break;
 	case 3:
 		die(_("options '%s', '%s', and '%s' cannot be used together"),
diff --git c/parse-options.h w/parse-options.h
index d7f896a933..50bd715b86 100644
--- c/parse-options.h
+++ w/parse-options.h
@@ -441,29 +441,43 @@ void NORETURN usage_msg_optf(const char *fmt,
 			     const char * const *usagestr,
 			     const struct option *options, ...);
 
-void die_for_incompatible_opt4(int opt1, const char *opt1_name,
-			       int opt2, const char *opt2_name,
-			       int opt3, const char *opt3_name,
-			       int opt4, const char *opt4_name);
+/*
+ * Take N pairs of <bool optN, const char *opt_nameN> as parameters,
+ * followed by EOF.  The caller declares "The options opt_name1 through
+ * opt_nameN exist and the command line has options whose optN is set."
+ * and asks that an error be raised if two or more of these options are
+ * set at the same time.
+ */
+void die_for_incompatible_opts(bool opt1, const char *opt1_name, ...);
 
+static inline void die_for_incompatible_opt4(int opt1, const char *opt1_name,
+					     int opt2, const char *opt2_name,
+					     int opt3, const char *opt3_name,
+					     int opt4, const char *opt4_name)
+{
+	die_for_incompatible_opts(!!opt1, opt1_name,
+				  !!opt2, opt2_name,
+				  !!opt3, opt3_name,
+				  !!opt4, opt4_name,
+				  EOF);
+}
 
 static inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
 					     int opt2, const char *opt2_name,
 					     int opt3, const char *opt3_name)
 {
-	die_for_incompatible_opt4(opt1, opt1_name,
-				  opt2, opt2_name,
-				  opt3, opt3_name,
-				  0, "");
+	die_for_incompatible_opts(!!opt1, opt1_name,
+				  !!opt2, opt2_name,
+				  !!opt3, opt3_name,
+				  EOF);
 }
 
 static inline void die_for_incompatible_opt2(int opt1, const char *opt1_name,
 					     int opt2, const char *opt2_name)
 {
-	die_for_incompatible_opt4(opt1, opt1_name,
-				  opt2, opt2_name,
-				  0, "",
-				  0, "");
+	die_for_incompatible_opts(!!opt1, opt1_name,
+				  !!opt2, opt2_name,
+				  EOF);
 }
 
 /*

  parent reply	other threads:[~2026-08-27 17:28 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26 23:31 [PATCH 0/2] die_for_incompatible_opts(): unbounded number of options Junio C Hamano
2026-08-26 23:31 ` [PATCH 1/2] die_for_incompatible_optN: swap the order of arguments Junio C Hamano
2026-08-26 23:31 ` [PATCH 2/2] die_for_incompatible_opts(): accept more than four options Junio C Hamano
2026-08-27  1:19   ` Elijah Newren
2026-08-27 14:22     ` Junio C Hamano
2026-08-27  4:55   ` Jeff King
2026-08-27 14:35     ` Junio C Hamano
2026-08-29 11:14       ` Jeff King
2026-08-29 17:51         ` Junio C Hamano
2026-08-29 18:04         ` René Scharfe
2026-08-27 17:28 ` Junio C Hamano [this message]
2026-08-29 11:15   ` [PATCH v2] die_for_incompatible_opts(): unbounded number of options Jeff King
2026-08-30 20:55     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqbjana2wv.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.