From 564be9c0adf9f5796b60f2727cecc9c7274f86ff Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Fri, 27 Jun 2014 17:27:25 +0200 Subject: [PATCH] Opt: Added OPT_BREAK This is useful for programs, which wish to process all their positional arguments by themselves without having to copy them to a different data structure. For example, this frequently happens with programs which have sub-commands. --- ucw/opt-internal.h | 2 +- ucw/opt.c | 8 ++++++-- ucw/opt.h | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ucw/opt-internal.h b/ucw/opt-internal.h index 99514c29..21c67a6e 100644 --- a/ucw/opt-internal.h +++ b/ucw/opt-internal.h @@ -30,7 +30,7 @@ struct opt_context { int hook_count; int positional_max; int positional_count; - bool stop_parsing; + int stop_parsing; enum opt_conf_state conf_state; }; diff --git a/ucw/opt.c b/ucw/opt.c index e8d7cbee..713ee784 100644 --- a/ucw/opt.c +++ b/ucw/opt.c @@ -225,6 +225,9 @@ static void opt_parse_value(struct opt_context * oc, struct opt_precomputed * op item->u.call(item, value, data); break; } + case OPT_CL_BREAK: + oc->stop_parsing = 2; + break; default: ASSERT(0); } @@ -388,8 +391,9 @@ int opt_parse(const struct opt_section * options, char ** argv) { opt_prepare_items(oc, options); int force_positional = 0; - int i; + int i, start_i = 0; for (i=0; argv[i] && !oc->stop_parsing; i++) { + start_i = i; char *arg = argv[i]; opt_invoke_hooks(oc, OPT_HOOK_BEFORE_ARG, NULL, NULL); if (arg[0] != '-' || force_positional) @@ -409,5 +413,5 @@ int opt_parse(const struct opt_section * options, char ** argv) { opt_check_required(oc); opt_invoke_hooks(oc, OPT_HOOK_FINAL, NULL, NULL); - return i; + return (oc->stop_parsing < 2 ? i : start_i); } diff --git a/ucw/opt.h b/ucw/opt.h index 695f607e..3f1be812 100644 --- a/ucw/opt.h +++ b/ucw/opt.h @@ -63,6 +63,8 @@ * contents of another list of options. * - `OPT_CL_HELP`: no option, just print a help text. * - `OPT_CL_HOOK`: no option, but a definition of a <>. + * - `OPT_CL_BREAK`: when a given option occurs, stop parsing and keep + * the option in the argument list. ***/ enum opt_class { @@ -76,6 +78,7 @@ enum opt_class { OPT_CL_SECTION, OPT_CL_HELP, OPT_CL_HOOK, + OPT_CL_BREAK, }; /*** @@ -206,6 +209,9 @@ struct opt_item { /** Incrementing option. @target should be a variable of type `int`. **/ #define OPT_INC(shortopt, longopt, target, fl, desc) { .letter = shortopt, .name = longopt, .ptr = CHECK_PTR_TYPE(&target, int *), .flags = fl, .help = desc, .cls = OPT_CL_INC, .type = CT_INT } +/** Breakpoint option. When this option occurs, parsing is terminated and the option is kept in the argument array. **/ +#define OPT_BREAK(shortopt, longopt, fl) { .letter = shortopt, .name = longopt, .flags = fl, .cls = OPT_CL_BREAK } + /* FIXME: Backwards compatibility only, should not be used anymore. */ #define OPT_UNS OPT_UINT #define OPT_UNS_MULTIPLE OPT_UINT_MULTIPLE -- 2.39.2