mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] environment variables: use linux list
@ 2012-10-16  7:35 Sascha Hauer
  0 siblings, 0 replies; only message in thread
From: Sascha Hauer @ 2012-10-16  7:35 UTC (permalink / raw)
  To: barebox

This switches environment variables to use linux list. This is easier
to read. An additional plus is that the environment variables no longer
need an initcall, so malloc is the only requirement for them.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 commands/printenv.c   |   22 ++++-----
 common/complete.c     |   12 +++--
 common/env.c          |  121 ++++++++++++++++++++++++++-----------------------
 include/environment.h |   11 +++--
 4 files changed, 85 insertions(+), 81 deletions(-)

diff --git a/commands/printenv.c b/commands/printenv.c
index b18c7a1..10e882a 100644
--- a/commands/printenv.c
+++ b/commands/printenv.c
@@ -27,8 +27,8 @@
 
 static int do_printenv(int argc, char *argv[])
 {
-	struct variable_d *var;
-	struct env_context *c, *current_c;
+	struct variable_d *v;
+	struct env_context *c;
 
 	if (argc == 2) {
 		const char *val = getenv(argv[1]);
@@ -40,22 +40,16 @@ static int do_printenv(int argc, char *argv[])
 		return 1;
 	}
 
-	current_c = get_current_context();
-	var = current_c->local->next;
+	c = get_current_context();
 	printf("locals:\n");
-	while (var) {
-		printf("%s=%s\n", var_name(var), var_val(var));
-		var = var->next;
-	}
+	list_for_each_entry(v, &c->local, list)
+		printf("%s=%s\n", var_name(v), var_val(v));
 
 	printf("globals:\n");
 	c = get_current_context();
-	while(c) {
-		var = c->global->next;
-		while (var) {
-			printf("%s=%s\n", var_name(var), var_val(var));
-			var = var->next;
-		}
+	while (c) {
+		list_for_each_entry(v, &c->global, list)
+			printf("%s=%s\n", var_name(v), var_val(v));
 		c = c->parent;
 	}
 
diff --git a/common/complete.c b/common/complete.c
index 32d0d19..9206ef0 100644
--- a/common/complete.c
+++ b/common/complete.c
@@ -208,7 +208,7 @@ static int env_param_complete(struct string_list *sl, char *instr, int eval)
 {
 	struct device_d *dev;
 	struct variable_d *var;
-	struct env_context *c, *current_c;
+	struct env_context *c;
 	char *instr_param;
 	int len;
 	char end = '=';
@@ -225,21 +225,23 @@ static int env_param_complete(struct string_list *sl, char *instr, int eval)
 	instr_param = strchr(instr, '.');
 	len = strlen(instr);
 
-	current_c = get_current_context();
-	for(var = current_c->local->next; var; var = var->next) {
+	c = get_current_context();
+	list_for_each_entry(var, &c->local, list) {
 		if (strncmp(instr, var_name(var), len))
 			continue;
 		string_list_add_asprintf(sl, "%s%s%c",
 			begin, var_name(var), end);
 	}
 
-	for (c = get_current_context(); c; c = c->parent) {
-		for (var = c->global->next; var; var = var->next) {
+	c = get_current_context();
+	while (c) {
+		list_for_each_entry(var, &c->global, list) {
 			if (strncmp(instr, var_name(var), len))
 				continue;
 			string_list_add_asprintf(sl, "%s%s%c",
 				begin, var_name(var), end);
 		}
+		c = c->parent;
 	}
 
 	if (instr_param) {
diff --git a/common/env.c b/common/env.c
index 1b2a7c2..33a871f 100644
--- a/common/env.c
+++ b/common/env.c
@@ -30,23 +30,36 @@
 #include <init.h>
 #include <environment.h>
 
-#define VARIABLE_D_SIZE(name, value) (sizeof(struct variable_d) + strlen(name) + strlen(value) + 2)
+static struct env_context root = {
+	.local = LIST_HEAD_INIT(root.local),
+	.global = LIST_HEAD_INIT(root.global),
+};
 
-static struct env_context *context;
+static struct env_context *context = &root;
 
 /**
  * Remove a list of environment variables
  * @param[in] v Variable anchor to remove
  */
-static void free_variables(struct variable_d *v)
+static void free_context(struct env_context *c)
 {
-	struct variable_d *next;
+	struct variable_d *v, *tmp;
 
-	while (v) {
-		next = v->next;
+	list_for_each_entry_safe(v, tmp, &c->local, list) {
+		free(v->name);
+		free(v->data);
+		list_del(&v->list);
 		free(v);
-		v = next;
 	}
+
+	list_for_each_entry_safe(v, tmp, &c->global, list) {
+		free(v->name);
+		free(v->data);
+		list_del(&v->list);
+		free(v);
+	}
+
+	free(c);
 }
 
 /** Read back current context */
@@ -58,19 +71,14 @@ EXPORT_SYMBOL(get_current_context);
 
 
 /**
- * FIXME
+ * Create a new variable context and put it on the stack
  */
 int env_push_context(void)
 {
 	struct env_context *c = xzalloc(sizeof(struct env_context));
 
-	c->local = xzalloc(VARIABLE_D_SIZE("", ""));
-	c->global = xzalloc(VARIABLE_D_SIZE("", ""));
-
-	if (!context) {
-		context = c;
-		return 0;
-	}
+	INIT_LIST_HEAD(&c->local);
+	INIT_LIST_HEAD(&c->global);
 
 	c->parent = context;
 	context = c;
@@ -78,10 +86,8 @@ int env_push_context(void)
 	return 0;
 }
 
-postcore_initcall(env_push_context);
-
 /**
- * FIXME
+ * free current variable context and restore the previous one
  */
 int env_pop_context(void)
 {
@@ -89,9 +95,7 @@ int env_pop_context(void)
 
 	if (context->parent) {
 		c = context->parent;
-		free_variables(context->local);
-		free_variables(context->global);
-		free(context);
+		free_context(context);
 		context = c;
 		return 0;
 	}
@@ -105,7 +109,7 @@ int env_pop_context(void)
  */
 char *var_val(struct variable_d *var)
 {
-	return &var->data[strlen(var->data) + 1];
+	return var->data;
 }
 
 /**
@@ -115,16 +119,18 @@ char *var_val(struct variable_d *var)
  */
 char *var_name(struct variable_d *var)
 {
-	return var->data;
+	return var->name;
 }
 
-static const char *getenv_raw(struct variable_d *var, const char *name)
+static const char *getenv_raw(struct list_head *l, const char *name)
 {
-	while (var) {
-		if (!strcmp(var_name(var), name))
-			return var_val(var);
-		var = var->next;
+	struct variable_d *v;
+
+	list_for_each_entry(v, l, list) {
+		if (!strcmp(var_name(v), name))
+			return var_val(v);
 	}
+
 	return NULL;
 }
 
@@ -150,12 +156,12 @@ const char *getenv (const char *name)
 
 	c = context;
 
-	val = getenv_raw(c->local, name);
+	val = getenv_raw(&c->local, name);
 	if (val)
 		return val;
 
 	while (c) {
-		val = getenv_raw(c->global, name);
+		val = getenv_raw(&c->global, name);
 		if (val)
 			return val;
 		c = c->parent;
@@ -164,34 +170,35 @@ const char *getenv (const char *name)
 }
 EXPORT_SYMBOL(getenv);
 
-static int setenv_raw(struct variable_d *var, const char *name, const char *value)
+static int setenv_raw(struct list_head *l, const char *name, const char *value)
 {
-	struct variable_d *newvar = NULL;
-
-	if (value) {
-		newvar = xzalloc(VARIABLE_D_SIZE(name, value));
-		strcpy(&newvar->data[0], name);
-		strcpy(&newvar->data[strlen(name) + 1], value);
-	}
+	struct variable_d *v;
 
-	while (var->next) {
-		if (!strcmp(var->next->data, name)) {
+	list_for_each_entry(v, l, list) {
+		if (!strcmp(v->name, name)) {
 			if (value) {
-				newvar->next = var->next->next;
-				free(var->next);
-				var->next = newvar;
+				free(v->data);
+				v->data = xstrdup(value);
+
 				return 0;
 			} else {
-				struct variable_d *tmp;
-				tmp = var->next;
-				var->next = var->next->next;
-				free(tmp);
+				list_del(&v->list);
+				free(v->name);
+				free(v->data);
+				free(v);
+
 				return 0;
 			}
 		}
-		var = var->next;
 	}
-	var->next = newvar;
+
+	if (value) {
+		v = xzalloc(sizeof(*v));
+		v->name = xstrdup(name);
+		v->data = xstrdup(value);
+		list_add_tail(&v->list, l);
+	}
+
 	return 0;
 }
 
@@ -199,8 +206,8 @@ int setenv(const char *_name, const char *value)
 {
 	char *name = strdup(_name);
 	char *par;
-	struct variable_d *var;
 	int ret = 0;
+	struct list_head *list;
 
 	if (value && !*value)
 		value = NULL;
@@ -224,12 +231,12 @@ int setenv(const char *_name, const char *value)
 		goto out;
 	}
 
-	if (getenv_raw(context->global, name))
-		var = context->global;
+	if (getenv_raw(&context->global, name))
+		list = &context->global;
 	else
-		var = context->local;
+		list = &context->local;
 
-	ret = setenv_raw(var, name, value);
+	ret = setenv_raw(list, name, value);
 out:
 	free(name);
 
@@ -239,11 +246,11 @@ EXPORT_SYMBOL(setenv);
 
 int export(const char *varname)
 {
-	const char *val = getenv_raw(context->local, varname);
+	const char *val = getenv_raw(&context->local, varname);
 
 	if (val) {
-		setenv_raw(context->global, varname, val);
-		setenv_raw(context->local, varname, NULL);
+		setenv_raw(&context->global, varname, val);
+		setenv_raw(&context->local, varname, NULL);
 	}
 	return 0;
 }
diff --git a/include/environment.h b/include/environment.h
index 95e75e7..4184977 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -26,14 +26,15 @@
  * Managment of a environment variable
  */
 struct variable_d {
-	struct variable_d *next;	/**< List management */
-	char data[0];			/**< variable length data */
+	struct list_head list;
+	char *name;
+	char *data;
 };
 
 struct env_context {
-	struct env_context *parent;	/**< FIXME */
-	struct variable_d *local;	/**< FIXME */
-	struct variable_d *global;	/**< FIXME */
+	struct env_context *parent;
+	struct list_head local;
+	struct list_head global;
 };
 
 struct env_context *get_current_context(void);
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2012-10-16  7:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-16  7:35 [PATCH] environment variables: use linux list Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox