api doc and minor changes
authorOlivier Matz <zer0@droids-corp.org>
Fri, 21 Feb 2020 20:56:07 +0000 (21:56 +0100)
committerOlivier Matz <zer0@droids-corp.org>
Fri, 21 Feb 2020 20:56:07 +0000 (21:56 +0100)
32 files changed:
examples/readline/main.c
include/ecoli.h
include/ecoli_complete.h
include/ecoli_node.h
include/ecoli_node_dynamic.h
include/ecoli_parse.h
meson.build
src/ecoli_complete.c
src/ecoli_editline.c
src/ecoli_node.c
src/ecoli_node_any.c
src/ecoli_node_bypass.c
src/ecoli_node_cmd.c
src/ecoli_node_cond.c
src/ecoli_node_dynamic.c
src/ecoli_node_empty.c
src/ecoli_node_expr.c
src/ecoli_node_file.c
src/ecoli_node_int.c
src/ecoli_node_many.c
src/ecoli_node_once.c
src/ecoli_node_option.c
src/ecoli_node_or.c
src/ecoli_node_re.c
src/ecoli_node_re_lex.c
src/ecoli_node_seq.c
src/ecoli_node_sh_lex.c
src/ecoli_node_space.c
src/ecoli_node_str.c
src/ecoli_node_subset.c
src/ecoli_parse.c
src/ecoli_test.c

index 90a25f0..a64d068 100644 (file)
@@ -106,16 +106,16 @@ static char **my_attempted_completion(const char *text, int start, int end)
 static char *get_node_help(const struct ec_comp_item *item)
 {
        const struct ec_comp_group *grp;
-       const struct ec_pnode *state;
+       const struct ec_pnode *pstate;
        const struct ec_node *node;
        char *help = NULL;
        const char *node_help = NULL;
-       const char *node_desc = NULL;
+       char *node_desc = NULL;
 
        grp = ec_comp_item_get_grp(item);
-       for (state = ec_comp_group_get_state(grp); state != NULL;
-            state = ec_pnode_get_parent(state)) {
-               node = ec_pnode_get_node(state);
+       for (pstate = ec_comp_group_get_pstate(grp); pstate != NULL;
+            pstate = ec_pnode_get_parent(pstate)) {
+               node = ec_pnode_get_node(pstate);
                if (node_help == NULL)
                        node_help = ec_dict_get(ec_node_attrs(node), "help");
                if (node_desc == NULL)
@@ -130,6 +130,8 @@ static char *get_node_help(const struct ec_comp_item *item)
        if (asprintf(&help, "%-20s %s", node_desc, node_help) < 0)
                return NULL;
 
+       ec_free(node_desc);
+
        return help;
 }
 
@@ -141,7 +143,7 @@ static int show_help(int ignore, int invoking_key)
        struct ec_comp *c = NULL;
        struct ec_pnode *p = NULL;
        char *line = NULL;
-       unsigned int count;
+       size_t count;
        char **helps = NULL;
        int match = 0;
        int cols;
index f5c42d2..3a6f328 100644 (file)
@@ -16,7 +16,7 @@
  *
  * The library also provides helpers to create a an interactive command
  * line based on @ref editline library, and a @ref yaml parser for
- * grammar trees.
+ * grammar graphs.
  */
 
 #ifndef ECOLI_
index c36019a..8cc28e1 100644 (file)
@@ -6,16 +6,16 @@
  * @defgroup complete Complete
  * @{
  *
- * @brief Complete string input using a grammar tree
+ * @brief Complete string input using a grammar graph.
  *
- * This file provide helpers to list and manipulate the possible
+ * This file provides helpers to list and manipulate the possible
  * completions for a given input.
  *
  * Use @ec_complete_strvec() to complete a vector of strings when
  * the input is already split into several tokens. You can use
  * @ec_complete() if you know that the size of the vector is
- * 1. This is common if you grammar tree has a lexer that will tokenize
- * the input.
+ * 1. This is common if your grammar graph includes a lexer that
+ * will tokenize the input.
  *
  * These 2 functions return a pointer to an @ec_comp structure, that
  * lists the possible completions. The completions are grouped into
@@ -42,8 +42,8 @@ struct ec_comp;
  */
 enum ec_comp_type {
        EC_COMP_UNKNOWN = 0x1,
-       EC_COMP_FULL = 0x2,
-       EC_COMP_PARTIAL = 0x4,
+       EC_COMP_FULL = 0x2,    /**< The item is fully completed. */
+       EC_COMP_PARTIAL = 0x4, /**< The item is partially completed. */
        EC_COMP_ALL = 0x7,
 };
 
@@ -54,12 +54,12 @@ enum ec_comp_type {
  * vector that only contains 1 element, the input string. Using this
  * function is often more convenient if you get your input from a
  * buffer, because you won't have to create a vector. Usually, it means
- * you have a lexer in your grammar tree that will tokenize the input.
+ * you have a lexer in your grammar graph that will tokenize the input.
  *
  * See @ec_complete_strvec() for more details.
  *
  * @param node
- *   The grammar tree.
+ *   The grammar graph.
  * @param str
  *   The input string.
  * @return
@@ -79,16 +79,16 @@ struct ec_comp *ec_complete(const struct ec_node *node,
  * vector should be ["cat", "x"].
  *
  * To get the completion list, the engine parses the beginning of the
- * input using the grammar tree. The resulting parsing tree is saved and
+ * input using the grammar graph. The resulting parsing tree is saved and
  * attached to each completion group.
  *
  * The result is a @ec_comp structure pointer, which contains several
  * groups of completion items.
  *
  * @param node
- *   The grammar tree.
- * @param str
- *   The input string.
+ *   The grammar graph.
+ * @param strvec
+ *   The input string vector.
  * @return
  *   A pointer to the completion list on success, or NULL
  *   on error (errno is set).
@@ -97,80 +97,159 @@ struct ec_comp *ec_complete_strvec(const struct ec_node *node,
        const struct ec_strvec *strvec);
 
 /**
- * Get the list of completions when called from a node completion.
+ * Get the list of completions of a child node.
  *
- * This function is to be used by ecoli nodes.
+ * This function is to be used by intermediate ecoli nodes, i.e. nodes
+ * which have children (ex: ec_node_seq, ec_node_or, ...). It fills an
+ * existing @ec_comp structure, passed by the parent node.
  *
+ * @param node
+ *   The grammar graph.
+ * @param comp
+ *   The current completion list to be filled.
+ * @param strvec
+ *   The input string vector.
+ * @return
+ *   0 on success, or -1 on error (errno is set).
  */
 int ec_complete_child(const struct ec_node *node,
                        struct ec_comp *comp,
                        const struct ec_strvec *strvec);
 
 /**
- * Create a completion object (list of completion items).
- *
+ * Create an empty completion object (list of completion items).
  *
+ * @return
+ *   A pointer to the completion structure on success, or NULL on error
+ *   (errno is set).
  */
-struct ec_comp *ec_comp(struct ec_pnode *state);
+struct ec_comp *ec_comp(void);
 
 /**
  * Free a completion object and all its items.
  *
- *
+ * @param comp
+ *   The pointer to the completion structure to free.
  */
 void ec_comp_free(struct ec_comp *comp);
 
 /**
+ * Dump the content of a completions list.
  *
- *
- *
+ * @param out
+ *   The stream where the dump is sent.
+ * @param comp
+ *   The pointer to the completion list structure.
  */
-void ec_comp_dump(FILE *out,
-       const struct ec_comp *comp);
+void ec_comp_dump(FILE *out, const struct ec_comp *comp);
 
 /**
- * Merge items contained in 'from' into 'to'
+ * Merge items contained in 'from' into 'to'.
  *
  * The 'from' comp struct is freed.
+ *
+ * @param to
+ *   The destination completion list.
+ * @param from
+ *   The source completion list.
+ * @return
+ *   0 on success, or -1 on error (errno is set).
  */
-int ec_comp_merge(struct ec_comp *to,
-               struct ec_comp *from);
+int ec_comp_merge(struct ec_comp *to, struct ec_comp *from);
 
 /**
- * Get current completion state.
+ * Get current parsing state of completion.
+ *
+ * This function can be called by a node during the completion process.
  *
+ * When processing the list of completions for a given input,
+ * an incomplete parsing tree is generated before the completion
+ * callback is invoked. A node may use it if the completions list
+ * depend on what was previously parsed. For instance, the "once"
+ * node checks in the parsing tree if the node is already parsed.
+ * In this case, no completion is issued.
+ *
+ * @param comp
+ *   The current completion list.
+ * @return
+ *   The current parsing state (cannot be NULL).
  */
-struct ec_pnode *ec_comp_get_state(const struct ec_comp *comp);
+struct ec_pnode *ec_comp_get_cur_pstate(const struct ec_comp *comp);
 
 /**
  * Get current completion group.
  *
+ * This function can be called by a node during the completion process.
+ *
+ * A completion group is a list of completion items that share the same
+ * parsing state and are issued by the same grammar node. The completion
+ * group is created when the first item is added, thus this function
+ * returns NULL if no item has been added in the group.
+ *
+ * @param comp
+ *   The current completion list.
+ * @return
+ *   The current completion group (can be NULL).
  */
-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);
 
 /**
- * Get completion group attributes.
+ * Get completion attributes.
+ *
+ * Arbitrary attributes (stored in a dictionary) can be attached to a
+ * completion state.
  *
+ * @param comp
+ *   The completion list.
+ * @return
+ *   The associated attributes.
  */
 struct ec_dict *ec_comp_get_attrs(const struct ec_comp *comp);
 
-/* shortcut for ec_comp_item() + ec_comp_item_add() */
-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);
-
 /**
+ * Add an item in competion list.
+ *
+ * This function can be called by a node during the completion process,
+ * for each completion item that should be added to the list. This is
+ * typically done in terminal nodes, like ec_node_str or ec_node_file.
+ *
+ * Create a new completion item, and add it into the completion
+ * list. A completion item has a type, which can be:
+ * - EC_COMP_FULL: the item is fully completed (common case, used
+ *   for instance in the str node)
+ * - EC_COMP_PARTIAL: the item is only partially completed (this
+ *   happens rarely, for instance in the file node, when a completion
+ *   goes up to the next slash).
+ * - EC_COMP_UNKNOWN: the node detects a valid token, but does not
+ *   how to complete it (ex: the int node).
  *
+ * @param comp
+ *   The current completion list.
+ * @param node
+ *   The node issuing the completion item.
+ * @param type
+ *   The type of the item.
+ * @param start
+ *   The incomplete string being completed.
+ * @param full
+ *   The string fully completed.
+ * @return
+ *   The item that was added in the list on success, or NULL
+ *   on error. Note: don't free the returned value, as it is referenced
+ *   by the completion list. It is returned in case it needs to be
+ *   modified, for instance with ec_comp_item_set_display().
  */
-int ec_comp_item_set_str(struct ec_comp_item *item,
-                       const char *str);
+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);
 
 /**
  * Get the string value of a completion item.
  *
- *
+ * @param item
+ *   The completion item..
+ * @return
+ *   The completion string of this item.
  */
 const char *
 ec_comp_item_get_str(const struct ec_comp_item *item);
@@ -178,7 +257,13 @@ ec_comp_item_get_str(const struct ec_comp_item *item);
 /**
  * Get the display string value of a completion item.
  *
+ * The display string corresponds to what is displayed when
+ * listing the possible completions.
  *
+ * @param item
+ *   The completion item..
+ * @return
+ *   The display string of this item.
  */
 const char *
 ec_comp_item_get_display(const struct ec_comp_item *item);
@@ -186,7 +271,13 @@ ec_comp_item_get_display(const struct ec_comp_item *item);
 /**
  * Get the completion string value of a completion item.
  *
+ * The completion string corresponds to what should be added to
+ * the incomplete token to complete it.
  *
+ * @param item
+ *   The completion item.
+ * @return
+ *   The completion string of this item.
  */
 const char *
 ec_comp_item_get_completion(const struct ec_comp_item *item);
@@ -194,7 +285,13 @@ ec_comp_item_get_completion(const struct ec_comp_item *item);
 /**
  * Get the group of a completion item.
  *
+ * The completion group corresponds to the list of items that share
+ * the same parsing state and are issued by the same node.
  *
+ * @param item
+ *   The completion item.
+ * @return
+ *   The completion group of this item.
  */
 const struct ec_comp_group *
 ec_comp_item_get_grp(const struct ec_comp_item *item);
@@ -202,7 +299,11 @@ ec_comp_item_get_grp(const struct ec_comp_item *item);
 /**
  * Get the type of a completion item.
  *
- *
+ * @param item
+ *   The completion item.
+ * @return
+ *   The type of this item (EC_COMP_UNKNOWN, EC_COMP_PARTIAL or
+ *   EC_COMP_FULL).
  */
 enum ec_comp_type
 ec_comp_item_get_type(const struct ec_comp_item *item);
@@ -210,15 +311,42 @@ ec_comp_item_get_type(const struct ec_comp_item *item);
 /**
  * Get the node associated to a completion item.
  *
- *
+ * @param item
+ *   The completion item.
+ * @return
+ *   The node that issued the completion item.
  */
 const struct ec_node *
 ec_comp_item_get_node(const struct ec_comp_item *item);
 
+/**
+ * Set the completion item string.
+ *
+ * Some intermediate nodes like sh_lex modify the completion string of
+ * items generated by their children, for instance to add quotes.
+ *
+ * @param item
+ *   The completion item to update.
+ * @param str
+ *   The new item string.
+ * @return
+ *   0 on success, or -1 on error (errno is set).
+ */
+int ec_comp_item_set_str(struct ec_comp_item *item, const char *str);
+
 /**
  * Set the display value of an item.
  *
+ * The display string corresponds to what is displayed when listing the
+ * possible completions. Some nodes like ec_node_file change the default
+ * value display the base name instead of the full path.
  *
+ * @param item
+ *   The completion item to update.
+ * @param str
+ *   The new display string.
+ * @return
+ *   0 on success, or -1 on error (errno is set).
  */
 int ec_comp_item_set_display(struct ec_comp_item *item,
                                const char *display);
@@ -226,7 +354,17 @@ int ec_comp_item_set_display(struct ec_comp_item *item,
 /**
  * Set the completion value of an item.
  *
+ * The completion string corresponds to what should be added to
+ * the incomplete token to complete it. Some nodes like sh_lex
+ * modify it in the items generated by their children, for instance
+ * to add a terminating quote.
  *
+ * @param item
+ *   The completion item to update.
+ * @param str
+ *   The new completion string.
+ * @return
+ *   0 on success, or -1 on error (errno is set).
  */
 int ec_comp_item_set_completion(struct ec_comp_item *item,
                                const char *completion);
@@ -234,52 +372,83 @@ int ec_comp_item_set_completion(struct ec_comp_item *item,
 /**
  * Get the completion group node.
  *
- *
+ * @param grp
+ *   The completion group.
  */
 const struct ec_node *
 ec_comp_group_get_node(const struct ec_comp_group *grp);
 
 /**
- * Get the completion group parsed state.
+ * Get the completion group parsing state.
  *
+ * All items of a completion group are issued by the same node.
+ * This function returns a pointer to this node.
  *
+ * @param grp
+ *   The completion group.
+ * @return
+ *   The node that issued the completion group.
  */
 const struct ec_pnode *
-ec_comp_group_get_state(const struct ec_comp_group *grp);
+ec_comp_group_get_pstate(const struct ec_comp_group *grp);
 
 /**
  * Get the completion group attributes.
  *
+ * The parsing state contains the parsing result of the input data
+ * preceding the completion. All items of a completion group share the
+ * same parsing state.
  *
+  * @param grp
+ *   The completion group.
+ * @return
+ *   The parsing state of the completion group.
  */
 const struct ec_dict *
 ec_comp_group_get_attrs(const struct ec_comp_group *grp);
 
 
 /**
+ * Default node completion callback
  *
+ * This function is the default completion method for nodes that do
+ * not define one.
  *
+ * This helper adds a completion item of type EC_COMP_UNKNOWN if the
+ * input string vector contains one element, to indicate that everything
+ * before the last element of the string vector has been parsed
+ * successfully, but the node doesn't know how to complete the last
+ * element.
  *
+ * @param node
+ *   The completion node.
+ * @param comp
+ *   The completion list to update.
+ * @param strvec
+ *   The input string vector.
+ * @return
+ *   0 on succes, or -1 on error (errno is set).
  */
 int
-ec_complete_unknown(const struct ec_node *gen_node,
+ec_complete_unknown(const struct ec_node *node,
                        struct ec_comp *comp,
                        const struct ec_strvec *strvec);
 
 /**
+ * Get the number of completion items.
  *
+ * Return the number of completion items that match a given type in a
+ * completion list.
  *
- *
- */
-unsigned int ec_comp_count(
-       const struct ec_comp *comp,
-       enum ec_comp_type flags);
-
-/**
- *
- *
- *
+ * @param comp
+ *   The completion list.
+ * @param type
+ *   A logical OR of flags among EC_COMP_UNKNOWN, EC_COMP_PARTIAL and
+ *   EC_COMP_FULL, to select the type to match.
+ * @return
+ *   The number of matching items.
  */
+size_t ec_comp_count(const struct ec_comp *comp, enum ec_comp_type type);
 
 /**
  * Get the first completion item matching the type.
index 129ca4d..908e47e 100644 (file)
@@ -3,7 +3,7 @@
  */
 
 /**
- * @defgroup grammar_tree Grammar Tree
+ * @defgroup grammar_graph Grammar Graph
  * @{
  *
  * @brief Libecoli grammar nodes.
  *
  * A node can have child nodes. For instance, a sequence node
  * ec_node_seq(ec_node_str("foo"), ec_node_str("bar")) will match
- * ["foo", "bar"].
+ * a sequence: ["foo", "bar"].
+ *
+ * Note: at some places in the documentation and the code, we may talk
+ * about the grammar tree, but as loops are allowed, we should instead
+ * talk about grammar graph.
  */
 
 #ifndef ECOLI_NODE_
@@ -47,6 +51,7 @@
 
 #include <sys/queue.h>
 #include <sys/types.h>
+#include <stdbool.h>
 #include <stdio.h>
 
 /**
@@ -76,7 +81,31 @@ struct ec_config_schema;
        static void __attribute__((constructor, used))                  \
        ec_node_init_##t(void)                                          \
        {                                                               \
-               if (ec_node_type_register(&t) < 0)                      \
+               if (ec_node_type_register(&t, 0) < 0)                   \
+                       fprintf(stderr,                                 \
+                               "cannot register node type %s\n",       \
+                               t.name);                                \
+       }
+
+/**
+ * Register a node type at library load, overriding previous registration.
+ *
+ * The node type is registered in a function that has the the
+ * constructor attribute: the function is called at library load.
+ *
+ * Be careful when using this macro, as the last type with a given name
+ * is the one that is actually registered. The call order may be hard to
+ * predict, especially within the same binary.
+ *
+ * @param t
+ *   The name of the ec_node_type structure variable.
+ */
+#define EC_NODE_TYPE_REGISTER_OVERRIDE(t)                              \
+       static void ec_node_init_##t(void);                             \
+       static void __attribute__((constructor, used))                  \
+       ec_node_init_##t(void)                                          \
+       {                                                               \
+               if (ec_node_type_register(&t, 1) < 0)                   \
                        fprintf(stderr,                                 \
                                "cannot register node type %s\n",       \
                                t.name);                                \
@@ -93,6 +122,9 @@ TAILQ_HEAD(ec_node_type_list, ec_node_type);
  * The function pointer is not called directly, the helper
  * @ec_node_set_config() should be used instead.
  *
+ * The configuration passed to this function pointer is valid,
+ * i.e. @ec_config_validate() returned 0 on it.
+ *
  * @param node
  *   The node to configure.
  * @param config
@@ -104,20 +136,20 @@ typedef int (*ec_node_set_config_t)(struct ec_node *node,
                                const struct ec_config *config);
 
 /**
- * Parse a string vector using the given grammar tree.
+ * Parse a string vector using the given grammar graph.
  *
  * The function pointer is not called directly, the helpers @ec_parse(),
  * ec_parse_strvec() or ec_parse_child() should be used instead.
  *
  * The implementation of this method for a node that manages children
- * will call ec_parse_child(child, state, child_strvec).
+ * will call ec_parse_child(child, pstate, child_strvec).
  *
  * @param node
- *   The root node of the grammar tree.
- * @param state
+ *   The grammar graph.
+ * @param pstate
  *   A pointer to the leaf being parsed in the parsing tree. It can be
  *   used by a node to retrieve information from the current parsing
- *   tree. To get the root of the tree, @ec_pnode_get_root(state) should
+ *   tree. To get the root of the tree, @ec_pnode_get_root(pstate) should
  *   be used.
  * @param strvec
  *   The string vector to be parsed.
@@ -127,25 +159,27 @@ typedef int (*ec_node_set_config_t)(struct ec_node *node,
  *   vector. On error, a negative value is returned and errno is set.
  */
 typedef int (*ec_parse_t)(const struct ec_node *node,
-                       struct ec_pnode *state,
+                       struct ec_pnode *pstate,
                        const struct ec_strvec *strvec);
 
 /**
- * Get completion items using the given grammar tree.
+ * Get completion items using the given grammar graph.
  *
- * The function pointer is not called directly, the helpers @ec_complete(),
- * ec_complete_strvec() or ec_complete_child() should be used instead.
+ * The function pointer should not be called directly, the helpers
+ * @ec_complete(), ec_complete_strvec() or ec_complete_child() should be
+ * used instead.
  *
  * This function completes the last element of the string vector.
  * For instance, node.type->complete(node, comp, ["ls"]) will
  * list all commands that starts with "ls", while
  * node.type->complete(node, comp, ["ls", ""]) will list all
  * possible values for the next argument.
-
- * The implementation of this function is supposed to either:
+ *
+ * The implementation of this function in the node is supposed
+ * to either:
  * - call @ec_comp_add_item(node, comp, ...) for each completion item
- *   that should be added to the list. This is done in terminal nodes,
- *   for example in ec_node_str or ec_node_file.
+ *   that should be added to the list. This is typically done in
+ *   terminal nodes, for example in ec_node_str or ec_node_file.
  * - call @ec_complete_child(child, comp, child_strvec) to let
  *   the children nodes add their own completion. This is the
  *   case of ec_node_or which trivially calls @ec_complete_child()
@@ -160,7 +194,7 @@ typedef int (*ec_parse_t)(const struct ec_node *node,
  * complete the last element.
  *
  * @param node
- *   The root node of the grammar tree.
+ *   The root node of the grammar graph.
  * @param comp
  *   The current list of completion items, to be filled by the
  *   node.type->complete() method.
@@ -174,17 +208,95 @@ typedef int (*ec_complete_t)(const struct ec_node *node,
                                const struct ec_strvec *strvec);
 
 /**
+ * Get the short description of a grammar node.
+ *
+ * This function pointer should not be called directly. The
+ * @ec_node_desc() helper should be used instead.
+ *
+ * This callback is typically used when building a help string for a
+ * grammar graph. It is used in ecoli editline interface to generate
+ * contextual help like this (first column):
+ *   <int>     An integer.
+ *   foo       The foo string.
+ *   bar       The bar string.
+ *
+ * If this callback is set to NULL in the node type, the
+ * default behavior is to return the node type name inside <>, for
+ * instance "<int>". The string node type implements this method to
+ * return the string value. An integer node could implement it
+ * to return its range (ex: "1..10").
+ *
+ * The returned value is a pointer that must be freed by
+ * the caller with @ec_free().
+ *
+ * On error, NULL is returned and errno is set.
+ */
+typedef char * (*ec_node_desc_t)(const struct ec_node *);
+
+/**
+ * Initialize the node private area.
+ *
+ * This function pointer should not be called directly. The @ec_node()
+ * and ec_node_from_type() helpers, that allocate new nodes, should be
+ * used instead.
+ *
+ * If not NULL, this function is called when a node is instanciated, to
+ * initialize the private area of a node. In any case, the private area
+ * is first zeroed.
  *
+ * On success, 0 is returned. On error, a negative value is returned and
+ * errno is set.
  */
-typedef const char * (*ec_node_desc_t)(const struct ec_node *);
 typedef int (*ec_node_init_priv_t)(struct ec_node *);
+
+/**
+ * Free the node private area.
+ *
+ * This function pointer should not be called directly. The
+ * @ec_node_free() helper should be used instead.
+ *
+ * When a node is deleted, this function is called to free the resources
+ * referenced in the node private area.
+ */
 typedef void (*ec_node_free_priv_t)(struct ec_node *);
+
+/**
+ * Count the number of node children.
+ *
+ * This function pointer should not be called directly. The
+ * @ec_node_get_children_count() helper should be used instead.
+ *
+ * Some grammar nodes like seq, or, many, (...), reference children
+ * nodes in the grammar graph. This function returns the number of
+ * children.
+ */
 typedef size_t (*ec_node_get_children_count_t)(const struct ec_node *);
+
+/**
+ * Count the number of node children.
+ *
+ * This function pointer should not be called directly. The
+ * @ec_node_get_child() helper should be used instead.
+ *
+ * Some grammar nodes like seq, or, many, (...), reference children
+ * nodes in the grammar graph. This function sets the i-th child (with i
+ * lower than the return value of ec_node_get_children_count()) in the
+ * child pointer. It also returns the number of references to the child
+ * owned by the parent. This information is used by the algorithm that
+ * frees a grammar graph taking care of loops.
+ *
+ * On success, 0 is returned. On error, a negative value is returned and
+ * errno is set.
+ */
 typedef int (*ec_node_get_child_t)(const struct ec_node *,
        size_t i, struct ec_node **child, unsigned int *refs);
 
 /**
- * A structure describing a node type.
+ * A structure describing a grammar node type.
+ *
+ * It is usually defined as a static const structure in the code
+ * defining a new grammar node type. Examples can be found in
+ * ecoli_node_<type>.c files.
  */
 struct ec_node_type {
        TAILQ_ENTRY(ec_node_type) next;  /**< Next in list. */
@@ -192,68 +304,85 @@ struct ec_node_type {
        /** Configuration schema array, must be terminated by a sentinel
         *  (.type = EC_CONFIG_TYPE_NONE). */
        const struct ec_config_schema *schema;
-       ec_node_set_config_t set_config; /* validate/ack a config change */
-       ec_parse_t parse;
-       ec_complete_t complete;
-       ec_node_desc_t desc;
-       size_t size;
-       ec_node_init_priv_t init_priv;
-       ec_node_free_priv_t free_priv;
+       size_t size;                     /**< Size of private area */
+       ec_node_set_config_t set_config; /**< Validate and set configuration. */
+       ec_parse_t parse;                /**< Parse a string vector. */
+       ec_complete_t complete;          /**< Get completion items. */
+       ec_node_desc_t desc;             /**< Get short description. */
+       ec_node_init_priv_t init_priv;   /**< Initialize private area. */
+       ec_node_free_priv_t free_priv;   /**< Free node resourses. */
+       /** Get children count. */
        ec_node_get_children_count_t get_children_count;
-       ec_node_get_child_t get_child;
+       ec_node_get_child_t get_child;   /**< Get the i-th child. */
 };
 
 /**
  * Register a node type.
  *
+ * The name of the type being registered is a uniq identifier. However,
+ * it is possible to force the registration of a type with an existing
+ * name by setting "override" to true. Note that the initial type is not
+ * removed from the list, instead the new one is added before in the
+ * list.
+ *
  * @param type
- *   A pointer to a ec_test structure describing the test
- *   to be registered.
+ *   The node type to be registered.
+ * @param override
+ *   Allow the registration of an existing type.
  * @return
  *   0 on success, negative value on error.
  */
-int ec_node_type_register(struct ec_node_type *type);
+int ec_node_type_register(struct ec_node_type *type, bool override);
 
 /**
- * Lookup node type by name
+ * Lookup node type by name.
  *
  * @param name
  *   The name of the node type to search.
  * @return
- *   The node type if found, or NULL on error.
+ *   The (read-only) node type if found, or NULL on error.
  */
 const struct ec_node_type *ec_node_type_lookup(const char *name);
 
 /**
- * Dump registered log types
+ * Dump registered log types.
+ *
+ * @param out
+ *   The stream where the dump is sent.
  */
 void ec_node_type_dump(FILE *out);
 
 /**
  * Get the config schema of a node type.
+ *
+ * @param type
+ *   The node type.
+ * @return
+ *   The (read-only) config schema of the node type, or NULL
+ *   if the node type has no config schema.
  */
 const struct ec_config_schema *
 ec_node_type_schema(const struct ec_node_type *type);
 
 /**
  * Get the name of a node type.
+ *
+ * @param type
+ *   The node type.
+ * @return
+ *   The (read-only) name of the node type.
  */
 const char *
 ec_node_type_name(const struct ec_node_type *type);
 
-enum ec_node_free_state {
-       EC_NODE_FREE_STATE_NONE,
-       EC_NODE_FREE_STATE_TRAVERSED,
-       EC_NODE_FREE_STATE_FREEABLE,
-       EC_NODE_FREE_STATE_NOT_FREEABLE,
-       EC_NODE_FREE_STATE_FREEING,
-};
-
-/* create a new node when the type is known, typically called from the node
+/**
+ * create a new node when the type is known, typically called from the node
  * code */
 struct ec_node *ec_node_from_type(const struct ec_node_type *type, const char *id);
 
-/* create a new node */
+/**
+ * Create a new node from type name.
+ */
 struct ec_node *ec_node(const char *typename, const char *id);
 
 struct ec_node *ec_node_clone(struct ec_node *node);
@@ -277,7 +406,8 @@ ec_node_get_child(const struct ec_node *node, size_t i,
 const struct ec_node_type *ec_node_type(const struct ec_node *node);
 struct ec_dict *ec_node_attrs(const struct ec_node *node);
 const char *ec_node_id(const struct ec_node *node);
-const char *ec_node_desc(const struct ec_node *node);
+
+char *ec_node_desc(const struct ec_node *node);
 
 void ec_node_dump(FILE *out, const struct ec_node *node);
 struct ec_node *ec_node_find(struct ec_node *node, const char *id);
index fd98971..e0aa85c 100644 (file)
@@ -16,7 +16,7 @@ struct ec_pnode;
 /* callback invoked by parse() or complete() to build the dynamic node
  * the behavior of the node can depend on what is already parsed */
 typedef struct ec_node *(*ec_node_dynamic_build_t)(
-       struct ec_pnode *state, void *opaque);
+       struct ec_pnode *pstate, void *opaque);
 
 struct ec_node *ec_node_dynamic(const char *id, ec_node_dynamic_build_t build,
                                void *opaque);
index 9bd98a3..b475522 100644 (file)
@@ -6,7 +6,7 @@
  * @defgroup parse Parse
  * @{
  *
- * @brief Create parse tree from string input and grammar tree
+ * @brief Create parse tree from string input and grammar graph
  *
  * Node parse API.
  *
@@ -93,10 +93,10 @@ struct ec_pnode *ec_parse_strvec(const struct ec_node *node,
 
 /* internal: used by nodes
  *
- * state is the current parse tree, which is built piece by piece while
+ * pstate is the current parse tree, which is built piece by piece while
  *   parsing the node tree: ec_parse_child() creates a new child in
  *   this state parse tree, and calls the parse() method for the child
- *   node, with state pointing to this new child. If it does not match,
+ *   node, with pstate pointing to this new child. If it does not match,
  *   the child is removed in the state, else it is kept, with its
  *   possible descendants.
  *
@@ -106,7 +106,7 @@ struct ec_pnode *ec_parse_strvec(const struct ec_node *node,
  * -1 on error, and errno is set
  */
 int ec_parse_child(const struct ec_node *node,
-                       struct ec_pnode *state,
+                       struct ec_pnode *pstate,
                        const struct ec_strvec *strvec);
 
 /**
@@ -234,7 +234,7 @@ struct ec_pnode *ec_pnode_find_next(struct ec_pnode *root,
  * Iterate among parse tree
  *
  * Use it with:
- * for (iter = state; iter != NULL; iter = EC_PNODE_ITER_NEXT(state, iter, 1))
+ * for (iter = pnode; iter != NULL; iter = EC_PNODE_ITER_NEXT(pnode, iter, 1))
  */
 struct ec_pnode *__ec_pnode_iter_next(const struct ec_pnode *root,
                                struct ec_pnode *pnode, bool iter_children);
index ca9ddf1..4223dc6 100644 (file)
@@ -10,8 +10,7 @@ project('libecoli',
 edit_dep = dependency('libedit', method: 'pkg-config')
 yaml_dep = dependency('yaml-0.1', method: 'pkg-config')
 
-# XXX if debug
-add_global_arguments('-Werror', language : 'c')
+add_global_arguments('-Wmissing-prototypes', language : 'c')
 
 inc = include_directories('include')
 priv_inc = include_directories('src')
index b1afb33..537de57 100644 (file)
@@ -27,10 +27,10 @@ struct ec_comp_item {
        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;
 };
 
@@ -39,26 +39,27 @@ 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_pnode *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_pnode *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_pnode *state)
+struct ec_comp *ec_comp(void)
 {
        struct ec_comp *comp = NULL;
 
@@ -72,8 +73,6 @@ struct ec_comp *ec_comp(struct ec_pnode *state)
 
        TAILQ_INIT(&comp->groups);
 
-       comp->cur_state = state;
-
        return comp;
 
  fail:
@@ -84,12 +83,12 @@ struct ec_comp *ec_comp(struct ec_pnode *state)
        return NULL;
 }
 
-struct ec_pnode *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;
 }
@@ -104,39 +103,38 @@ ec_complete_child(const struct ec_node *node,
                struct ec_comp *comp,
                const struct ec_strvec *strvec)
 {
-       struct ec_pnode *child_state, *cur_state;
+       struct ec_pnode *child_pstate, *cur_pstate;
        struct ec_comp_group *cur_group;
+       ec_complete_t complete_cb;
        int ret;
 
-       //XXX call ec_complete_unknown() instead, as
-       //described in API doc.
-       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_pnode(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_pnode_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_pnode_unlink_child(cur_state, child_state);
-               assert(!ec_pnode_has_child(child_state));
+       if (cur_pstate != NULL) {
+               ec_pnode_unlink_child(cur_pstate, child_pstate);
+               assert(!ec_pnode_has_child(child_pstate));
        }
-       ec_pnode_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)
@@ -151,7 +149,7 @@ struct ec_comp *ec_complete_strvec(const struct ec_node *node,
        struct ec_comp *comp = NULL;
        int ret;
 
-       comp = ec_comp(NULL);
+       comp = ec_comp();
        if (comp == NULL)
                goto fail;
 
@@ -193,7 +191,8 @@ struct ec_comp *ec_complete(const struct ec_node *node,
 }
 
 static struct ec_comp_group *
-ec_comp_group(const struct ec_node *node, struct ec_pnode *parse)
+ec_comp_group(const struct ec_comp *comp, const struct ec_node *node,
+       struct ec_pnode *parse)
 {
        struct ec_comp_group *grp = NULL;
 
@@ -201,12 +200,13 @@ ec_comp_group(const struct ec_node *node, struct ec_pnode *parse)
        if (grp == NULL)
                return NULL;
 
+       grp->comp = comp;
        grp->attrs = ec_dict();
        if (grp->attrs == NULL)
                goto fail;
 
-       grp->state = ec_pnode_dup(parse);
-       if (grp->state == NULL)
+       grp->pstate = ec_pnode_dup(parse);
+       if (grp->pstate == NULL)
                goto fail;
 
        grp->node = node;
@@ -216,7 +216,7 @@ ec_comp_group(const struct ec_node *node, struct ec_pnode *parse)
 
 fail:
        if (grp != NULL) {
-               ec_pnode_free(grp->state);
+               ec_pnode_free(grp->pstate);
                ec_dict_free(grp->attrs);
        }
        ec_free(grp);
@@ -393,7 +393,7 @@ ec_comp_item_add(struct ec_comp *comp, const struct ec_node *node,
        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);
@@ -457,50 +457,42 @@ ec_comp_item_free(struct ec_comp_item *item)
        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;
 }
 
-/* XXX move in helpers + rename ? */
 /* return a completion item of type "unknown" */
 int
 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;
 }
@@ -517,7 +509,7 @@ static void ec_comp_group_free(struct ec_comp_group *grp)
                TAILQ_REMOVE(&grp->items, item, next);
                ec_comp_item_free(item);
        }
-       ec_pnode_free(ec_pnode_get_root(grp->state));
+       ec_pnode_free(ec_pnode_get_root(grp->pstate));
        ec_dict_free(grp->attrs);
        ec_free(grp);
 }
@@ -529,9 +521,9 @@ ec_comp_group_get_node(const struct ec_comp_group *grp)
 }
 
 const struct ec_pnode *
-ec_comp_group_get_state(const struct ec_comp_group *grp)
+ec_comp_group_get_pstate(const struct ec_comp_group *grp)
 {
-       return grp->state;
+       return grp->pstate;
 }
 
 const struct ec_dict *
@@ -566,7 +558,7 @@ void ec_comp_dump(FILE *out, const struct ec_comp *comp)
                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);
 
@@ -609,11 +601,9 @@ int ec_comp_merge(struct ec_comp *to,
        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;
index 42083f8..e3e53cf 100644 (file)
@@ -370,34 +370,34 @@ static int get_node_help(const struct ec_comp_item *item,
                        struct ec_editline_help *help)
 {
        const struct ec_comp_group *grp;
-       const struct ec_pnode *state;
+       const struct ec_pnode *pstate;
        const struct ec_node *node;
        const char *node_help = NULL;
-       const char *node_desc = NULL;
+       char *node_desc = NULL;
 
        help->desc = NULL;
        help->help = NULL;
 
        grp = ec_comp_item_get_grp(item);
 
-       for (state = ec_comp_group_get_state(grp); state != NULL;
-            state = ec_pnode_get_parent(state)) {
-               node = ec_pnode_get_node(state);
+       for (pstate = ec_comp_group_get_pstate(grp); pstate != NULL;
+            pstate = ec_pnode_get_parent(pstate)) {
+               node = ec_pnode_get_node(pstate);
                if (node_help == NULL)
                        node_help = ec_dict_get(ec_node_attrs(node), "help");
-               if (node_desc == NULL)
+               if (node_desc == NULL) {
                        node_desc = ec_node_desc(node);
+                       if (node_desc == NULL)
+                               goto fail;
+               }
        }
 
-       if (node_help == NULL)
-               node_help = "";
        if (node_desc == NULL)
                goto fail;
+       if (node_help == NULL)
+               node_help = "";
 
-       help->desc = ec_strdup(node_desc);
-       if (help->desc == NULL)
-               goto fail;
-
+       help->desc = node_desc;
        help->help = ec_strdup(node_help);
        if (help->help == NULL)
                goto fail;
@@ -405,6 +405,7 @@ static int get_node_help(const struct ec_comp_item *item,
        return 0;
 
 fail:
+       ec_free(node_desc);
        ec_free(help->desc);
        ec_free(help->help);
        return -1;
index 935f4e6..1e9bf6b 100644 (file)
 
 EC_LOG_TYPE_REGISTER(node);
 
+/* These states are used to mark the grammar graph when freeing, to
+ * detect loop. */
+enum ec_node_free_state {
+       EC_NODE_FREE_STATE_NONE,
+       EC_NODE_FREE_STATE_TRAVERSED,
+       EC_NODE_FREE_STATE_FREEABLE,
+       EC_NODE_FREE_STATE_NOT_FREEABLE,
+       EC_NODE_FREE_STATE_FREEING,
+};
+
+/**
+ * The grammar node structure.
+ */
 struct ec_node {
-       const struct ec_node_type *type;
-       struct ec_config *config;    /**< Generic configuration. */
-       char *id;
-       char *desc;
-       struct ec_dict *attrs;
-       unsigned int refcnt;
+       const struct ec_node_type *type; /**< The node type. */
+       struct ec_config *config;        /**< Node configuration. */
+       char *id;                  /**< Node identifier (EC_NO_ID if none). */
+       struct ec_dict *attrs;           /**< Attributes of the node. */
+       unsigned int refcnt;             /**< Reference counter. */
        struct {
-               enum ec_node_free_state state; /**< State of loop detection */
+               enum ec_node_free_state state; /**< State of loop detection. */
                unsigned int refcnt;    /**< Number of reachable references
-                                        *   starting from node beeing freed */
+                                        *   starting from node beeing freed. */
        } free; /**< Freeing state: used for loop detection */
 };
 
@@ -56,14 +68,14 @@ ec_node_type_lookup(const char *name)
        return NULL;
 }
 
-int ec_node_type_register(struct ec_node_type *type)
+int ec_node_type_register(struct ec_node_type *type, bool override)
 {
-       if (ec_node_type_lookup(type->name) != NULL) {
+       if (!override && ec_node_type_lookup(type->name) != NULL) {
                errno = EEXIST;
                return -1;
        }
 
-       TAILQ_INSERT_TAIL(&node_type_list, type, next);
+       TAILQ_INSERT_HEAD(&node_type_list, type, next);
 
        return 0;
 }
@@ -99,9 +111,6 @@ struct ec_node *ec_node_from_type(const struct ec_node_type *type, const char *i
        if (node->id == NULL)
                goto fail;
 
-       if (ec_asprintf(&node->desc, "<%s>", type->name) < 0)
-               goto fail;
-
        node->attrs = ec_dict();
        if (node->attrs == NULL)
                goto fail;
@@ -116,7 +125,6 @@ struct ec_node *ec_node_from_type(const struct ec_node_type *type, const char *i
  fail:
        if (node != NULL) {
                ec_dict_free(node->attrs);
-               ec_free(node->desc);
                ec_free(node->id);
        }
        ec_free(node);
@@ -256,7 +264,6 @@ void ec_node_free(struct ec_node *node)
                if (node->type->free_priv != NULL)
                        node->type->free_priv(node);
                ec_free(node->id);
-               ec_free(node->desc);
                ec_dict_free(node->attrs);
        }
 
@@ -421,12 +428,17 @@ fail:
        EC_LOG(EC_LOG_ERR, "failed to dump node\n");
 }
 
-const char *ec_node_desc(const struct ec_node *node)
+char *ec_node_desc(const struct ec_node *node)
 {
+       char *desc = NULL;
+
        if (node->type->desc != NULL)
                return node->type->desc(node);
 
-       return node->desc;
+       if (ec_asprintf(&desc, "<%s>", node->type->name) < 0)
+               return NULL;
+
+       return desc;
 }
 
 int ec_node_check_type(const struct ec_node *node,
@@ -462,6 +474,7 @@ static int ec_node_testcase(void)
        unsigned int refs;
        FILE *f = NULL;
        char *buf = NULL;
+       char *desc = NULL;
        size_t buflen = 0;
        int testres = 0;
        int ret;
@@ -494,11 +507,14 @@ static int ec_node_testcase(void)
        free(buf);
        buf = NULL;
 
+       desc = ec_node_desc(node);
        testres |= EC_TEST_CHECK(
                !strcmp(ec_node_type(node)->name, "seq") &&
                !strcmp(ec_node_id(node), EC_NO_ID) &&
-               !strcmp(ec_node_desc(node), "<seq>"),
+               !strcmp(desc, "<seq>"),
                "bad child 0");
+       ec_free(desc);
+       desc = NULL;
 
        testres |= EC_TEST_CHECK(
                ec_node_get_children_count(node) == 2,
@@ -522,11 +538,14 @@ static int ec_node_testcase(void)
                "child 2 should be NULL");
 
        child = ec_node_find(node, "id_x");
+       desc = ec_node_desc(child);
        testres |= EC_TEST_CHECK(child != NULL &&
                !strcmp(ec_node_type(child)->name, "str") &&
                !strcmp(ec_node_id(child), "id_x") &&
-               !strcmp(ec_node_desc(child), "x"),
+               !strcmp(desc, "x"),
                "bad child id_x");
+       ec_free(desc);
+       desc = NULL;
        child = ec_node_find(node, "id_dezdex");
        testres |= EC_TEST_CHECK(child == NULL,
                "child with wrong id should be NULL");
index 43b886a..5bf4984 100644 (file)
@@ -25,13 +25,13 @@ struct ec_node_any {
 };
 
 static int ec_node_any_parse(const struct ec_node *node,
-                       struct ec_pnode *state,
+                       struct ec_pnode *pstate,
                        const struct ec_strvec *strvec)
 {
        struct ec_node_any *priv = ec_node_priv(node);
        const struct ec_dict *attrs;
 
-       (void)state;
+       (void)pstate;
 
        if (ec_strvec_len(strvec) == 0)
                return EC_PARSE_NOMATCH;
@@ -91,7 +91,6 @@ static struct ec_node_type ec_node_any_type = {
        .schema = ec_node_any_schema,
        .set_config = ec_node_any_set_config,
        .parse = ec_node_any_parse,
-       .complete = ec_complete_unknown,
        .size = sizeof(struct ec_node_any),
        .free_priv = ec_node_any_free_priv,
 };
index 21bb253..7380aeb 100644 (file)
@@ -28,12 +28,12 @@ struct ec_node_bypass {
 
 static int
 ec_node_bypass_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_bypass *priv = ec_node_priv(node);
 
-       return ec_parse_child(priv->child, state, strvec);
+       return ec_parse_child(priv->child, pstate, strvec);
 }
 
 static int
index 829c896..1fb006a 100644 (file)
@@ -391,12 +391,12 @@ fail:
 }
 
 static int
-ec_node_cmd_parse(const struct ec_node *node, struct ec_pnode *state,
+ec_node_cmd_parse(const struct ec_node *node, struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_cmd *priv = ec_node_priv(node);
 
-       return ec_parse_child(priv->cmd, state, strvec);
+       return ec_parse_child(priv->cmd, pstate, strvec);
 }
 
 static int
index 8ff81dc..def5b39 100644 (file)
@@ -71,10 +71,11 @@ struct cond_result {
 };
 
 typedef struct cond_result *(cond_func_t)(
-       const struct ec_pnode *state,
+       const struct ec_pnode *pstate,
        struct cond_result **in, size_t in_len);
 
-void cond_result_free(struct cond_result *res)
+static void
+cond_result_free(struct cond_result *res)
 {
        if (res == NULL)
                return;
@@ -94,7 +95,8 @@ void cond_result_free(struct cond_result *res)
        ec_free(res);
 }
 
-void cond_result_table_free(struct cond_result **table, size_t len)
+static void
+cond_result_table_free(struct cond_result **table, size_t len)
 {
        size_t i;
 
@@ -204,7 +206,7 @@ fail:
 }
 
 static struct cond_result *
-eval_root(const struct ec_pnode *state, struct cond_result **in, size_t in_len)
+eval_root(const struct ec_pnode *pstate, struct cond_result **in, size_t in_len)
 {
        struct cond_result *out = NULL;
        const struct ec_pnode *root = NULL;
@@ -226,7 +228,7 @@ eval_root(const struct ec_pnode *state, struct cond_result **in, size_t in_len)
        if (out->htable == NULL)
                goto fail;
 
-       root = ec_pnode_get_root(state);
+       root = ec_pnode_get_root(pstate);
        if (ec_htable_set(out->htable, &root, sizeof(root), NULL, NULL) < 0)
                goto fail;
 
@@ -240,7 +242,7 @@ fail:
 }
 
 static struct cond_result *
-eval_current(const struct ec_pnode *state, struct cond_result **in,
+eval_current(const struct ec_pnode *pstate, struct cond_result **in,
        size_t in_len)
 {
        struct cond_result *out = NULL;
@@ -262,7 +264,7 @@ eval_current(const struct ec_pnode *state, struct cond_result **in,
        if (out->htable == NULL)
                goto fail;
 
-       if (ec_htable_set(out->htable, &state, sizeof(state), NULL, NULL) < 0)
+       if (ec_htable_set(out->htable, &pstate, sizeof(pstate), NULL, NULL) < 0)
                goto fail;
 
        cond_result_table_free(in, in_len);
@@ -292,11 +294,11 @@ boolean_value(const struct cond_result *res)
 }
 
 static struct cond_result *
-eval_bool(const struct ec_pnode *state, struct cond_result **in, size_t in_len)
+eval_bool(const struct ec_pnode *pstate, struct cond_result **in, size_t in_len)
 {
        struct cond_result *out = NULL;
 
-       (void)state;
+       (void)pstate;
 
        if (in_len != 1) {
                EC_LOG(LOG_ERR, "bool() takes one argument.\n");
@@ -321,12 +323,12 @@ fail:
 }
 
 static struct cond_result *
-eval_or(const struct ec_pnode *state, struct cond_result **in, size_t in_len)
+eval_or(const struct ec_pnode *pstate, struct cond_result **in, size_t in_len)
 {
        struct cond_result *out = NULL;
        size_t i;
 
-       (void)state;
+       (void)pstate;
 
        if (in_len < 2) {
                EC_LOG(LOG_ERR, "or() takes at least two arguments\n");
@@ -355,12 +357,12 @@ fail:
 }
 
 static struct cond_result *
-eval_and(const struct ec_pnode *state, struct cond_result **in, size_t in_len)
+eval_and(const struct ec_pnode *pstate, struct cond_result **in, size_t in_len)
 {
        struct cond_result *out = NULL;
        size_t i;
 
-       (void)state;
+       (void)pstate;
 
        if (in_len < 2) {
                EC_LOG(LOG_ERR, "or() takes at least two arguments\n");
@@ -389,7 +391,7 @@ fail:
 }
 
 static struct cond_result *
-eval_first_child(const struct ec_pnode *state, struct cond_result **in,
+eval_first_child(const struct ec_pnode *pstate, struct cond_result **in,
        size_t in_len)
 {
        struct cond_result *out = NULL;
@@ -397,7 +399,7 @@ eval_first_child(const struct ec_pnode *state, struct cond_result **in,
        const struct ec_pnode * const *pparse;
        struct ec_pnode *parse;
 
-       (void)state;
+       (void)pstate;
 
        if (in_len != 1 || in[0]->type != NODESET) {
                EC_LOG(LOG_ERR, "first_child() takes one argument of type nodeset.\n");
@@ -435,7 +437,7 @@ fail:
 }
 
 static struct cond_result *
-eval_find(const struct ec_pnode *state, struct cond_result **in,
+eval_find(const struct ec_pnode *pstate, struct cond_result **in,
        size_t in_len)
 {
        struct cond_result *out = NULL;
@@ -444,7 +446,7 @@ eval_find(const struct ec_pnode *state, struct cond_result **in,
        struct ec_pnode *parse;
        const char *id;
 
-       (void)state;
+       (void)pstate;
 
        if (in_len != 2 || in[0]->type != NODESET || in[1]->type != STR) {
                EC_LOG(LOG_ERR, "find() takes two arguments (nodeset, str).\n");
@@ -485,14 +487,14 @@ fail:
 }
 
 static struct cond_result *
-eval_cmp(const struct ec_pnode *state, struct cond_result **in,
+eval_cmp(const struct ec_pnode *pstate, struct cond_result **in,
        size_t in_len)
 {
        struct cond_result *out = NULL;
        struct ec_htable_elt_ref *iter;
        bool eq = false, gt = false;
 
-       (void)state;
+       (void)pstate;
 
        if (in_len != 3 || in[0]->type != STR || in[1]->type != in[2]->type) {
                EC_LOG(LOG_ERR, "cmp() takes 3 arguments (str, <type>, <type>).\n");
@@ -568,11 +570,11 @@ fail:
 }
 
 static struct cond_result *
-eval_count(const struct ec_pnode *state, struct cond_result **in, size_t in_len)
+eval_count(const struct ec_pnode *pstate, struct cond_result **in, size_t in_len)
 {
        struct cond_result *out = NULL;
 
-       (void)state;
+       (void)pstate;
 
        if (in_len != 1 || in[0]->type != NODESET) {
                EC_LOG(LOG_ERR, "count() takes one argument of type nodeset.\n");
@@ -597,7 +599,7 @@ fail:
 }
 
 static struct cond_result *
-eval_func(const char *name, const struct ec_pnode *state,
+eval_func(const char *name, const struct ec_pnode *pstate,
        struct cond_result **in, size_t in_len)
 {
        cond_func_t *f;
@@ -611,12 +613,12 @@ eval_func(const char *name, const struct ec_pnode *state,
                return NULL;
        }
 
-       return f(state, in, in_len);
+       return f(pstate, in, in_len);
 }
 
 
 static struct cond_result *
-eval_condition(const struct ec_pnode *cond, const struct ec_pnode *state)
+eval_condition(const struct ec_pnode *cond, const struct ec_pnode *pstate)
 {
        const struct ec_pnode *iter;
        struct cond_result *res = NULL;
@@ -640,7 +642,7 @@ eval_condition(const struct ec_pnode *cond, const struct ec_pnode *state)
                iter = ec_pnode_find((void *)arg_list, "id_arg");
                while (iter != NULL) {
                        args = ec_realloc(args, (n_arg + 1) * sizeof(*args));
-                       args[n_arg] = eval_condition(iter, state);
+                       args[n_arg] = eval_condition(iter, pstate);
                        if (args[n_arg] == NULL)
                                goto fail;
                        n_arg++;
@@ -649,7 +651,7 @@ eval_condition(const struct ec_pnode *cond, const struct ec_pnode *state)
                }
 
                res = eval_func(ec_strvec_val(ec_pnode_strvec(func_name), 0),
-                               state, args, n_arg);
+                               pstate, args, n_arg);
                args = NULL;
                return res;
        }
@@ -686,12 +688,12 @@ fail:
 }
 
 static int
-validate_condition(const struct ec_pnode *cond, const struct ec_pnode *state)
+validate_condition(const struct ec_pnode *cond, const struct ec_pnode *pstate)
 {
        struct cond_result *res;
        int ret;
 
-       res = eval_condition(cond, state);
+       res = eval_condition(cond, pstate);
        if (res == NULL)
                return -1;
 
@@ -702,24 +704,24 @@ validate_condition(const struct ec_pnode *cond, const struct ec_pnode *state)
 }
 
 static int
-ec_node_cond_parse(const struct ec_node *node, struct ec_pnode *state,
+ec_node_cond_parse(const struct ec_node *node, struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_cond *priv = ec_node_priv(node);
        struct ec_pnode *child;
        int ret, valid;
 
-       ret = ec_parse_child(priv->child, state, strvec);
+       ret = ec_parse_child(priv->child, pstate, strvec);
        if (ret <= 0)
                return ret;
 
-       valid = validate_condition(priv->parsed_cond, state);
+       valid = validate_condition(priv->parsed_cond, pstate);
        if (valid < 0)
                return valid;
 
        if (valid == 0) {
-               child = ec_pnode_get_last_child(state);
-               ec_pnode_unlink_child(state, child);
+               child = ec_pnode_get_last_child(pstate);
+               ec_pnode_unlink_child(pstate, child);
                ec_pnode_free(child);
                return EC_PARSE_NOMATCH;
        }
index 2ce2e32..03bdd1c 100644 (file)
@@ -72,7 +72,7 @@ ec_node_dynamic_complete(const struct ec_node *node,
        char key[64];
        int ret = -1;
 
-       parse = ec_comp_get_state(comp);
+       parse = ec_comp_get_cur_pstate(comp);
        child = priv->build(parse, priv->opaque);
        if (child == NULL)
                goto fail;
index 090808e..c6585aa 100644 (file)
@@ -22,11 +22,11 @@ struct ec_node_empty {
 };
 
 static int ec_node_empty_parse(const struct ec_node *node,
-                       struct ec_pnode *state,
+                       struct ec_pnode *pstate,
                        const struct ec_strvec *strvec)
 {
        (void)node;
-       (void)state;
+       (void)pstate;
        (void)strvec;
        return 0;
 }
@@ -34,7 +34,6 @@ static int ec_node_empty_parse(const struct ec_node *node,
 static struct ec_node_type ec_node_empty_type = {
        .name = "empty",
        .parse = ec_node_empty_parse,
-       .complete = ec_complete_unknown,
        .size = sizeof(struct ec_node_empty),
 };
 
index ff654ef..2a78d4f 100644 (file)
@@ -43,7 +43,7 @@ struct ec_node_expr {
 };
 
 static int ec_node_expr_parse(const struct ec_node *node,
-                       struct ec_pnode *state,
+                       struct ec_pnode *pstate,
                        const struct ec_strvec *strvec)
 {
        struct ec_node_expr *priv = ec_node_priv(node);
@@ -53,7 +53,7 @@ static int ec_node_expr_parse(const struct ec_node *node,
                return -1;
        }
 
-       return ec_parse_child(priv->child, state, strvec);
+       return ec_parse_child(priv->child, pstate, strvec);
 }
 
 static int
index ff77e01..933b997 100644 (file)
@@ -36,11 +36,11 @@ struct ec_node_file {
 
 static int
 ec_node_file_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        (void)node;
-       (void)state;
+       (void)pstate;
 
        if (ec_strvec_len(strvec) == 0)
                return EC_PARSE_NOMATCH;
@@ -210,8 +210,8 @@ ec_node_file_complete(const struct ec_node *node,
                        if (ec_asprintf(&disp_str, "%s", de->d_name) < 0)
                                goto fail;
                }
-               if (ec_comp_add_item(comp, node, &item,
-                                               type, input, comp_str) < 0)
+               item = ec_comp_add_item(comp, node, type, input, comp_str);
+               if (item == NULL)
                        goto out;
 
                /* fix the display string: we don't want to display the full
index acad9ed..efebae9 100644 (file)
@@ -75,7 +75,7 @@ static int parse_ullint(struct ec_node_int_uint *priv, const char *str,
 }
 
 static int ec_node_int_uint_parse(const struct ec_node *node,
-                       struct ec_pnode *state,
+                       struct ec_pnode *pstate,
                        const struct ec_strvec *strvec)
 {
        struct ec_node_int_uint *priv = ec_node_priv(node);
@@ -83,7 +83,7 @@ static int ec_node_int_uint_parse(const struct ec_node *node,
        uint64_t u64;
        int64_t i64;
 
-       (void)state;
+       (void)pstate;
 
        if (ec_strvec_len(strvec) == 0)
                return EC_PARSE_NOMATCH;
@@ -177,7 +177,6 @@ static struct ec_node_type ec_node_int_type = {
        .schema = ec_node_int_schema,
        .set_config = ec_node_int_set_config,
        .parse = ec_node_int_uint_parse,
-       .complete = ec_complete_unknown,
        .size = sizeof(struct ec_node_int_uint),
        .init_priv = ec_node_uint_init_priv,
 };
@@ -290,7 +289,6 @@ static struct ec_node_type ec_node_uint_type = {
        .schema = ec_node_uint_schema,
        .set_config = ec_node_uint_set_config,
        .parse = ec_node_int_uint_parse,
-       .complete = ec_complete_unknown,
        .size = sizeof(struct ec_node_int_uint),
 };
 
index d99c2e3..54c100c 100644 (file)
@@ -30,7 +30,7 @@ struct ec_node_many {
 };
 
 static int ec_node_many_parse(const struct ec_node *node,
-                       struct ec_pnode *state,
+                       struct ec_pnode *pstate,
                        const struct ec_strvec *strvec)
 {
        struct ec_node_many *priv = ec_node_priv(node);
@@ -45,7 +45,7 @@ static int ec_node_many_parse(const struct ec_node *node,
                if (childvec == NULL)
                        goto fail;
 
-               ret = ec_parse_child(priv->child, state, childvec);
+               ret = ec_parse_child(priv->child, pstate, childvec);
                if (ret < 0)
                        goto fail;
 
@@ -57,8 +57,8 @@ static int ec_node_many_parse(const struct ec_node *node,
 
                /* it matches an empty strvec, no need to continue */
                if (ret == 0) {
-                       child_parse = ec_pnode_get_last_child(state);
-                       ec_pnode_unlink_child(state, child_parse);
+                       child_parse = ec_pnode_get_last_child(pstate);
+                       ec_pnode_unlink_child(pstate, child_parse);
                        ec_pnode_free(child_parse);
                        break;
                }
@@ -67,7 +67,7 @@ static int ec_node_many_parse(const struct ec_node *node,
        }
 
        if (count < priv->min) {
-               ec_pnode_free_children(state);
+               ec_pnode_free_children(pstate);
                return EC_PARSE_NOMATCH;
        }
 
@@ -83,7 +83,7 @@ __ec_node_many_complete(struct ec_node_many *priv, unsigned int max,
                        struct ec_comp *comp,
                        const struct ec_strvec *strvec)
 {
-       struct ec_pnode *parse = ec_comp_get_state(comp);
+       struct ec_pnode *parse = ec_comp_get_cur_pstate(comp);
        struct ec_strvec *childvec = NULL;
        unsigned int i;
        int ret;
index e3ed96a..f2c8ec1 100644 (file)
@@ -70,7 +70,7 @@ ec_node_once_complete(const struct ec_node *node,
                const struct ec_strvec *strvec)
 {
        struct ec_node_once *priv = ec_node_priv(node);
-       struct ec_pnode *parse = ec_comp_get_state(comp);
+       struct ec_pnode *parse = ec_comp_get_cur_pstate(comp);
        unsigned int count;
        int ret;
 
index 85f3451..192288c 100644 (file)
@@ -28,13 +28,13 @@ struct ec_node_option {
 
 static int
 ec_node_option_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_option *priv = ec_node_priv(node);
        int ret;
 
-       ret = ec_parse_child(priv->child, state, strvec);
+       ret = ec_parse_child(priv->child, pstate, strvec);
        if (ret < 0)
                return ret;
 
index 5f26f62..e9d6c1e 100644 (file)
@@ -31,7 +31,7 @@ struct ec_node_or {
 
 static int
 ec_node_or_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_or *priv = ec_node_priv(node);
@@ -39,7 +39,7 @@ ec_node_or_parse(const struct ec_node *node,
        int ret;
 
        for (i = 0; i < priv->len; i++) {
-               ret = ec_parse_child(priv->table[i], state, strvec);
+               ret = ec_parse_child(priv->table[i], pstate, strvec);
                if (ret == EC_PARSE_NOMATCH)
                        continue;
                return ret;
index 7d68b77..4bbc192 100644 (file)
@@ -27,14 +27,14 @@ struct ec_node_re {
 
 static int
 ec_node_re_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_re *priv = ec_node_priv(node);
        const char *str;
        regmatch_t pos;
 
-       (void)state;
+       (void)pstate;
 
        if (ec_strvec_len(strvec) == 0)
                return EC_PARSE_NOMATCH;
@@ -116,7 +116,6 @@ static struct ec_node_type ec_node_re_type = {
        .schema = ec_node_re_schema,
        .set_config = ec_node_re_set_config,
        .parse = ec_node_re_parse,
-       .complete = ec_complete_unknown,
        .size = sizeof(struct ec_node_re),
        .free_priv = ec_node_re_free_priv,
 };
index 48cf749..726c6cf 100644 (file)
@@ -116,7 +116,7 @@ fail:
 
 static int
 ec_node_re_lex_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_re_lex *priv = ec_node_priv(node);
@@ -139,15 +139,15 @@ ec_node_re_lex_parse(const struct ec_node *node,
        if (new_vec == NULL)
                goto fail;
 
-       ret = ec_parse_child(priv->child, state, new_vec);
+       ret = ec_parse_child(priv->child, pstate, new_vec);
        if (ret < 0)
                goto fail;
 
        if ((unsigned)ret == ec_strvec_len(new_vec)) {
                ret = 1;
        } else if (ret != EC_PARSE_NOMATCH) {
-               child_parse = ec_pnode_get_last_child(state);
-               ec_pnode_unlink_child(state, child_parse);
+               child_parse = ec_pnode_get_last_child(pstate);
+               ec_pnode_unlink_child(pstate, child_parse);
                ec_pnode_free(child_parse);
                ret = EC_PARSE_NOMATCH;
        }
@@ -372,7 +372,6 @@ static struct ec_node_type ec_node_re_lex_type = {
        .schema = ec_node_re_lex_schema,
        .set_config = ec_node_re_lex_set_config,
        .parse = ec_node_re_lex_parse,
-       .complete = ec_complete_unknown,
        .size = sizeof(struct ec_node_re_lex),
        .free_priv = ec_node_re_lex_free_priv,
        .get_children_count = ec_node_re_lex_get_children_count,
index d06b053..1102f3d 100644 (file)
@@ -34,7 +34,7 @@ struct ec_node_seq {
 
 static int
 ec_node_seq_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_seq *priv = ec_node_priv(node);
@@ -49,7 +49,7 @@ ec_node_seq_parse(const struct ec_node *node,
                if (childvec == NULL)
                        goto fail;
 
-               ret = ec_parse_child(priv->table[i], state, childvec);
+               ret = ec_parse_child(priv->table[i], pstate, childvec);
                if (ret < 0)
                        goto fail;
 
@@ -57,7 +57,7 @@ ec_node_seq_parse(const struct ec_node *node,
                childvec = NULL;
 
                if (ret == EC_PARSE_NOMATCH) {
-                       ec_pnode_free_children(state);
+                       ec_pnode_free_children(pstate);
                        return EC_PARSE_NOMATCH;
                }
 
@@ -76,7 +76,7 @@ __ec_node_seq_complete(struct ec_node **table, size_t table_len,
                struct ec_comp *comp,
                const struct ec_strvec *strvec)
 {
-       struct ec_pnode *parse = ec_comp_get_state(comp);
+       struct ec_pnode *parse = ec_comp_get_cur_pstate(comp);
        struct ec_strvec *childvec = NULL;
        unsigned int i;
        int ret;
index c6b6867..7dd0358 100644 (file)
@@ -214,7 +214,7 @@ static struct ec_strvec *tokenize(const char *str, int completion,
 
 static int
 ec_node_sh_lex_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_sh_lex *priv = ec_node_priv(node);
@@ -234,15 +234,15 @@ ec_node_sh_lex_parse(const struct ec_node *node,
        if (new_vec == NULL)
                goto fail;
 
-       ret = ec_parse_child(priv->child, state, new_vec);
+       ret = ec_parse_child(priv->child, pstate, new_vec);
        if (ret < 0)
                goto fail;
 
        if ((unsigned)ret == ec_strvec_len(new_vec)) {
                ret = 1;
        } else if (ret != EC_PARSE_NOMATCH) {
-               child_parse = ec_pnode_get_last_child(state);
-               ec_pnode_unlink_child(state, child_parse);
+               child_parse = ec_pnode_get_last_child(pstate);
+               ec_pnode_unlink_child(pstate, child_parse);
                ec_pnode_free(child_parse);
                ret = EC_PARSE_NOMATCH;
        }
index 4ab6ad3..ff7ca14 100644 (file)
@@ -23,13 +23,13 @@ struct ec_node_space {
 
 static int
 ec_node_space_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        const char *str;
        size_t len = 0;
 
-       (void)state;
+       (void)pstate;
        (void)node;
 
        if (ec_strvec_len(strvec) == 0)
@@ -47,7 +47,6 @@ ec_node_space_parse(const struct ec_node *node,
 static struct ec_node_type ec_node_space_type = {
        .name = "space",
        .parse = ec_node_space_parse,
-       .complete = ec_complete_unknown,
        .size = sizeof(struct ec_node_space),
 };
 
index f333abb..7c37220 100644 (file)
@@ -26,13 +26,13 @@ struct ec_node_str {
 
 static int
 ec_node_str_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_str *priv = ec_node_priv(node);
        const char *str;
 
-       (void)state;
+       (void)pstate;
 
        if (priv->string == NULL) {
                errno = EINVAL;
@@ -55,6 +55,7 @@ ec_node_str_complete(const struct ec_node *node,
                const struct ec_strvec *strvec)
 {
        struct ec_node_str *priv = ec_node_priv(node);
+       const struct ec_comp_item *item;
        const char *str;
        size_t n = 0;
 
@@ -72,18 +73,18 @@ ec_node_str_complete(const struct ec_node *node,
        if (str[n] != '\0')
                return EC_PARSE_NOMATCH;
 
-       if (ec_comp_add_item(comp, node, NULL, EC_COMP_FULL,
-                                       str, priv->string) < 0)
+       item = ec_comp_add_item(comp, node, EC_COMP_FULL, str, priv->string);
+       if (item == NULL)
                return -1;
 
        return 0;
 }
 
-static const char *ec_node_str_desc(const struct ec_node *node)
+static char *ec_node_str_desc(const struct ec_node *node)
 {
        struct ec_node_str *priv = ec_node_priv(node);
 
-       return priv->string;
+       return ec_strdup(priv->string);
 }
 
 static void ec_node_str_free_priv(struct ec_node *node)
@@ -201,14 +202,18 @@ static int ec_node_str_testcase(void)
 {
        struct ec_node *node;
        int testres = 0;
+       char *desc = NULL;
 
        node = ec_node_str(EC_NO_ID, "foo");
        if (node == NULL) {
                EC_LOG(EC_LOG_ERR, "cannot create node\n");
                return -1;
        }
-       testres |= EC_TEST_CHECK(!strcmp(ec_node_desc(node), "foo"),
+       desc = ec_node_desc(node);
+       testres |= EC_TEST_CHECK(!strcmp(desc, "foo"),
                "Invalid node description.");
+       ec_free(desc);
+       desc = NULL;
        testres |= EC_TEST_CHECK_PARSE(node, 1, "foo");
        testres |= EC_TEST_CHECK_PARSE(node, 1, "foo", "bar");
        testres |= EC_TEST_CHECK_PARSE(node, -1, "foobar");
index eddef84..7e65170 100644 (file)
@@ -37,7 +37,7 @@ struct parse_result {
  * updated accordingly. */
 static int
 __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
-               size_t table_len, struct ec_pnode *state,
+               size_t table_len, struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node **child_table;
@@ -58,7 +58,7 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
 
        for (i = 0; i < table_len; i++) {
                /* try to parse elt i */
-               ret = ec_parse_child(table[i], state, strvec);
+               ret = ec_parse_child(table[i], pstate, strvec);
                if (ret < 0)
                        goto fail;
 
@@ -82,7 +82,7 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
 
                memset(&result, 0, sizeof(result));
                ret = __ec_node_subset_parse(&result, child_table,
-                                       table_len - 1, state, childvec);
+                                       table_len - 1, pstate, childvec);
                ec_strvec_free(childvec);
                childvec = NULL;
                if (ret < 0)
@@ -91,14 +91,14 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
                /* if result is not the best, ignore */
                if (result.parse_len < best_result.parse_len) {
                        memset(&result, 0, sizeof(result));
-                       ec_pnode_del_last_child(state);
+                       ec_pnode_del_last_child(pstate);
                        continue;
                }
 
                /* replace the previous best result */
                ec_pnode_free(best_parse);
-               best_parse = ec_pnode_get_last_child(state);
-               ec_pnode_unlink_child(state, best_parse);
+               best_parse = ec_pnode_get_last_child(pstate);
+               ec_pnode_unlink_child(pstate, best_parse);
 
                best_result.parse_len = result.parse_len + 1;
                best_result.len = len + result.len;
@@ -109,7 +109,7 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
        *out = best_result;
        ec_free(child_table);
        if (best_parse != NULL)
-               ec_pnode_link_child(state, best_parse);
+               ec_pnode_link_child(pstate, best_parse);
 
        return 0;
 
@@ -122,7 +122,7 @@ __ec_node_subset_parse(struct parse_result *out, struct ec_node **table,
 
 static int
 ec_node_subset_parse(const struct ec_node *node,
-               struct ec_pnode *state,
+               struct ec_pnode *pstate,
                const struct ec_strvec *strvec)
 {
        struct ec_node_subset *priv = ec_node_priv(node);
@@ -133,7 +133,7 @@ ec_node_subset_parse(const struct ec_node *node,
        memset(&result, 0, sizeof(result));
 
        ret = __ec_node_subset_parse(&result, priv->table,
-                               priv->len, state, strvec);
+                               priv->len, pstate, strvec);
        if (ret < 0)
                goto fail;
 
@@ -153,7 +153,7 @@ __ec_node_subset_complete(struct ec_node **table, size_t table_len,
                        struct ec_comp *comp,
                        const struct ec_strvec *strvec)
 {
-       struct ec_pnode *parse = ec_comp_get_state(comp);
+       struct ec_pnode *parse = ec_comp_get_cur_pstate(comp);
        struct ec_strvec *childvec = NULL;
        struct ec_node *save;
        size_t i, len;
index e1b6018..9a6eabc 100644 (file)
@@ -35,7 +35,7 @@ struct ec_pnode {
 };
 
 static int __ec_parse_child(const struct ec_node *node,
-                               struct ec_pnode *state,
+                               struct ec_pnode *pstate,
                                bool is_root, const struct ec_strvec *strvec)
 {
        struct ec_strvec *match_strvec;
@@ -54,9 +54,9 @@ static int __ec_parse_child(const struct ec_node *node,
                if (child == NULL)
                        return -1;
 
-               ec_pnode_link_child(state, child);
+               ec_pnode_link_child(pstate, child);
        } else {
-               child = state;
+               child = pstate;
        }
        ret = ec_node_type(node)->parse(node, child, strvec);
        if (ret < 0)
@@ -64,7 +64,7 @@ static int __ec_parse_child(const struct ec_node *node,
 
        if (ret == EC_PARSE_NOMATCH) {
                if (!is_root) {
-                       ec_pnode_unlink_child(state, child);
+                       ec_pnode_unlink_child(pstate, child);
                        ec_pnode_free(child);
                }
                return ret;
@@ -80,17 +80,17 @@ static int __ec_parse_child(const struct ec_node *node,
 
 fail:
        if (!is_root) {
-               ec_pnode_unlink_child(state, child);
+               ec_pnode_unlink_child(pstate, child);
                ec_pnode_free(child);
        }
        return -1;
 }
 
-int ec_parse_child(const struct ec_node *node, struct ec_pnode *state,
+int ec_parse_child(const struct ec_node *node, struct ec_pnode *pstate,
                        const struct ec_strvec *strvec)
 {
-       assert(state != NULL);
-       return __ec_parse_child(node, state, false, strvec);
+       assert(pstate != NULL);
+       return __ec_parse_child(node, pstate, false, strvec);
 }
 
 // XXX what is returned if no match ??
index 3e7d625..4ec4d7b 100644 (file)
@@ -99,7 +99,7 @@ int ec_test_check_complete(struct ec_node *tk, enum ec_comp_type type, ...)
        struct ec_strvec *vec = NULL;
        const char *s;
        int ret = 0;
-       unsigned int count = 0;
+       size_t count = 0;
        va_list ap;
 
        va_start(ap, type);
@@ -155,7 +155,7 @@ int ec_test_check_complete(struct ec_node *tk, enum ec_comp_type type, ...)
        /* check if we have more completions (or less) than expected */
        if (count != ec_comp_count(c, type)) {
                EC_LOG(EC_LOG_ERR,
-                       "nb_completion (%d) does not match (%d)\n",
+                       "nb_completion (%zu) does not match (%zu)\n",
                        count, ec_comp_count(c, type));
                ec_comp_dump(stdout, c);
                ret = -1;