X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=src%2Fecoli_parse.c;h=9a6eabc2ecb1bfb398954bfd3bbea8409ba36da7;hb=331d87b8f34493ea7eb4db75fa9d90b2e3ed503b;hp=3d6be77a41b672c3dcb448f97053d304967ea736;hpb=18d03456d96f7a086a2ccc82ce97fcf056848d90;p=protos%2Flibecoli.git diff --git a/src/ecoli_parse.c b/src/ecoli_parse.c index 3d6be77..9a6eabc 100644 --- a/src/ecoli_parse.c +++ b/src/ecoli_parse.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -23,38 +23,40 @@ EC_LOG_TYPE_REGISTER(parse); -TAILQ_HEAD(ec_parse_list, ec_parse); +TAILQ_HEAD(ec_pnode_list, ec_pnode); -struct ec_parse { - TAILQ_ENTRY(ec_parse) next; - struct ec_parse_list children; - struct ec_parse *parent; +struct ec_pnode { + TAILQ_ENTRY(ec_pnode) next; + struct ec_pnode_list children; + struct ec_pnode *parent; const struct ec_node *node; struct ec_strvec *strvec; - struct ec_keyval *attrs; + struct ec_dict *attrs; }; -static int __ec_node_parse_child(const struct ec_node *node, - struct ec_parse *state, +static int __ec_parse_child(const struct ec_node *node, + struct ec_pnode *pstate, bool is_root, const struct ec_strvec *strvec) { struct ec_strvec *match_strvec; - struct ec_parse *child = NULL; + struct ec_pnode *child = NULL; int ret; + // XXX limit max number of recursions to avoid segfault + if (ec_node_type(node)->parse == NULL) { errno = ENOTSUP; return -1; } if (!is_root) { - child = ec_parse(node); + child = ec_pnode(node); if (child == NULL) return -1; - ec_parse_link_child(state, child); + ec_pnode_link_child(pstate, child); } else { - child = state; + child = pstate; } ret = ec_node_type(node)->parse(node, child, strvec); if (ret < 0) @@ -62,8 +64,8 @@ static int __ec_node_parse_child(const struct ec_node *node, if (ret == EC_PARSE_NOMATCH) { if (!is_root) { - ec_parse_unlink_child(state, child); - ec_parse_free(child); + ec_pnode_unlink_child(pstate, child); + ec_pnode_free(child); } return ret; } @@ -78,42 +80,42 @@ static int __ec_node_parse_child(const struct ec_node *node, fail: if (!is_root) { - ec_parse_unlink_child(state, child); - ec_parse_free(child); + ec_pnode_unlink_child(pstate, child); + ec_pnode_free(child); } return -1; } -int ec_node_parse_child(const struct ec_node *node, struct ec_parse *state, +int ec_parse_child(const struct ec_node *node, struct ec_pnode *pstate, const struct ec_strvec *strvec) { - assert(state != NULL); - return __ec_node_parse_child(node, state, false, strvec); + assert(pstate != NULL); + return __ec_parse_child(node, pstate, false, strvec); } // XXX what is returned if no match ?? -struct ec_parse *ec_node_parse_strvec(const struct ec_node *node, +struct ec_pnode *ec_parse_strvec(const struct ec_node *node, const struct ec_strvec *strvec) { - struct ec_parse *parse = ec_parse(node); + struct ec_pnode *parse = ec_pnode(node); int ret; if (parse == NULL) return NULL; - ret = __ec_node_parse_child(node, parse, true, strvec); + ret = __ec_parse_child(node, parse, true, strvec); if (ret < 0) { - ec_parse_free(parse); + ec_pnode_free(parse); return NULL; } return parse; } -struct ec_parse *ec_node_parse(const struct ec_node *node, const char *str) +struct ec_pnode *ec_parse(const struct ec_node *node, const char *str) { struct ec_strvec *strvec = NULL; - struct ec_parse *parse = NULL; + struct ec_pnode *parse = NULL; errno = ENOMEM; strvec = ec_strvec(); @@ -123,7 +125,7 @@ struct ec_parse *ec_node_parse(const struct ec_node *node, const char *str) if (ec_strvec_add(strvec, str) < 0) goto fail; - parse = ec_node_parse_strvec(node, strvec); + parse = ec_parse_strvec(node, strvec); if (parse == NULL) goto fail; @@ -132,13 +134,13 @@ struct ec_parse *ec_node_parse(const struct ec_node *node, const char *str) fail: ec_strvec_free(strvec); - ec_parse_free(parse); + ec_pnode_free(parse); return NULL; } -struct ec_parse *ec_parse(const struct ec_node *node) +struct ec_pnode *ec_pnode(const struct ec_node *node) { - struct ec_parse *parse = NULL; + struct ec_pnode *parse = NULL; parse = ec_calloc(1, sizeof(*parse)); if (parse == NULL) @@ -147,7 +149,7 @@ struct ec_parse *ec_parse(const struct ec_node *node) TAILQ_INIT(&parse->children); parse->node = node; - parse->attrs = ec_keyval(); + parse->attrs = ec_dict(); if (parse->attrs == NULL) goto fail; @@ -155,34 +157,34 @@ struct ec_parse *ec_parse(const struct ec_node *node) fail: if (parse != NULL) - ec_keyval_free(parse->attrs); + ec_dict_free(parse->attrs); ec_free(parse); return NULL; } -static struct ec_parse * -__ec_parse_dup(const struct ec_parse *root, const struct ec_parse *ref, - struct ec_parse **new_ref) +static struct ec_pnode * +__ec_pnode_dup(const struct ec_pnode *root, const struct ec_pnode *ref, + struct ec_pnode **new_ref) { - struct ec_parse *dup = NULL; - struct ec_parse *child, *dup_child; - struct ec_keyval *attrs = NULL; + struct ec_pnode *dup = NULL; + struct ec_pnode *child, *dup_child; + struct ec_dict *attrs = NULL; if (root == NULL) return NULL; - dup = ec_parse(root->node); + dup = ec_pnode(root->node); if (dup == NULL) return NULL; if (root == ref) *new_ref = dup; - attrs = ec_keyval_dup(root->attrs); + attrs = ec_dict_dup(root->attrs); if (attrs == NULL) goto fail; - ec_keyval_free(dup->attrs); + ec_dict_free(dup->attrs); dup->attrs = attrs; if (root->strvec != NULL) { @@ -192,26 +194,26 @@ __ec_parse_dup(const struct ec_parse *root, const struct ec_parse *ref, } TAILQ_FOREACH(child, &root->children, next) { - dup_child = __ec_parse_dup(child, ref, new_ref); + dup_child = __ec_pnode_dup(child, ref, new_ref); if (dup_child == NULL) goto fail; - ec_parse_link_child(dup, dup_child); + ec_pnode_link_child(dup, dup_child); } return dup; fail: - ec_parse_free(dup); + ec_pnode_free(dup); return NULL; } -struct ec_parse *ec_parse_dup(const struct ec_parse *parse) +struct ec_pnode *ec_pnode_dup(const struct ec_pnode *parse) { - const struct ec_parse *root; - struct ec_parse *dup_root, *dup = NULL; + const struct ec_pnode *root; + struct ec_pnode *dup_root, *dup = NULL; - root = ec_parse_get_root(parse); - dup_root = __ec_parse_dup(root, parse, &dup); + root = ec_pnode_get_root(parse); + dup_root = __ec_pnode_dup(root, parse, &dup); if (dup_root == NULL) return NULL; assert(dup != NULL); @@ -219,9 +221,9 @@ struct ec_parse *ec_parse_dup(const struct ec_parse *parse) return dup; } -void ec_parse_free_children(struct ec_parse *parse) +void ec_pnode_free_children(struct ec_pnode *parse) { - struct ec_parse *child; + struct ec_pnode *child; if (parse == NULL) return; @@ -230,47 +232,47 @@ void ec_parse_free_children(struct ec_parse *parse) child = TAILQ_FIRST(&parse->children); TAILQ_REMOVE(&parse->children, child, next); child->parent = NULL; - ec_parse_free(child); + ec_pnode_free(child); } } -void ec_parse_free(struct ec_parse *parse) +void ec_pnode_free(struct ec_pnode *parse) { if (parse == NULL) return; ec_assert_print(parse->parent == NULL, - "parent not NULL in ec_parse_free()"); + "parent not NULL in ec_pnode_free()"); - ec_parse_free_children(parse); + ec_pnode_free_children(parse); ec_strvec_free(parse->strvec); - ec_keyval_free(parse->attrs); + ec_dict_free(parse->attrs); ec_free(parse); } -static void __ec_parse_dump(FILE *out, - const struct ec_parse *parse, size_t indent) +static void __ec_pnode_dump(FILE *out, + const struct ec_pnode *parse, size_t indent) { - struct ec_parse *child; + struct ec_pnode *child; const struct ec_strvec *vec; const char *id = "none", *typename = "none"; /* node can be null when parsing is incomplete */ if (parse->node != NULL) { - id = parse->node->id; + id = ec_node_id(parse->node); typename = ec_node_type(parse->node)->name; } fprintf(out, "%*s" "type=%s id=%s vec=", (int)indent * 4, "", typename, id); - vec = ec_parse_strvec(parse); + vec = ec_pnode_strvec(parse); ec_strvec_dump(out, vec); TAILQ_FOREACH(child, &parse->children, next) - __ec_parse_dump(out, child, indent + 1); + __ec_pnode_dump(out, child, indent + 1); } -void ec_parse_dump(FILE *out, const struct ec_parse *parse) +void ec_pnode_dump(FILE *out, const struct ec_pnode *parse) { fprintf(out, "------------------- parse dump:\n"); @@ -283,51 +285,51 @@ void ec_parse_dump(FILE *out, const struct ec_parse *parse) * does not have children: an incomplete parse, like those * generated by complete() don't match but have children that * may match. */ - if (!ec_parse_matches(parse) && TAILQ_EMPTY(&parse->children)) { + if (!ec_pnode_matches(parse) && TAILQ_EMPTY(&parse->children)) { fprintf(out, "no match\n"); return; } - __ec_parse_dump(out, parse, 0); + __ec_pnode_dump(out, parse, 0); } -void ec_parse_link_child(struct ec_parse *parse, - struct ec_parse *child) +void ec_pnode_link_child(struct ec_pnode *parse, + struct ec_pnode *child) { TAILQ_INSERT_TAIL(&parse->children, child, next); child->parent = parse; } -void ec_parse_unlink_child(struct ec_parse *parse, - struct ec_parse *child) +void ec_pnode_unlink_child(struct ec_pnode *parse, + struct ec_pnode *child) { TAILQ_REMOVE(&parse->children, child, next); child->parent = NULL; } -struct ec_parse * -ec_parse_get_first_child(const struct ec_parse *parse) +struct ec_pnode * +ec_pnode_get_first_child(const struct ec_pnode *parse) { return TAILQ_FIRST(&parse->children); } -struct ec_parse * -ec_parse_get_last_child(const struct ec_parse *parse) +struct ec_pnode * +ec_pnode_get_last_child(const struct ec_pnode *parse) { - return TAILQ_LAST(&parse->children, ec_parse_list); + return TAILQ_LAST(&parse->children, ec_pnode_list); } -struct ec_parse *ec_parse_get_next(const struct ec_parse *parse) +struct ec_pnode *ec_pnode_next(const struct ec_pnode *parse) { return TAILQ_NEXT(parse, next); } -bool ec_parse_has_child(const struct ec_parse *parse) +bool ec_pnode_has_child(const struct ec_pnode *parse) { return !TAILQ_EMPTY(&parse->children); } -const struct ec_node *ec_parse_get_node(const struct ec_parse *parse) +const struct ec_node *ec_pnode_get_node(const struct ec_pnode *parse) { if (parse == NULL) return NULL; @@ -335,16 +337,16 @@ const struct ec_node *ec_parse_get_node(const struct ec_parse *parse) return parse->node; } -void ec_parse_del_last_child(struct ec_parse *parse) +void ec_pnode_del_last_child(struct ec_pnode *parse) { - struct ec_parse *child; + struct ec_pnode *child; - child = ec_parse_get_last_child(parse); - ec_parse_unlink_child(parse, child); - ec_parse_free(child); + child = ec_pnode_get_last_child(parse); + ec_pnode_unlink_child(parse, child); + ec_pnode_free(child); } -struct ec_parse *__ec_parse_get_root(struct ec_parse *parse) +struct ec_pnode *__ec_pnode_get_root(struct ec_pnode *parse) { if (parse == NULL) return NULL; @@ -355,7 +357,7 @@ struct ec_parse *__ec_parse_get_root(struct ec_parse *parse) return parse; } -struct ec_parse *ec_parse_get_parent(const struct ec_parse *parse) +struct ec_pnode *ec_pnode_get_parent(const struct ec_pnode *parse) { if (parse == NULL) return NULL; @@ -363,15 +365,18 @@ struct ec_parse *ec_parse_get_parent(const struct ec_parse *parse) return parse->parent; } -struct ec_parse *ec_parse_iter_next(struct ec_parse *parse) +struct ec_pnode *__ec_pnode_iter_next(const struct ec_pnode *root, + struct ec_pnode *parse, bool iter_children) { - struct ec_parse *child, *parent, *next; + struct ec_pnode *child, *parent, *next; - child = TAILQ_FIRST(&parse->children); - if (child != NULL) - return child; + if (iter_children) { + child = TAILQ_FIRST(&parse->children); + if (child != NULL) + return child; + } parent = parse->parent; - while (parent != NULL) { + while (parent != NULL && parse != root) { next = TAILQ_NEXT(parse, next); if (next != NULL) return next; @@ -381,26 +386,37 @@ struct ec_parse *ec_parse_iter_next(struct ec_parse *parse) return NULL; } -struct ec_parse *ec_parse_find_first(struct ec_parse *parse, - const char *id) +struct ec_pnode * +ec_pnode_find_next(struct ec_pnode *root, struct ec_pnode *start, + const char *id, bool iter_children) { - struct ec_parse *iter; + struct ec_pnode *iter; - if (parse == NULL) + if (root == NULL) return NULL; + if (start == NULL) + start = root; + else + start = EC_PNODE_ITER_NEXT(root, start, iter_children); - for (iter = parse; iter != NULL; iter = ec_parse_iter_next(iter)) { + for (iter = start; iter != NULL; + iter = EC_PNODE_ITER_NEXT(root, iter, 1)) { if (iter->node != NULL && - iter->node->id != NULL && - !strcmp(iter->node->id, id)) + !strcmp(ec_node_id(iter->node), id)) return iter; } return NULL; } -struct ec_keyval * -ec_parse_get_attrs(struct ec_parse *parse) +struct ec_pnode *ec_pnode_find(struct ec_pnode *parse, + const char *id) +{ + return ec_pnode_find_next(parse, NULL, id, 1); +} + +struct ec_dict * +ec_pnode_get_attrs(struct ec_pnode *parse) { if (parse == NULL) return NULL; @@ -408,7 +424,7 @@ ec_parse_get_attrs(struct ec_parse *parse) return parse->attrs; } -const struct ec_strvec *ec_parse_strvec(const struct ec_parse *parse) +const struct ec_strvec *ec_pnode_strvec(const struct ec_pnode *parse) { if (parse == NULL || parse->strvec == NULL) return NULL; @@ -417,7 +433,7 @@ const struct ec_strvec *ec_parse_strvec(const struct ec_parse *parse) } /* number of strings in the parse vector */ -size_t ec_parse_len(const struct ec_parse *parse) +size_t ec_pnode_len(const struct ec_pnode *parse) { if (parse == NULL || parse->strvec == NULL) return 0; @@ -425,7 +441,7 @@ size_t ec_parse_len(const struct ec_parse *parse) return ec_strvec_len(parse->strvec); } -size_t ec_parse_matches(const struct ec_parse *parse) +size_t ec_pnode_matches(const struct ec_pnode *parse) { if (parse == NULL) return 0; @@ -437,11 +453,11 @@ size_t ec_parse_matches(const struct ec_parse *parse) } /* LCOV_EXCL_START */ -static int ec_parse_testcase(void) +static int ec_pnode_testcase(void) { struct ec_node *node = NULL; - struct ec_parse *p = NULL, *p2 = NULL; - const struct ec_parse *pc; + struct ec_pnode *p = NULL, *p2 = NULL; + const struct ec_pnode *pc; FILE *f = NULL; char *buf = NULL; size_t buflen = 0; @@ -455,15 +471,15 @@ static int ec_parse_testcase(void) if (node == NULL) goto fail; - p = ec_node_parse(node, "xcdscds"); + p = ec_parse(node, "xcdscds"); testres |= EC_TEST_CHECK( - p != NULL && !ec_parse_matches(p), + p != NULL && !ec_pnode_matches(p), "parse should not match\n"); f = open_memstream(&buf, &buflen); if (f == NULL) goto fail; - ec_parse_dump(f, p); + ec_pnode_dump(f, p); fclose(f); f = NULL; @@ -471,43 +487,43 @@ static int ec_parse_testcase(void) strstr(buf, "no match"), "bad dump\n"); free(buf); buf = NULL; - ec_parse_free(p); + ec_pnode_free(p); - p = ec_node_parse(node, "x y"); + p = ec_parse(node, "x y"); testres |= EC_TEST_CHECK( - p != NULL && ec_parse_matches(p), + p != NULL && ec_pnode_matches(p), "parse should match\n"); testres |= EC_TEST_CHECK( - ec_parse_len(p) == 1, "bad parse len\n"); + ec_pnode_len(p) == 1, "bad parse len\n"); - ret = ec_keyval_set(ec_parse_get_attrs(p), "key", "val", NULL); + ret = ec_dict_set(ec_pnode_get_attrs(p), "key", "val", NULL); testres |= EC_TEST_CHECK(ret == 0, "cannot set parse attribute\n"); - p2 = ec_parse_dup(p); + p2 = ec_pnode_dup(p); testres |= EC_TEST_CHECK( - p2 != NULL && ec_parse_matches(p2), + p2 != NULL && ec_pnode_matches(p2), "parse should match\n"); - ec_parse_free(p2); + ec_pnode_free(p2); p2 = NULL; - pc = ec_parse_find_first(p, "id_x"); + pc = ec_pnode_find(p, "id_x"); testres |= EC_TEST_CHECK(pc != NULL, "cannot find id_x"); testres |= EC_TEST_CHECK(pc != NULL && - ec_parse_get_parent(pc) != NULL && - ec_parse_get_parent(ec_parse_get_parent(pc)) == p, + ec_pnode_get_parent(pc) != NULL && + ec_pnode_get_parent(ec_pnode_get_parent(pc)) == p, "invalid parent\n"); - pc = ec_parse_find_first(p, "id_y"); + pc = ec_pnode_find(p, "id_y"); testres |= EC_TEST_CHECK(pc != NULL, "cannot find id_y"); - pc = ec_parse_find_first(p, "id_dezdezdez"); + pc = ec_pnode_find(p, "id_dezdezdez"); testres |= EC_TEST_CHECK(pc == NULL, "should not find bad id"); f = open_memstream(&buf, &buflen); if (f == NULL) goto fail; - ec_parse_dump(f, p); + ec_pnode_dump(f, p); fclose(f); f = NULL; @@ -520,13 +536,13 @@ static int ec_parse_testcase(void) free(buf); buf = NULL; - ec_parse_free(p); + ec_pnode_free(p); ec_node_free(node); return testres; fail: - ec_parse_free(p2); - ec_parse_free(p); + ec_pnode_free(p2); + ec_pnode_free(p); ec_node_free(node); if (f != NULL) fclose(f); @@ -536,9 +552,9 @@ fail: } /* LCOV_EXCL_STOP */ -static struct ec_test ec_parse_test = { +static struct ec_test ec_pnode_test = { .name = "parse", - .test = ec_parse_testcase, + .test = ec_pnode_testcase, }; -EC_TEST_REGISTER(ec_parse_test); +EC_TEST_REGISTER(ec_pnode_test);