2011/7/21 Bert Wesarg <bert.wesarg@xxxxxxxxxxxxxx>: > > It should be. But I think that unveils one of the shortcomings of the > (any) option parser: You wont get notified when an option was given, > regardless of its value. To handle the above I would have to use > OPTION_CALLBACK to set an addition flag exc_given (like it is done in > git-ls-files) and test against this. The same problem is possible for > a number option, if you want to know whether the option was actually > given on the command line, one need to invent an invalid value (which > isn't always possible) and use this as the initializer or use > OPTION_CALLBACK again. Here is a proof-of-concept patch (probably whitespace damaged) to make it more clear what I meant: --- >8 --- Subject: [PoC/RFC/PATCH] parse-option: flag the presence of an option regardless of its value Signed-off-by: Bert Wesarg <bert.wesarg@xxxxxxxxxxxxxx> --- parse-options.c | 15 +++++++++++++-- parse-options.h | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/parse-options.c b/parse-options.c index 73bd28a..df0f483 100644 --- a/parse-options.c +++ b/parse-options.c @@ -156,7 +156,10 @@ static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *optio for (; options->type != OPTION_END; options++) { if (options->short_name == *p->opt) { p->opt = p->opt[1] ? p->opt + 1 : NULL; - return get_value(p, options, OPT_SHORT); + if (options->given) { + *options->given = 1; + return get_value(p, options, OPT_SHORT); + } } /* @@ -171,6 +174,9 @@ static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *optio char *arg; int rc; + if (options->given) + *options->given = 1; + while (isdigit(p->opt[len])) len++; arg = xmemdupz(p->opt, len); @@ -254,6 +260,8 @@ is_abbreviated: continue; p->opt = rest + 1; } + if (options->given) + *options->given = 1; return get_value(p, options, flags); } @@ -276,8 +284,11 @@ static int parse_nodash_opt(struct parse_opt_ctx_t *p, const char *arg, for (; options->type != OPTION_END; options++) { if (!(options->flags & PARSE_OPT_NODASH)) continue; - if (options->short_name == arg[0] && arg[1] == '\0') + if (options->short_name == arg[0] && arg[1] == '\0') { + if (options->given) + *options->given = 1; return get_value(p, options, OPT_SHORT); + } } return -2; } diff --git a/parse-options.h b/parse-options.h index d1b12fe..7fe3d49 100644 --- a/parse-options.h +++ b/parse-options.h @@ -100,6 +100,10 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, * OPTION_{BIT,SET_INT,SET_PTR} store the {mask,integer,pointer} to put in * the value when met. * CALLBACKS can use it like they want. + * + * `given`:: + * Pointer to a flag variable which is set to 1 if this option was given. + * The flag should be 0 initialized, to make sense. */ struct option { enum parse_opt_type type; @@ -112,6 +116,7 @@ struct option { int flags; parse_opt_cb *callback; intptr_t defval; + int *given; }; #define OPT_END() { OPTION_END } @@ -146,6 +151,21 @@ struct option { { OPTION_CALLBACK, (s), (l), (v), "when", (h), PARSE_OPT_OPTARG, \ parse_opt_color_flag_cb, (intptr_t)"always" } +/* same as above but with given flag pointer */ +#define OPT_BIT_GIVEN(s, l, v, h, b, g) \ + { OPTION_BIT, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG, NULL, (b), (g) } +#define OPT_NEGBIT_GIVEN(s, l, v, h, b, g) \ + { OPTION_NEGBIT, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG, NULL, (b), (g) } +#define OPT_BOOLEAN_GIVEN(s, l, v, h, g) \ + { OPTION_BOOLEAN, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG, NULL, 0, (g) } +#define OPT_SET_INT_GIVEN(s, l, v, h, i, g) \ + { OPTION_SET_INT, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG, NULL, (i), (g) } +#define OPT_SET_PTR_GIVEN(s, l, v, h, p, g) \ + { OPTION_SET_PTR, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG, NULL, (p), (g) } +#define OPT_INTEGER_GIVEN(s, l, v, h, g) \ + { OPTION_INTEGER, (s), (l), (v), "n", (h), 0, NULL, 0, (g) } +#define OPT_STRING_GIVEN(s, l, v, a, h, g) \ + { OPTION_STRING, (s), (l), (v), (a), (h), 0, NULL, 0, (g) } /* parse_options() will filter out the processed options and leave the * non-option arguments in argv[]. -- 1.7.6.588.g8d735 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html