api doc and minor changes
[protos/libecoli.git] / include / ecoli_node.h
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);