From d58d2f142e4983640bb961ef8f93c69ce528d089 Mon Sep 17 00:00:00 2001
From: midipix <writeonce@midipix.org>
Date: Sun, 25 Dec 2016 12:22:05 -0500
Subject: argv.h: use an option vector rather than a direct pointer to the
 option table.

---
 src/driver/slbt_driver_ctx.c        | 43 ++++++++++---------
 src/internal/argv/argv.h            | 83 +++++++++++++++++++++++--------------
 src/internal/slibtool_driver_impl.h |  2 +
 src/logic/slbt_exec_install.c       | 13 +++---
 src/logic/slbt_exec_uninstall.c     | 15 ++++---
 5 files changed, 95 insertions(+), 61 deletions(-)

(limited to 'src')

diff --git a/src/driver/slbt_driver_ctx.c b/src/driver/slbt_driver_ctx.c
index 40be65f..0abbf85 100644
--- a/src/driver/slbt_driver_ctx.c
+++ b/src/driver/slbt_driver_ctx.c
@@ -128,7 +128,7 @@ static uint32_t slbt_argv_flags(uint32_t flags)
 static int slbt_driver_usage(
 	const char *			program,
 	const char *			arg,
-	const struct argv_option *	options,
+	const struct argv_option **	optv,
 	struct argv_meta *		meta)
 {
 	char header[512];
@@ -137,7 +137,7 @@ static int slbt_driver_usage(
 		"Usage: %s [options] <file>...\n" "Options:\n",
 		program);
 
-	argv_usage(stdout,header,options,arg);
+	argv_usage(stdout,header,optv,arg);
 	argv_free(meta);
 
 	return SLBT_USAGE;
@@ -191,8 +191,9 @@ static int slbt_split_argv(
 	struct argv_entry *		mode;
 	struct argv_entry *		config;
 	struct argv_entry *		finish;
-	const struct argv_option *	option;
-	const struct argv_option *	options = slbt_default_options;
+	const struct argv_option **	popt;
+	const struct argv_option **	optout;
+	const struct argv_option *	optv[SLBT_OPTV_ELEMENTS];
 	struct argv_ctx			ctx = {ARGV_VERBOSITY_NONE,
 						ARGV_MODE_SCAN,
 						0,0,0,0,0,0,0};
@@ -200,17 +201,19 @@ static int slbt_split_argv(
 	program = argv_program_name(argv[0]);
 
 	/* missing arguments? */
+	argv_optv_init(slbt_default_options,optv);
+
 	if (!argv[1] && (flags & SLBT_DRIVER_VERBOSITY_USAGE))
-		return slbt_driver_usage(program,0,options,0);
+		return slbt_driver_usage(program,0,optv,0);
 
 	/* initial argv scan: ... --mode=xxx ... <compiler> ... */
-	argv_scan(argv,options,&ctx,0);
+	argv_scan(argv,optv,&ctx,0);
 
 	/* invalid slibtool arguments? */
 	if (ctx.erridx && !ctx.unitidx) {
 		if (flags & SLBT_DRIVER_VERBOSITY_ERRORS)
 			argv_get(
-				argv,options,
+				argv,optv,
 				slbt_argv_flags(flags));
 		return -1;
 	}
@@ -219,7 +222,7 @@ static int slbt_split_argv(
 	compiler = argv[ctx.unitidx];
 	argv[ctx.unitidx] = 0;
 
-	meta = argv_get(argv,options,ARGV_VERBOSITY_NONE);
+	meta = argv_get(argv,optv,ARGV_VERBOSITY_NONE);
 	argv[ctx.unitidx] = compiler;
 
 	/* missing all of --mode, --config, and --finish? */
@@ -263,9 +266,8 @@ static int slbt_split_argv(
 		sargv->targv[i] = argv[i];
 
 	/* split vectors: legacy mixture */
-	options = option_from_tag(
-			slbt_default_options,
-			TAG_OUTPUT);
+	for (optout=optv; optout[0]->tag != TAG_OUTPUT; optout++)
+		(void)0;
 
 	targv = sargv->targv + i;
 	cargv = sargv->cargv;
@@ -345,11 +347,11 @@ static int slbt_split_argv(
 			*targv++ = argv[i];
 
 		} else {
-			for (option=options; option->long_name; option++)
-				if (!(strcmp(option->long_name,&argv[i][1])))
+			for (popt=optout; popt[0] && popt[0]->long_name; popt++)
+				if (!(strcmp(popt[0]->long_name,&argv[i][1])))
 					break;
 
-			if (option->long_name)
+			if (popt[0] && popt[0]->long_name)
 				*targv++ = argv[i];
 			else
 				*cargv++ = argv[i];
@@ -797,17 +799,17 @@ int slbt_get_driver_ctx(
 	struct slbt_split_vector	sargv;
 	struct slbt_driver_ctx_impl *	ctx;
 	struct slbt_common_ctx		cctx;
-	const struct argv_option *	options;
+	const struct argv_option *	optv[SLBT_OPTV_ELEMENTS];
 	struct argv_meta *		meta;
 	struct argv_entry *		entry;
 	const char *			program;
 
-	options = slbt_default_options;
+	argv_optv_init(slbt_default_options,optv);
 
 	if (slbt_split_argv(argv,flags,&sargv))
 		return -1;
 
-	if (!(meta = argv_get(sargv.targv,options,slbt_argv_flags(flags))))
+	if (!(meta = argv_get(sargv.targv,optv,slbt_argv_flags(flags))))
 		return -1;
 
 	program = argv_program_name(argv[0]);
@@ -826,7 +828,7 @@ int slbt_get_driver_ctx(
 				case TAG_HELP:
 				case TAG_HELP_ALL:
 					if (flags & SLBT_DRIVER_VERBOSITY_USAGE)
-						return slbt_driver_usage(program,entry->arg,options,meta);
+						return slbt_driver_usage(program,entry->arg,optv,meta);
 
 				case TAG_VERSION:
 					cctx.drvflags |= SLBT_DRIVER_VERSION;
@@ -1122,11 +1124,14 @@ int slbt_create_driver_ctx(
 	const struct slbt_common_ctx *	cctx,
 	struct slbt_driver_ctx **	pctx)
 {
+	const struct argv_option *	optv[SLBT_OPTV_ELEMENTS];
 	struct argv_meta *		meta;
 	struct slbt_driver_ctx_impl *	ctx;
 	char *				argv[] = {"slibtool_driver",0};
 
-	if (!(meta = argv_get(argv,slbt_default_options,0)))
+	argv_optv_init(slbt_default_options,optv);
+
+	if (!(meta = argv_get(argv,optv,0)))
 		return -1;
 
 	if (!(ctx = slbt_driver_ctx_alloc(meta,cctx)))
diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h
index ca1ceba..60806a2 100644
--- a/src/internal/argv/argv.h
+++ b/src/internal/argv/argv.h
@@ -139,17 +139,21 @@ struct argv_ctx {
 
 #ifdef ARGV_DRIVER
 
+static int argv_optv_init(
+	const struct argv_option[],
+	const struct argv_option **);
+
 static const char * argv_program_name(const char *);
 
 static void argv_usage(
 	FILE *,
 	const char *	header,
-	const struct	argv_option[],
+	const struct	argv_option **,
 	const char *	mode);
 
 static struct argv_meta * argv_get(
 	char **,
-	const struct argv_option[],
+	const struct argv_option **,
 	int flags);
 
 static void argv_free(struct argv_meta *);
@@ -161,14 +165,30 @@ static void argv_free(struct argv_meta *);
 /* implementation of static functions */
 /*------------------------------------*/
 
+static int argv_optv_init(
+	const struct argv_option	options[],
+	const struct argv_option **	optv)
+{
+	const struct argv_option *	option;
+	int				i;
+
+	for (option=options,i=0; option->long_name || option->short_name; option++)
+		optv[i++] = option;
+
+	optv[i] = 0;
+	return i;
+}
+
 static const struct argv_option * argv_short_option(
 	const char *			ch,
-	const struct argv_option	options[],
+	const struct argv_option **	optv,
 	struct argv_entry *		entry)
 {
 	const struct argv_option *	option;
 
-	for (option=options; option->long_name || option->short_name; option++) {
+	for (; *optv; optv++) {
+		option = *optv;
+
 		if (option->short_name == *ch) {
 			entry->tag	= option->tag;
 			entry->fopt	= true;
@@ -181,15 +201,16 @@ static const struct argv_option * argv_short_option(
 
 static const struct argv_option * argv_long_option(
 	const char *			ch,
-	const struct argv_option	options[],
+	const struct argv_option **	optv,
 	struct argv_entry *		entry)
 {
 	const struct argv_option *	option;
 	const char *			arg;
 	size_t				len;
 
-	for (option=options; option->long_name || option->short_name; option++) {
-		len = option->long_name ? strlen(option->long_name) : 0;
+	for (; *optv; optv++) {
+		option = *optv;
+		len    = option->long_name ? strlen(option->long_name) : 0;
 
 		if (len && !(strncmp(option->long_name,ch,len))) {
 			arg = ch + len;
@@ -226,7 +247,7 @@ static inline bool is_last_option(const char * arg)
 
 static inline bool is_hybrid_option(
 	const char *			arg,
-	const struct argv_option	options[])
+	const struct argv_option **	optv)
 {
 	const struct argv_option *	option;
 	struct argv_entry		entry;
@@ -234,11 +255,11 @@ static inline bool is_hybrid_option(
 	if (!is_short_option(arg))
 		return false;
 
-	if (!(option = argv_long_option(++arg,options,&entry)))
+	if (!(option = argv_long_option(++arg,optv,&entry)))
 		return false;
 
 	if (!(option->flags & ARGV_OPTION_HYBRID_SWITCH))
-		if (argv_short_option(arg,options,&entry))
+		if (argv_short_option(arg,optv,&entry))
 			return false;
 
 	return true;
@@ -265,20 +286,18 @@ static inline bool is_arg_in_paradigm(const char * arg, const char * paradigm)
 }
 
 static inline const struct argv_option * option_from_tag(
-	const struct argv_option	options[],
+	const struct argv_option **	optv,
 	int				tag)
 {
-	const struct argv_option *	option;
-
-	for (option=options; option->short_name || option->long_name; option++)
-		if (option->tag == tag)
-			return option;
+	for (; *optv; optv++)
+		if (optv[0]->tag == tag)
+			return optv[0];
 	return 0;
 }
 
 static void argv_scan(
 	char **				argv,
-	const struct argv_option	options[],
+	const struct argv_option **	optv,
 	struct argv_ctx *		ctx,
 	struct argv_meta *		meta)
 {
@@ -316,14 +335,14 @@ static void argv_scan(
 		else if (is_last_option(ch))
 			fnoscan = true;
 
-		else if (!fshort && is_hybrid_option(ch,options))
+		else if (!fshort && is_hybrid_option(ch,optv))
 			fhybrid = true;
 
 		if (!fnoscan && !fhybrid && (fshort || is_short_option(ch))) {
 			if (!fshort)
 				ch++;
 
-			if ((option = argv_short_option(ch,options,&entry))) {
+			if ((option = argv_short_option(ch,optv,&entry))) {
 				if (ch[1]) {
 					ch++;
 					fnext	= false;
@@ -370,7 +389,7 @@ static void argv_scan(
 		} else if (!fnoscan && (fhybrid || is_long_option(ch))) {
 			ch += (fhybrid ? 1 : 2);
 
-			if ((option = argv_long_option(ch,options,&entry))) {
+			if ((option = argv_long_option(ch,optv,&entry))) {
 				val = ch + strlen(option->long_name);
 
 				/* val[0] is either '=' (or ',') or '\0' */
@@ -584,7 +603,7 @@ static void argv_show_error(struct argv_ctx * ctx)
 }
 
 static void argv_show_status(
-	const struct argv_option	options[],
+	const struct argv_option **	optv,
 	struct argv_ctx *		ctx,
 	struct argv_meta *		meta)
 {
@@ -610,7 +629,7 @@ static void argv_show_status(
 	fputs("\n\nparsed entries:\n",stderr);
 	for (entry=meta->entries; entry->arg || entry->fopt; entry++)
 		if (entry->fopt) {
-			option = option_from_tag(options,entry->tag);
+			option = option_from_tag(optv,entry->tag);
 			short_name[0] = option->short_name;
 
 			if (entry->fval)
@@ -683,13 +702,13 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx)
 
 static struct argv_meta * argv_get(
 	char *				argv[],
-	const struct argv_option	options[],
+	const struct argv_option **	optv,
 	int				flags)
 {
 	struct argv_meta *	meta;
 	struct argv_ctx		ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0};
 
-	argv_scan(argv,options,&ctx,0);
+	argv_scan(argv,optv,&ctx,0);
 
 	if (ctx.errcode != ARGV_ERROR_OK) {
 		ctx.program = argv_program_name(argv[0]);
@@ -704,7 +723,7 @@ static struct argv_meta * argv_get(
 		return 0;
 
 	ctx.mode = ARGV_MODE_COPY;
-	argv_scan(meta->argv,options,&ctx,meta);
+	argv_scan(meta->argv,optv,&ctx,meta);
 
 	if (ctx.errcode != ARGV_ERROR_OK) {
 		ctx.program = argv[0];
@@ -716,7 +735,7 @@ static struct argv_meta * argv_get(
 	}
 
 	if (ctx.flags & ARGV_VERBOSITY_STATUS)
-		argv_show_status(options,&ctx,meta);
+		argv_show_status(optv,&ctx,meta);
 
 	return meta;
 }
@@ -736,9 +755,10 @@ static void argv_free(struct argv_meta * xmeta)
 static void argv_usage(
 	FILE *				file,
 	const char *    		header,
-	const struct argv_option	options[],
+	const struct argv_option **	options,
 	const char *			mode)
 {
+	const struct argv_option **	optv;
 	const struct argv_option *	option;
 	bool				fshort,flong,fboth;
 	size_t				len,optlen,desclen;
@@ -771,10 +791,9 @@ static void argv_usage(
 	if (header)
 		fprintf(file,"%s",header);
 
-	option = options;
-	optlen = 0;
+	for (optlen=0,optv=options; *optv; optv++) {
+		option = *optv;
 
-	for (; option->short_name || option->long_name; option++) {
 		/* indent + comma */
 		len = fboth ? sizeof(indent) + 1 : sizeof(indent);
 
@@ -805,7 +824,9 @@ static void argv_usage(
 	optlen &= (~(ARGV_TAB_WIDTH-1));
 	desclen = (optlen < width / 2) ? width - optlen : optlen;
 
-	for (option=options; option->short_name || option->long_name; option++) {
+	for (optv=options; *optv; optv++) {
+		option = *optv;
+
 		/* color */
 		if (fcolor) {
 			color = (color == ccyan) ? cblue : ccyan;
diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h
index 72f86b0..738f308 100644
--- a/src/internal/slibtool_driver_impl.h
+++ b/src/internal/slibtool_driver_impl.h
@@ -8,6 +8,8 @@
 #include <slibtool/slibtool.h>
 #include "argv/argv.h"
 
+#define SLBT_OPTV_ELEMENTS 64
+
 extern const struct argv_option slbt_default_options[];
 
 enum app_tags {
diff --git a/src/logic/slbt_exec_install.c b/src/logic/slbt_exec_install.c
index 7dc2b72..311fc3c 100644
--- a/src/logic/slbt_exec_install.c
+++ b/src/logic/slbt_exec_install.c
@@ -14,6 +14,7 @@
 #define ARGV_DRIVER
 
 #include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
 #include "slibtool_install_impl.h"
 #include "slibtool_readlink_impl.h"
 #include "slibtool_spawn_impl.h"
@@ -24,7 +25,7 @@
 static int slbt_install_usage(
 	const char *			program,
 	const char *			arg,
-	const struct argv_option *	options,
+	const struct argv_option **	optv,
 	struct argv_meta *		meta)
 {
 	char header[512];
@@ -34,7 +35,7 @@ static int slbt_install_usage(
 		"Options:\n",
 		program);
 
-	argv_usage(stdout,header,options,arg);
+	argv_usage(stdout,header,optv,arg);
 	argv_free(meta);
 
 	return SLBT_USAGE;
@@ -545,8 +546,8 @@ int slbt_exec_install(
 	struct argv_entry *		copy;
 	struct argv_entry *		dest;
 	struct argv_entry *		last;
+	const struct argv_option *	optv[SLBT_OPTV_ELEMENTS];
 	char				dstdir[PATH_MAX];
-	const struct argv_option *	options = slbt_install_options;
 
 	/* dry run */
 	if (dctx->cctx->drvflags & SLBT_DRIVER_DRY_RUN)
@@ -570,13 +571,15 @@ int slbt_exec_install(
 		iargv++;
 
 	/* missing arguments? */
+	argv_optv_init(slbt_install_options,optv);
+
 	if (!iargv[1] && (dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_USAGE))
-		return slbt_install_usage(dctx->program,0,options,0);
+		return slbt_install_usage(dctx->program,0,optv,0);
 
 	/* <install> argv meta */
 	if (!(meta = argv_get(
 			iargv,
-			options,
+			optv,
 			dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS
 				? ARGV_VERBOSITY_ERRORS
 				: ARGV_VERBOSITY_NONE)))
diff --git a/src/logic/slbt_exec_uninstall.c b/src/logic/slbt_exec_uninstall.c
index cc27911..0dafa81 100644
--- a/src/logic/slbt_exec_uninstall.c
+++ b/src/logic/slbt_exec_uninstall.c
@@ -14,6 +14,7 @@
 #define ARGV_DRIVER
 
 #include <slibtool/slibtool.h>
+#include "slibtool_driver_impl.h"
 #include "slibtool_uninstall_impl.h"
 #include "slibtool_readlink_impl.h"
 #include "slibtool_errinfo_impl.h"
@@ -22,7 +23,7 @@
 static int slbt_uninstall_usage(
 	const char *			program,
 	const char *			arg,
-	const struct argv_option *	options,
+	const struct argv_option **	optv,
 	struct argv_meta *		meta)
 {
 	char header[512];
@@ -32,7 +33,7 @@ static int slbt_uninstall_usage(
 		"Options:\n",
 		program);
 
-	argv_usage(stdout,header,options,arg);
+	argv_usage(stdout,header,optv,arg);
 	argv_free(meta);
 
 	return SLBT_USAGE;
@@ -250,7 +251,7 @@ int slbt_exec_uninstall(
 	struct slbt_exec_ctx *		actx;
 	struct argv_meta *		meta;
 	struct argv_entry *		entry;
-	const struct argv_option *	options = slbt_uninstall_options;
+	const struct argv_option *	optv[SLBT_OPTV_ELEMENTS];
 
 	/* dry run */
 	if (dctx->cctx->drvflags & SLBT_DRIVER_DRY_RUN)
@@ -274,13 +275,15 @@ int slbt_exec_uninstall(
 		iargv++;
 
 	/* missing arguments? */
+	argv_optv_init(slbt_uninstall_options,optv);
+
 	if (!iargv[1] && (dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_USAGE))
-		return slbt_uninstall_usage(dctx->program,0,options,0);
+		return slbt_uninstall_usage(dctx->program,0,optv,0);
 
 	/* <uninstall> argv meta */
 	if (!(meta = argv_get(
 			iargv,
-			options,
+			optv,
 			dctx->cctx->drvflags & SLBT_DRIVER_VERBOSITY_ERRORS
 				? ARGV_VERBOSITY_ERRORS
 				: ARGV_VERBOSITY_NONE)))
@@ -325,7 +328,7 @@ int slbt_exec_uninstall(
 
 	/* --help */
 	if (flags & SLBT_UNINSTALL_HELP) {
-		slbt_uninstall_usage(dctx->program,0,options,meta);
+		slbt_uninstall_usage(dctx->program,0,optv,meta);
 		return 0;
 	}
 
-- 
cgit v1.2.3