If you set this for a given flag, and the flag appears without a value on the command line, then the `defval' is used to fake a new argument. Note that this flag is meaningless in presence of OPTARG or NOARG flags. (in the current implementation it will be ignored, but don't rely on it). Signed-off-by: Pierre Habouzit <madcoder@xxxxxxxxxx> --- > (3) inspired from (1) and (2), have a flag for options that says > "I do take an argument, but if I'm the last option on the > command line, please fake this argument for me. > > I really like (3) more FWIW as it doesn't generate ambiguous > parsers like (2) would, and it's not horrible like (1). And cherry > on top it's pretty trivial to implement I think. And here it is, untested though (in the sense that I didn't test the new feature, but git is not broken with the patch). parse-options.c | 55 +++++++++++++++++++++++++++---------------------------- parse-options.h | 1 + 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/parse-options.c b/parse-options.c index a90b336..a63485c 100644 --- a/parse-options.c +++ b/parse-options.c @@ -5,17 +5,6 @@ #define OPT_SHORT 1 #define OPT_UNSET 2 -static inline const char *get_arg(struct parse_opt_ctx_t *p) -{ - if (p->opt) { - const char *res = p->opt; - p->opt = NULL; - return res; - } - p->argc--; - return *++p->argv; -} - static int opterror(const struct option *opt, const char *reason, int flags) { if (flags & OPT_SHORT) @@ -25,8 +14,24 @@ static int opterror(const struct option *opt, const char *reason, int flags) return error("option `%s' %s", opt->long_name, reason); } +static inline int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, + int flags, const char **arg) +{ + if (p->opt) { + *arg = p->opt; + p->opt = NULL; + } else if (p->argc) { + p->argc--; + *arg = *++p->argv; + } else if (opt->flags & PARSE_OPT_FAKELASTARG) { + *arg = (const char *)opt->defval; + } else + return opterror(opt, "requires a value", flags); + return 0; +} + static int get_value(struct parse_opt_ctx_t *p, - const struct option *opt, int flags) + const struct option *opt, int flags) { const char *s, *arg; const int unset = flags & OPT_UNSET; @@ -52,7 +57,6 @@ static int get_value(struct parse_opt_ctx_t *p, } } - arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL); switch (opt->type) { case OPTION_BIT: if (unset) @@ -74,17 +78,12 @@ static int get_value(struct parse_opt_ctx_t *p, return 0; case OPTION_STRING: - if (unset) { + if (unset) *(const char **)opt->value = NULL; - return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) *(const char **)opt->value = (const char *)opt->defval; - return 0; - } - if (!arg) - return opterror(opt, "requires a value", flags); - *(const char **)opt->value = get_arg(p); + else + return get_arg(p, opt, flags, (const char **)opt->value); return 0; case OPTION_CALLBACK: @@ -94,9 +93,9 @@ static int get_value(struct parse_opt_ctx_t *p, 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 (!arg) - return opterror(opt, "requires a value", flags); - return (*opt->callback)(opt, get_arg(p), 0) ? (-1) : 0; + if (get_arg(p, opt, flags, &arg)) + return -1; + return (*opt->callback)(opt, arg, 0) ? (-1) : 0; case OPTION_INTEGER: if (unset) { @@ -107,9 +106,9 @@ static int get_value(struct parse_opt_ctx_t *p, *(int *)opt->value = opt->defval; return 0; } - if (!arg) - return opterror(opt, "requires a value", flags); - *(int *)opt->value = strtol(get_arg(p), (char **)&s, 10); + if (get_arg(p, opt, flags, &arg)) + return -1; + *(int *)opt->value = strtol(arg, (char **)&s, 10); if (*s) return opterror(opt, "expects a numerical value", flags); return 0; diff --git a/parse-options.h b/parse-options.h index c5f0b4b..6e9edd1 100644 --- a/parse-options.h +++ b/parse-options.h @@ -28,6 +28,7 @@ enum parse_opt_option_flags { PARSE_OPT_NOARG = 2, PARSE_OPT_NONEG = 4, PARSE_OPT_HIDDEN = 8, + PARSE_OPT_FAKELASTARG = 16, }; struct option; -- 1.5.6.2.398.g3c3f1.dirty
Attachment:
pgp5LHsa7m36c.pgp
Description: PGP signature