From: Olivier Matz Date: Thu, 24 Aug 2017 19:28:41 +0000 (+0200) Subject: save X-Git-Url: http://git.droids-corp.org/?p=protos%2Flibecoli.git;a=commitdiff_plain;h=6c99f3bcdcb786bee560c1582f3ad3c306681d6e save --- diff --git a/lib/Makefile b/lib/Makefile index 107cb80..29df719 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -76,7 +76,7 @@ ldflags-$(O)test = -rdynamic exe-y-$(O)test = $(srcs) main.c ldflags-$(O)readline = -lreadline -ltermcap -exe-y-$(O)readline = $(srcs) main-readline.c +#exe-y-$(O)readline = $(srcs) main-readline.c include $(ECOLI)/mk/ecoli-post.mk diff --git a/lib/ecoli_completed.c b/lib/ecoli_completed.c index 0b0e641..15f3dc9 100644 --- a/lib/ecoli_completed.c +++ b/lib/ecoli_completed.c @@ -53,68 +53,88 @@ struct ec_completed *ec_completed(void) 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); + + ret = ec_completed_add_node(completed, child_state, node); + if (ret < 0) + return ret; - 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, @@ -206,16 +226,24 @@ fail: return NULL; } -static int ec_completed_add_item(struct ec_completed *completed, - struct ec_completed_item *item) +int +ec_completed_add_match(struct ec_completed *completed, + struct ec_parsed *parsed_state, + const struct ec_node *node, const char *add) { + struct ec_completed_item *item = NULL; + int ret = -ENOMEM; size_t n; + item = ec_completed_item(EC_MATCH, parsed_state, node, add); + if (item == NULL) + goto fail; + if (item->add != NULL) { if (completed->smallest_start == NULL) { completed->smallest_start = ec_strdup(item->add); if (completed->smallest_start == NULL) - return -ENOMEM; + goto fail; } else { n = strcmp_count(item->add, completed->smallest_start); @@ -228,35 +256,22 @@ static int ec_completed_add_item(struct ec_completed *completed, completed->count++; return 0; -} -int ec_completed_add_match(struct ec_completed *completed, - struct ec_parsed *state, - const struct ec_node *node, const char *add) -{ - struct ec_completed_item *item; - int ret; - - item = ec_completed_item(EC_MATCH, state, node, add); - if (item == NULL) - return -ENOMEM; - - ret = ec_completed_add_item(completed, item); - if (ret < 0) { - ec_completed_item_free(item); - return ret; - } - - return 0; +fail: + ec_completed_item_free(item); + return ret; } -int ec_completed_add_no_match(struct ec_completed *completed, - struct ec_parsed *state, const struct ec_node *node) +int +ec_completed_add_node(struct ec_completed *completed, + struct ec_parsed *parsed_state, + const struct ec_node *node) { - struct ec_completed_item *item; +#if 0 + struct ec_completed_item *item = NULL; int ret; - item = ec_completed_item(EC_NO_MATCH, state, node, NULL); + item = ec_completed_item(EC_NO_MATCH, parsed_state, node, NULL); if (item == NULL) return -ENOMEM; @@ -265,7 +280,10 @@ int ec_completed_add_no_match(struct ec_completed *completed, ec_completed_item_free(item); return ret; } - +#endif + (void)completed; + (void)parsed_state; + (void)node; return 0; } @@ -276,29 +294,22 @@ void ec_completed_item_free(struct ec_completed_item *item) 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) +/* default completion function: return a no-item element */ +int +ec_node_default_complete(const struct ec_node *gen_node, + struct ec_completed *completed, + struct ec_parsed *parsed, + const struct ec_strvec *strvec) { - struct ec_completed *completed; - (void)strvec; - (void)state; - completed = ec_completed(); - if (completed == NULL) - return NULL; + if (ec_strvec_len(strvec) != 1) //XXX needed? + return 0; - if (ec_strvec_len(strvec) != 1) - return completed; + if (ec_completed_add_node(completed, parsed, gen_node) < 0) + return -1; - if (ec_completed_add_no_match(completed, state, gen_node) < 0) { - ec_completed_free(completed); - return NULL; - } - - return completed; + return 0; } void ec_completed_merge(struct ec_completed *completed1, @@ -312,7 +323,7 @@ void ec_completed_merge(struct ec_completed *completed1, while (!TAILQ_EMPTY(&completed2->matches)) { item = TAILQ_FIRST(&completed2->matches); TAILQ_REMOVE(&completed2->matches, item, next); - ec_completed_add_item(completed1, item); + //ec_completed_add_item(completed1, item); } ec_completed_free(completed2); diff --git a/lib/ecoli_completed.h b/lib/ecoli_completed.h index 4d0045e..85601f7 100644 --- a/lib/ecoli_completed.h +++ b/lib/ecoli_completed.h @@ -35,9 +35,9 @@ struct ec_node; enum ec_completed_type { - EC_NO_MATCH = 1, - EC_MATCH = 2, - EC_PARTIAL = 4, + EC_NO_MATCH, + EC_MATCH, + EC_PARTIAL, }; struct ec_completed_item { @@ -77,17 +77,21 @@ struct ec_completed *ec_node_complete_strvec(struct ec_node *node, const struct ec_strvec *strvec); /* internal: used by nodes */ -struct ec_completed *ec_node_complete_child(struct ec_node *node, - struct ec_parsed *state, - const struct ec_strvec *strvec); +int ec_node_complete_child(struct ec_node *node, + struct ec_completed *completed, + struct ec_parsed *parsed_state, + const struct ec_strvec *strvec); struct ec_completed *ec_completed(void); int ec_completed_add_match(struct ec_completed *completed, struct ec_parsed *state, const struct ec_node *node, const char *add); -int ec_completed_add_no_match(struct ec_completed *completed, +int ec_completed_add_node(struct ec_completed *completed, struct ec_parsed *state, const struct ec_node *node); +int ec_completed_add_partial(struct ec_completed *completed, + struct ec_parsed *state, const struct ec_node *node, + const char *add); void ec_completed_item_free(struct ec_completed_item *item); void ec_completed_merge(struct ec_completed *completed1, @@ -95,9 +99,11 @@ void ec_completed_merge(struct ec_completed *completed1, void ec_completed_free(struct ec_completed *completed); void ec_completed_dump(FILE *out, const struct ec_completed *completed); -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, + struct ec_completed *completed, + struct ec_parsed *state, + const struct ec_strvec *strvec); /* cannot return NULL */ const char *ec_completed_smallest_start( diff --git a/lib/ecoli_node.h b/lib/ecoli_node.h index 2c3501e..b5a424b 100644 --- a/lib/ecoli_node.h +++ b/lib/ecoli_node.h @@ -57,9 +57,10 @@ typedef int (*ec_node_build_t)(struct ec_node *node); typedef int (*ec_node_parse_t)(const struct ec_node *node, struct ec_parsed *state, const struct ec_strvec *strvec); -typedef struct ec_completed *(*ec_node_complete_t)(const struct ec_node *node, - struct ec_parsed *state, - const struct ec_strvec *strvec); +typedef int (*ec_node_complete_t)(const struct ec_node *node, + struct ec_completed *completed_state, + struct ec_parsed *parsed_state, + const struct ec_strvec *strvec); typedef size_t (*ec_node_get_max_parse_len_t)(const struct ec_node *node); typedef const char * (*ec_node_desc_t)(const struct ec_node *); typedef void (*ec_node_init_priv_t)(struct ec_node *); diff --git a/lib/ecoli_node_cmd.c b/lib/ecoli_node_cmd.c index 123c0a8..1f40b0f 100644 --- a/lib/ecoli_node_cmd.c +++ b/lib/ecoli_node_cmd.c @@ -246,22 +246,24 @@ static const struct ec_node_expr_eval_ops test_ops = { .eval_free = ec_node_cmd_eval_free, }; -static int ec_node_cmd_parse(const struct ec_node *gen_node, - struct ec_parsed *state, - const struct ec_strvec *strvec) +static int +ec_node_cmd_parse(const struct ec_node *gen_node, struct ec_parsed *state, + const struct ec_strvec *strvec) { struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; return ec_node_parse_child(node->cmd, state, strvec); } -static struct ec_completed *ec_node_cmd_complete(const struct ec_node *gen_node, - struct ec_parsed *state, - const struct ec_strvec *strvec) +static int +ec_node_cmd_complete(const struct ec_node *gen_node, + struct ec_completed *completed, + struct ec_parsed *parsed, + const struct ec_strvec *strvec) { struct ec_node_cmd *node = (struct ec_node_cmd *)gen_node; - return ec_node_complete_child(node->cmd, state, strvec); + return ec_node_complete_child(node->cmd, completed, parsed, strvec); } static void ec_node_cmd_free_priv(struct ec_node *gen_node) diff --git a/lib/ecoli_node_expr.c b/lib/ecoli_node_expr.c index cbc9441..e15c296 100644 --- a/lib/ecoli_node_expr.c +++ b/lib/ecoli_node_expr.c @@ -75,13 +75,15 @@ static int ec_node_expr_parse(const struct ec_node *gen_node, return ec_node_parse_child(node->child, state, strvec); } -static struct ec_completed *ec_node_expr_complete(const struct ec_node *gen_node, - struct ec_parsed *state, - const struct ec_strvec *strvec) +static int +ec_node_expr_complete(const struct ec_node *gen_node, + struct ec_completed *completed, + struct ec_parsed *parsed, + const struct ec_strvec *strvec) { struct ec_node_expr *node = (struct ec_node_expr *)gen_node; - return ec_node_complete_child(node->child, state, strvec); + return ec_node_complete_child(node->child, completed, parsed, strvec); } static void ec_node_expr_free_priv(struct ec_node *gen_node) diff --git a/lib/ecoli_node_many.c b/lib/ecoli_node_many.c index 7e1582c..4d748f8 100644 --- a/lib/ecoli_node_many.c +++ b/lib/ecoli_node_many.c @@ -100,29 +100,24 @@ fail: return ret; } -static struct ec_completed * +static int __ec_node_many_complete(struct ec_node_many *node, unsigned int max, - struct ec_parsed *state, const struct ec_strvec *strvec) + struct ec_completed *completed, + struct ec_parsed *parsed, + const struct ec_strvec *strvec) { - struct ec_completed *completed, *child_completed; struct ec_strvec *childvec = NULL; unsigned int i; int ret; - completed = ec_completed(); - if (completed == NULL) - return NULL; - /* first, try to complete with the child node */ - child_completed = ec_node_complete_child(node->child, state, strvec); - if (child_completed == NULL) + ret = ec_node_complete_child(node->child, completed, parsed, strvec); + if (ret < 0) goto fail; - ec_completed_merge(completed, child_completed); - child_completed = NULL; /* we're done, we reached the max number of nodes */ if (max == 1) - return completed; + return 0; /* if there is a maximum, decrease it before recursion */ if (max != 0) @@ -135,7 +130,7 @@ __ec_node_many_complete(struct ec_node_many *node, unsigned int max, if (childvec == NULL) goto fail; - ret = ec_node_parse_child(node->child, state, childvec); + ret = ec_node_parse_child(node->child, parsed, childvec); if (ret < 0 && ret != EC_PARSED_NOMATCH) goto fail; @@ -144,46 +139,43 @@ __ec_node_many_complete(struct ec_node_many *node, unsigned int max, if ((unsigned int)ret != i) { if (ret != EC_PARSED_NOMATCH) - ec_parsed_del_last_child(state); + ec_parsed_del_last_child(parsed); continue; } childvec = ec_strvec_ndup(strvec, i, ec_strvec_len(strvec) - i); if (childvec == NULL) { - ec_parsed_del_last_child(state); + ec_parsed_del_last_child(parsed); goto fail; } - child_completed = __ec_node_many_complete(node, max, - state, childvec); - ec_parsed_del_last_child(state); + ret = __ec_node_many_complete(node, max, completed, + parsed, childvec); + ec_parsed_del_last_child(parsed); ec_strvec_free(childvec); childvec = NULL; - if (child_completed == NULL) + if (ret < 0) goto fail; - - ec_completed_merge(completed, child_completed); - child_completed = NULL; } - return completed; + return 0; fail: ec_strvec_free(childvec); - ec_completed_free(child_completed); - ec_completed_free(completed); - return NULL; + return -1; } -static struct ec_completed * +static int ec_node_many_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_many *node = (struct ec_node_many *)gen_node; - return __ec_node_many_complete(node, node->max, state, strvec); + return __ec_node_many_complete(node, node->max, completed, + parsed, strvec); } static void ec_node_many_free_priv(struct ec_node *gen_node) diff --git a/lib/ecoli_node_once.c b/lib/ecoli_node_once.c index b89b80e..fd427b9 100644 --- a/lib/ecoli_node_once.c +++ b/lib/ecoli_node_once.c @@ -85,36 +85,28 @@ ec_node_once_parse(const struct ec_node *gen_node, return ec_node_parse_child(node->child, state, strvec); } -static struct ec_completed * +static int ec_node_once_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_once *node = (struct ec_node_once *)gen_node; - struct ec_completed *completed = NULL, *child_completed = NULL; unsigned int count; - - completed = ec_completed(); - if (completed == NULL) - goto fail; + int ret; /* count the number of occurences of the node: if already parsed, * do not match */ - count = count_node(ec_parsed_get_root(state), node->child); //XXX + count = count_node(ec_parsed_get_root(parsed), node->child); //XXX if (count > 0) - return completed; - - child_completed = ec_node_complete_child(node->child, state, strvec); - if (child_completed == NULL) - goto fail; + return 0; - ec_completed_merge(completed, child_completed); - return completed; + ret = ec_node_complete_child(node->child, completed, parsed, strvec); + if (ret < 0) + return ret; -fail: - ec_completed_free(completed); - return NULL; + return 0; } static void ec_node_once_free_priv(struct ec_node *gen_node) diff --git a/lib/ecoli_node_option.c b/lib/ecoli_node_option.c index 4b52814..4610a46 100644 --- a/lib/ecoli_node_option.c +++ b/lib/ecoli_node_option.c @@ -63,14 +63,15 @@ ec_node_option_parse(const struct ec_node *gen_node, return ret; } -static struct ec_completed * +static int ec_node_option_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_option *node = (struct ec_node_option *)gen_node; - return ec_node_complete_child(node->child, state, strvec); + return ec_node_complete_child(node->child, completed, parsed, strvec); } static void ec_node_option_free_priv(struct ec_node *gen_node) diff --git a/lib/ecoli_node_or.c b/lib/ecoli_node_or.c index dcd811b..c1b808f 100644 --- a/lib/ecoli_node_or.c +++ b/lib/ecoli_node_or.c @@ -67,30 +67,24 @@ ec_node_or_parse(const struct ec_node *gen_node, return EC_PARSED_NOMATCH; } -static struct ec_completed * +static int ec_node_or_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_or *node = (struct ec_node_or *)gen_node; - struct ec_completed *completed, *child_completed; + int ret; size_t n; - completed = ec_completed(); - if (completed == NULL) - return NULL; - for (n = 0; n < node->len; n++) { - child_completed = ec_node_complete_child(node->table[n], - state, strvec); - - if (child_completed == NULL) // XXX fail instead? - continue; - - ec_completed_merge(completed, child_completed); + ret = ec_node_complete_child(node->table[n], + completed, parsed, strvec); + if (ret < 0) + return ret; } - return completed; + return 0; } static size_t ec_node_or_get_max_parse_len(const struct ec_node *gen_node) diff --git a/lib/ecoli_node_seq.c b/lib/ecoli_node_seq.c index 9fa2d1a..d6338e9 100644 --- a/lib/ecoli_node_seq.c +++ b/lib/ecoli_node_seq.c @@ -91,21 +91,18 @@ fail: return ret; } -static struct ec_completed * +static int __ec_node_seq_complete(struct ec_node **table, size_t table_len, - struct ec_parsed *state, const struct ec_strvec *strvec) + struct ec_completed *completed, + struct ec_parsed *parsed, + const struct ec_strvec *strvec) { - struct ec_completed *completed, *child_completed; struct ec_strvec *childvec = NULL; unsigned int i; int ret; - completed = ec_completed(); - if (completed == NULL) - return NULL; - if (table_len == 0) - return completed; + return 0; /* * Example of completion for a sequence node = [n1,n2] and an @@ -119,13 +116,10 @@ __ec_node_seq_complete(struct ec_node **table, size_t table_len, */ /* first, try to complete with the first node of the table */ - child_completed = ec_node_complete_child(table[0], state, strvec); - if (child_completed == NULL) + ret = ec_node_complete_child(table[0], completed, parsed, strvec); + if (ret < 0) goto fail; - ec_completed_merge(completed, child_completed); - child_completed = NULL; - /* then, if the first node of the table matches the beginning of the * strvec, try to complete the rest */ for (i = 0; i < ec_strvec_len(strvec); i++) { @@ -133,7 +127,7 @@ __ec_node_seq_complete(struct ec_node **table, size_t table_len, if (childvec == NULL) goto fail; - ret = ec_node_parse_child(table[0], state, childvec); + ret = ec_node_parse_child(table[0], parsed, childvec); if (ret < 0 && ret != EC_PARSED_NOMATCH) goto fail; @@ -142,47 +136,44 @@ __ec_node_seq_complete(struct ec_node **table, size_t table_len, if ((unsigned int)ret != i) { if (ret != EC_PARSED_NOMATCH) - ec_parsed_del_last_child(state); + ec_parsed_del_last_child(parsed); continue; } childvec = ec_strvec_ndup(strvec, i, ec_strvec_len(strvec) - i); if (childvec == NULL) { - ec_parsed_del_last_child(state); + ec_parsed_del_last_child(parsed); goto fail; } - child_completed = __ec_node_seq_complete(&table[1], - table_len - 1, - state, childvec); - ec_parsed_del_last_child(state); + ret = __ec_node_seq_complete(&table[1], + table_len - 1, + completed, parsed, childvec); + ec_parsed_del_last_child(parsed); ec_strvec_free(childvec); childvec = NULL; - if (child_completed == NULL) + if (ret < 0) goto fail; - - ec_completed_merge(completed, child_completed); - child_completed = NULL; } - return completed; + return 0; fail: ec_strvec_free(childvec); - ec_completed_free(child_completed); - ec_completed_free(completed); - return NULL; + return -1; } -static struct ec_completed * +static int ec_node_seq_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_seq *node = (struct ec_node_seq *)gen_node; - return __ec_node_seq_complete(node->table, node->len, state, strvec); + return __ec_node_seq_complete(node->table, node->len, completed, + parsed, strvec); } static size_t ec_node_seq_get_max_parse_len(const struct ec_node *gen_node) diff --git a/lib/ecoli_node_sh_lex.c b/lib/ecoli_node_sh_lex.c index 0ce54fe..59b917f 100644 --- a/lib/ecoli_node_sh_lex.c +++ b/lib/ecoli_node_sh_lex.c @@ -279,46 +279,37 @@ ec_node_sh_lex_parse(const struct ec_node *gen_node, return ret; } -static struct ec_completed * +static int ec_node_sh_lex_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_sh_lex *node = (struct ec_node_sh_lex *)gen_node; - struct ec_completed *completed, *child_completed = NULL; struct ec_strvec *new_vec = NULL; const char *str; char missing_quote; - -// printf("==================\n"); - completed = ec_completed(); - if (completed == NULL) - return NULL; + int ret; if (ec_strvec_len(strvec) != 1) - return completed; + return 0; str = ec_strvec_val(strvec, 0); new_vec = tokenize(str, 1, 1, &missing_quote); if (new_vec == NULL) goto fail; -// ec_strvec_dump(new_vec, stdout); - - child_completed = ec_node_complete_child(node->child, state, new_vec); - if (child_completed == NULL) + ret = ec_node_complete_child(node->child, completed, parsed, new_vec); + if (ret < 0) goto fail; ec_strvec_free(new_vec); - new_vec = NULL; - ec_completed_merge(completed, child_completed); - return completed; + return 0; fail: ec_strvec_free(new_vec); - ec_completed_free(completed); - return NULL; + return -1; } static void ec_node_sh_lex_free_priv(struct ec_node *gen_node) diff --git a/lib/ecoli_node_str.c b/lib/ecoli_node_str.c index 4a9ee82..30e1a1a 100644 --- a/lib/ecoli_node_str.c +++ b/lib/ecoli_node_str.c @@ -65,24 +65,20 @@ ec_node_str_parse(const struct ec_node *gen_node, return 1; } -static struct ec_completed * +static int ec_node_str_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_str *node = (struct ec_node_str *)gen_node; - struct ec_completed *completed; const char *str; size_t n = 0; - (void)state; - - completed = ec_completed(); - if (completed == NULL) - return NULL; + (void)parsed; if (ec_strvec_len(strvec) != 1) - return completed; + return 0; str = ec_strvec_val(strvec, 0); for (n = 0; n < node->len; n++) { @@ -90,20 +86,13 @@ ec_node_str_complete(const struct ec_node *gen_node, break; } - if (str[n] != '\0') { - if (ec_completed_add_no_match(completed, state, gen_node) < 0) { - ec_completed_free(completed); - return NULL; - } - } else { - if (ec_completed_add_match(completed, state, gen_node, - node->string + n) < 0) { - ec_completed_free(completed); - return NULL; - } + if (str[n] == '\0') { + if (ec_completed_add_match(completed, parsed, gen_node, + node->string + n) < 0) + return -1; } - return completed; + return 0; } static const char *ec_node_str_desc(const struct ec_node *gen_node) diff --git a/lib/ecoli_node_subset.c b/lib/ecoli_node_subset.c index 599c761..02b3c28 100644 --- a/lib/ecoli_node_subset.c +++ b/lib/ecoli_node_subset.c @@ -173,14 +173,13 @@ ec_node_subset_parse(const struct ec_node *gen_node, return ret; } -static struct ec_completed * +static int __ec_node_subset_complete(struct ec_node **table, size_t table_len, - struct ec_parsed *state, const struct ec_strvec *strvec) + struct ec_completed *completed, + struct ec_parsed *parsed, + const struct ec_strvec *strvec) { - struct ec_completed *completed = NULL; - struct ec_completed *child_completed = NULL; struct ec_strvec *childvec = NULL; - struct ec_parsed *parsed = NULL; struct ec_node *save; size_t i, len; int ret; @@ -194,23 +193,15 @@ __ec_node_subset_complete(struct ec_node **table, size_t table_len, * + __subset_complete([a, b], childvec) if c matches */ - completed = ec_completed(); - if (completed == NULL) - goto fail; - /* first, try to complete with each node of the table */ for (i = 0; i < table_len; i++) { if (table[i] == NULL) continue; - child_completed = ec_node_complete_child(table[i], - state, strvec); - - if (child_completed == NULL) + ret = ec_node_complete_child(table[i], + completed, parsed, strvec); + if (ret < 0) goto fail; - - ec_completed_merge(completed, child_completed); - child_completed = NULL; } /* then, if a node matches, advance in strvec and try to complete with @@ -219,7 +210,7 @@ __ec_node_subset_complete(struct ec_node **table, size_t table_len, if (table[i] == NULL) continue; - ret = ec_node_parse_child(table[i], state, strvec); + ret = ec_node_parse_child(table[i], parsed, strvec); if (ret == EC_PARSED_NOMATCH) continue; else if (ret < 0) @@ -229,46 +220,39 @@ __ec_node_subset_complete(struct ec_node **table, size_t table_len, childvec = ec_strvec_ndup(strvec, len, ec_strvec_len(strvec) - len); if (childvec == NULL) { - ec_parsed_del_last_child(state); + ec_parsed_del_last_child(parsed); goto fail; } save = table[i]; table[i] = NULL; - child_completed = __ec_node_subset_complete(table, table_len, - state, childvec); + ret = __ec_node_subset_complete(table, table_len, + completed, parsed, childvec); table[i] = save; ec_strvec_free(childvec); childvec = NULL; - ec_parsed_del_last_child(state); + ec_parsed_del_last_child(parsed); - if (child_completed == NULL) + if (ret < 0) goto fail; - - ec_completed_merge(completed, child_completed); - child_completed = NULL; - - ec_parsed_free(parsed); - parsed = NULL; } - return completed; -fail: - ec_parsed_free(parsed); - ec_completed_free(child_completed); - ec_completed_free(completed); + return 0; - return NULL; +fail: + return -1; } -static struct ec_completed * +static int ec_node_subset_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_subset *node = (struct ec_node_subset *)gen_node; - return __ec_node_subset_complete(node->table, node->len, state, strvec); + return __ec_node_subset_complete(node->table, node->len, completed, + parsed, strvec); } static void ec_node_subset_free_priv(struct ec_node *gen_node) diff --git a/lib/ecoli_node_weakref.c b/lib/ecoli_node_weakref.c index 3e202d3..73da26b 100644 --- a/lib/ecoli_node_weakref.c +++ b/lib/ecoli_node_weakref.c @@ -58,14 +58,15 @@ ec_node_weakref_parse(const struct ec_node *gen_node, return ec_node_parse_child(node->child, state, strvec); } -static struct ec_completed * +static int ec_node_weakref_complete(const struct ec_node *gen_node, - struct ec_parsed *state, + struct ec_completed *completed, + struct ec_parsed *parsed, const struct ec_strvec *strvec) { struct ec_node_weakref *node = (struct ec_node_weakref *)gen_node; - return ec_node_complete_child(node->child, state, strvec); + return ec_node_complete_child(node->child, completed, parsed, strvec); } static struct ec_node_type ec_node_weakref_type = { diff --git a/lib/ecoli_parsed.h b/lib/ecoli_parsed.h index df24f05..637059a 100644 --- a/lib/ecoli_parsed.h +++ b/lib/ecoli_parsed.h @@ -80,6 +80,7 @@ struct ec_parsed *ec_node_parse_strvec(struct ec_node *node, * EC_PARSED_NOMATCH (negative) if it does not match * any other negative value (-errno) for other errors * the number of matched strings in strvec + * XXX state is not freed on error ? */ int ec_node_parse_child(struct ec_node *node, struct ec_parsed *state, diff --git a/lib/ecoli_test.c b/lib/ecoli_test.c index 31f2c37..9b05575 100644 --- a/lib/ecoli_test.c +++ b/lib/ecoli_test.c @@ -101,7 +101,6 @@ out: int ec_test_check_complete(struct ec_node *tk, ...) { struct ec_completed *c = NULL; - struct ec_completed_item *item; struct ec_strvec *vec = NULL; const char *s, *expected; int ret = 0; @@ -131,17 +130,23 @@ int ec_test_check_complete(struct ec_node *tk, ...) goto out; } + /* for each expected completion, check it is there */ for (s = va_arg(ap, const char *); s != EC_NODE_ENDLIST; s = va_arg(ap, const char *)) { + struct ec_completed_iter *iter; + const struct ec_completed_item *item; + if (s == NULL) { ret = -1; goto out; } count++; - TAILQ_FOREACH(item, &c->matches, next) { - /* only check matching completions */ + + /* only check matching completions */ + iter = ec_completed_iter(c, EC_MATCH); + while ((item = ec_completed_iter_next(iter)) != NULL) { if (item->add != NULL && strcmp(item->add, s) == 0) break; } @@ -151,8 +156,10 @@ int ec_test_check_complete(struct ec_node *tk, ...) "completion <%s> not in list\n", s); ret = -1; } + ec_completed_iter_free(iter); } + /* check if we have more completions (or less) than expected */ if (count != ec_completed_count(c, EC_MATCH)) { ec_log(EC_LOG_ERR, "nb_completion (%d) does not match (%d)\n", @@ -161,7 +168,7 @@ int ec_test_check_complete(struct ec_node *tk, ...) ret = -1; } - + /* check the expected smallest start */ expected = va_arg(ap, const char *); s = ec_completed_smallest_start(c); if (strcmp(s, expected)) { diff --git a/lib/main-readline.c b/lib/main-readline.c index b147e8a..b8c6459 100644 --- a/lib/main-readline.c +++ b/lib/main-readline.c @@ -79,11 +79,11 @@ static char *my_completion_entry(const char *s, int state) return NULL; } - item = ec_completed_iter_next(iter); - if (item == NULL) + elt = ec_completed_iter_next(iter); + if (elt == NULL) return NULL; - if (asprintf(&out_string, "%s%s", s, item->add) < 0) + if (asprintf(&out_string, "%s%s", s, elt->add) < 0) return NULL; return out_string; @@ -101,7 +101,7 @@ static char **my_attempted_completion(const char *text, int start, int end) } /* this function builds the help string */ -static char *get_node_help(const struct ec_completed_item *item) +static char *get_node_help(const struct ec_completed_elt *elt) { const struct ec_node *node; char *help = NULL; @@ -109,8 +109,8 @@ static char *get_node_help(const struct ec_completed_item *item) const char *node_desc = NULL; size_t i; - for (i = 0; i < item->pathlen; i++) { - node = item->path[i]; + for (i = 0; i < elt->pathlen; i++) { + node = elt->path[i]; if (node_help == NULL) node_help = ec_keyval_get(ec_node_attrs(node), "help"); if (node_desc == NULL)