[PATCH 9/9] option: handle switches by table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, the parsing of options is often quite ad-hoc and thus:
- need a lot of code
- is not clear at all

Improve this by making this table driven.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 lib.c | 91 +++++++++++++++++++++++++++++++++++--------------------------------
 1 file changed, 48 insertions(+), 43 deletions(-)

diff --git a/lib.c b/lib.c
index 3c9618a02..a03a94d69 100644
--- a/lib.c
+++ b/lib.c
@@ -483,13 +483,18 @@ const char *match_option(const char *arg, const char *prefix)
 	return NULL;
 }
 
+
+#define OPT_INVERSE	1
 struct flag {
 	const char *name;
 	int *flag;
+	int (*fun)(const char *arg, const char *opt, const struct flag *, int options);
+	unsigned long mask;
 };
 
-static int handle_simple_switch(const char *arg, const struct flag *flags)
+static int handle_switches(const char *ori, const char *opt, const struct flag *flags)
 {
+	const char *arg = opt;
 	int val = 1;
 
 	// Prefixe "no-" mean to turn flag off.
@@ -499,7 +504,22 @@ static int handle_simple_switch(const char *arg, const struct flag *flags)
 	}
 
 	for (; flags->name; flags++) {
-		if (strcmp(arg, flags->name) == 0) {
+		const char *opt = match_option(arg, flags->name);
+		int rc;
+
+		if (!opt)
+			continue;
+
+		if (flags->fun) {
+			int options = 0;
+			if (!val)
+				options |= OPT_INVERSE;
+			if ((rc = flags->fun(ori, opt, flags, options)))
+				return rc;
+		}
+
+		// boolean flag
+		if (opt[0] == '\0' && flags->flag) {
 			*flags->flag = val;
 			return 1;
 		}
@@ -514,21 +534,17 @@ static int handle_simple_switch(const char *arg, const struct flag *flags)
 #define	OPTNUM_UNLIMITED		2
 
 #define OPT_NUMERIC(NAME, TYPE, FUNCTION)	\
-static int opt_##NAME(const char *arg, const char *name, TYPE *ptr, int flag)\
+static int opt_##NAME(const char *arg, const char *opt, TYPE *ptr, int flag)	\
 {									\
-	const char *opt;						\
 	char *end;							\
 	TYPE val;							\
 									\
-	if (!(opt = match_option(arg, name+2)))				\
-		return 0;						\
-	opt++; /* opt's last char is '=' */				\
 	val = FUNCTION(opt, &end, 0);					\
 	if (*end != '\0' || end == opt) {				\
 		if ((flag & OPTNUM_UNLIMITED) && !strcmp(opt, "unlimited"))	\
 			val = ~val;					\
 		else							\
-			die("error: missing argument to \"%s\"", name);	\
+			die("error: wrong argument to \'%s\'", arg);	\
 	}								\
 	if ((flag & OPTNUM_ZERO_IS_INF) && val == 0)			\
 		val = ~val;						\
@@ -728,62 +744,51 @@ static char **handle_switch_O(char *arg, char **next)
 	return next;
 }
 
-static char **handle_switch_ftabstop(const char *arg, char **next)
+static int handle_ftabstop(const char *arg, const char *opt, const struct flag *flag, int options)
 {
-	char *end;
 	unsigned long val;
+	char *end;
 
-	if (*arg == '\0')
-		die("error: missing argument to \"-ftabstop=\"");
+	if (*opt == '\0')
+		die("error: missing argument to \"%s\"", arg);
 
 	/* we silently ignore silly values */
-	val = strtoul(arg, &end, 10);
+	val = strtoul(opt, &end, 10);
 	if (*end == '\0' && 1 <= val && val <= 100)
 		tabstop = val;
 
-	return next;
+	return 1;
 }
 
-static char **handle_switch_fdump(const char *arg, char **next)
+static int handle_fdump_ir(const char *arg, const char *opt, const struct flag *flag, int options)
 {
-	const char *opt;
-
-	if ((opt = match_option(arg, "linearize"))) {
-		if (*opt == '\0')
-			fdump_linearize = 1;
-		else if (!strcmp(opt, "=only"))
-			fdump_linearize = 2;
-		else
-			goto err;
-	}
+	if (*opt == '\0')
+		fdump_linearize = 1;
+	else if (!strcmp(opt, "=only"))
+		fdump_linearize = 2;
+	else
+		die("error: wrong option \"%s\"", arg);
 
-	/* ignore others flags */
-	return next;
+	return 1;
+}
 
-err:
-	die("error: unknown flag \"-fdump-%s\"", arg);
+static int handle_fmemcpy_max_count(const char *arg, const char *opt, const struct flag *flag, int options)
+{
+	opt_ullong(arg, opt, &fmemcpy_max_count, OPTNUM_ZERO_IS_INF|OPTNUM_UNLIMITED);
+	return 1;
 }
 
 static struct flag fflags[] = {
-	{ "mem-report",			&fmem_report },
+	{ "dump-linearize",	NULL,	handle_fdump_ir },
+	{ "mem-report",		&fmem_report },
+	{ "memcpy-max-count=",	NULL,	handle_fmemcpy_max_count },
+	{ "tabstop=",		NULL,	handle_ftabstop },
 	{ },
 };
 
 static char **handle_switch_f(char *arg, char **next)
 {
-	const char *opt;
-	arg++;
-
-	if ((opt = match_option(arg, "tabstop=")))
-		return handle_switch_ftabstop(opt, next);
-	if ((opt = match_option(arg, "dump-")))
-		return handle_switch_fdump(opt, next);
-	if (opt_ullong(arg, "-fmemcpy-max-count=", &fmemcpy_max_count,
-				OPTNUM_ZERO_IS_INF|OPTNUM_UNLIMITED))
-		return next;
-
-	/* handle switches w/ arguments above, boolean and only boolean below */
-	if (handle_simple_switch(arg, fflags))
+	if (handle_switches(arg-1, arg+1, fflags))
 		return next;
 
 	return next;
-- 
2.14.0

--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux