]> mj.ucw.cz Git - libucw.git/commitdiff
Opt: OPT_HELP_OPTION does not need passing pointer to current definitions
authorMartin Mares <mj@ucw.cz>
Mon, 27 Jan 2014 19:59:02 +0000 (20:59 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 27 Jan 2014 19:59:02 +0000 (20:59 +0100)
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.

ucw/opt-help.c
ucw/opt-internal.h
ucw/opt-test.c
ucw/opt.c
ucw/opt.h

index c69c22d360e6f55b498acf0f396360ad01fd36c2..4166cc5f717e627e41e993b0a7e7d53dd83f5885 100644 (file)
@@ -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);
 }
index 54717b3952addc13425795ec05c1d3dd9a404d9d..0ac2a77324f05e0998923f69a17e155156931d41 100644 (file)
 #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;
index 66f95ea15e7fbbabdf415871ed413095036f298f..408464d6c217b98cfee53fff28f1cfc98db76815 100644 (file)
@@ -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)"),
index 0135652cc9dee1817a36bff48789bb11b61cf63f..c0986aa736075a4ceb8837d09581df2a828c6ac7 100644 (file)
--- 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);
index aa9166e98d48e5e9a9b155a205b5651a9f28f3c2..ae0b53d01ed3352bb4c8d89f0eb6322f762c2c80 100644 (file)
--- 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, "<file>\tOverride the default configuration file")
-#define OPT_CONF_SET       OPT_CALL('S', "set", opt_handle_set, NULL, OPT_BEFORE_CONFIG | OPT_REQUIRED_VALUE, "<item>\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, "<file>\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, "<item>\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);