From ac5c029143b60498116adbea326eb7b3ce6fa160 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 27 Jan 2014 19:38:25 +0100 Subject: [PATCH] Opt: Make OPT_LAST_ARG actually work and document interface of opt_parse() --- ucw/opt.c | 11 +++++++++-- ucw/opt.h | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ucw/opt.c b/ucw/opt.c index edbd5223..2552efce 100644 --- a/ucw/opt.c +++ b/ucw/opt.c @@ -16,6 +16,7 @@ #include #include +#include /*** * Value flags defaults @@ -49,6 +50,7 @@ struct opt_context { short hooks_after_value_count; int positional_max; int positional_count; + bool stop_parsing; }; void opt_failure(const char * mesg, ...) { @@ -144,6 +146,9 @@ static void opt_parse_value(struct opt_context * oc, struct opt_precomputed * op if (opt->count++ && (opt->flags & OPT_SINGLE)) opt_failure("Option %s must be specified at most once.", THIS_OPT); + if (opt->flags & OPT_LAST_ARG) + oc->stop_parsing = 1; + for (int i = 0; i < oc->hooks_before_value_count; i++) oc->hooks_before_value[i]->u.call(item, value, oc->hooks_before_value[i]->ptr); @@ -385,7 +390,7 @@ static void opt_check_required(struct opt_context *oc) } } -void opt_parse(const struct opt_section * options, char ** argv) { +int opt_parse(const struct opt_section * options, char ** argv) { struct opt_context * oc = alloca(sizeof(*oc)); memset(oc, 0, sizeof (*oc)); @@ -404,7 +409,8 @@ void opt_parse(const struct opt_section * options, char ** argv) { opt_prepare_items(oc, options); int force_positional = 0; - for (int i = 0; argv[i]; i++) { + int i; + for (i=0; argv[i] && !oc->stop_parsing; i++) { char *arg = argv[i]; for (int j = 0; j < oc->hooks_before_arg_count; j++) oc->hooks_before_arg[j]->u.call(NULL, NULL, oc->hooks_before_arg[j]->ptr); @@ -424,4 +430,5 @@ void opt_parse(const struct opt_section * options, char ** argv) { } opt_check_required(oc); + return i; } diff --git a/ucw/opt.h b/ucw/opt.h index c50bac00..0ae88e97 100644 --- a/ucw/opt.h +++ b/ucw/opt.h @@ -183,10 +183,18 @@ static inline void opt_show_help_internal(struct opt_item * opt UNUSED, const ch } /** - * Parse all the arguments. + * Parse all arguments, given in a NULL-terminated array of strings. + * + * Typically, this is called from `main(argc, argv)` as `opt_parse(options, argv+1)`, + * skipping the 0th argument, which contains program name. + * + * Returns the number of arguments used (which need not be all of them + * if `OPT_LAST_ARG` was encountered). + * + * The argument array is left untouched. + * However, option values are not necessarily copied, the variables + * set by the parser may point to the argument array. **/ -void opt_parse(const struct opt_section * options, char ** argv); -// FIXME: When parsing finishes (possibly due to OPT_LAST_ARG), what is guaranteed -// about the state of argv[]? +int opt_parse(const struct opt_section * options, char ** argv); #endif -- 2.39.2