opt: allow const arguments.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 22 Mar 2011 01:18:43 +0000 (11:48 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 22 Mar 2011 01:18:43 +0000 (11:48 +1030)
This need shows up most clearly with opt_usage_and_exit and gcc's
-Wwrite-strings, where string literals become "const char *".  Our
callbacks should take const void *: since we overload the arg field
already (to hold table size) it make sense to turn it into a proper
union.

ccan/opt/opt.c
ccan/opt/opt.h
ccan/opt/parse.c
ccan/opt/test/compile_ok-const-arg.c [new file with mode: 0644]
ccan/opt/usage.c

index f05d125fc828dda1e647a49788d5ccb1ac5b5d05..827109e34074f0edc33226f8157ab31bd27bd70c 100644 (file)
@@ -150,7 +150,7 @@ void _opt_register(const char *names, enum opt_type type,
                   char *(*cb)(void *arg),
                   char *(*cb_arg)(const char *optarg, void *arg),
                   void (*show)(char buf[OPT_SHOW_LEN], const void *arg),
-                  void *arg, const char *desc)
+                  const void *arg, const char *desc)
 {
        struct opt_table opt;
        opt.names = names;
@@ -158,7 +158,7 @@ void _opt_register(const char *names, enum opt_type type,
        opt.cb = cb;
        opt.cb_arg = cb_arg;
        opt.show = show;
-       opt.arg = arg;
+       opt.u.carg = arg;
        opt.desc = desc;
        check_opt(&opt);
        add_opt(&opt);
@@ -183,7 +183,7 @@ void opt_register_table(const struct opt_table entry[], const char *desc)
        }
        /* We store the table length in arg ptr. */
        if (desc)
-               opt_table[start].arg = (void *)(intptr_t)(opt_count - start);
+               opt_table[start].u.tlen = (opt_count - start);
 }
 
 /* Parse your arguments. */
index 812fec869aeba311d27e0dd4844ab34d862a9958..539a0a664de155962f3d2efdf116eca52d25fcee 100644 (file)
@@ -30,7 +30,7 @@ struct opt_table;
  *     OPT_WITH_ARG()
  */
 #define OPT_WITHOUT_ARG(names, cb, arg, desc)  \
-       { (names), OPT_CB_NOARG((cb), (arg)), (desc) }
+       { (names), OPT_CB_NOARG((cb), (arg)), { (arg) }, (desc) }
 
 /**
  * OPT_WITH_ARG() - macro for initializing long and short option (with arg)
@@ -65,7 +65,7 @@ struct opt_table;
  *     OPT_WITHOUT_ARG()
  */
 #define OPT_WITH_ARG(name, cb, show, arg, desc)        \
-       { (name), OPT_CB_ARG((cb), (show), (arg)), (desc) }
+       { (name), OPT_CB_ARG((cb), (show), (arg)), { (arg) }, (desc) }
 
 /**
  * OPT_SUBTABLE() - macro for including another table inside a table.
@@ -74,14 +74,15 @@ struct opt_table;
  */
 #define OPT_SUBTABLE(table, desc)                                      \
        { (const char *)(table), OPT_SUBTABLE,                          \
-       sizeof(_check_is_entry(table)) ? NULL : NULL, NULL, NULL, NULL, (desc) }
+         sizeof(_check_is_entry(table)) ? NULL : NULL, NULL, NULL,     \
+         { NULL }, (desc) }
 
 /**
  * OPT_ENDTABLE - macro to create final entry in table.
  *
  * This must be the final element in the opt_table array.
  */
-#define OPT_ENDTABLE { NULL, OPT_END, NULL, NULL, NULL, NULL, NULL }
+#define OPT_ENDTABLE { NULL, OPT_END, NULL, NULL, NULL, { NULL }, NULL }
 
 /**
  * opt_register_table - register a table of options
@@ -127,7 +128,7 @@ void opt_register_table(const struct opt_table *table, const char *desc);
  * string and return false.
  */
 #define opt_register_noarg(names, cb, arg, desc)                       \
-       _opt_register((names), OPT_CB_NOARG((cb), (arg)), (desc))
+       _opt_register((names), OPT_CB_NOARG((cb), (arg)), (arg), (desc))
 
 /**
  * opt_register_arg - register an option with an arguments
@@ -157,7 +158,7 @@ void opt_register_table(const struct opt_table *table, const char *desc);
  *     opt_register_arg("--explode|--boom", explode, NULL, NULL, opt_hidden);
  */
 #define opt_register_arg(names, cb, show, arg, desc)                   \
-       _opt_register((names), OPT_CB_ARG((cb), (show), (arg)), (desc))
+       _opt_register((names), OPT_CB_ARG((cb), (show), (arg)), (arg), (desc))
 
 /**
  * opt_parse - parse arguments.
@@ -303,7 +304,11 @@ struct opt_table {
        char *(*cb)(void *arg); /* OPT_NOARG */
        char *(*cb_arg)(const char *optarg, void *arg); /* OPT_HASARG */
        void (*show)(char buf[OPT_SHOW_LEN], const void *arg);
-       void *arg;
+       union {
+               const void *carg;
+               void *arg;
+               size_t tlen;
+       } u;
        const char *desc;
 };
 
@@ -314,7 +319,7 @@ struct opt_table {
                    char *(*)(typeof(*(arg))*),         \
                    char *(*)(const typeof(*(arg))*),   \
                    char *(*)(const void *)),           \
-       NULL, NULL, (arg)
+       NULL, NULL
 
 /* Resolves to the four parameters for arg callbacks. */
 #define OPT_CB_ARG(cb, show, arg)                                      \
@@ -324,15 +329,14 @@ struct opt_table {
                    char *(*)(const char *, const typeof(*(arg))*),     \
                    char *(*)(const char *, const void *)),             \
        cast_if_type(void (*)(char buf[], const void *), (show), (show)+0, \
-                    void (*)(char buf[], const typeof(*(arg))*)),      \
-       (arg)
+                    void (*)(char buf[], const typeof(*(arg))*))
 
 /* Non-typesafe register function. */
 void _opt_register(const char *names, enum opt_type type,
                   char *(*cb)(void *arg),
                   char *(*cb_arg)(const char *optarg, void *arg),
                   void (*show)(char buf[OPT_SHOW_LEN], const void *arg),
-                  void *arg, const char *desc);
+                  const void *arg, const char *desc);
 
 /* We use this to get typechecking for OPT_SUBTABLE */
 static inline int _check_is_entry(struct opt_table *e UNUSED) { return 0; }
index 228808dd4a6707b73e37173575ca25e36e62a1ac..7b7c02c5936f5af60d7b702979473fdf2dbd1820 100644 (file)
@@ -94,7 +94,7 @@ int parse_one(int *argc, char *argv[], unsigned *offset,
                if (optarg)
                        return parse_err(errlog, argv[0], o, len,
                                         "doesn't allow an argument");
-               problem = opt_table[i].cb(opt_table[i].arg);
+               problem = opt_table[i].cb(opt_table[i].u.arg);
        } else {
                if (!optarg) {
                        /* Swallow any short options as optarg, eg -afile */
@@ -107,7 +107,7 @@ int parse_one(int *argc, char *argv[], unsigned *offset,
                if (!optarg)
                        return parse_err(errlog, argv[0], o, len,
                                         "requires an argument");
-               problem = opt_table[i].cb_arg(optarg, opt_table[i].arg);
+               problem = opt_table[i].cb_arg(optarg, opt_table[i].u.arg);
        }
 
        if (problem) {
diff --git a/ccan/opt/test/compile_ok-const-arg.c b/ccan/opt/test/compile_ok-const-arg.c
new file mode 100644 (file)
index 0000000..f1d10da
--- /dev/null
@@ -0,0 +1,13 @@
+#include <ccan/opt/opt.h>
+#include <ccan/opt/opt.c>
+#include <ccan/opt/helpers.c>
+#include <ccan/opt/parse.c>
+#include <ccan/opt/usage.c>
+
+int main(int argc, char *argv[])
+{
+       opt_register_noarg("-v", opt_version_and_exit,
+                          (const char *)"1.2.3",
+                          (const char *)"Print version");
+       return 0;
+}
index 60e1586861adc0981a5bf0eaf00bc63bcff450a4..4d784bc2be73550a5b9818a31a245eafbc56adf7 100644 (file)
@@ -32,8 +32,8 @@ char *opt_usage(const char *argv0, const char *extra)
                extra = "";
                for (i = 0; i < opt_count; i++) {
                        if (opt_table[i].cb == (void *)opt_usage_and_exit
-                           && opt_table[i].arg) {
-                               extra = opt_table[i].arg;
+                           && opt_table[i].u.carg) {
+                               extra = opt_table[i].u.carg;
                                break;
                        }
                }
@@ -100,7 +100,7 @@ char *opt_usage(const char *argv0, const char *extra)
                if (opt_table[i].show) {
                        char buf[OPT_SHOW_LEN + sizeof("...")];
                        strcpy(buf + OPT_SHOW_LEN, "...");
-                       opt_table[i].show(buf, opt_table[i].arg);
+                       opt_table[i].show(buf, opt_table[i].u.arg);
                        len += sprintf(p + len, " (default: %s)", buf);
                }
                p += len;