From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 08/75] parse-options: allow ll_callback with OPTION_CALLBACK
Date: Thu, 27 Dec 2018 17:25:29 +0100 [thread overview]
Message-ID: <20181227162536.15895-9-pclouds@gmail.com> (raw)
In-Reply-To: <20181227162536.15895-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 1c8652e455..b4f4b401eb 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 720a8663eb..b336b4fa97 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -170,8 +170,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 634484d8f0..8e0aefe86b 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -96,7 +96,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)
@@ -162,16 +162,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;
}
@@ -413,10 +427,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 617bca8efe..75c953a887 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`::
@@ -270,7 +271,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
next prev parent reply other threads:[~2018-12-27 16:26 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-27 16:25 [PATCH 00/75] Convert diff opt parser to parse_options() Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 01/75] parse-options.h: remove extern on function prototypes Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 02/75] parse-options: add one-shot mode Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 03/75] parse-options: allow keep-unknown + stop-at-non-opt combination Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 04/75] parse-options: disable option abbreviation with PARSE_OPT_KEEP_UNKNOWN Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 05/75] parse-options: add OPT_BITOP() Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 06/75] parse-options: stop abusing 'callback' for lowlevel callbacks Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 07/75] parse-options: avoid magic return codes Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` Nguyễn Thái Ngọc Duy [this message]
2018-12-27 16:25 ` [PATCH 09/75] diff.h: keep forward struct declarations sorted Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 10/75] diff.h: avoid bit fields in struct diff_flags Nguyễn Thái Ngọc Duy
2019-01-09 20:21 ` Stefan Beller
2018-12-27 16:25 ` [PATCH 11/75] diff.c: prepare to use parse_options() for parsing Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 12/75] diff.c: convert -u|-p|--patch Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 73/75] range-diff: use parse_options() instead of diff_opt_parse() Nguyễn Thái Ngọc Duy
2018-12-27 16:25 ` [PATCH 74/75] diff --no-index: " Nguyễn Thái Ngọc Duy
2018-12-27 20:34 ` Eric Sunshine
2018-12-27 16:25 ` [PATCH 75/75] am: avoid diff_opt_parse() Nguyễn Thái Ngọc Duy
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=20181227162536.15895-9-pclouds@gmail.com \
--to=pclouds@gmail.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.