From 841068939a49153d682f15e8fefa1d950f7179c0 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 3 Sep 2013 16:14:33 +0200 Subject: [PATCH] Opt: Introduced contexts `struct opt_precomputed' was turning to a option parser context, so let's admit it. Renamed to `opt_context' and make it passed as the first argument. The name of `struct opt_precomputed_option' was a way too unwieldy, so I renamed it to `struct opt_precomputed'. Also got rid of several globals variables, but others remain. --- ucw/opt.c | 199 +++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 101 deletions(-) diff --git a/ucw/opt.c b/ucw/opt.c index d8e84a62..6bcbff02 100644 --- a/ucw/opt.c +++ b/ucw/opt.c @@ -18,9 +18,31 @@ #include #include +// FIXME: Do we need these? int opt_parsed_count = 0; int opt_conf_parsed_count = 0; +struct opt_precomputed { + struct opt_item * item; + const char * name; + short flags; + short count; +}; + +struct opt_context { + struct opt_precomputed ** opts; + struct opt_precomputed ** shortopt; + struct opt_item ** hooks_before_arg; + struct opt_item ** hooks_before_value; + struct opt_item ** hooks_after_value; + short opt_count; + short hooks_before_arg_count; + short hooks_before_value_count; + short hooks_after_value_count; + int positional_max; + int positional_count; +}; + static void opt_failure(const char * mesg, ...) FORMAT_CHECK(printf,1,2) NONRET; static void opt_failure(const char * mesg, ...) { va_list args; @@ -175,29 +197,8 @@ void opt_help_internal(const struct opt_section * help) { } } -static int opt_positional_max = 0; -static int opt_positional_count = 0; - -struct opt_precomputed { - struct opt_precomputed_option { - struct opt_precomputed *pre; - struct opt_item * item; - const char * name; - short flags; - short count; - } ** opts; - struct opt_precomputed_option ** shortopt; - struct opt_item ** hooks_before_arg; - struct opt_item ** hooks_before_value; - struct opt_item ** hooks_after_value; - short opt_count; - short hooks_before_arg_count; - short hooks_before_value_count; - short hooks_after_value_count; -}; - -static struct opt_precomputed_option * opt_find_item_shortopt(int chr, struct opt_precomputed * pre) { - struct opt_precomputed_option * candidate = pre->shortopt[chr]; +static struct opt_precomputed * opt_find_item_shortopt(struct opt_context * oc, int chr) { + struct opt_precomputed * candidate = oc->shortopt[chr]; if (!candidate) opt_failure("Invalid option -%c", chr); if (candidate->count++ && (candidate->flags & OPT_SINGLE)) @@ -205,36 +206,36 @@ static struct opt_precomputed_option * opt_find_item_shortopt(int chr, struct op return candidate; } -static struct opt_precomputed_option * opt_find_item_longopt(char * str, struct opt_precomputed * pre) { +static struct opt_precomputed * opt_find_item_longopt(struct opt_context * oc, char * str) { uns len = strlen(str); - struct opt_precomputed_option * candidate = NULL; + struct opt_precomputed * candidate = NULL; - for (int i=0; iopt_count; i++) { - if (!pre->opts[i]->name) + for (int i=0; iopt_count; i++) { + if (!oc->opts[i]->name) continue; - if (!strncmp(pre->opts[i]->name, str, len)) { - if (strlen(pre->opts[i]->name) == len) { - if (pre->opts[i]->count++ && (pre->opts[i]->flags & OPT_SINGLE)) - opt_failure("Option %s appeared the second time.", pre->opts[i]->name); + if (!strncmp(oc->opts[i]->name, str, len)) { + if (strlen(oc->opts[i]->name) == len) { + if (oc->opts[i]->count++ && (oc->opts[i]->flags & OPT_SINGLE)) + opt_failure("Option %s appeared the second time.", oc->opts[i]->name); - return pre->opts[i]; + return oc->opts[i]; } if (candidate) - opt_failure("Ambiguous prefix %s: Found matching %s and %s.", str, candidate->name, pre->opts[i]->name); + opt_failure("Ambiguous prefix %s: Found matching %s and %s.", str, candidate->name, oc->opts[i]->name); else - candidate = pre->opts[i]; + candidate = oc->opts[i]; } - if (!strncmp("no-", str, 3) && !strncmp(pre->opts[i]->name, str+3, len-3)) { - if (strlen(pre->opts[i]->name) == len-3) { - if (pre->opts[i]->count++ && (pre->opts[i]->flags & OPT_SINGLE)) - opt_failure("Option %s appeared the second time.", pre->opts[i]->name); + if (!strncmp("no-", str, 3) && !strncmp(oc->opts[i]->name, str+3, len-3)) { + if (strlen(oc->opts[i]->name) == len-3) { + if (oc->opts[i]->count++ && (oc->opts[i]->flags & OPT_SINGLE)) + opt_failure("Option %s appeared the second time.", oc->opts[i]->name); - return pre->opts[i]; + return oc->opts[i]; } if (candidate) - opt_failure("Ambiguous prefix %s: Found matching %s and %s.", str, candidate->name, pre->opts[i]->name); + opt_failure("Ambiguous prefix %s: Found matching %s and %s.", str, candidate->name, oc->opts[i]->name); else - candidate = pre->opts[i]; + candidate = oc->opts[i]; } } @@ -257,12 +258,11 @@ static struct opt_precomputed_option * opt_find_item_longopt(char * str, struct ptr = item->ptr; \ ptr; }) -#define OPT_NAME (longopt == 2 ? stk_printf("positional arg #%d", opt_positional_count) : (longopt == 1 ? stk_printf("--%s", opt->name) : stk_printf("-%c", item->letter))) -static void opt_parse_value(struct opt_precomputed_option * opt, char * value, int longopt) { +#define OPT_NAME (longopt == 2 ? stk_printf("positional arg #%d", oc->positional_count) : (longopt == 1 ? stk_printf("--%s", opt->name) : stk_printf("-%c", item->letter))) +static void opt_parse_value(struct opt_context * oc, struct opt_precomputed * opt, char * value, int longopt) { struct opt_item * item = opt->item; - struct opt_precomputed * pre = opt->pre; - for (int i=0;ihooks_before_value_count;i++) - pre->hooks_before_value[i]->u.call(item, value, pre->hooks_before_value[i]->ptr); + for (int i=0;ihooks_before_value_count;i++) + oc->hooks_before_value[i]->u.call(item, value, oc->hooks_before_value[i]->ptr); switch (item->cls) { case OPT_CL_BOOL: @@ -348,16 +348,16 @@ static void opt_parse_value(struct opt_precomputed_option * opt, char * value, i } opt_parsed_count++; - for (int i=0;ihooks_after_value_count;i++) - pre->hooks_after_value[i]->u.call(item, value, pre->hooks_after_value[i]->ptr); + for (int i=0;ihooks_after_value_count;i++) + oc->hooks_after_value[i]->u.call(item, value, oc->hooks_after_value[i]->ptr); } #undef OPT_NAME -static int opt_longopt(char ** argv, int index, struct opt_precomputed * pre) { +static int opt_longopt(struct opt_context * oc, char ** argv, int index) { int eaten = 0; char * name_in = argv[index] + 2; // skipping the -- on the beginning uns pos = strchrnul(name_in, '=') - name_in; - struct opt_precomputed_option * opt = opt_find_item_longopt(strndupa(name_in, pos), pre); + struct opt_precomputed * opt = opt_find_item_longopt(oc, strndupa(name_in, pos)); // FIXME: free? char * value = NULL; if (opt->item->cls == OPT_CL_BOOL && !strncmp(name_in, "no-", 3) && !strncmp(name_in+3, opt->item->name, pos-3)) @@ -380,20 +380,20 @@ static int opt_longopt(char ** argv, int index, struct opt_precomputed * pre) { if (pos < strlen(name_in)) opt_failure("Argument --%s must not have any value.", opt->name); } - opt_parse_value(opt, value, 1); + opt_parse_value(oc, opt, value, 1); return eaten; } -static int opt_shortopt(char ** argv, int index, struct opt_precomputed * pre) { +static int opt_shortopt(struct opt_context * oc, char ** argv, int index) { int chr = 0; - struct opt_precomputed_option * opt; - while (argv[index][++chr] && (opt = opt_find_item_shortopt(argv[index][chr], pre))) { + struct opt_precomputed * opt; + while (argv[index][++chr] && (opt = opt_find_item_shortopt(oc, argv[index][chr]))) { if (opt->flags & OPT_NO_VALUE) { - opt_parse_value(opt, NULL, 0); + opt_parse_value(oc, opt, NULL, 0); } else if (opt->flags & OPT_REQUIRED_VALUE) { if (chr == 1 && argv[index][2]) { - opt_parse_value(opt, argv[index] + 2, 0); + opt_parse_value(oc, opt, argv[index] + 2, 0); return 0; } else if (argv[index][chr+1]) @@ -401,17 +401,17 @@ static int opt_shortopt(char ** argv, int index, struct opt_precomputed * pre) { else if (!argv[index+1]) opt_failure("Option -%c must have a value but nothing supplied.", opt->item->letter); else { - opt_parse_value(opt, argv[index+1], 0); + opt_parse_value(oc, opt, argv[index+1], 0); return 1; } } else if (opt->flags & OPT_MAYBE_VALUE) { if (chr == 1 && argv[index][2]) { - opt_parse_value(opt, argv[index] + 2, 0); + opt_parse_value(oc, opt, argv[index] + 2, 0); return 0; } else - opt_parse_value(opt, NULL, 0); + opt_parse_value(oc, opt, NULL, 0); } else { ASSERT(0); @@ -424,15 +424,15 @@ static int opt_shortopt(char ** argv, int index, struct opt_precomputed * pre) { return 0; } -static void opt_positional(char * value, struct opt_precomputed * pre) { - opt_positional_count++; - struct opt_precomputed_option * opt = opt_find_item_shortopt((opt_positional_count > opt_positional_max ? 256 : opt_positional_count + 256), pre); +static void opt_positional(struct opt_context * oc, char * value) { + oc->positional_count++; + struct opt_precomputed * opt = opt_find_item_shortopt(oc, (oc->positional_count > oc->positional_max ? 256 : oc->positional_count + 256)); if (!opt) { - ASSERT(opt_positional_count > opt_positional_max); + ASSERT(oc->positional_count > oc->positional_max); opt_failure("Too many positional args."); } - opt_parse_value(opt, value, 2); + opt_parse_value(oc, opt, value, 2); } #define OPT_TRAVERSE_SECTIONS \ @@ -456,8 +456,6 @@ static void opt_positional(char * value, struct opt_precomputed * pre) { } void opt_parse(const struct opt_section * options, char ** argv) { - opt_section_root = options; - struct opt_stack { struct opt_item * this; struct opt_stack * prev; @@ -467,8 +465,8 @@ void opt_parse(const struct opt_section * options, char ** argv) { stk->prev = NULL; stk->next = NULL; - struct opt_precomputed * pre = alloca(sizeof(*pre)); - memset(pre, 0, sizeof (*pre)); + struct opt_context * oc = alloca(sizeof(*oc)); + memset(oc, 0, sizeof (*oc)); int count = 0; int hooks = 0; @@ -480,45 +478,44 @@ void opt_parse(const struct opt_section * options, char ** argv) { if (item->cls == OPT_CL_BOOL) count++; if (item->letter > 256) - opt_positional_max++; + oc->positional_max++; if (item->cls == OPT_CL_HOOK) hooks++; } - pre->opts = alloca(sizeof(*pre->opts) * count); - pre->shortopt = alloca(sizeof(*pre->shortopt) * (opt_positional_max + 257)); - memset(pre->shortopt, 0, sizeof(*pre->shortopt) * (opt_positional_max + 257)); - pre->hooks_before_arg = alloca(sizeof (*pre->hooks_before_arg) * hooks); - pre->hooks_before_value = alloca(sizeof (*pre->hooks_before_value) * hooks); - pre->hooks_after_value = alloca(sizeof (*pre->hooks_after_value) * hooks); + oc->opts = alloca(sizeof(*oc->opts) * count); + oc->shortopt = alloca(sizeof(*oc->shortopt) * (oc->positional_max + 257)); + memset(oc->shortopt, 0, sizeof(*oc->shortopt) * (oc->positional_max + 257)); + oc->hooks_before_arg = alloca(sizeof (*oc->hooks_before_arg) * hooks); + oc->hooks_before_value = alloca(sizeof (*oc->hooks_before_value) * hooks); + oc->hooks_after_value = alloca(sizeof (*oc->hooks_after_value) * hooks); - pre->hooks_before_arg_count = 0; - pre->hooks_before_value_count = 0; - pre->hooks_after_value_count = 0; + oc->hooks_before_arg_count = 0; + oc->hooks_before_value_count = 0; + oc->hooks_after_value_count = 0; - pre->opt_count = 0; + oc->opt_count = 0; for (struct opt_item * item = options->opt; ; item++) { OPT_TRAVERSE_SECTIONS; if (item->letter || item->name) { - struct opt_precomputed_option * opt = xmalloc(sizeof(*opt)); - opt->pre = pre; + struct opt_precomputed * opt = xmalloc(sizeof(*opt)); opt->item = item; opt->flags = item->flags; opt->count = 0; opt->name = item->name; - pre->opts[pre->opt_count++] = opt; + oc->opts[oc->opt_count++] = opt; if (item->letter) - pre->shortopt[(int) item->letter] = opt; + oc->shortopt[(int) item->letter] = opt; OPT_ADD_DEFAULT_ITEM_FLAGS(item, opt->flags); } if (item->cls == OPT_CL_HOOK) { if (item->flags & OPT_HOOK_BEFORE_ARG) - pre->hooks_before_arg[pre->hooks_before_arg_count++] = item; + oc->hooks_before_arg[oc->hooks_before_arg_count++] = item; else if (item->flags & OPT_HOOK_BEFORE_VALUE) - pre->hooks_before_value[pre->hooks_before_value_count++] = item; + oc->hooks_before_value[oc->hooks_before_value_count++] = item; else if (item->flags & OPT_HOOK_AFTER_VALUE) - pre->hooks_after_value[pre->hooks_after_value_count++] = item; + oc->hooks_after_value[oc->hooks_after_value_count++] = item; else ASSERT(0); } @@ -526,40 +523,40 @@ void opt_parse(const struct opt_section * options, char ** argv) { int force_positional = 0; for (int i=0;argv[i];i++) { - for (int j=0;jhooks_before_arg_count;j++) - pre->hooks_before_arg[j]->u.call(NULL, NULL, pre->hooks_before_arg[j]->ptr); + for (int j=0;jhooks_before_arg_count;j++) + oc->hooks_before_arg[j]->u.call(NULL, NULL, oc->hooks_before_arg[j]->ptr); if (argv[i][0] != '-' || force_positional) { - opt_positional(argv[i], pre); + opt_positional(oc, argv[i]); } else { if (argv[i][1] == '-') { if (argv[i][2] == '\0') force_positional++; else - i += opt_longopt(argv, i, pre); + i += opt_longopt(oc, argv, i); } else if (argv[i][1]) - i += opt_shortopt(argv, i, pre); + i += opt_shortopt(oc, argv, i); else - opt_positional(argv[i], pre); + opt_positional(oc, argv[i]); } } - for (int i=0;ishortopt[i]) + for (int i=0;ipositional_max+257;i++) { + if (!oc->shortopt[i]) continue; - if (!pre->shortopt[i]->count && (pre->shortopt[i]->flags & OPT_REQUIRED)) + if (!oc->shortopt[i]->count && (oc->shortopt[i]->flags & OPT_REQUIRED)) if (i < 256) - opt_failure("Required option -%c not found.", pre->shortopt[i]->item->letter); + opt_failure("Required option -%c not found.", oc->shortopt[i]->item->letter); else - opt_failure("Required positional argument #%d not found.", (i > 256) ? pre->shortopt[i]->item->letter-256 : opt_positional_max+1); + opt_failure("Required positional argument #%d not found.", (i > 256) ? oc->shortopt[i]->item->letter-256 : oc->positional_max+1); } - for (int i=0;iopt_count;i++) { - if (!pre->opts[i]) + for (int i=0;iopt_count;i++) { + if (!oc->opts[i]) continue; - if (!pre->opts[i]->count && (pre->opts[i]->flags & OPT_REQUIRED)) - opt_failure("Required option --%s not found.", pre->opts[i]->item->name); + if (!oc->opts[i]->count && (oc->opts[i]->flags & OPT_REQUIRED)) + opt_failure("Required option --%s not found.", oc->opts[i]->item->name); } } -- 2.39.2