TAILQ_ENTRY(ec_comp_item) next;
enum ec_comp_type type;
struct ec_comp_group *grp;
- char *start; /* the initial token */
- char *full; /* the full token after completion */
- char *completion; /* chars that are added, NULL if not applicable */
- char *display; /* what should be displayed by help/completers */
+ char *start; /**< The initial token */
+ char *full; /**< The full token after completion */
+ char *completion; /**< Chars that are added, NULL if not applicable */
+ char *display; /**< What should be displayed by help/completers */
struct ec_dict *attrs;
};
TAILQ_HEAD(ec_comp_item_list, ec_comp_item);
struct ec_comp_group {
+ /* XXX counts ? */
TAILQ_ENTRY(ec_comp_group) next;
+ const struct ec_comp *comp;
const struct ec_node *node;
struct ec_comp_item_list items;
- struct ec_parse *state;
+ struct ec_pnode *pstate;
struct ec_dict *attrs;
};
TAILQ_HEAD(ec_comp_group_list, ec_comp_group);
struct ec_comp {
- unsigned count;
- unsigned count_full;
- unsigned count_partial;
- unsigned count_unknown;
- struct ec_parse *cur_state;
+ size_t count;
+ size_t count_full;
+ size_t count_partial;
+ size_t count_unknown;
+ struct ec_pnode *cur_pstate;
struct ec_comp_group *cur_group;
struct ec_comp_group_list groups;
struct ec_dict *attrs;
};
-struct ec_comp *ec_comp(struct ec_parse *state)
+struct ec_comp *ec_comp(void)
{
struct ec_comp *comp = NULL;
TAILQ_INIT(&comp->groups);
- comp->cur_state = state;
-
return comp;
fail:
return NULL;
}
-struct ec_parse *ec_comp_get_state(const struct ec_comp *comp)
+struct ec_pnode *ec_comp_get_cur_pstate(const struct ec_comp *comp)
{
- return comp->cur_state;
+ return comp->cur_pstate;
}
-struct ec_comp_group *ec_comp_get_group(const struct ec_comp *comp)
+struct ec_comp_group *ec_comp_get_cur_group(const struct ec_comp *comp)
{
return comp->cur_group;
}
}
int
-ec_node_complete_child(const struct ec_node *node,
+ec_complete_child(const struct ec_node *node,
struct ec_comp *comp,
const struct ec_strvec *strvec)
{
- struct ec_parse *child_state, *cur_state;
+ struct ec_pnode *child_pstate, *cur_pstate;
struct ec_comp_group *cur_group;
+ ec_complete_t complete_cb;
int ret;
- if (ec_node_type(node)->complete == NULL) {
- errno = ENOTSUP;
- return -1;
- }
+ /* get the complete method, falling back to ec_complete_unknown() */
+ complete_cb = ec_node_type(node)->complete;
+ if (complete_cb == NULL)
+ complete_cb = ec_complete_unknown;
/* save previous parse state, prepare child state */
- cur_state = comp->cur_state;
- child_state = ec_parse(node);
- if (child_state == NULL)
+ cur_pstate = comp->cur_pstate;
+ child_pstate = ec_pnode(node);
+ if (child_pstate == NULL)
return -1;
- if (cur_state != NULL)
- ec_parse_link_child(cur_state, child_state);
- comp->cur_state = child_state;
+ if (cur_pstate != NULL)
+ ec_pnode_link_child(cur_pstate, child_pstate);
+ comp->cur_pstate = child_pstate;
cur_group = comp->cur_group;
comp->cur_group = NULL;
/* fill the comp struct with items */
- ret = ec_node_type(node)->complete(node, comp, strvec);
+ ret = complete_cb(node, comp, strvec);
/* restore parent parse state */
- if (cur_state != NULL) {
- ec_parse_unlink_child(cur_state, child_state);
- assert(!ec_parse_has_child(child_state));
+ if (cur_pstate != NULL) {
+ ec_pnode_unlink_child(child_pstate);
+ assert(ec_pnode_get_first_child(child_pstate) == NULL);
}
- ec_parse_free(child_state);
- comp->cur_state = cur_state;
+ ec_pnode_free(child_pstate);
+ comp->cur_pstate = cur_pstate;
comp->cur_group = cur_group;
if (ret < 0)
return 0;
}
-struct ec_comp *ec_node_complete_strvec(const struct ec_node *node,
+struct ec_comp *ec_complete_strvec(const struct ec_node *node,
const struct ec_strvec *strvec)
{
struct ec_comp *comp = NULL;
int ret;
- comp = ec_comp(NULL);
+ comp = ec_comp();
if (comp == NULL)
goto fail;
- ret = ec_node_complete_child(node, comp, strvec);
+ ret = ec_complete_child(node, comp, strvec);
if (ret < 0)
goto fail;
return NULL;
}
-struct ec_comp *ec_node_complete(const struct ec_node *node,
+struct ec_comp *ec_complete(const struct ec_node *node,
const char *str)
{
struct ec_strvec *strvec = NULL;
if (ec_strvec_add(strvec, str) < 0)
goto fail;
- comp = ec_node_complete_strvec(node, strvec);
+ comp = ec_complete_strvec(node, strvec);
if (comp == NULL)
goto fail;
}
static struct ec_comp_group *
-ec_comp_group(const struct ec_node *node, struct ec_parse *parse)
+ec_comp_group(const struct ec_comp *comp, const struct ec_node *node,
+ struct ec_pnode *parse)
{
struct ec_comp_group *grp = NULL;
if (grp == NULL)
return NULL;
+ grp->comp = comp;
grp->attrs = ec_dict();
if (grp->attrs == NULL)
goto fail;
- grp->state = ec_parse_dup(parse);
- if (grp->state == NULL)
+ grp->pstate = ec_pnode_dup(parse);
+ if (grp->pstate == NULL)
goto fail;
grp->node = node;
fail:
if (grp != NULL) {
- ec_parse_free(grp->state);
+ ec_pnode_free(grp->pstate);
ec_dict_free(grp->attrs);
}
ec_free(grp);
if (comp->cur_group == NULL) {
struct ec_comp_group *grp;
- grp = ec_comp_group(node, comp->cur_state);
+ grp = ec_comp_group(comp, node, comp->cur_pstate);
if (grp == NULL)
return -1;
TAILQ_INSERT_TAIL(&comp->groups, grp, next);
ec_free(item);
}
-int ec_comp_add_item(struct ec_comp *comp,
- const struct ec_node *node,
- struct ec_comp_item **p_item,
- enum ec_comp_type type,
- const char *start, const char *full)
+struct ec_comp_item *ec_comp_add_item(struct ec_comp *comp,
+ const struct ec_node *node, enum ec_comp_type type,
+ const char *start, const char *full)
{
struct ec_comp_item *item = NULL;
int ret;
item = ec_comp_item(type, start, full);
if (item == NULL)
- return -1;
+ return NULL;
ret = ec_comp_item_add(comp, node, item);
if (ret < 0)
goto fail;
- if (p_item != NULL)
- *p_item = item;
-
- return 0;
+ return item;
fail:
ec_comp_item_free(item);
-
- return -1;
+ return NULL;
}
/* return a completion item of type "unknown" */
int
-ec_node_complete_unknown(const struct ec_node *gen_node,
+ec_complete_unknown(const struct ec_node *gen_node,
struct ec_comp *comp,
const struct ec_strvec *strvec)
{
- int ret;
+ const struct ec_comp_item *item = NULL;
if (ec_strvec_len(strvec) != 1)
return 0;
- ret = ec_comp_add_item(comp, gen_node, NULL,
- EC_COMP_UNKNOWN, NULL, NULL);
- if (ret < 0)
- return ret;
+ item = ec_comp_add_item(comp, gen_node, EC_COMP_UNKNOWN, NULL, NULL);
+ if (item == NULL)
+ return -1;
return 0;
}
TAILQ_REMOVE(&grp->items, item, next);
ec_comp_item_free(item);
}
- ec_parse_free(ec_parse_get_root(grp->state));
+ ec_pnode_free(ec_pnode_get_root(grp->pstate));
ec_dict_free(grp->attrs);
ec_free(grp);
}
return grp->node;
}
-const struct ec_parse *
-ec_comp_group_get_state(const struct ec_comp_group *grp)
+const struct ec_pnode *
+ec_comp_group_get_pstate(const struct ec_comp_group *grp)
{
- return grp->state;
+ return grp->pstate;
}
const struct ec_dict *
return;
}
- fprintf(out, "completion: count=%u full=%u partial=%u unknown=%u\n",
+ fprintf(out, "completion: count=%zu full=%zu partial=%zu unknown=%zu\n",
comp->count, comp->count_full,
comp->count_partial, comp->count_unknown);
return 0;
}
-unsigned int ec_comp_count(
- const struct ec_comp *comp,
- enum ec_comp_type type)
+size_t ec_comp_count(const struct ec_comp *comp, enum ec_comp_type type)
{
- unsigned int count = 0;
+ size_t count = 0;
if (comp == NULL)
return count;
return count;
}
-struct ec_comp_iter *
-ec_comp_iter(const struct ec_comp *comp,
- enum ec_comp_type type)
-{
- struct ec_comp_iter *iter;
-
- iter = ec_calloc(1, sizeof(*iter));
- if (iter == NULL)
- return NULL;
-
- iter->comp = comp;
- iter->type = type;
- iter->cur_node = NULL;
- iter->cur_match = NULL;
-
- return iter;
-}
-
-struct ec_comp_item *ec_comp_iter_next(
- struct ec_comp_iter *iter)
+static struct ec_comp_item *
+__ec_comp_iter_next(const struct ec_comp *comp, struct ec_comp_item *item,
+ enum ec_comp_type type)
{
- const struct ec_comp *comp;
- struct ec_comp_group *cur_node;
+ struct ec_comp_group *cur_grp;
struct ec_comp_item *cur_match;
- if (iter == NULL)
- return NULL;
- comp = iter->comp;
- if (comp == NULL)
- return NULL;
-
- cur_node = iter->cur_node;
- cur_match = iter->cur_match;
-
/* first call */
- if (cur_node == NULL) {
- TAILQ_FOREACH(cur_node, &comp->groups, next) {
- TAILQ_FOREACH(cur_match, &cur_node->items, next) {
- if (cur_match != NULL &&
- cur_match->type & iter->type)
- goto found;
+ if (item == NULL) {
+ TAILQ_FOREACH(cur_grp, &comp->groups, next) {
+ TAILQ_FOREACH(cur_match, &cur_grp->items, next) {
+ if (cur_match->type & type)
+ return cur_match;
}
}
return NULL;
- } else {
+ }
+
+ cur_grp = item->grp;
+ cur_match = TAILQ_NEXT(item, next);
+ while (cur_match != NULL) {
+ if (cur_match->type & type)
+ return cur_match;
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);
+ }
+ cur_grp = TAILQ_NEXT(cur_grp, next);
+ while (cur_grp != NULL) {
+ TAILQ_FOREACH(cur_match, &cur_grp->items, next) {
+ if (cur_match->type & type)
+ return cur_match;
}
- return NULL;
}
-found:
- iter->cur_node = cur_node;
- iter->cur_match = cur_match;
+ return NULL;
+}
- return iter->cur_match;
+struct ec_comp_item *
+ec_comp_iter_next(struct ec_comp_item *item, enum ec_comp_type type)
+{
+ if (item == NULL)
+ return NULL;
+ return __ec_comp_iter_next(item->grp->comp, item, type);
}
-void ec_comp_iter_free(struct ec_comp_iter *iter)
+
+struct ec_comp_item *
+ec_comp_iter_first(const struct ec_comp *comp, enum ec_comp_type type)
{
- ec_free(iter);
+ return __ec_comp_iter_next(comp, NULL, type);
}
/* LCOV_EXCL_START */
{
struct ec_node *node = NULL;
struct ec_comp *c = NULL;
- struct ec_comp_iter *iter = NULL;
struct ec_comp_item *item;
FILE *f = NULL;
char *buf = NULL;
if (node == NULL)
goto fail;
- c = ec_node_complete(node, "xcdscds");
+ c = ec_complete(node, "xcdscds");
testres |= EC_TEST_CHECK(
c != NULL && ec_comp_count(c, EC_COMP_ALL) == 0,
"complete count should is not 0\n");
ec_comp_free(c);
- c = ec_node_complete(node, "x");
+ c = ec_complete(node, "x");
testres |= EC_TEST_CHECK(
c != NULL && ec_comp_count(c, EC_COMP_ALL) == 1,
"complete count should is not 1\n");
ec_comp_free(c);
- c = ec_node_complete(node, "");
+ c = ec_complete(node, "");
testres |= EC_TEST_CHECK(
c != NULL && ec_comp_count(c, EC_COMP_ALL) == 2,
"complete count should is not 2\n");
free(buf);
buf = NULL;
- iter = ec_comp_iter(c, EC_COMP_ALL);
- item = ec_comp_iter_next(iter);
+ item = ec_comp_iter_first(c, EC_COMP_ALL);
if (item == NULL)
goto fail;
!strcmp(ec_node_id(ec_comp_item_get_node(item)), "id_x"),
"bad item node\n");
- item = ec_comp_iter_next(iter);
+ item = ec_comp_iter_next(item, EC_COMP_ALL);
if (item == NULL)
goto fail;
!strcmp(ec_node_id(ec_comp_item_get_node(item)), "id_y"),
"bad item node\n");
- item = ec_comp_iter_next(iter);
+ item = ec_comp_iter_next(item, EC_COMP_ALL);
testres |= EC_TEST_CHECK(item == NULL, "should be the last item\n");
- ec_comp_iter_free(iter);
ec_comp_free(c);
ec_node_free(node);
return testres;
fail:
- ec_comp_iter_free(iter);
ec_comp_free(c);
ec_node_free(node);
if (f != NULL)