Commit e34192d5 authored by Rusty Russell's avatar Rusty Russell

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.
parent 66711021
......@@ -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. */
......
......@@ -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; }
......
......@@ -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) {
......
#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;
}
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment