X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fecoli_node_cmd.c;h=c61b75922f1c3c79b479f6d84cfb9f875782a77c;hb=804dfa9a29a52ebe59bbf93d222adde3c1c3938c;hp=bd2f76784a36843009b28758f52f136ee4a29fb7;hpb=f4ec52ffc80b673a0f7e848c568359abf4f3bc47;p=protos%2Flibecoli.git diff --git a/lib/ecoli_node_cmd.c b/lib/ecoli_node_cmd.c index bd2f767..c61b759 100644 --- a/lib/ecoli_node_cmd.c +++ b/lib/ecoli_node_cmd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -411,12 +412,21 @@ ec_node_cmd_complete(const struct ec_node *gen_node, static void ec_node_cmd_free_priv(struct ec_node *gen_node) { struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; + size_t i; ec_free(node->cmd_str); - ec_node_free(node->cmd); + node->cmd_str = NULL; ec_node_free(node->expr); + node->expr = NULL; ec_node_free(node->parser); + node->parser = NULL; + ec_node_free(node->cmd); + node->cmd = NULL; + for (i = 0; i < node->len; i++) + ec_node_free(node->table[i]); ec_free(node->table); + node->table = NULL; + node->len = 0; } static const struct ec_config_schema ec_node_cmd_subschema[] = { @@ -424,6 +434,9 @@ static const struct ec_config_schema ec_node_cmd_subschema[] = { .desc = "A child node whose id is referenced in the expression.", .type = EC_CONFIG_TYPE_NODE, }, + { + .type = EC_CONFIG_TYPE_NONE, + }, }; static const struct ec_config_schema ec_node_cmd_schema[] = { @@ -442,7 +455,9 @@ static const struct ec_config_schema ec_node_cmd_schema[] = { .desc = "The list of children nodes.", .type = EC_CONFIG_TYPE_LIST, .subschema = ec_node_cmd_subschema, - .subschema_len = EC_COUNT_OF(ec_node_cmd_subschema), + }, + { + .type = EC_CONFIG_TYPE_NONE, }, }; @@ -450,11 +465,11 @@ static int ec_node_cmd_set_config(struct ec_node *gen_node, const struct ec_config *config) { struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; - const struct ec_config *expr = NULL, *children = NULL, *child; + const struct ec_config *expr = NULL; struct ec_node *cmd = NULL; struct ec_node **table = NULL; char *cmd_str = NULL; - size_t n; + size_t len = 0, i; /* retrieve config locally */ expr = ec_config_dict_get(config, "expr"); @@ -463,46 +478,36 @@ static int ec_node_cmd_set_config(struct ec_node *gen_node, goto fail; } - children = ec_config_dict_get(config, "children"); - if (children == NULL) { - errno = EINVAL; + table = ec_node_config_node_list_to_table( + ec_config_dict_get(config, "children"), &len); + if (table == NULL) goto fail; - } cmd_str = ec_strdup(expr->string); if (cmd_str == NULL) goto fail; - n = 0; - TAILQ_FOREACH(child, &children->list, next) - n++; - - table = ec_malloc(n * sizeof(*table)); - if (table == NULL) - goto fail; - - n = 0; - TAILQ_FOREACH(child, &children->list, next) { - table[n] = child->node; - n++; - } - /* parse expression to build the cmd child node */ - cmd = ec_node_cmd_build(node, cmd_str, table, n); + cmd = ec_node_cmd_build(node, cmd_str, table, len); if (cmd == NULL) goto fail; + /* ok, store the config */ ec_node_free(node->cmd); node->cmd = cmd; ec_free(node->cmd_str); node->cmd_str = cmd_str; + for (i = 0; i < node->len; i++) + ec_node_free(node->table[i]); ec_free(node->table); node->table = table; - node->len = n; + node->len = len; return 0; fail: + for (i = 0; i < len; i++) + ec_node_free(table[i]); ec_free(table); ec_free(cmd_str); ec_node_free(cmd); @@ -513,24 +518,29 @@ static size_t ec_node_cmd_get_children_count(const struct ec_node *gen_node) { struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; - return node->len; + + if (node->cmd == NULL) + return 0; + return 1; } -static struct ec_node * -ec_node_cmd_get_child(const struct ec_node *gen_node, size_t i) +static int +ec_node_cmd_get_child(const struct ec_node *gen_node, size_t i, + struct ec_node **child, unsigned int *refs) { struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; - if (i >= node->len) - return NULL; + if (i > 0) + return -1; - return node->table[i]; + *child = node->cmd; + *refs = 1; + return 0; } static struct ec_node_type ec_node_cmd_type = { .name = "cmd", .schema = ec_node_cmd_schema, - .schema_len = EC_COUNT_OF(ec_node_cmd_schema), .set_config = ec_node_cmd_set_config, .parse = ec_node_cmd_parse, .complete = ec_node_cmd_complete, @@ -547,43 +557,35 @@ struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...) struct ec_config *config = NULL, *children = NULL; struct ec_node *gen_node = NULL; struct ec_node_cmd *node = NULL; - struct ec_node *child; va_list ap; + int ret; + /* this block must stay first, it frees the nodes on error */ va_start(ap, cmd); - child = va_arg(ap, struct ec_node *); + children = ec_node_config_node_list_from_vargs(ap); + va_end(ap); + if (children == NULL) + goto fail; - gen_node = __ec_node(&ec_node_cmd_type, id); + gen_node = ec_node_from_type(&ec_node_cmd_type, id); if (gen_node == NULL) - goto fail_free_children; + goto fail; node = (struct ec_node_cmd *)gen_node; node->expr = ec_node_cmd_build_expr(); if (node->expr == NULL) - goto fail_free_children; + goto fail; node->parser = ec_node_cmd_build_parser(node->expr); if (node->parser == NULL) - goto fail_free_children; + goto fail; config = ec_config_dict(); if (config == NULL) - goto fail_free_children; + goto fail; if (ec_config_dict_set(config, "expr", ec_config_string(cmd)) < 0) - goto fail_free_children; - - children = ec_config_list(); - if (children == NULL) - goto fail_free_children; - - for (; child != EC_NODE_ENDLIST; child = va_arg(ap, struct ec_node *)) { - if (child == NULL) - goto fail_free_children; - - if (ec_config_list_add(children, ec_config_node(child)) < 0) - goto fail_free_children; - } + goto fail; if (ec_config_dict_set(config, "children", children) < 0) { children = NULL; /* freed */ @@ -591,20 +593,17 @@ struct ec_node *__ec_node_cmd(const char *id, const char *cmd, ...) } children = NULL; - if (ec_node_set_config(gen_node, config) < 0) + ret = ec_node_set_config(gen_node, config); + config = NULL; /* freed */ + if (ret < 0) goto fail; - va_end(ap); - return gen_node; -fail_free_children: - for (; child != EC_NODE_ENDLIST; child = va_arg(ap, struct ec_node *)) - ec_node_free(child); fail: ec_node_free(gen_node); /* will also free added children */ + ec_config_free(children); ec_config_free(config); - va_end(ap); return NULL; } @@ -620,9 +619,6 @@ static int ec_node_cmd_testcase(void) ec_node_int("x", 0, 10, 10), ec_node_int("y", 20, 30, 10) ); - ec_node_free(node); - return 0; - if (node == NULL) { EC_LOG(EC_LOG_ERR, "cannot create node\n"); return -1;