summaryrefslogtreecommitdiff
path: root/parse-options.c
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2019-01-27 07:35:28 +0700
committerJunio C Hamano <gitster@pobox.com>2019-01-27 16:28:18 -0800
commit3ebbe289896a698b99c91b797440563272dcd716 (patch)
tree09798977c8fc962c33fb6e3c95285484d9d855b2 /parse-options.c
parentf41179f16ba2fc16e31be81518536008afe2e278 (diff)
downloadgit-3ebbe289896a698b99c91b797440563272dcd716.tar.gz
parse-options: allow ll_callback with OPTION_CALLBACK
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'parse-options.c')
-rw-r--r--parse-options.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/parse-options.c b/parse-options.c
index 50c340474c..cec74522e5 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)