From: Olivier Matz <zer0@droids-corp.org>
Date: Sun, 18 Mar 2018 21:39:47 +0000 (+0100)
Subject: standardize return values + errno
X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=044f2e33e83ec36df6601e3950820d07facde0a7;p=protos%2Flibecoli.git

standardize return values + errno
---

diff --git a/lib/Makefile b/lib/Makefile
index e033dd8..b97f619 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -8,7 +8,7 @@ include $(ECOLI)/mk/ecoli-pre.mk
 O ?= build/
 
 # XXX -O0
-CFLAGS  = -g -O0 -Wall -Werror -W -Wextra -fPIC -Wmissing-prototypes
+CFLAGS  = -g -O3 -Wall -Werror -W -Wextra -fPIC -Wmissing-prototypes
 CFLAGS += -I.
 
 # XXX coverage
diff --git a/lib/ecoli_assert.h b/lib/ecoli_assert.h
index b1ef0ec..fcd2186 100644
--- a/lib/ecoli_assert.h
+++ b/lib/ecoli_assert.h
@@ -5,8 +5,8 @@
 /**
  * Assert API
  *
- * Helpers to check at runtime if a condition is true, and abort
- * (exit) otherwise.
+ * Helpers to check at runtime if a condition is true, or otherwise
+ * either abort (exit program) or return an error.
  */
 
 #ifndef ECOLI_ASSERT_
@@ -32,4 +32,24 @@
 void __ec_assert_print(bool expr, const char *expr_str,
 		const char *format, ...);
 
+/**
+ * Check a condition or return.
+ *
+ * If the condition is true, do nothing. If it is false, set
+ * errno and return the specified value.
+ *
+ * @param cond
+ *   The condition to test.
+ * @param ret
+ *   The value to return.
+ * @param err
+ *   The errno to set.
+ */
+#define EC_CHECK_ARG(cond, ret, err) do {				\
+		if (!(cond)) {						\
+			errno = err;					\
+			return ret;					\
+		}							\
+	} while(0)
+
 #endif
diff --git a/lib/ecoli_complete.c b/lib/ecoli_complete.c
index cbe51b2..815b825 100644
--- a/lib/ecoli_complete.c
+++ b/lib/ecoli_complete.c
@@ -74,14 +74,16 @@ ec_node_complete_child(const struct ec_node *node,
 	struct ec_comp_group *cur_group;
 	int ret;
 
-	if (ec_node_type(node)->complete == NULL)
-		return -ENOTSUP;
+	if (ec_node_type(node)->complete == NULL) {
+		errno = ENOTSUP;
+		return -1;
+	}
 
 	/* save previous parse state, prepare child state */
 	cur_state = comp->cur_state;
 	child_state = ec_parse(node);
 	if (child_state == NULL)
-		return -ENOMEM;
+		return -1;
 
 	if (cur_state != NULL)
 		ec_parse_link_child(cur_state, child_state);
@@ -102,7 +104,7 @@ ec_node_complete_child(const struct ec_node *node,
 	comp->cur_group = cur_group;
 
 	if (ret < 0)
-		return ret;
+		return -1;
 
 	return 0;
 }
@@ -255,11 +257,12 @@ int ec_comp_item_set_display(struct ec_comp_item *item,
 				const char *display)
 {
 	char *display_copy = NULL;
-	int ret = 0;
 
 	if (item == NULL || display == NULL ||
-			item->type == EC_COMP_UNKNOWN)
-		return -EINVAL;
+			item->type == EC_COMP_UNKNOWN) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	display_copy = ec_strdup(display);
 	if (display_copy == NULL)
@@ -272,7 +275,7 @@ int ec_comp_item_set_display(struct ec_comp_item *item,
 
 fail:
 	ec_free(display_copy);
-	return ret;
+	return -1;
 }
 
 int
@@ -280,13 +283,13 @@ ec_comp_item_set_completion(struct ec_comp_item *item,
 				const char *completion)
 {
 	char *completion_copy = NULL;
-	int ret = 0;
 
 	if (item == NULL || completion == NULL ||
-			item->type == EC_COMP_UNKNOWN)
-		return -EINVAL;
+			item->type == EC_COMP_UNKNOWN) {
+		errno = EINVAL;
+		return -1;
+	}
 
-	ret = -ENOMEM;
 	completion_copy = ec_strdup(completion);
 	if (completion_copy == NULL)
 		goto fail;
@@ -298,7 +301,7 @@ ec_comp_item_set_completion(struct ec_comp_item *item,
 
 fail:
 	ec_free(completion_copy);
-	return ret;
+	return -1;
 }
 
 int
@@ -306,13 +309,13 @@ ec_comp_item_set_str(struct ec_comp_item *item,
 			const char *str)
 {
 	char *str_copy = NULL;
-	int ret = 0;
 
 	if (item == NULL || str == NULL ||
-			item->type == EC_COMP_UNKNOWN)
-		return -EINVAL;
+			item->type == EC_COMP_UNKNOWN) {
+		errno = EINVAL;
+		return -1;
+	}
 
-	ret = -ENOMEM;
 	str_copy = ec_strdup(str);
 	if (str_copy == NULL)
 		goto fail;
@@ -324,15 +327,17 @@ ec_comp_item_set_str(struct ec_comp_item *item,
 
 fail:
 	ec_free(str_copy);
-	return ret;
+	return -1;
 }
 
 static int
 ec_comp_item_add(struct ec_comp *comp, const struct ec_node *node,
 		struct ec_comp_item *item)
 {
-	if (comp == NULL || item == NULL)
-		return -EINVAL;
+	if (comp == NULL || item == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	switch (item->type) {
 	case EC_COMP_UNKNOWN:
@@ -345,7 +350,8 @@ ec_comp_item_add(struct ec_comp *comp, const struct ec_node *node,
 		comp->count_partial++;
 		break;
 	default:
-		return -EINVAL;
+		errno = EINVAL;
+		return -1;
 	}
 
 	if (comp->cur_group == NULL) {
@@ -353,7 +359,7 @@ ec_comp_item_add(struct ec_comp *comp, const struct ec_node *node,
 
 		grp = ec_comp_group(node, comp->cur_state);
 		if (grp == NULL)
-			return -ENOMEM;
+			return -1;
 		TAILQ_INSERT_TAIL(&comp->groups, grp, next);
 		comp->cur_group = grp;
 	}
diff --git a/lib/ecoli_node.c b/lib/ecoli_node.c
index 4360336..bf57238 100644
--- a/lib/ecoli_node.c
+++ b/lib/ecoli_node.c
@@ -35,15 +35,18 @@ ec_node_type_lookup(const char *name)
 			return type;
 	}
 
+	errno = ENOENT;
 	return NULL;
 }
 
 int ec_node_type_register(struct ec_node_type *type)
 {
-	if (ec_node_type_lookup(type->name) != NULL)
-		return -EEXIST;
-	if (type->size < sizeof(struct ec_node))
-		return -EINVAL;
+	EC_CHECK_ARG(type->size >= sizeof(struct ec_node), -1, EINVAL);
+
+	if (ec_node_type_lookup(type->name) != NULL) {
+		errno = EEXIST;
+		return -1;
+	}
 
 	TAILQ_INSERT_TAIL(&node_type_list, type, next);
 
@@ -182,6 +185,7 @@ int ec_node_add_child(struct ec_node *node, struct ec_node *child)
 
 fail:
 	ec_free(children);
+	assert(errno != 0);
 	return -1;
 }
 
@@ -289,6 +293,7 @@ int ec_node_check_type(const struct ec_node *node,
 		errno = EINVAL;
 		return -1;
 	}
+
 	return 0;
 }
 
@@ -393,6 +398,7 @@ fail:
 		fclose(f);
 	free(buf);
 
+	assert(errno != 0);
 	return -1;
 }
 /* LCOV_EXCL_STOP */
diff --git a/lib/ecoli_node_cmd.c b/lib/ecoli_node_cmd.c
index 64242e6..99a7732 100644
--- a/lib/ecoli_node_cmd.c
+++ b/lib/ecoli_node_cmd.c
@@ -56,8 +56,10 @@ ec_node_cmd_eval_var(void **result, void *userctx,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(var);
-	if (ec_strvec_len(vec) != 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) != 1) {
+		errno = EINVAL;
+		return -1;
+	}
 	str = ec_strvec_val(vec, 0);
 
 	for (i = 0; i < node->len; i++) {
@@ -69,7 +71,7 @@ ec_node_cmd_eval_var(void **result, void *userctx,
 		/* if id matches, use a node provided by the user... */
 		eval = ec_node_clone(node->table[i]);
 		if (eval == NULL)
-			return -ENOMEM;
+			return -1;
 		break;
 	}
 
@@ -77,7 +79,7 @@ ec_node_cmd_eval_var(void **result, void *userctx,
 	if (eval == NULL) {
 		eval = ec_node_str(EC_NO_ID, str);
 		if (eval == NULL)
-			return -ENOMEM;
+			return -1;
 	}
 
 	*result = eval;
@@ -94,7 +96,8 @@ ec_node_cmd_eval_pre_op(void **result, void *userctx, void *operand,
 	(void)operand;
 	(void)operator;
 
-	return -EINVAL;
+	errno = EINVAL;
+	return -1;
 }
 
 static int
@@ -109,18 +112,21 @@ ec_node_cmd_eval_post_op(void **result, void *userctx, void *operand,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(operator);
-	if (ec_strvec_len(vec) != 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) != 1) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	if (!strcmp(ec_strvec_val(vec, 0), "*")) {
 		out = ec_node_many(EC_NO_ID,
 				ec_node_clone(in), 0, 0);
 		if (out == NULL)
-			return -EINVAL;
+			return -1;
 		ec_node_free(in);
 		*result = out;
 	} else {
-		return -EINVAL;
+		errno = EINVAL;
+		return -1;
 	}
 
 	return 0;
@@ -140,20 +146,22 @@ ec_node_cmd_eval_bin_op(void **result, void *userctx, void *operand1,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(operator);
-	if (ec_strvec_len(vec) > 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) > 1) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	if (ec_strvec_len(vec) == 0) {
 		if (!strcmp(in1->type->name, "seq")) {
 			if (ec_node_seq_add(in1, ec_node_clone(in2)) < 0)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in2);
 			*result = in1;
 		} else {
 			out = EC_NODE_SEQ(EC_NO_ID, ec_node_clone(in1),
 					ec_node_clone(in2));
 			if (out == NULL)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in1);
 			ec_node_free(in2);
 			*result = out;
@@ -161,19 +169,19 @@ ec_node_cmd_eval_bin_op(void **result, void *userctx, void *operand1,
 	} else if (!strcmp(ec_strvec_val(vec, 0), "|")) {
 		if (!strcmp(in2->type->name, "or")) {
 			if (ec_node_or_add(in2, ec_node_clone(in1)) < 0)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in1);
 			*result = in2;
 		} else if (!strcmp(in1->type->name, "or")) {
 			if (ec_node_or_add(in1, ec_node_clone(in2)) < 0)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in2);
 			*result = in1;
 		} else {
 			out = EC_NODE_OR(EC_NO_ID, ec_node_clone(in1),
 					ec_node_clone(in2));
 			if (out == NULL)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in1);
 			ec_node_free(in2);
 			*result = out;
@@ -181,25 +189,26 @@ ec_node_cmd_eval_bin_op(void **result, void *userctx, void *operand1,
 	} else if (!strcmp(ec_strvec_val(vec, 0), ",")) {
 		if (!strcmp(in2->type->name, "subset")) {
 			if (ec_node_subset_add(in2, ec_node_clone(in1)) < 0)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in1);
 			*result = in2;
 		} else if (!strcmp(in1->type->name, "subset")) {
 			if (ec_node_subset_add(in1, ec_node_clone(in2)) < 0)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in2);
 			*result = in1;
 		} else {
 			out = EC_NODE_SUBSET(EC_NO_ID, ec_node_clone(in1),
 					ec_node_clone(in2));
 			if (out == NULL)
-				return -EINVAL;
+				return -1;
 			ec_node_free(in1);
 			ec_node_free(in2);
 			*result = out;
 		}
 	} else {
-		return -EINVAL;
+		errno = EINVAL;
+		return -1;
 	}
 
 	return 0;
@@ -220,18 +229,21 @@ ec_node_cmd_eval_parenthesis(void **result, void *userctx,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(open_paren);
-	if (ec_strvec_len(vec) != 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) != 1) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	if (!strcmp(ec_strvec_val(vec, 0), "[")) {
 		out = ec_node_option(EC_NO_ID, ec_node_clone(in));
 		if (out == NULL)
-			return -EINVAL;
+			return -1;
 		ec_node_free(in);
 	} else if (!strcmp(ec_strvec_val(vec, 0), "(")) {
 		out = in;
 	} else {
-		return -EINVAL;
+		errno = EINVAL;
+		return -1;
 	}
 
 	*result = out;
@@ -270,11 +282,11 @@ static int ec_node_cmd_build(struct ec_node_cmd *node)
 	node->cmd = NULL;
 
 	/* build the expression parser */
-	ret = -ENOMEM;
 	expr = ec_node("expr", "expr");
 	if (expr == NULL)
 		goto fail;
-	ret = ec_node_expr_set_val_node(expr, ec_node_re(EC_NO_ID, "[a-zA-Z0-9]+"));
+	ret = ec_node_expr_set_val_node(expr, ec_node_re(EC_NO_ID,
+					"[a-zA-Z0-9]+"));
 	if (ret < 0)
 		goto fail;
 	ret = ec_node_expr_add_bin_op(expr, ec_node_str(EC_NO_ID, ","));
@@ -302,7 +314,6 @@ static int ec_node_cmd_build(struct ec_node_cmd *node)
 		goto fail;
 
 	/* prepend a lexer to the expression node */
-	ret = -ENOMEM;
 	lex = ec_node_re_lex(EC_NO_ID, ec_node_clone(expr));
 	if (lex == NULL)
 		goto fail;
@@ -324,16 +335,18 @@ static int ec_node_cmd_build(struct ec_node_cmd *node)
 		goto fail;
 
 	/* parse the command expression */
-	ret = -ENOMEM;
 	p = ec_node_parse(lex, node->cmd_str);
 	if (p == NULL)
 		goto fail;
 
-	ret = -EINVAL;
-	if (!ec_parse_matches(p))
+	if (!ec_parse_matches(p)) {
+		errno = EINVAL;
 		goto fail;
-	if (!ec_parse_has_child(p))
+	}
+	if (!ec_parse_has_child(p)) {
+		errno = EINVAL;
 		goto fail;
+	}
 
 	ret = ec_node_expr_eval(&result, expr, ec_parse_get_first_child(p),
 				&test_ops, node);
@@ -354,7 +367,8 @@ fail:
 	ec_node_free(expr);
 	ec_node_free(lex);
 	ec_node_free(cmd);
-	return ret;
+
+	return -1;
 }
 
 static int
@@ -363,8 +377,6 @@ ec_node_cmd_parse(const struct ec_node *gen_node, struct ec_parse *state,
 {
 	struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node;
 
-	if (node->cmd == NULL)
-		return -ENOENT;
 	return ec_node_parse_child(node->cmd, state, strvec);
 }
 
@@ -375,8 +387,6 @@ ec_node_cmd_complete(const struct ec_node *gen_node,
 {
 	struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node;
 
-	if (node->cmd == NULL)
-		return -ENOENT;
 	return ec_node_complete_child(node->cmd, comp, strvec);
 }
 
diff --git a/lib/ecoli_node_expr.c b/lib/ecoli_node_expr.c
index 8a0d319..41a14bb 100644
--- a/lib/ecoli_node_expr.c
+++ b/lib/ecoli_node_expr.c
@@ -51,8 +51,11 @@ static int ec_node_expr_parse(const struct ec_node *gen_node,
 {
 	struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 
-	if (node->child == NULL)
-		return -ENOENT;
+	if (node->child == NULL) {
+		errno = ENOENT;
+		return -1;
+	}
+
 	return ec_node_parse_child(node->child, state, strvec);
 }
 
@@ -63,8 +66,11 @@ ec_node_expr_complete(const struct ec_node *gen_node,
 {
 	struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 
-	if (node->child == NULL)
-		return -ENOENT;
+	if (node->child == NULL) {
+		errno = ENOENT;
+		return -1;
+	}
+
 	return ec_node_complete_child(node->child, comp, strvec);
 }
 
@@ -101,16 +107,20 @@ static int ec_node_expr_build(struct ec_node_expr *node)
 		*pre_op = NULL, *post_op = NULL,
 		*post = NULL, *weak = NULL;
 	unsigned int i;
-	int ret;
 
 	ec_node_free(node->child);
 	node->child = NULL;
 
-	if (node->val_node == NULL)
-		return -EINVAL;
+	if (node->val_node == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
 	if (node->bin_ops_len == 0 && node->pre_ops_len == 0 &&
-			node->post_ops_len == 0)
-		return -EINVAL;
+			node->post_ops_len == 0) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	/*
 	 * Example of created grammar:
@@ -128,7 +138,6 @@ static int ec_node_expr_build(struct ec_node_expr *node)
 
 	/* create the object, we will initialize it later: this is
 	 * needed because we have a circular dependency */
-	ret = -ENOMEM;
 	weak = ec_node("weakref", "weak");
 	if (weak == NULL)
 		return -1;
@@ -220,7 +229,7 @@ fail:
 	ec_node_free(post);
 	ec_node_free(weak);
 
-	return ret;
+	return -1;
 }
 
 static struct ec_node_type ec_node_expr_type = {
@@ -236,15 +245,14 @@ EC_NODE_TYPE_REGISTER(ec_node_expr_type);
 int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node)
 {
 	struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
-	int ret;
 
-	ret = ec_node_check_type(gen_node, &ec_node_expr_type);
-	if (ret < 0)
-		return ret;
+	if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
+		goto fail;
 
-	ret = -EINVAL;
-	if (val_node == NULL)
+	if (val_node == NULL) {
+		errno = EINVAL;
 		goto fail;
+	}
 
 	ec_node_free(node->val_node);
 	node->val_node = val_node;
@@ -254,7 +262,7 @@ int ec_node_expr_set_val_node(struct ec_node *gen_node, struct ec_node *val_node
 
 fail:
 	ec_node_free(val_node);
-	return ret;
+	return -1;
 }
 
 /* add a binary operator */
@@ -262,17 +270,15 @@ int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
 {
 	struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 	struct ec_node **bin_ops;
-	int ret;
 
-	ret = ec_node_check_type(gen_node, &ec_node_expr_type);
-	if (ret < 0)
-		return ret;
+	if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
+		goto fail;
 
-	ret = -EINVAL;
-	if (node == NULL || op == NULL)
+	if (node == NULL || op == NULL) {
+		errno = EINVAL;
 		goto fail;
+	}
 
-	ret = -ENOMEM;
 	bin_ops = ec_realloc(node->bin_ops,
 		(node->bin_ops_len + 1) * sizeof(*node->bin_ops));
 	if (bin_ops == NULL)
@@ -287,7 +293,7 @@ int ec_node_expr_add_bin_op(struct ec_node *gen_node, struct ec_node *op)
 
 fail:
 	ec_node_free(op);
-	return ret;
+	return -1;
 }
 
 /* add a unary pre-operator */
@@ -295,17 +301,15 @@ int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
 {
 	struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 	struct ec_node **pre_ops;
-	int ret;
 
-	ret = ec_node_check_type(gen_node, &ec_node_expr_type);
-	if (ret < 0)
-		return ret;
+	if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
+		goto fail;
 
-	ret = -EINVAL;
-	if (node == NULL || op == NULL)
+	if (node == NULL || op == NULL) {
+		errno = EINVAL;
 		goto fail;
+	}
 
-	ret = -ENOMEM;
 	pre_ops = ec_realloc(node->pre_ops,
 		(node->pre_ops_len + 1) * sizeof(*node->pre_ops));
 	if (pre_ops == NULL)
@@ -320,7 +324,7 @@ int ec_node_expr_add_pre_op(struct ec_node *gen_node, struct ec_node *op)
 
 fail:
 	ec_node_free(op);
-	return ret;
+	return -1;
 }
 
 /* add a unary post-operator */
@@ -328,17 +332,15 @@ int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
 {
 	struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 	struct ec_node **post_ops;
-	int ret;
 
-	ret = ec_node_check_type(gen_node, &ec_node_expr_type);
-	if (ret < 0)
-		return ret;
+	if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
+		goto fail;
 
-	ret = -EINVAL;
-	if (node == NULL || op == NULL)
+	if (node == NULL || op == NULL) {
+		errno = EINVAL;
 		goto fail;
+	}
 
-	ret = -ENOMEM;
 	post_ops = ec_realloc(node->post_ops,
 		(node->post_ops_len + 1) * sizeof(*node->post_ops));
 	if (post_ops == NULL)
@@ -353,7 +355,7 @@ int ec_node_expr_add_post_op(struct ec_node *gen_node, struct ec_node *op)
 
 fail:
 	ec_node_free(op);
-	return ret;
+	return -1;
 }
 
 /* add parenthesis symbols */
@@ -362,17 +364,15 @@ int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
 {
 	struct ec_node_expr *node = (struct ec_node_expr *)gen_node;
 	struct ec_node **open_ops, **close_ops;
-	int ret;
 
-	ret = ec_node_check_type(gen_node, &ec_node_expr_type);
-	if (ret < 0)
-		return ret;
+	if (ec_node_check_type(gen_node, &ec_node_expr_type) < 0)
+		goto fail;
 
-	ret = -EINVAL;
-	if (node == NULL || open == NULL || close == NULL)
+	if (node == NULL || open == NULL || close == NULL) {
+		errno = EINVAL;
 		goto fail;
+	}
 
-	ret = -ENOMEM;
 	open_ops = ec_realloc(node->open_ops,
 		(node->paren_len + 1) * sizeof(*node->open_ops));
 	if (open_ops == NULL)
@@ -394,7 +394,7 @@ int ec_node_expr_add_parenthesis(struct ec_node *gen_node,
 fail:
 	ec_node_free(open);
 	ec_node_free(close);
-	return ret;
+	return -1;
 }
 
 enum expr_node_type {
@@ -453,8 +453,6 @@ static int merge_results(void *userctx,
 	const struct ec_node_expr_eval_ops *ops,
 	struct result *x, const struct result *y)
 {
-	int ret;
-
 	if (y->has_val == 0 && y->op == NULL)
 		return 0;
 	if (x->has_val == 0 && x->op == NULL) {
@@ -464,10 +462,9 @@ static int merge_results(void *userctx,
 
 	if (x->has_val && y->has_val && y->op != NULL) {
 		if (y->op_type == BIN_OP) {
-			ret = ops->eval_bin_op(&x->val, userctx, x->val,
-					y->op, y->val);
-			if (ret < 0)
-				return ret;
+			if (ops->eval_bin_op(&x->val, userctx, x->val,
+					y->op, y->val) < 0)
+				return -1;
 
 			return 0;
 		}
@@ -475,9 +472,9 @@ static int merge_results(void *userctx,
 
 	if (x->has_val == 0 && x->op != NULL && y->has_val && y->op == NULL) {
 		if (x->op_type == PRE_OP) {
-			ret = ops->eval_pre_op(&x->val, userctx, y->val, x->op);
-			if (ret < 0)
-				return ret;
+			if (ops->eval_pre_op(&x->val, userctx, y->val,
+						x->op) < 0)
+				return -1;
 			x->has_val = true;
 			x->op_type = NONE;
 			x->op = NULL;
@@ -490,15 +487,14 @@ static int merge_results(void *userctx,
 	}
 
 	if (x->has_val && x->op == NULL && y->has_val == 0 && y->op != NULL) {
-		ret = ops->eval_post_op(&x->val, userctx, x->val, y->op);
-		if (ret < 0)
-			return ret;
+		if (ops->eval_post_op(&x->val, userctx, x->val, y->op) < 0)
+			return -1;
 
 		return 0;
 	}
 
 	assert(false); /* we should not get here */
-	return -EINVAL;
+	return -1;
 }
 
 static int eval_expression(struct result *result,
@@ -512,15 +508,13 @@ static int eval_expression(struct result *result,
 	struct result child_result;
 	struct ec_parse *child;
 	enum expr_node_type type;
-	int ret;
 
 	memset(result, 0, sizeof(*result));
 	memset(&child_result, 0, sizeof(child_result));
 
 	type = get_node_type(expr_gen_node, ec_parse_get_node(parse));
 	if (type == VAL) {
-		ret = ops->eval_var(&result->val, userctx, parse);
-		if (ret < 0)
+		if (ops->eval_var(&result->val, userctx, parse) < 0)
 			goto fail;
 		result->has_val = 1;
 	} else if (type == PRE_OP || type == POST_OP || type == BIN_OP) {
@@ -539,22 +533,19 @@ static int eval_expression(struct result *result,
 			continue;
 		}
 
-		ret = eval_expression(&child_result, userctx, ops,
-			expr_gen_node, child);
-		if (ret < 0)
+		if (eval_expression(&child_result, userctx, ops,
+			expr_gen_node, child) < 0)
 			goto fail;
 
-		ret = merge_results(userctx, ops, result, &child_result);
-		if (ret < 0)
+		if (merge_results(userctx, ops, result, &child_result) < 0)
 			goto fail;
 
 		memset(&child_result, 0, sizeof(child_result));
 	}
 
 	if (open != NULL && close != NULL) {
-		ret = ops->eval_parenthesis(&result->val, userctx, open, close,
-			result->val);
-		if (ret < 0)
+		if (ops->eval_parenthesis(&result->val, userctx, open, close,
+			result->val) < 0)
 			goto fail;
 	}
 
@@ -567,7 +558,7 @@ fail:
 		ops->eval_free(child_result.val, userctx);
 	memset(result, 0, sizeof(*result));
 
-	return ret;
+	return -1;
 }
 
 int ec_node_expr_eval(void **user_result, const struct ec_node *node,
@@ -575,23 +566,25 @@ int ec_node_expr_eval(void **user_result, const struct ec_node *node,
 	void *userctx)
 {
 	struct result result;
-	int ret;
 
 	if (ops == NULL || ops->eval_var == NULL || ops->eval_pre_op == NULL ||
 			ops->eval_post_op == NULL || ops->eval_bin_op == NULL ||
-			ops->eval_parenthesis == NULL || ops->eval_free == NULL)
-		return -EINVAL;
+			ops->eval_parenthesis == NULL ||
+			ops->eval_free == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
 
-	ret = ec_node_check_type(node, &ec_node_expr_type);
-	if (ret < 0)
-		return ret;
+	if (ec_node_check_type(node, &ec_node_expr_type) < 0)
+		return -1;
 
-	if (!ec_parse_matches(parse))
-		return -EINVAL;
+	if (!ec_parse_matches(parse)) {
+		errno = EINVAL;
+		return -1;
+	}
 
-	ret = eval_expression(&result, userctx, ops, node, parse);
-	if (ret < 0)
-		return ret;
+	if (eval_expression(&result, userctx, ops, node, parse) < 0)
+		return -1;
 
 	assert(result.has_val);
 	assert(result.op == NULL);
diff --git a/lib/ecoli_node_expr_test.c b/lib/ecoli_node_expr_test.c
index 2c9d58e..93e33a4 100644
--- a/lib/ecoli_node_expr_test.c
+++ b/lib/ecoli_node_expr_test.c
@@ -36,16 +36,18 @@ ec_node_expr_test_eval_var(void **result, void *userctx,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(var);
-	if (ec_strvec_len(vec) != 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) != 1) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	node = ec_parse_get_node(var);
 	if (ec_node_int_getval(node, ec_strvec_val(vec, 0), &val) < 0)
-		return -EINVAL;
+		return -1;
 
 	eval = ec_malloc(sizeof(*eval));
 	if (eval == NULL)
-		return -ENOMEM;
+		return -1;
 
 	eval->val = val;
 	EC_LOG(EC_LOG_DEBUG, "eval var %d\n", eval->val);
@@ -65,13 +67,18 @@ ec_node_expr_test_eval_pre_op(void **result, void *userctx, void *operand,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(operator);
-	if (ec_strvec_len(vec) != 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) != 1) {
+		errno = EINVAL;
+		return -1;
+	}
 
-	if (!strcmp(ec_strvec_val(vec, 0), "!"))
+	if (!strcmp(ec_strvec_val(vec, 0), "!")) {
 		eval->val = !eval->val;
-	else
-		return -EINVAL;
+	} else {
+		errno = EINVAL;
+		return -1;
+	}
+
 
 	EC_LOG(EC_LOG_DEBUG, "eval pre_op %d\n", eval->val);
 	*result = eval;
@@ -90,13 +97,17 @@ ec_node_expr_test_eval_post_op(void **result, void *userctx, void *operand,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(operator);
-	if (ec_strvec_len(vec) != 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) != 1) {
+		errno = EINVAL;
+		return -1;
+	}
 
-	if (!strcmp(ec_strvec_val(vec, 0), "^"))
+	if (!strcmp(ec_strvec_val(vec, 0), "^")) {
 		eval->val = eval->val * eval->val;
-	else
-		return -EINVAL;
+	} else {
+		errno = EINVAL;
+		return -1;
+	}
 
 	EC_LOG(EC_LOG_DEBUG, "eval post_op %d\n", eval->val);
 	*result = eval;
@@ -117,15 +128,19 @@ ec_node_expr_test_eval_bin_op(void **result, void *userctx, void *operand1,
 
 	/* get parsed string vector, it should contain only one str */
 	vec = ec_parse_strvec(operator);
-	if (ec_strvec_len(vec) != 1)
-		return -EINVAL;
+	if (ec_strvec_len(vec) != 1) {
+		errno = EINVAL;
+		return -1;
+	}
 
-	if (!strcmp(ec_strvec_val(vec, 0), "+"))
+	if (!strcmp(ec_strvec_val(vec, 0), "+")) {
 		eval1->val = eval1->val + eval2->val;
-	else if (!strcmp(ec_strvec_val(vec, 0), "*"))
+	} else if (!strcmp(ec_strvec_val(vec, 0), "*")) {
 		eval1->val = eval1->val * eval2->val;
-	else
-		return -EINVAL;
+	} else {
+		errno = EINVAL;
+		return -1;
+	}
 
 	EC_LOG(EC_LOG_DEBUG, "eval bin_op %d\n", eval1->val);
 	ec_free(eval2);
diff --git a/lib/ecoli_node_int.c b/lib/ecoli_node_int.c
index 2e1f2a2..34fd501 100644
--- a/lib/ecoli_node_int.c
+++ b/lib/ecoli_node_int.c
@@ -51,14 +51,20 @@ static int parse_llint(struct ec_node_int_uint *node, const char *str,
 			(errno != 0 && *val == 0))
 		return -1;
 
-	if (node->check_min && *val < node->min)
+	if (node->check_min && *val < node->min) {
+		errno = ERANGE;
 		return -1;
+	}
 
-	if (node->check_max && *val > node->max)
+	if (node->check_max && *val > node->max) {
+		errno = ERANGE;
 		return -1;
+	}
 
-	if (*endptr != 0)
+	if (*endptr != 0) {
+		errno = EINVAL;
 		return -1;
+	}
 
 	return 0;
 }
diff --git a/lib/ecoli_node_many.c b/lib/ecoli_node_many.c
index 7748045..69e8e6c 100644
--- a/lib/ecoli_node_many.c
+++ b/lib/ecoli_node_many.c
@@ -42,10 +42,8 @@ static int ec_node_many_parse(const struct ec_node *gen_node,
 	for (count = 0; node->max == 0 || count < node->max; count++) {
 		childvec = ec_strvec_ndup(strvec, off,
 			ec_strvec_len(strvec) - off);
-		if (childvec == NULL) {
-			ret = -ENOMEM;
+		if (childvec == NULL)
 			goto fail;
-		}
 
 		ret = ec_node_parse_child(node->child, state, childvec);
 		if (ret < 0)
@@ -77,7 +75,7 @@ static int ec_node_many_parse(const struct ec_node *gen_node,
 
 fail:
 	ec_strvec_free(childvec);
-	return ret;
+	return -1;
 }
 
 static int
diff --git a/lib/ecoli_node_re.c b/lib/ecoli_node_re.c
index ee381d2..05db048 100644
--- a/lib/ecoli_node_re.c
+++ b/lib/ecoli_node_re.c
@@ -75,17 +75,20 @@ int ec_node_re_set_regexp(struct ec_node *gen_node, const char *str)
 	regex_t re;
 	int ret;
 
-	if (str == NULL)
-		return -EINVAL;
+	EC_CHECK_ARG(str != NULL, -1, EINVAL);
 
-	ret = -ENOMEM;
 	str_copy = ec_strdup(str);
 	if (str_copy == NULL)
 		goto fail;
 
-	ret = -EINVAL;
-	if (regcomp(&re, str_copy, REG_EXTENDED) != 0)
+	ret = regcomp(&re, str_copy, REG_EXTENDED);
+	if (ret != 0) {
+		if (ret == REG_ESPACE)
+			errno = ENOMEM;
+		else
+			errno = EINVAL;
 		goto fail;
+	}
 
 	if (node->re_str != NULL) {
 		ec_free(node->re_str);
@@ -98,7 +101,7 @@ int ec_node_re_set_regexp(struct ec_node *gen_node, const char *str)
 
 fail:
 	ec_free(str_copy);
-	return ret;
+	return -1;
 }
 
 struct ec_node *ec_node_re(const char *id, const char *re_str)
diff --git a/lib/ecoli_node_re_lex.c b/lib/ecoli_node_re_lex.c
index a74685f..a017635 100644
--- a/lib/ecoli_node_re_lex.c
+++ b/lib/ecoli_node_re_lex.c
@@ -112,10 +112,8 @@ ec_node_re_lex_parse(const struct ec_node *gen_node,
 		str = ec_strvec_val(strvec, 0);
 		new_vec = tokenize(node->table, node->len, str);
 	}
-	if (new_vec == NULL) {
-		ret = -ENOMEM;
+	if (new_vec == NULL)
 		goto fail;
-	}
 
 	ret = ec_node_parse_child(node->child, state, new_vec);
 	if (ret < 0)
@@ -137,7 +135,7 @@ ec_node_re_lex_parse(const struct ec_node *gen_node,
 
  fail:
 	ec_strvec_free(new_vec);
-	return ret;
+	return -1;
 }
 
 static void ec_node_re_lex_free_priv(struct ec_node *gen_node)
@@ -171,12 +169,10 @@ int ec_node_re_lex_add(struct ec_node *gen_node, const char *pattern, int keep)
 	int ret;
 	char *pat_dup = NULL;
 
-	ret = -ENOMEM;
 	pat_dup = ec_strdup(pattern);
 	if (pat_dup == NULL)
 		goto fail;
 
-	ret = -ENOMEM;
 	table = ec_realloc(node->table, sizeof(*table) * (node->len + 1));
 	if (table == NULL)
 		goto fail;
@@ -187,9 +183,9 @@ int ec_node_re_lex_add(struct ec_node *gen_node, const char *pattern, int keep)
 			"Regular expression <%s> compilation failed: %d\n",
 			pattern, ret);
 		if (ret == REG_ESPACE)
-			ret = -ENOMEM;
+			errno = ENOMEM;
 		else
-			ret = -EINVAL;
+			errno = EINVAL;
 
 		goto fail;
 	}
@@ -203,7 +199,7 @@ int ec_node_re_lex_add(struct ec_node *gen_node, const char *pattern, int keep)
 
 fail:
 	ec_free(pat_dup);
-	return ret;
+	return -1;
 }
 
 struct ec_node *ec_node_re_lex(const char *id, struct ec_node *child)
diff --git a/lib/ecoli_node_seq.c b/lib/ecoli_node_seq.c
index 164063e..77738ed 100644
--- a/lib/ecoli_node_seq.c
+++ b/lib/ecoli_node_seq.c
@@ -45,10 +45,8 @@ ec_node_seq_parse(const struct ec_node *gen_node,
 	for (i = 0; i < node->len; i++) {
 		childvec = ec_strvec_ndup(strvec, len,
 			ec_strvec_len(strvec) - len);
-		if (childvec == NULL) {
-			ret = -ENOMEM;
+		if (childvec == NULL)
 			goto fail;
-		}
 
 		ret = ec_node_parse_child(node->table[i], state, childvec);
 		if (ret < 0)
@@ -69,7 +67,7 @@ ec_node_seq_parse(const struct ec_node *gen_node,
 
 fail:
 	ec_strvec_free(childvec);
-	return ret;
+	return -1;
 }
 
 static int
diff --git a/lib/ecoli_node_sh_lex.c b/lib/ecoli_node_sh_lex.c
index c3a79ab..53122c4 100644
--- a/lib/ecoli_node_sh_lex.c
+++ b/lib/ecoli_node_sh_lex.c
@@ -93,7 +93,7 @@ static char *unquote_str(const char *str, size_t n, int allow_missing_quote,
 			*missing_quote = str[0];
 		if (allow_missing_quote == 0) {
 			ec_free(dst);
-			errno = EINVAL;
+			errno = EBADMSG;
 			return NULL;
 		}
 	}
@@ -229,13 +229,10 @@ ec_node_sh_lex_parse(const struct ec_node *gen_node,
 		str = ec_strvec_val(strvec, 0);
 		new_vec = tokenize(str, 0, 0, NULL);
 	}
-	if (new_vec == NULL) {
-		if (errno == EINVAL)
-			ret = EC_PARSE_NOMATCH;
-		else
-			ret = -ENOMEM;
+	if (new_vec == NULL && errno == EBADMSG) /* quotes not closed */
+		return EC_PARSE_NOMATCH;
+	if (new_vec == NULL)
 		goto fail;
-	}
 
 	ret = ec_node_parse_child(node->child, state, new_vec);
 	if (ret < 0)
@@ -257,7 +254,7 @@ ec_node_sh_lex_parse(const struct ec_node *gen_node,
 
  fail:
 	ec_strvec_free(new_vec);
-	return ret;
+	return -1;
 }
 
 static int
diff --git a/lib/ecoli_node_str.c b/lib/ecoli_node_str.c
index 6b11ebc..6f373e6 100644
--- a/lib/ecoli_node_str.c
+++ b/lib/ecoli_node_str.c
@@ -101,19 +101,24 @@ EC_NODE_TYPE_REGISTER(ec_node_str_type);
 int ec_node_str_set_str(struct ec_node *gen_node, const char *str)
 {
 	struct ec_node_str *node = (struct ec_node_str *)gen_node;
+	char *s = NULL;
 	int ret;
 
 	ret = ec_node_check_type(gen_node, &ec_node_str_type);
 	if (ret < 0)
 		return ret;
 
-	if (str == NULL)
-		return -EINVAL;
-	ec_free(node->string);
-	node->string = ec_strdup(str);
-	if (node->string == NULL)
-		return -ENOMEM;
+	if (str == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
 
+	s = ec_strdup(str);
+	if (s == NULL)
+		return -1;
+
+	ec_free(node->string);
+	node->string = s;
 	node->len = strlen(node->string);
 
 	return 0;
diff --git a/lib/ecoli_node_subset.c b/lib/ecoli_node_subset.c
index 62a2871..cc3442b 100644
--- a/lib/ecoli_node_subset.c
+++ b/lib/ecoli_node_subset.c
@@ -54,10 +54,8 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
 	memset(&best_result, 0, sizeof(best_result));
 
 	child_table = ec_calloc(table_len - 1, sizeof(*child_table));
-	if (child_table == NULL) {
-		ret = -ENOMEM;
+	if (child_table == NULL)
 		goto fail;
-	}
 
 	for (i = 0; i < table_len; i++) {
 		/* try to parse elt i */
@@ -80,10 +78,8 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
 		len = ret;
 		childvec = ec_strvec_ndup(strvec, len,
 					ec_strvec_len(strvec) - len);
-		if (childvec == NULL) {
-			ret = -ENOMEM;
+		if (childvec == NULL)
 			goto fail;
-		}
 
 		memset(&result, 0, sizeof(result));
 		ret = __ec_node_subset_parse(&result, child_table,
@@ -122,7 +118,7 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
 	ec_parse_free(best_parse);
 	ec_strvec_free(childvec);
 	ec_free(child_table);
-	return ret;
+	return -1;
 }
 
 static int
diff --git a/lib/ecoli_parse.c b/lib/ecoli_parse.c
index a6def04..6396fc1 100644
--- a/lib/ecoli_parse.c
+++ b/lib/ecoli_parse.c
@@ -42,38 +42,46 @@ static int __ec_node_parse_child(const struct ec_node *node,
 	struct ec_parse *child = NULL;
 	int ret;
 
-	if (ec_node_type(node)->parse == NULL)
-		return -ENOTSUP;
+	if (ec_node_type(node)->parse == NULL) {
+		errno = ENOTSUP;
+		return -1;
+	}
 
 	if (!is_root) {
 		child = ec_parse(node);
 		if (child == NULL)
-			return -ENOMEM;
+			return -1;
 
 		ec_parse_link_child(state, child);
 	} else {
 		child = state;
 	}
 	ret = ec_node_type(node)->parse(node, child, strvec);
-	if (ret < 0 || ret == EC_PARSE_NOMATCH)
-		goto free;
+	if (ret < 0)
+		goto fail;
 
-	match_strvec = ec_strvec_ndup(strvec, 0, ret);
-	if (match_strvec == NULL) {
-		ret = -ENOMEM;
-		goto free;
+	if (ret == EC_PARSE_NOMATCH) {
+		if (!is_root) {
+			ec_parse_unlink_child(state, child);
+			ec_parse_free(child);
+		}
+		return ret;
 	}
 
+	match_strvec = ec_strvec_ndup(strvec, 0, ret);
+	if (match_strvec == NULL)
+		goto fail;
+
 	child->strvec = match_strvec;
 
 	return ret;
 
-free:
+fail:
 	if (!is_root) {
 		ec_parse_unlink_child(state, child);
 		ec_parse_free(child);
 	}
-	return ret;
+	return -1;
 }
 
 int ec_node_parse_child(const struct ec_node *node, struct ec_parse *state,
@@ -244,7 +252,7 @@ static void __ec_parse_dump(FILE *out,
 {
 	struct ec_parse *child;
 	const struct ec_strvec *vec;
-	const char *id, *typename = "none";
+	const char *id = "none", *typename = "none";
 
 	/* node can be null when parsing is incomplete */
 	if (parse->node != NULL) {
diff --git a/lib/ecoli_parse.h b/lib/ecoli_parse.h
index 0559214..79e644f 100644
--- a/lib/ecoli_parse.h
+++ b/lib/ecoli_parse.h
@@ -92,9 +92,9 @@ struct ec_parse *ec_node_parse_strvec(const struct ec_node *node,
  *   possible descendants.
  *
  * return:
+ * the number of matched strings in strvec on success
  * EC_PARSE_NOMATCH (positive) if it does not match
- * any other negative value (-errno) for other errors
- * the number of matched strings in strvec
+ * -1 on error, and errno is set
  */
 int ec_node_parse_child(const struct ec_node *node,
 			struct ec_parse *state,
diff --git a/lib/ecoli_strvec.c b/lib/ecoli_strvec.c
index bd23d98..132183d 100644
--- a/lib/ecoli_strvec.c
+++ b/lib/ecoli_strvec.c
@@ -42,18 +42,18 @@ int ec_strvec_add(struct ec_strvec *strvec, const char *s)
 	new_vec = ec_realloc(strvec->vec,
 		sizeof(*strvec->vec) * (strvec->len + 1));
 	if (new_vec == NULL)
-		return -ENOMEM;
+		return -1;
 
 	strvec->vec = new_vec;
 
 	elt = ec_malloc(sizeof(*elt));
 	if (elt == NULL)
-		return -ENOMEM;
+		return -1;
 
 	elt->str = ec_strdup(s);
 	if (elt->str == NULL) {
 		ec_free(elt);
-		return -ENOMEM;
+		return -1;
 	}
 	elt->refcnt = 1;
 
@@ -69,6 +69,9 @@ struct ec_strvec *ec_strvec_from_array(const char * const *strarr,
 	size_t i;
 
 	strvec = ec_strvec();
+	if (strvec == NULL)
+		goto fail;
+
 	for (i = 0; i < n; i++) {
 		if (ec_strvec_add(strvec, strarr[i]) < 0)
 			goto fail;
@@ -342,6 +345,16 @@ static int ec_strvec_testcase(void)
 	free(buf);
 	buf = NULL;
 
+	ec_strvec_del_last(strvec);
+	strvec2 = EC_STRVEC("0");
+	if (strvec2 == NULL) {
+		EC_TEST_ERR("cannot create strvec from array\n");
+		goto fail;
+	}
+	testres |= EC_TEST_CHECK(ec_strvec_cmp(strvec, strvec2) == 0,
+		"strvec and strvec2 should be equal\n");
+	ec_strvec_free(strvec2);
+
 	f = open_memstream(&buf, &buflen);
 	if (f == NULL)
 		goto fail;
diff --git a/lib/ecoli_vec.c b/lib/ecoli_vec.c
index 1e07c48..fe8c572 100644
--- a/lib/ecoli_vec.c
+++ b/lib/ecoli_vec.c
@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <assert.h>
 
+#include <ecoli_assert.h>
 #include <ecoli_malloc.h>
 #include <ecoli_log.h>
 #include <ecoli_test.h>
@@ -69,11 +70,11 @@ int ec_vec_add_by_ref(struct ec_vec *vec, void *ptr)
 	if (vec->len + 1 > vec->size) {
 		new_vec = ec_realloc(vec->vec, vec->elt_size * (vec->len + 1));
 		if (new_vec == NULL)
-			return -ENOMEM;
+			return -1;
 		vec->size = vec->len + 1;
+		vec->vec = new_vec;
 	}
 
-	vec->vec = new_vec;
 	memcpy(get_obj(vec, vec->len), ptr, vec->elt_size);
 	vec->len++;
 
@@ -82,40 +83,35 @@ int ec_vec_add_by_ref(struct ec_vec *vec, void *ptr)
 
 int ec_vec_add_ptr(struct ec_vec *vec, void *elt)
 {
-	if (vec->elt_size != sizeof(elt))
-		return -EINVAL;
+	EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
 
 	return ec_vec_add_by_ref(vec, &elt);
 }
 
 int ec_vec_add_u8(struct ec_vec *vec, uint8_t elt)
 {
-	if (vec->elt_size != sizeof(elt))
-		return -EINVAL;
+	EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
 
 	return ec_vec_add_by_ref(vec, &elt);
 }
 
 int ec_vec_add_u16(struct ec_vec *vec, uint16_t elt)
 {
-	if (vec->elt_size != sizeof(elt))
-		return -EINVAL;
+	EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
 
 	return ec_vec_add_by_ref(vec, &elt);
 }
 
 int ec_vec_add_u32(struct ec_vec *vec, uint32_t elt)
 {
-	if (vec->elt_size != sizeof(elt))
-		return -EINVAL;
+	EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
 
 	return ec_vec_add_by_ref(vec, &elt);
 }
 
 int ec_vec_add_u64(struct ec_vec *vec, uint64_t elt)
 {
-	if (vec->elt_size != sizeof(elt))
-		return -EINVAL;
+	EC_CHECK_ARG(vec->elt_size == sizeof(elt), -1, EINVAL);
 
 	return ec_vec_add_by_ref(vec, &elt);
 }
diff --git a/lib/main-readline.c b/lib/main-readline.c
index 91a1e6e..47a26fb 100644
--- a/lib/main-readline.c
+++ b/lib/main-readline.c
@@ -136,10 +136,10 @@ static char *get_node_help(const struct ec_comp_item *item)
 
 static int show_help(int ignore, int invoking_key)
 {
-	struct ec_comp_iter *iter;
+	struct ec_comp_iter *iter = NULL;
 	const struct ec_comp_group *grp, *prev_grp = NULL;
 	const struct ec_comp_item *item;
-	struct ec_comp *c;
+	struct ec_comp *c = NULL;
 	struct ec_parse *p;
 	char *line = NULL;
 	unsigned int count;
diff --git a/lib/todo.txt b/lib/todo.txt
index ccc5824..4517a79 100644
--- a/lib/todo.txt
+++ b/lib/todo.txt
@@ -40,6 +40,8 @@ X save node path in completion to fix help string
 - anything better than weakref?
 - add ec_node_defaults.[ch] providing usual implementations of node methods
 X use vec for strvec
+- ELOOP in case of loop
+- remove weakref?
 
 dependencies
 ============