X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fecoli_completed.c;h=64bb70d593942e75213ddde124e7528444e11809;hb=db0e63b8c415918f70b93d1d15caa933247f1595;hp=ea3d18cb758b4ed0e41c772b901814da8550a496;hpb=139916ef3060ed731bc50ea9b619cc265213588c;p=protos%2Flibecoli.git diff --git a/lib/ecoli_completed.c b/lib/ecoli_completed.c index ea3d18c..64bb70d 100644 --- a/lib/ecoli_completed.c +++ b/lib/ecoli_completed.c @@ -47,74 +47,88 @@ struct ec_completed *ec_completed(void) if (completed == NULL) return NULL; - TAILQ_INIT(&completed->items); - completed->count_match = 0; + TAILQ_INIT(&completed->nodes); return completed; } -struct ec_completed * +/* XXX on error, states are not freed ? + * they can be left in a bad state and should not be reused */ +int ec_node_complete_child(struct ec_node *node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed_state, const struct ec_strvec *strvec) { - struct ec_completed *completed; - struct ec_parsed *child; + struct ec_parsed *child_state = NULL; int ret; /* build the node if required */ if (node->type->build != NULL) { if ((node->flags & EC_NODE_F_BUILT) == 0) { ret = node->type->build(node); - if (ret < 0) { - errno = -ret; - return NULL; - } + if (ret < 0) + return ret; } } node->flags |= EC_NODE_F_BUILT; - if (node->type->complete == NULL) { - errno = ENOTSUP; - return NULL; - } + if (node->type->complete == NULL) + return -ENOTSUP; - child = ec_parsed(); - if (child == NULL) - return NULL; + child_state = ec_parsed(); + if (child_state == NULL) + return -ENOMEM; + child_state->node = node; + ec_parsed_add_child(parsed_state, child_state); - child->node = node; - ec_parsed_add_child(state, child); - completed = node->type->complete(node, child, strvec); + ret = node->type->complete(node, completed, child_state, strvec); + if (ret < 0) + return ret; #if 0 // XXX dump printf("----------------------------------------------------------\n"); ec_node_dump(stdout, node); ec_strvec_dump(stdout, strvec); ec_completed_dump(stdout, completed); - ec_parsed_dump(stdout, state); + ec_parsed_dump(stdout, parsed_state); #endif - ec_parsed_del_child(state, child); - assert(TAILQ_EMPTY(&child->children)); - ec_parsed_free(child); + ec_parsed_del_child(parsed_state, child_state); + assert(TAILQ_EMPTY(&child_state->children)); + ec_parsed_free(child_state); - return completed; + return 0; } struct ec_completed *ec_node_complete_strvec(struct ec_node *node, const struct ec_strvec *strvec) { - struct ec_parsed *state = ec_parsed(); - struct ec_completed *completed; + struct ec_parsed *parsed_state = NULL; + struct ec_completed *completed = NULL; + int ret; - if (state == NULL) - return NULL; + parsed_state = ec_parsed(); + if (parsed_state == NULL) + goto fail; - completed = ec_node_complete_child(node, state, strvec); - ec_parsed_free(state); + completed = ec_completed(); + if (completed == NULL) + goto fail; + + ret = ec_node_complete_child(node, completed, + parsed_state, strvec); + if (ret < 0) + goto fail; + + ec_parsed_free(parsed_state); return completed; + +fail: + ec_parsed_free(parsed_state); + ec_completed_free(completed); + return NULL; } struct ec_completed *ec_node_complete(struct ec_node *node, @@ -143,198 +157,240 @@ struct ec_completed *ec_node_complete(struct ec_node *node, return NULL; } -/* count the number of identical chars at the beginning of 2 strings */ -static size_t strcmp_count(const char *s1, const char *s2) +static struct ec_completed_node * +ec_completed_node(const struct ec_node *node) { - size_t i = 0; + struct ec_completed_node *compnode = NULL; - while (s1[i] && s2[i] && s1[i] == s2[i]) - i++; + compnode = ec_calloc(1, sizeof(*compnode)); + if (compnode == NULL) + return NULL; - return i; + compnode->node = node; + TAILQ_INIT(&compnode->items); + + return compnode; } -static struct ec_completed_item * -ec_completed_item(enum ec_completed_type type, struct ec_parsed *state, - const struct ec_node *node, const char *add) +struct ec_completed_item * +ec_completed_item(struct ec_parsed *state, const struct ec_node *node) { struct ec_completed_item *item = NULL; + struct ec_parsed *p; + size_t len; item = ec_calloc(1, sizeof(*item)); if (item == NULL) return NULL; - /* XXX can state be NULL? */ - if (state != NULL) { - struct ec_parsed *p; - size_t len; - - /* get path len */ - for (p = state, len = 0; p != NULL; - p = ec_parsed_get_parent(p), len++) - ; - - item->path = ec_calloc(len, sizeof(*item->path)); - if (item->path == NULL) - goto fail; - - item->pathlen = len; - - /* write path in array */ - for (p = state, len = 0; p != NULL; - p = ec_parsed_get_parent(p), len++) - item->path[len] = p->node; - } + /* get path len */ + for (p = state, len = 0; p != NULL; + p = ec_parsed_get_parent(p), len++) + ; + /* allocate room for path */ + item->path = ec_calloc(len, sizeof(*item->path)); + if (item->path == NULL) + goto fail; + item->pathlen = len; + /* write path in array */ + for (p = state, len = 0; p != NULL; + p = ec_parsed_get_parent(p), len++) + item->path[len] = p->node; - item->type = type; + item->type = EC_NO_MATCH; item->node = node; - if (add != NULL) { - item->add = ec_strdup(add); - if (item->add == NULL) - goto fail; - } return item; fail: if (item != NULL) { ec_free(item->path); - ec_free(item->add); + ec_free(item->str); + ec_free(item->display); } ec_completed_item_free(item); return NULL; } -static int ec_completed_add_item(struct ec_completed *completed, - struct ec_completed_item *item) +int +ec_completed_item_set(struct ec_completed_item *item, + enum ec_completed_type type, const char *str) { - size_t n; - - if (item->add != NULL) { - if (completed->smallest_start == NULL) { - completed->smallest_start = ec_strdup(item->add); - if (completed->smallest_start == NULL) - return -ENOMEM; - } else { - n = strcmp_count(item->add, - completed->smallest_start); - completed->smallest_start[n] = '\0'; - } - completed->count_match++; + char *str_copy = NULL; + char *display_copy = NULL; + int ret = 0; + + if (item == NULL) + return -EINVAL; + if (item->str != NULL) + return -EEXIST; + + switch (type) { + case EC_NO_MATCH: + if (str != NULL) + return -EINVAL; + break; + case EC_MATCH: + case EC_PARTIAL_MATCH: + if (str == NULL) + return -EINVAL; + break; + default: + return -EINVAL; } - TAILQ_INSERT_TAIL(&completed->items, item, next); - completed->count++; + if (str != NULL) { + ret = -ENOMEM; + str_copy = ec_strdup(str); + if (str_copy == NULL) + goto fail; + display_copy = ec_strdup(str); + if (display_copy == NULL) + goto fail; + } + + item->type = type; + item->str = str_copy; + item->display = display_copy; return 0; + +fail: + ec_free(str_copy); + ec_free(display_copy); + return ret; } -int ec_completed_add_match(struct ec_completed *completed, - struct ec_parsed *state, - const struct ec_node *node, const char *add) +int ec_completed_item_set_display(struct ec_completed_item *item, + const char *display) { - struct ec_completed_item *item; - int ret; + char *display_copy = NULL; + int ret = 0; - item = ec_completed_item(EC_MATCH, state, node, add); - if (item == NULL) - return -ENOMEM; + if (item == NULL || display == NULL || + item->type == EC_NO_MATCH || item->str == NULL) + return -EINVAL; - ret = ec_completed_add_item(completed, item); - if (ret < 0) { - ec_completed_item_free(item); - return ret; - } + ret = -ENOMEM; + display_copy = ec_strdup(display); + if (display_copy == NULL) + goto fail; + + ec_free(item->display); + item->display = display_copy; return 0; + +fail: + ec_free(display_copy); + return ret; + } -int ec_completed_add_no_match(struct ec_completed *completed, - struct ec_parsed *state, const struct ec_node *node) +int +ec_completed_item_add(struct ec_completed *completed, + struct ec_completed_item *item) { - struct ec_completed_item *item; - int ret; - - item = ec_completed_item(EC_NO_MATCH, state, node, NULL); - if (item == NULL) - return -ENOMEM; + struct ec_completed_node *compnode = NULL; + + if (completed == NULL || item == NULL || item->node == NULL) + return -EINVAL; + + switch (item->type) { + case EC_NO_MATCH: + break; + case EC_MATCH: + case EC_PARTIAL_MATCH: + completed->count_match++; //XXX + break; + default: + return -EINVAL; + } - ret = ec_completed_add_item(completed, item); - if (ret < 0) { - ec_completed_item_free(item); - return ret; + /* find the compnode entry corresponding to this node */ + TAILQ_FOREACH(compnode, &completed->nodes, next) { + if (compnode->node == item->node) + break; + } + if (compnode == NULL) { + compnode = ec_completed_node(item->node); + if (compnode == NULL) + return -ENOMEM; + TAILQ_INSERT_TAIL(&completed->nodes, compnode, next); } + completed->count++; + TAILQ_INSERT_TAIL(&compnode->items, item, next); + return 0; } void ec_completed_item_free(struct ec_completed_item *item) { - ec_free(item->add); + if (item == NULL) + return; + + ec_free(item->str); + ec_free(item->display); ec_free(item->path); ec_free(item); } /* default completion function: return a no-match element */ -struct ec_completed *ec_node_default_complete(const struct ec_node *gen_node, - struct ec_parsed *state, - const struct ec_strvec *strvec) +int +ec_node_default_complete(const struct ec_node *gen_node, // XXX rename in nomatch + struct ec_completed *completed, + struct ec_parsed *parsed_state, + const struct ec_strvec *strvec) { - struct ec_completed *completed; - - (void)strvec; - (void)state; - - completed = ec_completed(); - if (completed == NULL) - return NULL; + struct ec_completed_item *item = NULL; + int ret; if (ec_strvec_len(strvec) != 1) - return completed; + return 0; - if (ec_completed_add_no_match(completed, state, gen_node) < 0) { - ec_completed_free(completed); - return NULL; + item = ec_completed_item(parsed_state, gen_node); + if (item == NULL) + return -ENOMEM; + ret = ec_completed_item_set(item, EC_NO_MATCH, NULL); + if (ret < 0) { + ec_completed_item_free(item); + return ret; } - - return completed; -} - -void ec_completed_merge(struct ec_completed *completed1, - struct ec_completed *completed2) -{ - struct ec_completed_item *item; - - assert(completed1 != NULL); - assert(completed2 != NULL); - - while (!TAILQ_EMPTY(&completed2->items)) { - item = TAILQ_FIRST(&completed2->items); - TAILQ_REMOVE(&completed2->items, item, next); - ec_completed_add_item(completed1, item); + ret = ec_completed_item_add(completed, item); + if (ret < 0) { + ec_completed_item_free(item); + return ret; } - ec_completed_free(completed2); + return 0; } void ec_completed_free(struct ec_completed *completed) { + struct ec_completed_node *compnode; struct ec_completed_item *item; if (completed == NULL) return; - while (!TAILQ_EMPTY(&completed->items)) { - item = TAILQ_FIRST(&completed->items); - TAILQ_REMOVE(&completed->items, item, next); - ec_completed_item_free(item); + while (!TAILQ_EMPTY(&completed->nodes)) { + compnode = TAILQ_FIRST(&completed->nodes); + TAILQ_REMOVE(&completed->nodes, compnode, next); + + while (!TAILQ_EMPTY(&compnode->items)) { + item = TAILQ_FIRST(&compnode->items); + TAILQ_REMOVE(&compnode->items, item, next); + ec_completed_item_free(item); + } + ec_free(compnode); } - ec_free(completed->smallest_start); ec_free(completed); } void ec_completed_dump(FILE *out, const struct ec_completed *completed) { + struct ec_completed_node *compnode; struct ec_completed_item *item; if (completed == NULL || completed->count == 0) { @@ -342,23 +398,26 @@ void ec_completed_dump(FILE *out, const struct ec_completed *completed) return; } - fprintf(out, "completion: count=%u match=%u smallest_start=<%s>\n", - completed->count, completed->count_match, - completed->smallest_start); + fprintf(out, "completion: count=%u match=%u\n", + completed->count, completed->count_match); - TAILQ_FOREACH(item, &completed->items, next) { - fprintf(out, "add=<%s>, node=%p, node_type=%s\n", - item->add, item->node, item->node->type->name); - } -} + TAILQ_FOREACH(compnode, &completed->nodes, next) { + fprintf(out, "node=%p, node_type=%s\n", + compnode->node, compnode->node->type->name); + TAILQ_FOREACH(item, &compnode->items, next) { + const char *typestr; -const char *ec_completed_smallest_start( - const struct ec_completed *completed) -{ - if (completed == NULL || completed->smallest_start == NULL) - return ""; + switch (item->type) { + case EC_NO_MATCH: typestr = "no-match"; break; + case EC_MATCH: typestr = "match"; break; + case EC_PARTIAL_MATCH: typestr = "partial-match"; break; + default: typestr = "unknown"; break; + } - return completed->smallest_start; + fprintf(out, " type=%s str=<%s> disp=<%s>\n", + typestr, item->str, item->display); + } + } } unsigned int ec_completed_count( @@ -390,7 +449,8 @@ ec_completed_iter(struct ec_completed *completed, iter->completed = completed; iter->type = type; - iter->cur = NULL; + iter->cur_node = NULL; + iter->cur_match = NULL; return iter; } @@ -398,29 +458,47 @@ ec_completed_iter(struct ec_completed *completed, const struct ec_completed_item *ec_completed_iter_next( struct ec_completed_iter *iter) { - if (iter->completed == NULL) - return NULL; - - do { - if (iter->cur == NULL) - iter->cur = TAILQ_FIRST(&iter->completed->items); - else - iter->cur = TAILQ_NEXT(iter->cur, next); + const struct ec_completed *completed = iter->completed; + const struct ec_completed_node *cur_node; + const struct ec_completed_item *cur_match; - if (iter->cur == NULL) - break; + if (completed == NULL) + return NULL; - if (iter->cur->add == NULL && - (iter->type & EC_NO_MATCH)) - break; + cur_node = iter->cur_node; + cur_match = iter->cur_match; - if (iter->cur->add != NULL && - (iter->type & EC_MATCH)) - break; + /* first call */ + if (cur_node == NULL) { + TAILQ_FOREACH(cur_node, &completed->nodes, next) { + TAILQ_FOREACH(cur_match, &cur_node->items, next) { + if (cur_match != NULL && + cur_match->type & iter->type) + goto found; + } + } + return NULL; + } else { + cur_match = TAILQ_NEXT(cur_match, next); + if (cur_match != NULL && + cur_match->type & iter->type) + goto found; + cur_node = TAILQ_NEXT(cur_node, next); + while (cur_node != NULL) { + cur_match = TAILQ_FIRST(&cur_node->items); + if (cur_match != NULL && + cur_match->type & iter->type) + goto found; + cur_node = TAILQ_NEXT(cur_node, next); + } + return NULL; + } - } while (iter->cur != NULL); +found: + iter->cur_node = cur_node; + iter->cur_match = cur_match; - return iter->cur; + return iter->cur_match; } void ec_completed_iter_free(struct ec_completed_iter *iter)