From 044f2e33e83ec36df6601e3950820d07facde0a7 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Sun, 18 Mar 2018 22:39:47 +0100 Subject: [PATCH] standardize return values + errno --- lib/Makefile | 2 +- lib/ecoli_assert.h | 24 +++++- lib/ecoli_complete.c | 50 ++++++----- lib/ecoli_node.c | 14 +++- lib/ecoli_node_cmd.c | 82 ++++++++++-------- lib/ecoli_node_expr.c | 165 ++++++++++++++++++------------------- lib/ecoli_node_expr_test.c | 55 ++++++++----- lib/ecoli_node_int.c | 12 ++- lib/ecoli_node_many.c | 6 +- lib/ecoli_node_re.c | 15 ++-- lib/ecoli_node_re_lex.c | 14 ++-- lib/ecoli_node_seq.c | 6 +- lib/ecoli_node_sh_lex.c | 13 ++- lib/ecoli_node_str.c | 17 ++-- lib/ecoli_node_subset.c | 10 +-- lib/ecoli_parse.c | 32 ++++--- lib/ecoli_parse.h | 4 +- lib/ecoli_strvec.c | 19 ++++- lib/ecoli_vec.c | 20 ++--- lib/main-readline.c | 4 +- lib/todo.txt | 2 + 21 files changed, 317 insertions(+), 249 deletions(-) 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 #include +#include #include #include #include @@ -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 ============ -- 2.39.5