summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2011-03-22 11:48:43 +1030
committerRusty Russell <rusty@rustcorp.com.au>2011-03-22 11:48:43 +1030
commite34192d580958aaffff3754a4e2bf1eccbb489f8 (patch)
treefab43e9baaab74f49360c198da41b415a0487425
parent66711021849dd07cd29383c9ed40ab4b9f3d1e07 (diff)
opt: allow const arguments.
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.
-rw-r--r--ccan/opt/opt.c6
-rw-r--r--ccan/opt/opt.h26
-rw-r--r--ccan/opt/parse.c4
-rw-r--r--ccan/opt/test/compile_ok-const-arg.c13
-rw-r--r--ccan/opt/usage.c6
5 files changed, 36 insertions, 19 deletions
diff --git a/ccan/opt/opt.c b/ccan/opt/opt.c
index f05d125f..827109e3 100644
--- a/ccan/opt/opt.c
+++ b/ccan/opt/opt.c
@@ -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. */
diff --git a/ccan/opt/opt.h b/ccan/opt/opt.h
index 812fec86..539a0a66 100644
--- a/ccan/opt/opt.h
+++ b/ccan/opt/opt.h
@@ -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; }
diff --git a/ccan/opt/parse.c b/ccan/opt/parse.c
index 228808dd..7b7c02c5 100644
--- a/ccan/opt/parse.c
+++ b/ccan/opt/parse.c
@@ -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
index 00000000..f1d10da1
--- /dev/null
+++ b/ccan/opt/test/compile_ok-const-arg.c
@@ -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;
+}
diff --git a/ccan/opt/usage.c b/ccan/opt/usage.c
index 60e15868..4d784bc2 100644
--- a/ccan/opt/usage.c
+++ b/ccan/opt/usage.c
@@ -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;