From: Martin Mares Date: Mon, 27 Jan 2014 19:59:02 +0000 (+0100) Subject: Opt: OPT_HELP_OPTION does not need passing pointer to current definitions X-Git-Tag: v5.99~25^2~3 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=beffdda5bfe844b0db22eb6e6c393b396a4f13f1;p=libucw.git Opt: OPT_HELP_OPTION does not need passing pointer to current definitions I have introduced a new flag OPT_INTERNAL / OPT_HOOK_INTERNAL, which can be used by internal handlers and hooks to get the pointer to the current opt_context. --- diff --git a/ucw/opt-help.c b/ucw/opt-help.c index c69c22d3..4166cc5f 100644 --- a/ucw/opt-help.c +++ b/ucw/opt-help.c @@ -160,6 +160,7 @@ void opt_help(const struct opt_section * sec) { void opt_handle_help(struct opt_item * opt UNUSED, const char * value UNUSED, void * data) { - opt_help(data); + struct opt_context *oc = data; + opt_help(oc->options); exit(0); } diff --git a/ucw/opt-internal.h b/ucw/opt-internal.h index 54717b39..0ac2a773 100644 --- a/ucw/opt-internal.h +++ b/ucw/opt-internal.h @@ -15,6 +15,18 @@ #define opt_precompute ucw_opt_precompute #endif +struct opt_context { + const struct opt_section * options; + struct opt_precomputed * opts; + struct opt_precomputed ** shortopt; + struct opt_item ** hooks; + int opt_count; + int hook_count; + int positional_max; + int positional_count; + bool stop_parsing; +}; + struct opt_precomputed { struct opt_item * item; const char * name; diff --git a/ucw/opt-test.c b/ucw/opt-test.c index 66f95ea1..408464d6 100644 --- a/ucw/opt-test.c +++ b/ucw/opt-test.c @@ -124,7 +124,7 @@ static struct opt_section help = { OPT_HELP("At least one kind of tea must be specified."), OPT_HELP(""), OPT_HELP("Options:"), - OPT_HELP_OPTION(help), + OPT_HELP_OPTION, OPT_CALL('V', "version", show_version, NULL, OPT_NO_VALUE, "\tShow the version"), OPT_HELP(""), OPT_BOOL('e', "english-style", english, 0, "\tEnglish style (with milk)"), diff --git a/ucw/opt.c b/ucw/opt.c index 0135652c..c0986aa7 100644 --- a/ucw/opt.c +++ b/ucw/opt.c @@ -37,17 +37,6 @@ static uns opt_default_value_flags[] = { [OPT_CL_HELP] = 0 }; -struct opt_context { - struct opt_precomputed * opts; - struct opt_precomputed ** shortopt; - struct opt_item ** hooks; - int opt_count; - int hook_count; - int positional_max; - int positional_count; - bool stop_parsing; -}; - void opt_failure(const char * mesg, ...) { va_list args; va_start(args, mesg); @@ -94,8 +83,10 @@ static void opt_invoke_hooks(struct opt_context *oc, uns event, struct opt_item { for (int i = 0; i < oc->hook_count; i++) { struct opt_item *hook = oc->hooks[i]; - if (hook->flags & event) - hook->u.hook(item, event, value, hook->ptr); + if (hook->flags & event) { + void *data = (hook->flags & OPT_HOOK_INTERNAL) ? oc : hook->ptr; + hook->u.hook(item, event, value, data); + } } } @@ -223,8 +214,11 @@ static void opt_parse_value(struct opt_context * oc, struct opt_precomputed * op (*((int *)item->ptr))++; break; case OPT_CL_CALL: - item->u.call(item, value, item->ptr); - break; + { + void *data = (opt->flags & OPT_INTERNAL) ? oc : item->ptr; + item->u.call(item, value, data); + break; + } case OPT_CL_USER: { char * e = NULL; @@ -380,6 +374,7 @@ static void opt_check_required(struct opt_context *oc) int opt_parse(const struct opt_section * options, char ** argv) { struct opt_context * oc = alloca(sizeof(*oc)); memset(oc, 0, sizeof (*oc)); + oc->options = options; opt_count_items(oc, options); oc->opts = alloca(sizeof(*oc->opts) * oc->opt_count); diff --git a/ucw/opt.h b/ucw/opt.h index aa9166e9..ae0b53d0 100644 --- a/ucw/opt.h +++ b/ucw/opt.h @@ -95,7 +95,7 @@ struct opt_section { * ***/ -#define OPT_HELP_OPTION(help) OPT_CALL(0, "help", opt_handle_help, &help, OPT_BEFORE_CONFIG | OPT_NO_VALUE, "\tShow this help") +#define OPT_HELP_OPTION OPT_CALL(0, "help", opt_handle_help, NULL, OPT_BEFORE_CONFIG | OPT_INTERNAL | OPT_NO_VALUE, "\tShow this help") #define OPT_HELP(line) { .help = line, .cls = OPT_CL_HELP } #define OPT_BOOL(shortopt, longopt, target, fl, desc) { .letter = shortopt, .name = longopt, .ptr = &target, .help = desc, .flags = fl, .cls = OPT_CL_BOOL, .type = CT_INT } #define OPT_STRING(shortopt, longopt, target, fl, desc) { .letter = shortopt, .name = longopt, .ptr = &target, .help = desc, .flags = fl, .cls = OPT_CL_STATIC, .type = CT_STRING } @@ -129,10 +129,10 @@ struct opt_section { #define OPT_CONF_OPTIONS OPT_CONF_CONFIG, OPT_CONF_SET, OPT_CONF_HOOK #endif -#define OPT_CONF_CONFIG OPT_CALL('C', "config", opt_handle_config, NULL, OPT_BEFORE_CONFIG | OPT_REQUIRED_VALUE, "\tOverride the default configuration file") -#define OPT_CONF_SET OPT_CALL('S', "set", opt_handle_set, NULL, OPT_BEFORE_CONFIG | OPT_REQUIRED_VALUE, "\tManual setting of a configuration item") -#define OPT_CONF_DUMPCONFIG OPT_CALL(0, "dumpconfig", opt_handle_dumpconfig, NULL, OPT_NO_VALUE, "\tDump program configuration") -#define OPT_CONF_HOOK OPT_HOOK(opt_conf_hook_internal, NULL, OPT_HOOK_BEFORE_VALUE | OPT_HOOK_FINAL) +#define OPT_CONF_CONFIG OPT_CALL('C', "config", opt_handle_config, NULL, OPT_BEFORE_CONFIG | OPT_INTERNAL | OPT_REQUIRED_VALUE, "\tOverride the default configuration file") +#define OPT_CONF_SET OPT_CALL('S', "set", opt_handle_set, NULL, OPT_BEFORE_CONFIG | OPT_INTERNAL | OPT_REQUIRED_VALUE, "\tManual setting of a configuration item") +#define OPT_CONF_DUMPCONFIG OPT_CALL(0, "dumpconfig", opt_handle_dumpconfig, NULL, OPT_INTERNAL | OPT_NO_VALUE, "\tDump program configuration") +#define OPT_CONF_HOOK OPT_HOOK(opt_conf_hook_internal, NULL, OPT_HOOK_BEFORE_VALUE | OPT_HOOK_FINAL | OPT_HOOK_INTERNAL) void opt_handle_config(struct opt_item * opt, const char * value, void * data); void opt_handle_set(struct opt_item * opt, const char * value, void * data); @@ -185,14 +185,16 @@ extern char *cf_env_file; #define OPT_LAST_ARG 0x40 /** Stop processing argv after this line **/ #define OPT_SINGLE 0x100 /** Argument must appear at most once **/ #define OPT_MULTIPLE 0x200 /** Argument may appear any time; will save all the values into a simple list **/ -#define OPT_SEEN_AS_LONG 0x400 // Used internally +#define OPT_SEEN_AS_LONG 0x400 // Used internally to signal that we currently process the long form of the option #define OPT_BEFORE_CONFIG 0x800 /** Argument may appear before config file is loaded **/ +#define OPT_INTERNAL 0x4000 // Used internally to ask for passing of struct opt_context to OPT_CALL // For hooks, the flags contain a combination of events. #define OPT_HOOK_BEFORE_ARG 0x1 /** Call before option parsing **/ #define OPT_HOOK_BEFORE_VALUE 0x2 /** Call before value parsing **/ #define OPT_HOOK_AFTER_VALUE 0x4 /** Call after value parsing **/ #define OPT_HOOK_FINAL 0x8 /** Call just before opt_parse() returns **/ +#define OPT_HOOK_INTERNAL 0x4000 // Used internally to ask for passing of struct opt_context void opt_failure(const char * mesg, ...) FORMAT_CHECK(printf,1,2) NONRET; void opt_help(const struct opt_section * sec);