Commit 7a57ccf94946f867de7b9853601d0968f8b822aa

Con Kolivas 2014-04-03T16:21:28

Provide a ccan variant OPT_WITH_CBARG that assigns the arguments passed as a string and then performs the callback function on the string.

diff --git a/ccan/opt/opt.c b/ccan/opt/opt.c
index 9bc34d9..8ff00ea 100644
--- a/ccan/opt/opt.c
+++ b/ccan/opt/opt.c
@@ -116,7 +116,7 @@ static void check_opt(const struct opt_table *entry)
 	const char *p;
 	unsigned len;
 
-	if (entry->type != OPT_HASARG && entry->type != OPT_NOARG)
+	if (entry->type != OPT_HASARG && entry->type != OPT_NOARG && entry->type != OPT_PROCESSARG)
 		errx(1, "Option %s: unknown entry type %u",
 		     entry->names, entry->type);
 
diff --git a/ccan/opt/opt.h b/ccan/opt/opt.h
index 6fe2fb0..90ff680 100644
--- a/ccan/opt/opt.h
+++ b/ccan/opt/opt.h
@@ -68,6 +68,13 @@ struct opt_table;
 	{ (name), OPT_CB_ARG((cb), (show), (arg)), { (arg) }, (desc) }
 
 /**
+ * OPT_WITH_CBARG() - variant of OPT_WITH_ARG which assigns arguments to arg
+ * and then performs the callback function on the args as well.
+ */
+#define OPT_WITH_CBARG(name, cb, show, arg, desc)	\
+	{ (name), OPT_CB_WITHARG((cb), (show), (arg)), { (arg) }, (desc) }
+
+/**
  * OPT_SUBTABLE() - macro for including another table inside a table.
  * @table: the table to include in this table.
  * @desc: description of this subtable (for opt_usage()) or NULL.
@@ -296,8 +303,9 @@ char *opt_usage_and_exit(const char *extra);
 enum opt_type {
 	OPT_NOARG = 1,		/* -f|--foo */
 	OPT_HASARG = 2,		/* -f arg|--foo=arg|--foo arg */
-	OPT_SUBTABLE = 4,	/* Actually, longopt points to a subtable... */
-	OPT_END = 8,		/* End of the table. */
+	OPT_PROCESSARG = 4,
+	OPT_SUBTABLE = 8,	/* Actually, longopt points to a subtable... */
+	OPT_END = 16,		/* End of the table. */
 };
 
 struct opt_table {
@@ -334,6 +342,16 @@ struct opt_table {
 	typesafe_cb_cast(void (*)(char buf[], const void *),		\
 			 void (*)(char buf[], const typeof(*(arg))*), (show))
 
+#define OPT_CB_WITHARG(cb, show, arg)					\
+	OPT_PROCESSARG, NULL,						\
+	typesafe_cb_cast3(char *(*)(const char *,void *),	\
+			  char *(*)(const char *, typeof(*(arg))*),	\
+			  char *(*)(const char *, const typeof(*(arg))*), \
+			  char *(*)(const char *, const void *),	\
+			  (cb)),					\
+	typesafe_cb_cast(void (*)(char buf[], const void *),		\
+			 void (*)(char buf[], const typeof(*(arg))*), (show))
+
 /* Non-typesafe register function. */
 void _opt_register(const char *names, enum opt_type type,
 		   char *(*cb)(void *arg),
diff --git a/ccan/opt/parse.c b/ccan/opt/parse.c
index 7b7c02c..18af157 100644
--- a/ccan/opt/parse.c
+++ b/ccan/opt/parse.c
@@ -107,6 +107,8 @@ int parse_one(int *argc, char *argv[], unsigned *offset,
 		if (!optarg)
 			return parse_err(errlog, argv[0], o, len,
 					 "requires an argument");
+		if (opt_table[i].type == OPT_PROCESSARG)
+			opt_set_charp(optarg, opt_table[i].u.arg);
 		problem = opt_table[i].cb_arg(optarg, opt_table[i].u.arg);
 	}