On Mon, 23 Jun 2008, Linus Torvalds wrote: > > Or are we going to sit around discussing this for another five months? So the gauntlet is thrown. This is the trivial version that (on top of my original patch in this thread) makes git blame --since=April -b Makefile work. Does it handle all cases? No. In particular, because it still makes builtin-blame.c use PARSE_OPT_STOP_AT_NON_OPTION, and because cmd_blame.c simply doesn't do the sane thing (it took me more than five minutes just because I tried to make it do the same thing and not do any argument parsing at all, but I just gave up), you still cannot pass it things like --default HEAD because it will stop at HEAD, and then do the exact wrong thing. Could it be improved? I'm sure. And I didn't test it much at all. I also didn't change any existing users that could possibly use the new PARSE_OPT_STOP_AT_UNKNOWN thing. So this patch is an example patch only, to show what I'm talking about when I say "simple". Linus --- builtin-blame.c | 2 +- parse-options.c | 26 ++++++++++++++++++++++---- parse-options.h | 2 ++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index f04bd93..059062c 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -2195,7 +2195,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) cmd_is_annotate = !strcmp(argv[0], "annotate"); argc = parse_options(argc, argv, options, blame_opt_usage, - PARSE_OPT_STOP_AT_NON_OPTION | PARSE_OPT_KEEP_DASHDASH); + PARSE_OPT_STOP_AT_NON_OPTION | PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_UNKNOWN); /* * parse_options() offsets things by one - undo for now to make diff --git a/parse-options.c b/parse-options.c index acf3fe3..5b4653f 100644 --- a/parse-options.c +++ b/parse-options.c @@ -7,7 +7,7 @@ struct optparse_t { const char **argv; const char **out; - int argc, cpidx; + int argc, cpidx, flags; const char *opt; }; @@ -139,6 +139,8 @@ static int parse_short_opt(struct optparse_t *p, const struct option *options) return get_value(p, options, OPT_SHORT); } } + if (p->flags & (PARSE_OPT_STOP_AT_UNKNOWN | PARSE_OPT_KEEP_UNKNOWN)) + return -1; return error("unknown switch `%c'", *p->opt); } @@ -224,6 +226,8 @@ is_abbreviated: abbrev_option->long_name); if (abbrev_option) return get_value(p, abbrev_option, abbrev_flags); + if (p->flags & (PARSE_OPT_STOP_AT_UNKNOWN | PARSE_OPT_KEEP_UNKNOWN)) + return -1; return error("unknown option `%s'", arg); } @@ -253,7 +257,7 @@ static NORETURN void usage_with_options_internal(const char * const *, int parse_options(int argc, const char **argv, const struct option *options, const char * const usagestr[], int flags) { - struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL }; + struct optparse_t args = { argv + 1, argv, argc - 1, 0, flags, NULL }; for (; args.argc; args.argc--, args.argv++) { const char *arg = args.argv[0]; @@ -269,8 +273,15 @@ int parse_options(int argc, const char **argv, const struct option *options, args.opt = arg + 1; if (*args.opt == 'h') usage_with_options(usagestr, options); - if (parse_short_opt(&args, options) < 0) + if (parse_short_opt(&args, options) < 0) { + if (flags & PARSE_OPT_STOP_AT_UNKNOWN) + break; + if (flags & PARSE_OPT_KEEP_UNKNOWN) { + args.out[args.cpidx++] = args.argv[0]; + continue; + } usage_with_options(usagestr, options); + } if (args.opt) check_typos(arg + 1, options); while (args.opt) { @@ -294,8 +305,15 @@ int parse_options(int argc, const char **argv, const struct option *options, usage_with_options_internal(usagestr, options, 1); if (!strcmp(arg + 2, "help")) usage_with_options(usagestr, options); - if (parse_long_opt(&args, arg + 2, options)) + if (parse_long_opt(&args, arg + 2, options)) { + if (flags & PARSE_OPT_STOP_AT_UNKNOWN) + break; + if (flags & PARSE_OPT_KEEP_UNKNOWN) { + args.out[args.cpidx++] = args.argv[0]; + continue; + } usage_with_options(usagestr, options); + } } memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out)); diff --git a/parse-options.h b/parse-options.h index 4ee443d..a98f0ec 100644 --- a/parse-options.h +++ b/parse-options.h @@ -20,6 +20,8 @@ enum parse_opt_type { enum parse_opt_flags { PARSE_OPT_KEEP_DASHDASH = 1, PARSE_OPT_STOP_AT_NON_OPTION = 2, + PARSE_OPT_KEEP_UNKNOWN = 4, + PARSE_OPT_STOP_AT_UNKNOWN = 8, }; enum parse_opt_option_flags { -- 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