From: Martin Mares Date: Mon, 27 Jan 2014 19:05:15 +0000 (+0100) Subject: Opt: Cleaned up opt-conf X-Git-Tag: v5.99~25^2~8 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=924caf6f42990dc99c1d7e4a954da1533e37e537;p=libucw.git Opt: Cleaned up opt-conf First of all, the names of configuration options are no longer fixed. Each of these options has its own handler and as long as OPT_CONF_HOOK is used, the caller is free to define configuration options with the names and help texts of his choice. The same applies to --help. To achieve these goals, the OPT_BEFORE_CONFIG flag has been introduced. --- diff --git a/tools/libucw.api b/tools/libucw.api index 1690b67c..80b2472a 100644 --- a/tools/libucw.api +++ b/tools/libucw.api @@ -385,10 +385,14 @@ mp_vprintf_append opt_failure opt_precompute # ucw/opt.h -opt_conf_internal +opt_handle_config +opt_handle_set +opt_handle_dumpconfig opt_conf_hook_internal -opt_section_root +cf_def_file +cf_env_file opt_help +opt_handle_help opt_parse # ucw/partmap.h partmap_open diff --git a/ucw/opt-conf.c b/ucw/opt-conf.c index 780c8747..d306db98 100644 --- a/ucw/opt-conf.c +++ b/ucw/opt-conf.c @@ -17,6 +17,7 @@ #include #include +#include static void opt_conf_end_of_options(struct cf_context *cc) { cf_load_default(cc); @@ -24,28 +25,28 @@ static void opt_conf_end_of_options(struct cf_context *cc) { opt_failure("Loading of configuration failed"); } -void opt_conf_internal(struct opt_item * opt, const char * value, void * data UNUSED) { +void opt_handle_config(struct opt_item * opt UNUSED, const char * value, void * data UNUSED) +{ + if (cf_load(value)) + exit(1); // Error message is already printed by cf_load() +} + +void opt_handle_set(struct opt_item * opt UNUSED, const char * value, void * data UNUSED) +{ struct cf_context *cc = cf_get_context(); - switch (opt->letter) { - case 'S': - cf_load_default(cc); - if (cf_set(value)) - opt_failure("Cannot set %s", value); - break; - case 'C': - if (cf_load(value)) - opt_failure("Cannot load config file %s", value); - break; -#ifdef CONFIG_UCW_DEBUG - case '0': - opt_conf_end_of_options(cc); - struct fastbuf *b = bfdopen(1, 4096); - cf_dump_sections(b); - bclose(b); - exit(0); - break; -#endif - } + cf_load_default(cc); + if (cf_set(value)) + opt_failure("Cannot set %s", value); +} + +void opt_handle_dumpconfig(struct opt_item * opt UNUSED, const char * value UNUSED, void * data UNUSED) +{ + struct cf_context *cc = cf_get_context(); + opt_conf_end_of_options(cc); + struct fastbuf *b = bfdopen(1, 4096); + cf_dump_sections(b); + bclose(b); + exit(0); } void opt_conf_hook_internal(struct opt_item * opt, const char * value UNUSED, void * data UNUSED) { @@ -55,10 +56,7 @@ void opt_conf_hook_internal(struct opt_item * opt, const char * value UNUSED, vo OPT_CONF_HOOK_OTHERS } state = OPT_CONF_HOOK_BEGIN; - int confopt = 0; - - if (opt->letter == 'S' || opt->letter == 'C' || (opt->name && !strcmp(opt->name, "dumpconfig"))) - confopt = 1; + bool confopt = opt->flags & OPT_BEFORE_CONFIG; switch (state) { case OPT_CONF_HOOK_BEGIN: @@ -77,7 +75,7 @@ void opt_conf_hook_internal(struct opt_item * opt, const char * value UNUSED, vo break; case OPT_CONF_HOOK_OTHERS: if (confopt) - opt_failure("Config options (-C, -S) must stand before other options."); + opt_failure("Config options must stand before other options."); break; default: ASSERT(0); diff --git a/ucw/opt-help.c b/ucw/opt-help.c index 83b39835..5c4b44e8 100644 --- a/ucw/opt-help.c +++ b/ucw/opt-help.c @@ -156,3 +156,8 @@ void opt_help(const struct opt_section * sec) { mp_delete(h.pool); } +void opt_handle_help(struct opt_item * opt UNUSED, const char * value UNUSED, void * data) +{ + opt_help(data); + exit(0); +} diff --git a/ucw/opt-test.c b/ucw/opt-test.c index f7e7fa02..a7117460 100644 --- a/ucw/opt-test.c +++ b/ucw/opt-test.c @@ -151,6 +151,8 @@ static struct opt_section help = { OPT_HOOK(opt_test_hook, "preval", OPT_HOOK_BEFORE_VALUE), OPT_HOOK(opt_test_hook, "postval", OPT_HOOK_AFTER_VALUE), OPT_BOOL('H', "show-hooks", show_hooks, 0, "\tDemonstrate the hooks."), + OPT_HELP(""), + OPT_HELP("Configuration options:"), OPT_CONF_OPTIONS, OPT_END } @@ -163,6 +165,7 @@ struct intnode { int main(int argc UNUSED, char ** argv) { + cf_def_file = "etc/libucw"; clist_init(&black_magic); opt_parse(&help, argv+1); diff --git a/ucw/opt.h b/ucw/opt.h index 0ae88e97..f9332b86 100644 --- a/ucw/opt.h +++ b/ucw/opt.h @@ -18,11 +18,15 @@ #include #ifdef CONFIG_UCW_CLEAN_ABI +#define cf_def_file ucw_cf_def_file +#define cf_env_file ucw_cf_env_file #define opt_conf_hook_internal ucw_opt_conf_hook_internal -#define opt_conf_internal ucw_opt_conf_internal +#define opt_handle_config ucw_opt_handle_config +#define opt_handle_dumpconfig ucw_opt_handle_dumpconfig +#define opt_handle_help ucw_opt_handle_help +#define opt_handle_set ucw_opt_handle_set #define opt_help ucw_opt_help #define opt_parse ucw_opt_parse -#define opt_section_root ucw_opt_section_root #endif #define OPT_EXIT_BAD_ARGS 2 @@ -89,7 +93,7 @@ struct opt_section { * ***/ -#define OPT_HELP_OPTION(help) OPT_CALL(0, "help", opt_show_help_internal, &help, OPT_NO_VALUE, "\tShow this help") +#define OPT_HELP_OPTION(help) OPT_CALL(0, "help", opt_handle_help, &help, 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 } @@ -123,14 +127,28 @@ 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_conf_internal, NULL, OPT_REQUIRED_VALUE, "\tOverride the default configuration file") -#define OPT_CONF_SET OPT_CALL('S', "set", opt_conf_internal, NULL, OPT_REQUIRED_VALUE, "\tManual setting of a configuration item") -#define OPT_CONF_DUMPCONFIG OPT_CALL(0, "dumpconfig", opt_conf_internal, NULL, OPT_NO_VALUE, "\tDump program configuration") +#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) -void opt_conf_internal(struct opt_item * opt, const char * value, void * data); +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); +void opt_handle_dumpconfig(struct opt_item * opt, const char * value, void * data); void opt_conf_hook_internal(struct opt_item * opt, const char * value, void * data); +// XXX: This is duplicated with , but that one will hopefully go away one day. +/** + * The default config (as set by `CONFIG_UCW_DEFAULT_CONFIG`) or NULL if already loaded. + * You can set it to something else manually. + */ +extern char *cf_def_file; +/** + * Name of environment variable that can override what configuration is loaded. + * Defaults to `CONFIG_UCW_ENV_VAR_CONFIG`. + **/ +extern char *cf_env_file; + /*** * Predefined shortopt arguments * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -166,22 +184,19 @@ void opt_conf_hook_internal(struct opt_item * opt, const char * value, void * da #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_BEFORE_CONFIG 0x800 /** Argument may appear before config file is loaded **/ #define OPT_HOOK_BEFORE_ARG 0x1000 /** Call before option parsing **/ #define OPT_HOOK_BEFORE_VALUE 0x2000 /** Call before value parsing **/ #define OPT_HOOK_AFTER_VALUE 0x4000 /** Call after value parsing **/ -extern const struct opt_section * opt_section_root; void opt_help(const struct opt_section * sec); +void opt_handle_help(struct opt_item * opt, const char * value, void * data); +// FIXME: Should this be public? static inline void opt_usage(void) { fprintf(stderr, "Run with argument --help for more information.\n"); } -static inline void opt_show_help_internal(struct opt_item * opt UNUSED, const char * value UNUSED, void * data) { - opt_help(data); - exit(0); -} - /** * Parse all arguments, given in a NULL-terminated array of strings. * diff --git a/ucw/opt.t b/ucw/opt.t index aeafd199..4d4f7f58 100644 --- a/ucw/opt.t +++ b/ucw/opt.t @@ -33,9 +33,9 @@ Run: ../obj/ucw/opt-test -t120F -w4 -b15 -b54 -he -- --puerh darjeeling earl-gre Out: English style: yes|Chosen teapot: hands|Temperature: 120F|Verbosity: 1|Black magic: 15|Black magic: 54|Prayer: no|Water amount: 4|Gas: no|First tea: --puerh|Boiling a tea: darjeeling|Boiling a tea: earl-grey|Everything OK. Bye. Name: Opt-Conf-1 -Run: ../obj/ucw/opt-test -h --dumpconfig 2>&1 1>/dev/null +Run: ../obj/ucw/opt-test -h -SX.Y=Z 2>&1 1>/dev/null Exit: 2 -Out: Config options (-C, -S) must stand before other options. +Out: Config options must stand before other options. Run with argument --help for more information. Name: Opt-Hook-1