git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 08/76] parse-options: allow ll_callback with OPTION_CALLBACK

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Jan 17, 2019, 13:05 UTC
Message-ID
<20190117130615.18732-9-pclouds@gmail.com>
In-Reply-To
<20190117130615.18732-1-pclouds@gmail.com>

OPTION_CALLBACK is much simpler/safer to use, but parse_opt_cb does not allow access to parse_opt_ctx_t, which sometimes is useful (e.g. to obtain the prefix).

Extending parse_opt_cb to take parse_opt_cb could result in a lot of changes. Instead let's just allow ll_callback to be used with OPTION_CALLBACK. The user will have to be careful, not to change anything in ctx, or return wrong result code. But that's the price for ll_callback.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/merge.c        |  2 ++
 builtin/update-index.c | 20 +++++++++++++++-----
 parse-options-cb.c     |  4 +++-
 parse-options.c        | 42 ++++++++++++++++++++++++++++--------------
 parse-options.h        |  5 +++--
 5 files changed, 51 insertions(+), 22 deletions(-)
diff --git a/builtin/merge.c b/builtin/merge.c
index de64d7850e..563a16f38a 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -114,11 +114,13 @@ static int option_parse_message(const struct option *opt,
 
 static enum parse_opt_result option_read_message(struct parse_opt_ctx_t *ctx,
 						 const struct option *opt,
+						 const char *arg_not_used,
 						 int unset)
 {
 	struct strbuf *buf = opt->value;
 	const char *arg;
 
+	BUG_ON_OPT_ARG(arg_not_used);
 	if (unset)
 		BUG("-F cannot be negated");
 
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 21c84e5590..7abde20169 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -848,13 +848,15 @@ static int parse_new_style_cacheinfo(const char *arg,
 }
 
 static enum parse_opt_result cacheinfo_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt, int unset)
+	struct parse_opt_ctx_t *ctx, const struct option *opt,
+	const char *arg, int unset)
 {
 	struct object_id oid;
 	unsigned int mode;
 	const char *path;
 
 	BUG_ON_OPT_NEG(unset);
+	BUG_ON_OPT_ARG(arg);
 
 	if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) {
 		if (add_cacheinfo(mode, &oid, path, 0))
@@ -874,11 +876,13 @@ static enum parse_opt_result cacheinfo_callback(
 }
 
 static enum parse_opt_result stdin_cacheinfo_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt, int unset)
+	struct parse_opt_ctx_t *ctx, const struct option *opt,
+	const char *arg, int unset)
 {
 	int *nul_term_line = opt->value;
 
 	BUG_ON_OPT_NEG(unset);
+	BUG_ON_OPT_ARG(arg);
 
 	if (ctx->argc != 1)
 		return error("option '%s' must be the last argument", opt->long_name);
@@ -888,11 +892,13 @@ static enum parse_opt_result stdin_cacheinfo_callback(
 }
 
 static enum parse_opt_result stdin_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt, int unset)
+	struct parse_opt_ctx_t *ctx, const struct option *opt,
+	const char *arg, int unset)
 {
 	int *read_from_stdin = opt->value;
 
 	BUG_ON_OPT_NEG(unset);
+	BUG_ON_OPT_ARG(arg);
 
 	if (ctx->argc != 1)
 		return error("option '%s' must be the last argument", opt->long_name);
@@ -901,12 +907,14 @@ static enum parse_opt_result stdin_callback(
 }
 
 static enum parse_opt_result unresolve_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt, int unset)
+	struct parse_opt_ctx_t *ctx, const struct option *opt,
+	const char *arg, int unset)
 {
 	int *has_errors = opt->value;
 	const char *prefix = startup_info->prefix;
 
 	BUG_ON_OPT_NEG(unset);
+	BUG_ON_OPT_ARG(arg);
 
 	/* consume remaining arguments. */
 	*has_errors = do_unresolve(ctx->argc, ctx->argv,
@@ -920,12 +928,14 @@ static enum parse_opt_result unresolve_callback(
 }
 
 static enum parse_opt_result reupdate_callback(
-	struct parse_opt_ctx_t *ctx, const struct option *opt, int unset)
+	struct parse_opt_ctx_t *ctx, const struct option *opt,
+	const char *arg, int unset)
 {
 	int *has_errors = opt->value;
 	const char *prefix = startup_info->prefix;
 
 	BUG_ON_OPT_NEG(unset);
+	BUG_ON_OPT_ARG(arg);
 
 	/* consume remaining arguments. */
 	setup_work_tree();
diff --git a/parse-options-cb.c b/parse-options-cb.c
index ec01ef722b..2733393546 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -171,8 +171,10 @@ int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset)
  * parse_options().
  */
 enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx,
-					   const struct option *opt, int unset)
+					   const struct option *opt,
+					   const char *arg, int unset)
 {
+	BUG_ON_OPT_ARG(arg);
 	return PARSE_OPT_UNKNOWN;
 }
 
diff --git a/parse-options.c b/parse-options.c
index 372f5cede4..a0ff8ea225 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -95,7 +95,7 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
 
 	switch (opt->type) {
 	case OPTION_LOWLEVEL_CALLBACK:
-		return opt->ll_callback(p, opt, unset);
+		return opt->ll_callback(p, opt, NULL, unset);
 
 	case OPTION_BIT:
 		if (unset)
@@ -161,16 +161,27 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
 		return err;
 
 	case OPTION_CALLBACK:
+	{
+		const char *p_arg = NULL;
+		int p_unset;
+
 		if (unset)
-			return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
-		if (opt->flags & PARSE_OPT_NOARG)
-			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
-		if (get_arg(p, opt, flags, &arg))
+			p_unset = 1;
+		else if (opt->flags & PARSE_OPT_NOARG)
+			p_unset = 0;
+		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+			p_unset = 0;
+		else if (get_arg(p, opt, flags, &arg))
 			return -1;
-		return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
-
+		else {
+			p_unset = 0;
+			p_arg = arg;
+		}
+		if (opt->callback)
+			return (*opt->callback)(opt, p_arg, p_unset) ? (-1) : 0;
+		else
+			return (*opt->ll_callback)(p, opt, p_arg, p_unset);
+	}
 	case OPTION_INTEGER:
 		if (unset) {
 			*(int *)opt->value = 0;
@@ -238,7 +249,10 @@ static enum parse_opt_result parse_short_opt(struct parse_opt_ctx_t *p,
 			len++;
 		arg = xmemdupz(p->opt, len);
 		p->opt = p->opt[len] ? p->opt + len : NULL;
-		rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
+		if (numopt->callback)
+			rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
+		else
+			rc = (*numopt->ll_callback)(p, numopt, arg, 0);
 		free(arg);
 		return rc;
 	}
@@ -414,10 +428,10 @@ static void parse_options_check(const struct option *opts)
 				err |= optbug(opts, "should not accept an argument");
 			break;
 		case OPTION_CALLBACK:
-			if (!opts->callback)
-				BUG("OPTION_CALLBACK needs a callback");
-			if (opts->ll_callback)
-				BUG("OPTION_CALLBACK needs no ll_callback");
+			if (!opts->callback && !opts->ll_callback)
+				BUG("OPTION_CALLBACK needs one callback");
+			if (opts->callback && opts->ll_callback)
+				BUG("OPTION_CALLBACK can't have two callbacks");
 			break;
 		case OPTION_LOWLEVEL_CALLBACK:
 			if (!opts->ll_callback)
diff --git a/parse-options.h b/parse-options.h
index 4e49185027..ce75278804 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -50,7 +50,8 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
 
 struct parse_opt_ctx_t;
 typedef enum parse_opt_result parse_opt_ll_cb(struct parse_opt_ctx_t *ctx,
-					      const struct option *opt, int unset);
+					      const struct option *opt,
+					      const char *arg, int unset);
 
 /*
  * `type`::
@@ -267,7 +268,7 @@ int parse_opt_commits(const struct option *, const char *, int);
 int parse_opt_tertiary(const struct option *, const char *, int);
 int parse_opt_string_list(const struct option *, const char *, int);
 int parse_opt_noop_cb(const struct option *, const char *, int);
-int parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, const struct option *, int);
+int parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, const struct option *, const char *, int);
 int parse_opt_passthru(const struct option *, const char *, int);
 int parse_opt_passthru_argv(const struct option *, const char *, int);
 
-- 
2.20.0.482.g66447595a7
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 10 of 88 in “Convert diff opt parser to parse_options()”
  1. 00/76 Convert diff opt parser to parse_options()Nguyễn Thái Ngọc Duy, Jan 17, 2019
  2. 01/76 parse-options.h: remove extern on function prototypesNguyễn Thái Ngọc Duy, Jan 17, 2019
  3. 02/76 parse-options: add one-shot modeNguyễn Thái Ngọc Duy, Jan 17, 2019
  4. 03/76 parse-options: allow keep-unknown + stop-at-non-opt combinationNguyễn Thái Ngọc Duy, Jan 17, 2019
  5. Stefan BellerJan 17, 2019
  6. 04/76 parse-options: disable option abbreviation with PARSE_OPT_KEEP_UNKNOWNNguyễn Thái Ngọc Duy, Jan 17, 2019
  7. 05/76 parse-options: add OPT_BITOP()Nguyễn Thái Ngọc Duy, Jan 17, 2019
  8. 06/76 parse-options: stop abusing 'callback' for lowlevel callbacksNguyễn Thái Ngọc Duy, Jan 17, 2019
  9. 07/76 parse-options: avoid magic return codesNguyễn Thái Ngọc Duy, Jan 17, 2019
  10. 08/76 parse-options: allow ll_callback with OPTION_CALLBACKNguyễn Thái Ngọc Duy, Jan 17, 2019
  11. 09/76 diff.h: keep forward struct declarations sortedNguyễn Thái Ngọc Duy, Jan 17, 2019
  12. 10/76 diff.h: avoid bit fields in struct diff_flagsNguyễn Thái Ngọc Duy, Jan 17, 2019
  13. 11/76 diff.c: prepare to use parse_options() for parsingNguyễn Thái Ngọc Duy, Jan 17, 2019
  14. 12/76 diff.c: convert -u|-p|--patchNguyễn Thái Ngọc Duy, Jan 17, 2019
  15. 13/76 diff.c: convert -U|--unifiedNguyễn Thái Ngọc Duy, Jan 17, 2019
  16. 14/76 diff.c: convert -W|--[no-]function-contextNguyễn Thái Ngọc Duy, Jan 17, 2019
  17. 15/76 diff.c: convert --rawNguyễn Thái Ngọc Duy, Jan 17, 2019
  18. 16/76 diff.c: convert --patch-with-rawNguyễn Thái Ngọc Duy, Jan 17, 2019
  19. 17/76 diff.c: convert --numstat and --shortstatNguyễn Thái Ngọc Duy, Jan 17, 2019
  20. 18/76 diff.c: convert --dirstat and friendsNguyễn Thái Ngọc Duy, Jan 17, 2019
  21. 19/76 diff.c: convert --checkNguyễn Thái Ngọc Duy, Jan 17, 2019
  22. 20/76 diff.c: convert --summaryNguyễn Thái Ngọc Duy, Jan 17, 2019
  23. 21/76 diff.c: convert --patch-with-statNguyễn Thái Ngọc Duy, Jan 17, 2019
  24. 22/76 diff.c: convert --name-onlyNguyễn Thái Ngọc Duy, Jan 17, 2019
  25. 23/76 diff.c: convert --name-statusNguyễn Thái Ngọc Duy, Jan 17, 2019
  26. 24/76 diff.c: convert -s|--no-patchNguyễn Thái Ngọc Duy, Jan 17, 2019
  27. 25/76 diff.c: convert --stat*Nguyễn Thái Ngọc Duy, Jan 17, 2019
  28. SZEDER GáborJan 19, 2019
  29. 26/76 diff.c: convert --[no-]compact-summaryNguyễn Thái Ngọc Duy, Jan 17, 2019
  30. 27/76 diff.c: convert --output-*Nguyễn Thái Ngọc Duy, Jan 17, 2019
  31. 28/76 diff.c: convert -B|--break-rewritesNguyễn Thái Ngọc Duy, Jan 17, 2019
  32. Johannes SchindelinJan 21, 2019
  33. 29/76 diff.c: convert -M|--find-renamesNguyễn Thái Ngọc Duy, Jan 17, 2019
  34. 30/76 diff.c: convert -D|--irreversible-deleteNguyễn Thái Ngọc Duy, Jan 17, 2019
  35. 31/76 diff.c: convert -C|--find-copiesNguyễn Thái Ngọc Duy, Jan 17, 2019
  36. 32/76 diff.c: convert --find-copies-harderNguyễn Thái Ngọc Duy, Jan 17, 2019
  37. 33/76 diff.c: convert --no-renames|--[no--rename-emptyNguyễn Thái Ngọc Duy, Jan 17, 2019
  38. 34/76 diff.c: convert --relativeNguyễn Thái Ngọc Duy, Jan 17, 2019
  39. 35/76 diff.c: convert --[no-]minimalNguyễn Thái Ngọc Duy, Jan 17, 2019
  40. 36/76 diff.c: convert --ignore-some-changesNguyễn Thái Ngọc Duy, Jan 17, 2019
  41. 37/76 diff.c: convert --[no-]indent-heuristicNguyễn Thái Ngọc Duy, Jan 17, 2019
  42. 38/76 diff.c: convert --patienceNguyễn Thái Ngọc Duy, Jan 17, 2019
  43. 39/76 diff.c: convert --histogramNguyễn Thái Ngọc Duy, Jan 17, 2019
  44. 40/76 diff.c: convert --diff-algorithmNguyễn Thái Ngọc Duy, Jan 17, 2019
  45. 41/76 diff.c: convert --anchoredNguyễn Thái Ngọc Duy, Jan 17, 2019
  46. 42/76 diff.c: convert --binaryNguyễn Thái Ngọc Duy, Jan 17, 2019
  47. 43/76 diff.c: convert --full-indexNguyễn Thái Ngọc Duy, Jan 17, 2019
  48. 44/76 diff.c: convert -a|--textNguyễn Thái Ngọc Duy, Jan 17, 2019
  49. 45/76 diff.c: convert -RNguyễn Thái Ngọc Duy, Jan 17, 2019
  50. 46/76 diff.c: convert --[no-]followNguyễn Thái Ngọc Duy, Jan 17, 2019
  51. 47/76 diff.c: convert --[no-]colorNguyễn Thái Ngọc Duy, Jan 17, 2019
  52. 48/76 diff.c: convert --word-diffNguyễn Thái Ngọc Duy, Jan 17, 2019
  53. 49/76 diff.c: convert --word-diff-regexNguyễn Thái Ngọc Duy, Jan 17, 2019
  54. 50/76 diff.c: convert --color-wordsNguyễn Thái Ngọc Duy, Jan 17, 2019
  55. 51/76 diff.c: convert --exit-codeNguyễn Thái Ngọc Duy, Jan 17, 2019
  56. 52/76 diff.c: convert --quietNguyễn Thái Ngọc Duy, Jan 17, 2019
  57. 53/76 diff.c: convert --ext-diffNguyễn Thái Ngọc Duy, Jan 17, 2019
  58. 54/76 diff.c: convert --textconvNguyễn Thái Ngọc Duy, Jan 17, 2019
  59. 55/76 diff.c: convert --ignore-submodulesNguyễn Thái Ngọc Duy, Jan 17, 2019
  60. 56/76 diff.c: convert --submoduleNguyễn Thái Ngọc Duy, Jan 17, 2019
  61. 57/76 diff.c: convert --ws-error-highlightNguyễn Thái Ngọc Duy, Jan 17, 2019
  62. 58/76 diff.c: convert --ita-[in]visible-in-indexNguyễn Thái Ngọc Duy, Jan 17, 2019
  63. 59/76 diff.c: convert -zNguyễn Thái Ngọc Duy, Jan 17, 2019
  64. 60/76 diff.c: convert -lNguyễn Thái Ngọc Duy, Jan 17, 2019
  65. 61/76 diff.c: convert -S|-GNguyễn Thái Ngọc Duy, Jan 17, 2019
  66. 62/76 diff.c: convert --pickaxe-all|--pickaxe-regexNguyễn Thái Ngọc Duy, Jan 17, 2019
  67. 63/76 diff.c: convert -ONguyễn Thái Ngọc Duy, Jan 17, 2019
  68. Johannes SchindelinJan 21, 2019
  69. 64/76 diff.c: convert --find-objectNguyễn Thái Ngọc Duy, Jan 17, 2019
  70. 65/76 diff.c: convert --diff-filterNguyễn Thái Ngọc Duy, Jan 17, 2019
  71. 66/76 diff.c: convert --[no-]abbrevNguyễn Thái Ngọc Duy, Jan 17, 2019
  72. 67/76 diff.c: convert --[src|dst]-prefixNguyễn Thái Ngọc Duy, Jan 17, 2019
  73. 68/76 diff.c: convert --line-prefixNguyễn Thái Ngọc Duy, Jan 17, 2019
  74. 69/76 diff.c: convert --no-prefixNguyễn Thái Ngọc Duy, Jan 17, 2019
  75. 70/76 diff.c: convert --inter-hunk-contextNguyễn Thái Ngọc Duy, Jan 17, 2019
  76. SZEDER GáborJan 19, 2019
  77. 71/76 diff.c: convert --color-movedNguyễn Thái Ngọc Duy, Jan 17, 2019
  78. 72/76 diff.c: convert --color-moved-wsNguyễn Thái Ngọc Duy, Jan 17, 2019
  79. 73/76 diff.c: allow --no-color-moved-wsNguyễn Thái Ngọc Duy, Jan 17, 2019
  80. 74/76 range-diff: use parse_options() instead of diff_opt_parse()Nguyễn Thái Ngọc Duy, Jan 17, 2019
  81. Stefan BellerJan 17, 2019
  82. Duy NguyenJan 18, 2019
  83. 75/76 diff --no-index: use parse_options() instead of diff_opt_parse()Nguyễn Thái Ngọc Duy, Jan 17, 2019
  84. 76/76 am: avoid diff_opt_parse()Nguyễn Thái Ngọc Duy, Jan 17, 2019
  85. Johannes SchindelinJan 17, 2019
  86. Duy NguyenJan 18, 2019
  87. Ævar Arnfjörð BjarmasonJan 17, 2019
  88. Stefan BellerJan 17, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.