[PATCH uci] reduce code complexity of uci_show_package

Jan Venekamp jan at venekamp.net
Fri Sep 8 11:24:22 PDT 2023


For the extended syntax on "uci show" a list of previous section types
is build and iterated over to determine the current type index of a
section. However, instead building this list and iterate over that we
can simply iterate over the previous sections to find the index. This
reduces the code complexity of uci_show_package, uci_show_section and
uci_show_option.

Signed-off-by: Jan Venekamp <jan at venekamp.net>
---
 cli.c                                         | 132 +++++-------------
 .../references/show_parsing_multiline.data    |   3 +
 .../show_parsing_multiline_package.result     |   2 +
 3 files changed, 37 insertions(+), 100 deletions(-)

diff --git a/cli.c b/cli.c
index f169e42..2cbfecf 100644
--- a/cli.c
+++ b/cli.c
@@ -55,88 +55,8 @@ enum {
 	CMD_HELP,
 };
 
-struct uci_type_list {
-	unsigned int idx;
-	const char *name;
-	struct uci_type_list *next;
-};
-
-static struct uci_type_list *type_list = NULL;
-static char *typestr = NULL;
-static const char *cur_section_ref = NULL;
-
 static int uci_cmd(int argc, char **argv);
 
-static void
-uci_reset_typelist(void)
-{
-	struct uci_type_list *type;
-	while (type_list != NULL) {
-			type = type_list;
-			type_list = type_list->next;
-			free(type);
-	}
-	if (typestr) {
-		free(typestr);
-		typestr = NULL;
-	}
-	cur_section_ref = NULL;
-}
-
-static char *
-uci_lookup_section_ref(struct uci_section *s)
-{
-	struct uci_type_list *ti = type_list;
-	char *ret;
-	int maxlen;
-
-	if (!(flags & CLI_FLAG_SHOW_EXT))
-		return s->e.name;
-
-	/* look up in section type list */
-	while (ti) {
-		if (strcmp(ti->name, s->type) == 0)
-			break;
-		ti = ti->next;
-	}
-	if (!ti) {
-		ti = calloc(1, sizeof(struct uci_type_list));
-		if (!ti)
-			return NULL;
-		ti->next = type_list;
-		type_list = ti;
-		ti->name = s->type;
-	}
-
-	if (s->anonymous) {
-		maxlen = strlen(s->type) + 1 + 2 + 10;
-		if (!typestr) {
-			typestr = malloc(maxlen);
-			if (!typestr)
-				return NULL;
-		} else {
-			void *p = realloc(typestr, maxlen);
-			if (!p) {
-				free(typestr);
-				return NULL;
-			}
-
-			typestr = p;
-		}
-
-		if (typestr)
-			sprintf(typestr, "@%s[%d]", ti->name, ti->idx);
-
-		ret = typestr;
-	} else {
-		ret = s->e.name;
-	}
-
-	ti->idx++;
-
-	return ret;
-}
-
 static void uci_usage(void)
 {
 	fprintf(stderr,
@@ -243,40 +163,52 @@ static void uci_show_value(struct uci_option *o, bool quote)
 	}
 }
 
-static void uci_show_option(struct uci_option *o, bool quote)
+static void uci_show_option(struct uci_option *o)
 {
-	printf("%s.%s.%s=",
-		o->section->package->e.name,
-		(cur_section_ref ? cur_section_ref : o->section->e.name),
-		o->e.name);
-	uci_show_value(o, quote);
+	printf("%s.%s.%s=", o->section->package->e.name, o->section->e.name, o->e.name);
+	uci_show_value(o, true);
 }
 
 static void uci_show_section(struct uci_section *s)
 {
 	struct uci_element *e;
-	const char *cname;
-	const char *sname;
 
-	cname = s->package->e.name;
-	sname = (cur_section_ref ? cur_section_ref : s->e.name);
-	printf("%s.%s=%s\n", cname, sname, s->type);
+	printf("%s.%s=%s\n", s->package->e.name, s->e.name, s->type);
 	uci_foreach_element(&s->options, e) {
-		uci_show_option(uci_to_option(e), true);
+		uci_show_option(uci_to_option(e));
 	}
 }
 
 static void uci_show_package(struct uci_package *p)
 {
-	struct uci_element *e;
+	struct uci_element *e0, *e1;
+	bool show_ext = flags & CLI_FLAG_SHOW_EXT;
+
+	uci_foreach_element(&p->sections, e0) {
+		struct uci_section *s = uci_to_section(e0);
+		unsigned int idx = 0;
+
+		if (!s->anonymous || !show_ext) {
+			uci_show_section(s);
+			continue;
+		}
 
-	uci_reset_typelist();
-	uci_foreach_element( &p->sections, e) {
-		struct uci_section *s = uci_to_section(e);
-		cur_section_ref = uci_lookup_section_ref(s);
-		uci_show_section(s);
+		/* count preceding sections with same type */
+		uci_foreach_element(&p->sections, e1) {
+			if (e1 == e0)
+				break;
+			if (strcmp(uci_to_section(e1)->type, s->type) == 0)
+				idx++;
+		}
+
+		/* show anonymous section and its options with extended syntax */
+		printf("%s.@%s[%d]=%s\n", s->package->e.name, s->type, idx, s->type);
+		uci_foreach_element(&s->options, e1) {
+			struct uci_option *o = uci_to_option(e1);
+			printf("%s.@%s[%d].%s=", s->package->e.name, s->type, idx, o->e.name);
+			uci_show_value(o, true);
+		}
 	}
-	uci_reset_typelist();
 }
 
 static void uci_show_changes(struct uci_package *p)
@@ -348,7 +280,7 @@ static int package_cmd(int cmd, char *tuple)
 			goto out;
 		}
 		if (ptr.o)
-			uci_show_option(ptr.o, true);
+			uci_show_option(ptr.o);
 		else if (ptr.s)
 			uci_show_section(ptr.s);
 		else if (ptr.p)
diff --git a/tests/shunit2/references/show_parsing_multiline.data b/tests/shunit2/references/show_parsing_multiline.data
index 670e809..a114d67 100644
--- a/tests/shunit2/references/show_parsing_multiline.data
+++ b/tests/shunit2/references/show_parsing_multiline.data
@@ -18,3 +18,6 @@ config sockd 'instance0'
 			from: 0.0.0.0/0 to: 0.0.0.0/0
 			log: connect
 		} '
+
+config sockd
+        option enabled  0
diff --git a/tests/shunit2/references/show_parsing_multiline_package.result b/tests/shunit2/references/show_parsing_multiline_package.result
index 218082d..b1d9704 100644
--- a/tests/shunit2/references/show_parsing_multiline_package.result
+++ b/tests/shunit2/references/show_parsing_multiline_package.result
@@ -16,3 +16,5 @@ sockd.instance0.extra_config='
 			from: 0.0.0.0/0 to: 0.0.0.0/0
 			log: connect
 		} '
+sockd. at sockd[1]=sockd
+sockd. at sockd[1].enabled='0'
-- 
2.32.0 (Apple Git-132)




More information about the openwrt-devel mailing list