X-Git-Url: http://git.droids-corp.org/?p=protos%2Flibecoli.git;a=blobdiff_plain;f=src%2Fecoli_node.c;fp=src%2Fecoli_node.c;h=1e9bf6b24d6c0449f38fb01e24faa7c01ce4082f;hp=935f4e6c0cbc8e8ab0d6adf9d9513e5609ccd3ef;hb=331d87b8f34493ea7eb4db75fa9d90b2e3ed503b;hpb=67b4d8d2b2593e3e64a848ce548bc0fd76bc440a diff --git a/src/ecoli_node.c b/src/ecoli_node.c index 935f4e6..1e9bf6b 100644 --- a/src/ecoli_node.c +++ b/src/ecoli_node.c @@ -25,17 +25,29 @@ EC_LOG_TYPE_REGISTER(node); +/* These states are used to mark the grammar graph when freeing, to + * detect loop. */ +enum ec_node_free_state { + EC_NODE_FREE_STATE_NONE, + EC_NODE_FREE_STATE_TRAVERSED, + EC_NODE_FREE_STATE_FREEABLE, + EC_NODE_FREE_STATE_NOT_FREEABLE, + EC_NODE_FREE_STATE_FREEING, +}; + +/** + * The grammar node structure. + */ struct ec_node { - const struct ec_node_type *type; - struct ec_config *config; /**< Generic configuration. */ - char *id; - char *desc; - struct ec_dict *attrs; - unsigned int refcnt; + const struct ec_node_type *type; /**< The node type. */ + struct ec_config *config; /**< Node configuration. */ + char *id; /**< Node identifier (EC_NO_ID if none). */ + struct ec_dict *attrs; /**< Attributes of the node. */ + unsigned int refcnt; /**< Reference counter. */ struct { - enum ec_node_free_state state; /**< State of loop detection */ + enum ec_node_free_state state; /**< State of loop detection. */ unsigned int refcnt; /**< Number of reachable references - * starting from node beeing freed */ + * starting from node beeing freed. */ } free; /**< Freeing state: used for loop detection */ }; @@ -56,14 +68,14 @@ ec_node_type_lookup(const char *name) return NULL; } -int ec_node_type_register(struct ec_node_type *type) +int ec_node_type_register(struct ec_node_type *type, bool override) { - if (ec_node_type_lookup(type->name) != NULL) { + if (!override && ec_node_type_lookup(type->name) != NULL) { errno = EEXIST; return -1; } - TAILQ_INSERT_TAIL(&node_type_list, type, next); + TAILQ_INSERT_HEAD(&node_type_list, type, next); return 0; } @@ -99,9 +111,6 @@ struct ec_node *ec_node_from_type(const struct ec_node_type *type, const char *i if (node->id == NULL) goto fail; - if (ec_asprintf(&node->desc, "<%s>", type->name) < 0) - goto fail; - node->attrs = ec_dict(); if (node->attrs == NULL) goto fail; @@ -116,7 +125,6 @@ struct ec_node *ec_node_from_type(const struct ec_node_type *type, const char *i fail: if (node != NULL) { ec_dict_free(node->attrs); - ec_free(node->desc); ec_free(node->id); } ec_free(node); @@ -256,7 +264,6 @@ void ec_node_free(struct ec_node *node) if (node->type->free_priv != NULL) node->type->free_priv(node); ec_free(node->id); - ec_free(node->desc); ec_dict_free(node->attrs); } @@ -421,12 +428,17 @@ fail: EC_LOG(EC_LOG_ERR, "failed to dump node\n"); } -const char *ec_node_desc(const struct ec_node *node) +char *ec_node_desc(const struct ec_node *node) { + char *desc = NULL; + if (node->type->desc != NULL) return node->type->desc(node); - return node->desc; + if (ec_asprintf(&desc, "<%s>", node->type->name) < 0) + return NULL; + + return desc; } int ec_node_check_type(const struct ec_node *node, @@ -462,6 +474,7 @@ static int ec_node_testcase(void) unsigned int refs; FILE *f = NULL; char *buf = NULL; + char *desc = NULL; size_t buflen = 0; int testres = 0; int ret; @@ -494,11 +507,14 @@ static int ec_node_testcase(void) free(buf); buf = NULL; + desc = ec_node_desc(node); testres |= EC_TEST_CHECK( !strcmp(ec_node_type(node)->name, "seq") && !strcmp(ec_node_id(node), EC_NO_ID) && - !strcmp(ec_node_desc(node), ""), + !strcmp(desc, ""), "bad child 0"); + ec_free(desc); + desc = NULL; testres |= EC_TEST_CHECK( ec_node_get_children_count(node) == 2, @@ -522,11 +538,14 @@ static int ec_node_testcase(void) "child 2 should be NULL"); child = ec_node_find(node, "id_x"); + desc = ec_node_desc(child); testres |= EC_TEST_CHECK(child != NULL && !strcmp(ec_node_type(child)->name, "str") && !strcmp(ec_node_id(child), "id_x") && - !strcmp(ec_node_desc(child), "x"), + !strcmp(desc, "x"), "bad child id_x"); + ec_free(desc); + desc = NULL; child = ec_node_find(node, "id_dezdex"); testres |= EC_TEST_CHECK(child == NULL, "child with wrong id should be NULL");