]> git.droids-corp.org - protos/libecoli.git/commitdiff
save state in completed objects
authorOlivier Matz <zer0@droids-corp.org>
Thu, 25 Jan 2018 19:22:20 +0000 (20:22 +0100)
committerOlivier Matz <zer0@droids-corp.org>
Thu, 25 Jan 2018 19:22:20 +0000 (20:22 +0100)
20 files changed:
lib/ecoli_completed.c
lib/ecoli_completed.h
lib/ecoli_node.h
lib/ecoli_node_cmd.c
lib/ecoli_node_expr.c
lib/ecoli_node_file.c
lib/ecoli_node_many.c
lib/ecoli_node_once.c
lib/ecoli_node_option.c
lib/ecoli_node_or.c
lib/ecoli_node_seq.c
lib/ecoli_node_sh_lex.c
lib/ecoli_node_str.c
lib/ecoli_node_subset.c
lib/ecoli_node_weakref.c
lib/ecoli_parsed.c
lib/ecoli_parsed.h
lib/ecoli_test.c
lib/main-readline.c
lib/todo.txt

index a39c719fc19930b0abb0727ead925b2127cb16c2..68209712b4f4db01fb20404cb630d34ef8bffb72 100644 (file)
@@ -43,13 +43,10 @@ struct ec_completed_item {
        TAILQ_ENTRY(ec_completed_item) next;
        enum ec_completed_type type;
        const struct ec_node *node;
+       struct ec_completed_group *grp;
        char *str;
        char *display;
        struct ec_keyval *attrs;
-
-       /* reverse order: [0] = last, [len-1] = root */
-       const struct ec_node **path;
-       size_t pathlen;
 };
 
 struct ec_completed *ec_completed(void)
@@ -60,12 +57,14 @@ struct ec_completed *ec_completed(void)
        if (completed == NULL)
                goto fail;
 
-       TAILQ_INIT(&completed->nodes);
+       TAILQ_INIT(&completed->groups);
 
        completed->attrs = ec_keyval();
        if (completed->attrs == NULL)
                goto fail;
 
+       completed->cur_state = NULL;
+
        return completed;
 
  fail:
@@ -76,15 +75,17 @@ struct ec_completed *ec_completed(void)
        return NULL;
 }
 
-/* XXX on error, states are not freed ?
- * they can be left in a bad state and should not be reused */
+struct ec_parsed *ec_completed_cur_parse_state(struct ec_completed *completed)
+{
+       return completed->cur_state;
+}
+
 int
-ec_node_complete_child(struct ec_node *node,
-               struct ec_completed *completed,
-               struct ec_parsed *parsed_state,
-               const struct ec_strvec *strvec)
+ec_node_complete_child(struct ec_node *node, struct ec_completed *completed,
+                       const struct ec_strvec *strvec)
 {
-       struct ec_parsed *child_state = NULL;
+       struct ec_parsed *child_state, *cur_state;
+       struct ec_completed_group *cur_group;
        int ret;
 
        /* build the node if required */
@@ -100,13 +101,31 @@ ec_node_complete_child(struct ec_node *node,
        if (node->type->complete == NULL)
                return -ENOTSUP;
 
+       /* save previous parse state, prepare child state */
+       cur_state = completed->cur_state;
        child_state = ec_parsed();
        if (child_state == NULL)
                return -ENOMEM;
+
+       if (cur_state != NULL)
+               ec_parsed_add_child(cur_state, child_state);
        ec_parsed_set_node(child_state, node);
-       ec_parsed_add_child(parsed_state, child_state);
+       completed->cur_state = child_state;
+       cur_group = completed->cur_group;
+       completed->cur_group = NULL;
+
+       /* complete */
+       ret = node->type->complete(node, completed, strvec);
+
+       /* restore parent parse state */
+       if (cur_state != NULL) {
+               ec_parsed_del_child(cur_state, child_state);
+               assert(!ec_parsed_has_child(child_state));
+       }
+       ec_parsed_free(child_state);
+       completed->cur_state = cur_state;
+       completed->cur_group = cur_group;
 
-       ret = node->type->complete(node, completed, child_state, strvec);
        if (ret < 0)
                return ret;
 
@@ -115,42 +134,28 @@ ec_node_complete_child(struct ec_node *node,
        ec_node_dump(stdout, node);
        ec_strvec_dump(stdout, strvec);
        ec_completed_dump(stdout, completed);
-       ec_parsed_dump(stdout, parsed_state);
 #endif
 
-       ec_parsed_del_child(parsed_state, child_state);
-       assert(!ec_parsed_has_child(child_state));
-       ec_parsed_free(child_state);
-
        return 0;
 }
 
 struct ec_completed *ec_node_complete_strvec(struct ec_node *node,
        const struct ec_strvec *strvec)
 {
-       struct ec_parsed *parsed_state = NULL;
        struct ec_completed *completed = NULL;
        int ret;
 
-       parsed_state = ec_parsed();
-       if (parsed_state == NULL)
-               goto fail;
-
        completed = ec_completed();
        if (completed == NULL)
                goto fail;
 
-       ret = ec_node_complete_child(node, completed,
-                               parsed_state, strvec);
+       ret = ec_node_complete_child(node, completed, 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;
 }
@@ -181,27 +186,35 @@ struct ec_completed *ec_node_complete(struct ec_node *node,
        return NULL;
 }
 
-static struct ec_completed_node *
-ec_completed_node(const struct ec_node *node)
+static struct ec_completed_group *
+ec_completed_group(const struct ec_node *node, struct ec_parsed *parsed)
 {
-       struct ec_completed_node *compnode = NULL;
+       struct ec_completed_group *grp = NULL;
 
-       compnode = ec_calloc(1, sizeof(*compnode));
-       if (compnode == NULL)
+       grp = ec_calloc(1, sizeof(*grp));
+       if (grp == NULL)
                return NULL;
 
-       compnode->node = node;
-       TAILQ_INIT(&compnode->items);
+       grp->state = ec_parsed_dup(parsed);
+       if (grp->state == NULL)
+               goto fail;
+
+       grp->node = node;
+       TAILQ_INIT(&grp->items);
+
+       return grp;
 
-       return compnode;
+fail:
+       if (grp != NULL)
+               ec_parsed_free(grp->state);
+       ec_free(grp);
+       return NULL;
 }
 
 struct ec_completed_item *
-ec_completed_item(struct ec_parsed *state, const struct ec_node *node)
+ec_completed_item(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)
@@ -211,28 +224,13 @@ ec_completed_item(struct ec_parsed *state, const struct ec_node *node)
        if (item->attrs == NULL)
                goto fail;
 
-       /* 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] = ec_parsed_get_node(p);
-
-       item->type = EC_NO_MATCH;
+       item->type = EC_COMP_UNKNOWN;
        item->node = node;
 
        return item;
 
 fail:
        if (item != NULL) {
-               ec_free(item->path);
                ec_free(item->str);
                ec_free(item->display);
                ec_keyval_free(item->attrs);
@@ -256,11 +254,11 @@ ec_completed_item_set(struct ec_completed_item *item,
                return -EEXIST;
 
        switch (type) {
-       case EC_NO_MATCH:
+       case EC_COMP_UNKNOWN:
                if (str != NULL)
                        return -EINVAL;
                break;
-       case EC_MATCH:
+       case EC_COMP_FULL:
        case EC_PARTIAL_MATCH:
                if (str == NULL)
                        return -EINVAL;
@@ -297,7 +295,7 @@ int ec_completed_item_set_display(struct ec_completed_item *item,
        int ret = 0;
 
        if (item == NULL || display == NULL ||
-                       item->type == EC_NO_MATCH || item->str == NULL)
+                       item->type == EC_COMP_UNKNOWN || item->str == NULL)
                return -EINVAL;
 
        ret = -ENOMEM;
@@ -315,19 +313,18 @@ fail:
        return ret;
 }
 
+// XXX refactor ec_completed_item(), ec_completed_item_add(), ec_completed_item_set* 
 int
 ec_completed_item_add(struct ec_completed *completed,
                struct ec_completed_item *item)
 {
-       struct ec_completed_node *compnode = NULL;
-
        if (completed == NULL || item == NULL || item->node == NULL)
                return -EINVAL;
 
        switch (item->type) {
-       case EC_NO_MATCH:
+       case EC_COMP_UNKNOWN:
                break;
-       case EC_MATCH:
+       case EC_COMP_FULL:
        case EC_PARTIAL_MATCH:
                completed->count_match++; //XXX
                break;
@@ -335,20 +332,19 @@ ec_completed_item_add(struct ec_completed *completed,
                return -EINVAL;
        }
 
-       /* 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)
+       if (completed->cur_group == NULL) {
+               struct ec_completed_group *grp;
+
+               grp = ec_completed_group(item->node, completed->cur_state);
+               if (grp == NULL)
                        return -ENOMEM;
-               TAILQ_INSERT_TAIL(&completed->nodes, compnode, next);
+               TAILQ_INSERT_TAIL(&completed->groups, grp, next);
+               completed->cur_group = grp;
        }
 
        completed->count++;
-       TAILQ_INSERT_TAIL(&compnode->items, item, next);
+       TAILQ_INSERT_TAIL(&completed->cur_group->items, item, next);
+       item->grp = completed->cur_group;
 
        return 0;
 }
@@ -377,6 +373,12 @@ ec_completed_item_get_node(const struct ec_completed_item *item)
        return item->node;
 }
 
+const struct ec_completed_group *
+ec_completed_item_get_grp(const struct ec_completed_item *item)
+{
+       return item->grp;
+}
+
 void ec_completed_item_free(struct ec_completed_item *item)
 {
        if (item == NULL)
@@ -384,7 +386,6 @@ void ec_completed_item_free(struct ec_completed_item *item)
 
        ec_free(item->str);
        ec_free(item->display);
-       ec_free(item->path);
        ec_keyval_free(item->attrs);
        ec_free(item);
 }
@@ -393,7 +394,6 @@ void ec_completed_item_free(struct ec_completed_item *item)
 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_item *item = NULL;
@@ -402,10 +402,10 @@ ec_node_default_complete(const struct ec_node *gen_node, // XXX rename in nomatc
        if (ec_strvec_len(strvec) != 1)
                return 0;
 
-       item = ec_completed_item(parsed_state, gen_node);
+       item = ec_completed_item(gen_node);
        if (item == NULL)
                return -ENOMEM;
-       ret = ec_completed_item_set(item, EC_NO_MATCH, NULL);
+       ret = ec_completed_item_set(item, EC_COMP_UNKNOWN, NULL);
        if (ret < 0) {
                ec_completed_item_free(item);
                return ret;
@@ -419,24 +419,33 @@ ec_node_default_complete(const struct ec_node *gen_node, // XXX rename in nomatc
        return 0;
 }
 
-void ec_completed_free(struct ec_completed *completed)
+static void ec_completed_group_free(struct ec_completed_group *grp)
 {
-       struct ec_completed_node *compnode;
        struct ec_completed_item *item;
 
-       if (completed == NULL)
+       if (grp == NULL)
                return;
 
-       while (!TAILQ_EMPTY(&completed->nodes)) {
-               compnode = TAILQ_FIRST(&completed->nodes);
-               TAILQ_REMOVE(&completed->nodes, compnode, next);
+       while (!TAILQ_EMPTY(&grp->items)) {
+               item = TAILQ_FIRST(&grp->items);
+               TAILQ_REMOVE(&grp->items, item, next);
+               ec_completed_item_free(item);
+       }
+       ec_parsed_free(ec_parsed_get_root(grp->state));
+       ec_free(grp);
+}
 
-               while (!TAILQ_EMPTY(&compnode->items)) {
-                       item = TAILQ_FIRST(&compnode->items);
-                       TAILQ_REMOVE(&compnode->items, item, next);
-                       ec_completed_item_free(item);
-               }
-               ec_free(compnode);
+void ec_completed_free(struct ec_completed *completed)
+{
+       struct ec_completed_group *grp;
+
+       if (completed == NULL)
+               return;
+
+       while (!TAILQ_EMPTY(&completed->groups)) {
+               grp = TAILQ_FIRST(&completed->groups);
+               TAILQ_REMOVE(&completed->groups, grp, next);
+               ec_completed_group_free(grp);
        }
        ec_keyval_free(completed->attrs);
        ec_free(completed);
@@ -444,7 +453,7 @@ void ec_completed_free(struct ec_completed *completed)
 
 void ec_completed_dump(FILE *out, const struct ec_completed *completed)
 {
-       struct ec_completed_node *compnode;
+       struct ec_completed_group *grp;
        struct ec_completed_item *item;
 
        if (completed == NULL || completed->count == 0) {
@@ -455,15 +464,15 @@ void ec_completed_dump(FILE *out, const struct ec_completed *completed)
        fprintf(out, "completion: count=%u match=%u\n",
                completed->count, completed->count_match);
 
-       TAILQ_FOREACH(compnode, &completed->nodes, next) {
+       TAILQ_FOREACH(grp, &completed->groups, next) {
                fprintf(out, "node=%p, node_type=%s\n",
-                       compnode->node, compnode->node->type->name);
-               TAILQ_FOREACH(item, &compnode->items, next) {
+                       grp->node, grp->node->type->name);
+               TAILQ_FOREACH(item, &grp->items, next) {
                        const char *typestr;
 
                        switch (item->type) {
-                       case EC_NO_MATCH: typestr = "no-match"; break;
-                       case EC_MATCH: typestr = "match"; break;
+                       case EC_COMP_UNKNOWN: typestr = "no-match"; break;
+                       case EC_COMP_FULL: typestr = "match"; break;
                        case EC_PARTIAL_MATCH: typestr = "partial-match"; break;
                        default: typestr = "unknown"; break;
                        }
@@ -483,9 +492,9 @@ unsigned int ec_completed_count(
        if (completed == NULL)
                return count;
 
-       if (type & EC_MATCH)
+       if (type & EC_COMP_FULL)
                count += completed->count_match;
-       if (type & EC_NO_MATCH)
+       if (type & EC_COMP_UNKNOWN)
                count += (completed->count - completed->count_match); //XXX
 
        return count;
@@ -513,7 +522,7 @@ const struct ec_completed_item *ec_completed_iter_next(
        struct ec_completed_iter *iter)
 {
        const struct ec_completed *completed = iter->completed;
-       const struct ec_completed_node *cur_node;
+       const struct ec_completed_group *cur_node;
        const struct ec_completed_item *cur_match;
 
        if (completed == NULL)
@@ -524,7 +533,7 @@ const struct ec_completed_item *ec_completed_iter_next(
 
        /* first call */
        if (cur_node == NULL) {
-               TAILQ_FOREACH(cur_node, &completed->nodes, next) {
+               TAILQ_FOREACH(cur_node, &completed->groups, next) {
                        TAILQ_FOREACH(cur_match, &cur_node->items, next) {
                                if (cur_match != NULL &&
                                                cur_match->type & iter->type)
index 4054a1a9710b4e8920148c546e80c207c52db89e..c05499404e6d7a17c7a9f8a55e4240b73b42db9a 100644 (file)
@@ -44,8 +44,8 @@
 struct ec_node;
 
 enum ec_completed_type {
-       EC_NO_MATCH,
-       EC_MATCH,
+       EC_COMP_UNKNOWN,
+       EC_COMP_FULL,
        EC_PARTIAL_MATCH,
 };
 
@@ -53,18 +53,21 @@ struct ec_completed_item;
 
 TAILQ_HEAD(ec_completed_item_list, ec_completed_item);
 
-struct ec_completed_node {
-       TAILQ_ENTRY(ec_completed_node) next;
+struct ec_completed_group {
+       TAILQ_ENTRY(ec_completed_group) next;
        const struct ec_node *node;
        struct ec_completed_item_list items;
+       struct ec_parsed *state;
 };
 
-TAILQ_HEAD(ec_completed_node_list, ec_completed_node);
+TAILQ_HEAD(ec_completed_group_list, ec_completed_group);
 
 struct ec_completed {
        unsigned count;
        unsigned count_match;
-       struct ec_completed_node_list nodes;
+       struct ec_parsed *cur_state;
+       struct ec_completed_group *cur_group;
+       struct ec_completed_group_list groups;
        struct ec_keyval *attrs; // XXX per node instead?
 };
 
@@ -80,7 +83,6 @@ struct ec_completed *ec_node_complete_strvec(struct ec_node *node,
 /* internal: used by nodes */
 int ec_node_complete_child(struct ec_node *node,
                        struct ec_completed *completed,
-                       struct ec_parsed *parsed_state,
                        const struct ec_strvec *strvec);
 
 /**
@@ -106,13 +108,15 @@ void ec_completed_dump(FILE *out,
        const struct ec_completed *completed);
 
 
+struct ec_parsed *ec_completed_cur_parse_state(struct ec_completed *completed);
+
 /**
  * Create a completion item.
  *
  *
  */
 struct ec_completed_item *
-ec_completed_item(struct ec_parsed *state, const struct ec_node *node);
+ec_completed_item(const struct ec_node *node);
 
 /**
  * Set type and value of a completion item.
@@ -146,6 +150,14 @@ ec_completed_item_get_str(const struct ec_completed_item *item);
 const char *
 ec_completed_item_get_display(const struct ec_completed_item *item);
 
+/**
+ * Get the group of a completion item.
+ *
+ *
+ */
+const struct ec_completed_group *
+ec_completed_item_get_grp(const struct ec_completed_item *item);
+
 /**
  * Get the type of a completion item.
  *
@@ -185,7 +197,6 @@ int ec_completed_item_set_display(struct ec_completed_item *item,
 int
 ec_node_default_complete(const struct ec_node *gen_node,
                        struct ec_completed *completed,
-                       struct ec_parsed *state,
                        const struct ec_strvec *strvec);
 
 /**
@@ -205,7 +216,7 @@ unsigned int ec_completed_count(
 struct ec_completed_iter {
        enum ec_completed_type type;
        const struct ec_completed *completed;
-       const struct ec_completed_node *cur_node;
+       const struct ec_completed_group *cur_node;
        const struct ec_completed_item *cur_match;
 };
 
index 11e993659b838e9cec6a24f1027af192b04cce89..8fe2d769ed962fa08e61f7b9f0903d6ed5f237c1 100644 (file)
@@ -96,7 +96,6 @@ typedef int (*ec_node_parse_t)(const struct ec_node *node,
                        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 *);
@@ -108,8 +107,8 @@ typedef void (*ec_node_free_priv_t)(struct ec_node *);
  */
 struct ec_node_type {
        TAILQ_ENTRY(ec_node_type) next;  /**< Next in list. */
-       const char *name;              /**< Node type name. */
-       ec_node_build_t build; /* (re)build the node, called by generic parse */
+       const char *name;                /**< Node type name. */
+       ec_node_build_t build;           /**< (Re)build the node */
        ec_node_parse_t parse;
        ec_node_complete_t complete;
        ec_node_get_max_parse_len_t get_max_parse_len;
index 3068fc0f35c9df692e306687505919f79691c671..b698f756b1f78456badccddaeee13624e7898393 100644 (file)
@@ -260,12 +260,11 @@ ec_node_cmd_parse(const struct ec_node *gen_node, struct ec_parsed *state,
 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, completed, parsed, strvec);
+       return ec_node_complete_child(node->cmd, completed, strvec);
 }
 
 static void ec_node_cmd_free_priv(struct ec_node *gen_node)
index 58d4969e2a2d0370173cee5e16b8baf1f9f288fa..129163e3c9c275ab811272db77b554b4d88a3cac 100644 (file)
@@ -80,12 +80,11 @@ static int ec_node_expr_parse(const struct ec_node *gen_node,
 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, completed, parsed, strvec);
+       return ec_node_complete_child(node->child, completed, strvec);
 }
 
 static void ec_node_expr_free_priv(struct ec_node *gen_node)
index 0a78cbad23948fc2fcb2cdb1b27e8c5a5b79c8f8..951c494a055ada5a3e49df83d0b96dd60a1fd32b 100644 (file)
@@ -116,7 +116,6 @@ static int split_path(const char *path, char **dname_p, char **bname_p)
 static int
 ec_node_file_complete(const struct ec_node *gen_node,
                struct ec_completed *completed,
-               struct ec_parsed *state,
                const struct ec_strvec *strvec)
 {
        struct ec_completed_item *item = NULL;
@@ -200,7 +199,7 @@ ec_node_file_complete(const struct ec_node *gen_node,
                        is_dir = 0;
                }
 
-               item = ec_completed_item(state, gen_node);
+               item = ec_completed_item(gen_node);
                if (item == NULL) {
                        ret = -ENOMEM;
                        goto out;
@@ -230,7 +229,7 @@ ec_node_file_complete(const struct ec_node *gen_node,
                                ret = -errno;
                                goto out;
                        }
-                       ret = ec_completed_item_set(item, EC_MATCH,
+                       ret = ec_completed_item_set(item, EC_COMP_FULL,
                                                comp_str);
                        if (ret < 0)
                                goto out;
index cc5f738e366539e150dd23b8108de856a71f94e8..8395bd10b556ae8e3ebb3f00959c9502202a4814 100644 (file)
@@ -106,15 +106,15 @@ fail:
 static int
 __ec_node_many_complete(struct ec_node_many *node, unsigned int max,
                        struct ec_completed *completed,
-                       struct ec_parsed *parsed,
                        const struct ec_strvec *strvec)
 {
+       struct ec_parsed *parsed = ec_completed_cur_parse_state(completed);
        struct ec_strvec *childvec = NULL;
        unsigned int i;
        int ret;
 
        /* first, try to complete with the child node */
-       ret = ec_node_complete_child(node->child, completed, parsed, strvec);
+       ret = ec_node_complete_child(node->child, completed, strvec);
        if (ret < 0)
                goto fail;
 
@@ -152,8 +152,7 @@ __ec_node_many_complete(struct ec_node_many *node, unsigned int max,
                        goto fail;
                }
 
-               ret = __ec_node_many_complete(node, max, completed,
-                                       parsed, childvec);
+               ret = __ec_node_many_complete(node, max, completed, childvec);
                ec_parsed_del_last_child(parsed);
                ec_strvec_free(childvec);
                childvec = NULL;
@@ -172,13 +171,12 @@ fail:
 static int
 ec_node_many_complete(const struct ec_node *gen_node,
                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, completed,
-                               parsed, strvec);
+                               strvec);
 }
 
 static void ec_node_many_free_priv(struct ec_node *gen_node)
index 0df4bcd2548835f6809b6207d909eec365780a7e..20200881ce8bcb27f4d5d9b4a30ed147ee922409 100644 (file)
@@ -90,10 +90,10 @@ ec_node_once_parse(const struct ec_node *gen_node,
 static int
 ec_node_once_complete(const struct ec_node *gen_node,
                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_parsed *parsed = ec_completed_cur_parse_state(completed);
        unsigned int count;
        int ret;
 
@@ -104,7 +104,7 @@ ec_node_once_complete(const struct ec_node *gen_node,
        if (count > 0)
                return 0;
 
-       ret = ec_node_complete_child(node->child, completed, parsed, strvec);
+       ret = ec_node_complete_child(node->child, completed, strvec);
        if (ret < 0)
                return ret;
 
index ab4f9f3040deaee7c46be24c3ffad0bfbc475ee0..3f79754dad1755b2b10805db4b6adbcefb4bfc45 100644 (file)
@@ -69,12 +69,11 @@ ec_node_option_parse(const struct ec_node *gen_node,
 static int
 ec_node_option_complete(const struct ec_node *gen_node,
                        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, completed, parsed, strvec);
+       return ec_node_complete_child(node->child, completed, strvec);
 }
 
 static void ec_node_option_free_priv(struct ec_node *gen_node)
index 963f970076a202a2db5bc8ebdeff973ad15ea379..7e6b49e3e69d3b8318d566d8605bf78eb11d27f0 100644 (file)
@@ -72,7 +72,6 @@ ec_node_or_parse(const struct ec_node *gen_node,
 static int
 ec_node_or_complete(const struct ec_node *gen_node,
                struct ec_completed *completed,
-               struct ec_parsed *parsed,
                const struct ec_strvec *strvec)
 {
        struct ec_node_or *node = (struct ec_node_or *)gen_node;
@@ -81,7 +80,7 @@ ec_node_or_complete(const struct ec_node *gen_node,
 
        for (n = 0; n < node->len; n++) {
                ret = ec_node_complete_child(node->table[n],
-                                       completed, parsed, strvec);
+                                       completed, strvec);
                if (ret < 0)
                        return ret;
        }
index 2b33503118ead9164fb15d88d91f59dbe5f7b53c..6025fd7f1e5faa6f127a07bfbced56c3f7127aee 100644 (file)
@@ -98,9 +98,9 @@ fail:
 static int
 __ec_node_seq_complete(struct ec_node **table, size_t table_len,
                struct ec_completed *completed,
-               struct ec_parsed *parsed,
                const struct ec_strvec *strvec)
 {
+       struct ec_parsed *parsed = ec_completed_cur_parse_state(completed);
        struct ec_strvec *childvec = NULL;
        unsigned int i;
        int ret;
@@ -120,7 +120,7 @@ __ec_node_seq_complete(struct ec_node **table, size_t table_len,
         */
 
        /* first, try to complete with the first node of the table */
-       ret = ec_node_complete_child(table[0], completed, parsed, strvec);
+       ret = ec_node_complete_child(table[0], completed, strvec);
        if (ret < 0)
                goto fail;
 
@@ -152,7 +152,7 @@ __ec_node_seq_complete(struct ec_node **table, size_t table_len,
 
                ret = __ec_node_seq_complete(&table[1],
                                        table_len - 1,
-                                       completed, parsed, childvec);
+                                       completed, childvec);
                ec_parsed_del_last_child(parsed);
                ec_strvec_free(childvec);
                childvec = NULL;
@@ -171,13 +171,12 @@ fail:
 static int
 ec_node_seq_complete(const struct ec_node *gen_node,
                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, completed,
-                               parsed, strvec);
+                               strvec);
 }
 
 static size_t ec_node_seq_get_max_parse_len(const struct ec_node *gen_node)
@@ -322,6 +321,8 @@ static int ec_node_seq_testcase(void)
        ret |= EC_TEST_CHECK_COMPLETE(node,
                "", EC_NODE_ENDLIST,
                "foo", EC_NODE_ENDLIST);
+       ec_node_free(node);
+       return 0;
        ret |= EC_TEST_CHECK_COMPLETE(node,
                "f", EC_NODE_ENDLIST,
                "foo", EC_NODE_ENDLIST);
index 94d0d73e39e685d65a10c4d4b04135d868354c58..1a5e4ab2c8fda7e010124b063e8bf35b5c85a23c 100644 (file)
@@ -280,7 +280,6 @@ ec_node_sh_lex_parse(const struct ec_node *gen_node,
 static int
 ec_node_sh_lex_complete(const struct ec_node *gen_node,
                        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;
@@ -301,7 +300,7 @@ ec_node_sh_lex_complete(const struct ec_node *gen_node,
 
        // XXX: complete should add the quotes for !EC_PARTIAL
        // XXX: if no quotes, replace " " by "\ "
-       ret = ec_node_complete_child(node->child, completed, parsed, new_vec);
+       ret = ec_node_complete_child(node->child, completed, new_vec);
        if (ret < 0)
                goto fail;
 
index 483f63c0fbffcbebe315d74547aed5de2fd6bab5..6c47980221d81419180309cf7575d009795184a6 100644 (file)
@@ -70,7 +70,6 @@ ec_node_str_parse(const struct ec_node *gen_node,
 static int
 ec_node_str_complete(const struct ec_node *gen_node,
                struct ec_completed *completed,
-               struct ec_parsed *parsed,
                const struct ec_strvec *strvec)
 {
        struct ec_completed_item *item = NULL;
@@ -79,8 +78,6 @@ ec_node_str_complete(const struct ec_node *gen_node,
        size_t n = 0;
        int ret;
 
-       (void)parsed;
-
        if (ec_strvec_len(strvec) != 1)
                return 0;
 
@@ -94,10 +91,10 @@ ec_node_str_complete(const struct ec_node *gen_node,
        if (str[n] != '\0')
                return 0; // XXX add a no_match instead?
 
-       item = ec_completed_item(parsed, gen_node);
+       item = ec_completed_item(gen_node);
        if (item == NULL)
                return -ENOMEM;
-       ret = ec_completed_item_set(item, EC_MATCH, node->string);
+       ret = ec_completed_item_set(item, EC_COMP_FULL, node->string);
        if (ret < 0) {
                ec_completed_item_free(item);
                return ret;
index 18de0cb298d9287006c2cc38ef507e51289d13f9..b56bf810090c6ce301a90b8f871cd35cdb68d691 100644 (file)
@@ -179,9 +179,9 @@ ec_node_subset_parse(const struct ec_node *gen_node,
 static int
 __ec_node_subset_complete(struct ec_node **table, size_t table_len,
                        struct ec_completed *completed,
-                       struct ec_parsed *parsed,
                        const struct ec_strvec *strvec)
 {
+       struct ec_parsed *parsed = ec_completed_cur_parse_state(completed);
        struct ec_strvec *childvec = NULL;
        struct ec_node *save;
        size_t i, len;
@@ -202,7 +202,7 @@ __ec_node_subset_complete(struct ec_node **table, size_t table_len,
                        continue;
 
                ret = ec_node_complete_child(table[i],
-                                       completed, parsed, strvec);
+                                       completed, strvec);
                if (ret < 0)
                        goto fail;
        }
@@ -231,7 +231,7 @@ __ec_node_subset_complete(struct ec_node **table, size_t table_len,
                save = table[i];
                table[i] = NULL;
                ret = __ec_node_subset_complete(table, table_len,
-                                               completed, parsed, childvec);
+                                               completed, childvec);
                table[i] = save;
                ec_strvec_free(childvec);
                childvec = NULL;
@@ -250,13 +250,12 @@ fail:
 static int
 ec_node_subset_complete(const struct ec_node *gen_node,
                        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, completed,
-                                       parsed, strvec);
+                                       strvec);
 }
 
 static void ec_node_subset_free_priv(struct ec_node *gen_node)
index eacec4ca46061da995275f5c2d0b2c87fde430cd..516b0bbe455d342c75996751f9889363f40d60c8 100644 (file)
@@ -63,12 +63,11 @@ ec_node_weakref_parse(const struct ec_node *gen_node,
 static int
 ec_node_weakref_complete(const struct ec_node *gen_node,
                        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, completed, parsed, strvec);
+       return ec_node_complete_child(node->child, completed, strvec);
 }
 
 static struct ec_node_type ec_node_weakref_type = {
index d338953ac37af7a959aa3179405f94b330d3d5ca..3fb9db249e899dd5a0a18898ae639861c893fa87 100644 (file)
@@ -32,6 +32,7 @@
 #include <assert.h>
 #include <errno.h>
 
+#include <ecoli_assert.h>
 #include <ecoli_malloc.h>
 #include <ecoli_strvec.h>
 #include <ecoli_keyval.h>
@@ -50,15 +51,13 @@ struct ec_parsed {
        struct ec_keyval *attrs;
 };
 
-int ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
-                       const struct ec_strvec *strvec)
+static int __ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
+                               bool is_root, const struct ec_strvec *strvec)
 {
        struct ec_strvec *match_strvec;
        struct ec_parsed *child;
        int ret;
 
-       assert(state != NULL);
-
        /* build the node if required */
        if (node->type->build != NULL) {
                if ((node->flags & EC_NODE_F_BUILT) == 0) {
@@ -72,20 +71,26 @@ int ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
        if (node->type->parse == NULL)
                return -ENOTSUP;
 
-       child = ec_parsed();
-       if (child == NULL)
-               return -ENOMEM;
+       if (!is_root) {
+               child = ec_parsed();
+               if (child == NULL)
+                       return -ENOMEM;
 
+               ec_parsed_add_child(state, child);
+       } else {
+               child = state;
+       }
        ec_parsed_set_node(child, node);
-       ec_parsed_add_child(state, child);
        ret = node->type->parse(node, child, strvec);
-       if (ret < 0)
+       if (ret < 0) // XXX should we free state, child?
                return ret;
 
        if (ret == EC_PARSED_NOMATCH) {
-               ec_parsed_del_child(state, child);
-               assert(TAILQ_EMPTY(&child->children));
-               ec_parsed_free(child);
+               if (!is_root) {
+                       ec_parsed_del_child(state, child);
+                       assert(TAILQ_EMPTY(&child->children));
+                       ec_parsed_free(child);
+               }
                return ret;
        }
 
@@ -98,30 +103,28 @@ int ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
        return ret;
 }
 
+int ec_node_parse_child(struct ec_node *node, struct ec_parsed *state,
+                       const struct ec_strvec *strvec)
+{
+       assert(state != NULL);
+       return __ec_node_parse_child(node, state, false, strvec);
+}
+
 struct ec_parsed *ec_node_parse_strvec(struct ec_node *node,
                                const struct ec_strvec *strvec)
 {
        struct ec_parsed *parsed = ec_parsed();
-       struct ec_parsed *child_parsed;
        int ret;
 
        if (parsed == NULL)
                return NULL;
 
-       ret = ec_node_parse_child(node, parsed, strvec);
+       ret = __ec_node_parse_child(node, parsed, true, strvec);
        if (ret < 0) {
                ec_parsed_free(parsed);
                return NULL;
        }
 
-       if (ret != EC_PARSED_NOMATCH) {
-               /* remove dummy root node */
-               child_parsed = ec_parsed_get_last_child(parsed);
-               ec_parsed_del_child(parsed, child_parsed);
-               ec_parsed_free(parsed);
-               parsed = child_parsed;
-       }
-
        return parsed;
 }
 
@@ -175,33 +178,39 @@ struct ec_parsed *ec_parsed(void)
        return NULL;
 }
 
-struct ec_parsed *ec_parsed_dup(const struct ec_parsed *parsed)
+static struct ec_parsed *
+__ec_parsed_dup(const struct ec_parsed *root, const struct ec_parsed *ref,
+               struct ec_parsed **new_ref)
 {
        struct ec_parsed *dup = NULL;
        struct ec_parsed *child, *dup_child;
        struct ec_keyval *attrs = NULL;
 
-       if (parsed == NULL)
+       if (root == NULL)
                return NULL;
 
        dup = ec_parsed();
        if (dup == NULL)
                return NULL;
 
-       attrs = ec_keyval_dup(parsed->attrs);
+       if (root == ref)
+               *new_ref = dup;
+
+       attrs = ec_keyval_dup(root->attrs);
        if (attrs == NULL)
                goto fail;
        ec_keyval_free(dup->attrs);
        dup->attrs = attrs;
+       dup->node = root->node;
 
-       if (parsed->strvec != NULL) {
-               dup->strvec = ec_strvec_dup(parsed->strvec);
+       if (root->strvec != NULL) {
+               dup->strvec = ec_strvec_dup(root->strvec);
                if (dup->strvec == NULL)
                        goto fail;
        }
 
-       TAILQ_FOREACH(child, &parsed->children, next) {
-               dup_child = ec_parsed_dup(child);
+       TAILQ_FOREACH(child, &root->children, next) {
+               dup_child = __ec_parsed_dup(child, ref, new_ref);
                if (dup_child == NULL)
                        goto fail;
                ec_parsed_add_child(dup, dup_child);
@@ -214,6 +223,19 @@ fail:
        return NULL;
 }
 
+struct ec_parsed *ec_parsed_dup(struct ec_parsed *parsed) //XXX const
+{
+       struct ec_parsed *root, *dup_root, *dup = NULL;
+
+       root = ec_parsed_get_root(parsed);
+       dup_root = __ec_parsed_dup(root, parsed, &dup);
+       if (dup_root == NULL)
+               return NULL;
+       assert(dup != NULL);
+
+       return dup;
+}
+
 void ec_parsed_free_children(struct ec_parsed *parsed)
 {
        struct ec_parsed *child;
@@ -233,6 +255,10 @@ void ec_parsed_free(struct ec_parsed *parsed)
        if (parsed == NULL)
                return;
 
+       // assert(parsed->parent == NULL); XXX
+       // or
+       // parsed = ec_parsed_get_root(parsed);
+
        ec_parsed_free_children(parsed);
        ec_strvec_free(parsed->strvec);
        ec_keyval_free(parsed->attrs);
@@ -277,7 +303,12 @@ void ec_parsed_dump(FILE *out, const struct ec_parsed *parsed)
                fprintf(out, "parsed is NULL, error in parse\n");
                return;
        }
-       if (!ec_parsed_matches(parsed)) {
+
+       /* only exist if it does not match (strvec == NULL) and if it
+        * does not have children: an incomplete parse, like those
+        * generated by complete() don't match but have children that
+        * may match. */
+       if (!ec_parsed_matches(parsed) && TAILQ_EMPTY(&parsed->children)) {
                fprintf(out, "no match\n");
                return;
        }
@@ -292,6 +323,7 @@ void ec_parsed_add_child(struct ec_parsed *parsed,
        child->parent = parsed;
 }
 
+// XXX we can remove the first arg ? parsed == child->parent ?
 void ec_parsed_del_child(struct ec_parsed *parsed, // XXX rename del in unlink?
        struct ec_parsed *child)
 {
@@ -403,7 +435,7 @@ size_t ec_parsed_matches(const struct ec_parsed *parsed)
        if (parsed == NULL)
                return 0;
 
-       if (parsed->node == NULL && TAILQ_EMPTY(&parsed->children)) // XXX both needed?
+       if (parsed->strvec == NULL)
                return 0;
 
        return 1;
index afb765e706a438f14ad733598e333d4974069d56..33da8fc3a16ccd1ae756d9acbda492ff6a674dd7 100644 (file)
@@ -71,7 +71,7 @@ void ec_parsed_free_children(struct ec_parsed *parsed);
  *
  *
  */
-struct ec_parsed *ec_parsed_dup(const struct ec_parsed *parsed);
+struct ec_parsed *ec_parsed_dup(struct ec_parsed *parsed);
 
 /**
  *
index 80e6a9fe0b1bcc99e1ce5321450fd12f4acfa2ff..b9b515b02d92473fca9a4c7003115482762b4d6c 100644 (file)
@@ -147,7 +147,7 @@ int ec_test_check_complete(struct ec_node *tk, ...)
                count++;
 
                /* only check matching completions */
-               iter = ec_completed_iter(c, EC_MATCH);
+               iter = ec_completed_iter(c, EC_COMP_FULL);
                while ((item = ec_completed_iter_next(iter)) != NULL) {
                        const char *str = ec_completed_item_get_str(item);
                        if (str != NULL && strcmp(str, s) == 0)
@@ -163,10 +163,10 @@ int ec_test_check_complete(struct ec_node *tk, ...)
        }
 
        /* check if we have more completions (or less) than expected */
-       if (count != ec_completed_count(c, EC_MATCH)) {
+       if (count != ec_completed_count(c, EC_COMP_FULL)) {
                EC_LOG(EC_LOG_ERR,
                        "nb_completion (%d) does not match (%d)\n",
-                       count, ec_completed_count(c, EC_MATCH));
+                       count, ec_completed_count(c, EC_COMP_FULL));
                ec_completed_dump(stdout, c);
                ret = -1;
        } else
index da447d8714870cc9444b5929206a96b0007f2859..141c8cd0b308bce9c6fca1e21c28f565e1b4c105 100644 (file)
@@ -83,7 +83,7 @@ static char *my_completion_entry(const char *s, int state)
                        return NULL;
 
                ec_completed_iter_free(iter);
-               iter = ec_completed_iter(c, EC_MATCH | EC_PARTIAL_MATCH);
+               iter = ec_completed_iter(c, EC_COMP_FULL | EC_PARTIAL_MATCH);
                if (iter == NULL)
                        return NULL;
        }
@@ -98,7 +98,7 @@ static char *my_completion_entry(const char *s, int state)
                /* don't add the trailing space for partial completions */
                if (state == 0) {
                        item_type = ec_completed_item_get_type(item);
-                       if (item_type == EC_MATCH)
+                       if (item_type == EC_COMP_FULL)
                                rl_completion_suppress_append = 0;
                        else
                                rl_completion_suppress_append = 1;
@@ -128,6 +128,8 @@ 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)
 {
+       const struct ec_completed_group *grp;
+       struct ec_parsed *state; // XXX keep const with macro
        const struct ec_node *node;
        char *help = NULL;
        const char *node_help = NULL;
@@ -135,10 +137,12 @@ static char *get_node_help(const struct ec_completed_item *item)
 //     size_t i;
 
        (void)item;
-#if 0 //XXX
-       /* Retrieve the most precise help for this node. */
-       for (i = 0; i < item->pathlen; i++) {
-               node = item->path[i];
+#if 1
+       grp = ec_completed_item_get_grp(item);
+       state = grp->state;
+       for (state = grp->state; state != NULL;
+            state = ec_parsed_get_parent(state)) {
+               node = ec_parsed_get_node(state);
                if (node_help == NULL)
                        node_help = ec_keyval_get(ec_node_attrs(node), "help");
                if (node_desc == NULL)
@@ -164,8 +168,8 @@ static char *get_node_help(const struct ec_completed_item *item)
 static int show_help(int ignore, int invoking_key)
 {
        struct ec_completed_iter *iter;
+       const struct ec_completed_group *grp, *prev_grp = NULL;
        const struct ec_completed_item *item;
-       const struct ec_node *prev_node = NULL;
        struct ec_completed *c;
        struct ec_parsed *p;
        char *line = NULL;
@@ -199,7 +203,8 @@ static int show_help(int ignore, int invoking_key)
 
        /* let's display one contextual help per node */
        count = 0;
-       iter = ec_completed_iter(c, EC_NO_MATCH | EC_MATCH | EC_PARTIAL_MATCH);
+       iter = ec_completed_iter(c,
+               EC_COMP_UNKNOWN | EC_COMP_FULL | EC_PARTIAL_MATCH);
        if (iter == NULL)
                goto fail;
 
@@ -211,14 +216,15 @@ static int show_help(int ignore, int invoking_key)
                helps[1] = "<return>";
 
        while ((item = ec_completed_iter_next(iter)) != NULL) {
-               const struct ec_node *node;
                char **tmp;
 
-               /* keep one help per node, skip other items  */
-               node = ec_completed_item_get_node(item);
-               if (node == prev_node)
+               /* keep one help per group, skip other items  */
+               grp = ec_completed_item_get_grp(item);
+               if (grp == prev_grp)
                        continue;
 
+               prev_grp = grp;
+
                tmp = realloc(helps, (count + match + 2) * sizeof(char *));
                if (tmp == NULL)
                        goto fail;
index 58b7996dd1483e16970a72659082e1d980f21509..734de6bcf8cbf7adc368d8a9f448d6d254219d67 100644 (file)
@@ -82,6 +82,8 @@ examples
 - example with libedit
 - mini script language
 - configuration file
+- mini shell: cd, ls, cat, stat
+- mini network console based on ip
 
 doc
 ===