On Mon, Jun 23, 2008 at 04:25:10PM +0000, Linus Torvalds wrote: > > > 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); -- ·O· Pierre Habouzit ··O madcoder@xxxxxxxxxx OOO http://www.madism.org
Attachment:
pgpczOdrkmBMB.pgp
Description: PGP signature