Show 49 quoted lines
>
>
> On Mon, 23 Jun 2008, Johannes Schindelin wrote:
> >
> > Thinking about the recursive approach again, I came up with this POC:
>
> "recursive" is pointless.
>
> The problem with the current "parse_options()" is not that it's recursive
> (although that has been claimed multiple times!.
>
> The problem with parse_options() is that it's currently impossible to
> write something that handles _partial_ cases.
>
> Let me explain.
>
> Look at cmd_apply() in builtin-apply.c. Notice how it currently absolutely
> CANNOT sanely be turned into using "parse_options()", not because it needs
> any "recursive" handling, but simply because it wants to do *incremental*
> handling.
>
> It should be perfectly possible to change that argument loop from
>
> for (i = 1; i < argc; i++) {
> const char *arg = argv[i];
> if (strcmp(arg, "-")) {
> .. handle <stdin> ..
> continue;
> }
> ...
>
> to doing something like this:
>
> for (;;) {
> const char *arg;
> argc = parse_options(argc, argv,
> options, usage, PARSE_OPT_STOP_AT_UNKNOWN);
> if (!argc)
> break;
> arg = argv[1];
> argv++;
> argc--;
> if (strcmp(arg, "-")) {
> .. handle <stdin> ..
> continue;
> }
> ...
>
> or whatever. See? Indeed, I read the thread many times, and I like the incremental
approach very much, it really makes sense, and we can easily migrate
code this way indeed. In fact that should have been the way
parse_options was designed from the beginning.
There is a bit of work to do from this "handwaved" solution, because
people care about the filtered argv, so one should rememeber some kind
of "writing" position. SOmething like:
parse_opt_ctx_t ctx;
/* will basically copy argc/argv */
parse_options_start(&ctx, argc, argv);
for (;;) {
const char *arg;
int res = parse_options_step(&ctx, options, usage, 0)); if (res == PARSE_OPT_HELP) {
/* generate help and exit */
}
if (res == PARSE_OPT_DONE)
break; arg = ctx->argv[ctx->pos++];
if (strcmp(arg, "-")) {
... handle <stdin>....
continue;
}
} argc = parse_options_end(&ctx);
/* at this point (argc,argv) is almost what parse_options would have
left us */ THis way, parse_options can be written:
parse_opt_ctx_t ctx;
parse_options_start(&ctx, argc, argv);
switch (parse_options_step(&ctx, options, usage, 0)) {
case PARSE_OPT_HELP: exit....
case PARSE_OPT_DONE: break;
default: exit(error("unknown option ....");
}
return parse_options_end(&ctx);