api documentation
[protos/libecoli.git] / include / ecoli_node.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
3  */
4
5 /**
6  * @defgroup grammar_tree Grammar Tree
7  * @{
8  *
9  * @brief Libecoli grammar nodes.
10  *
11  * The grammar node is a main structure of the ecoli library, used to define
12  * how to match and complete the input tokens. A node is a generic object
13  * that implements:
14  * - a parse(node, input) method: check if an input matches
15  * - a complete(node, input) method: return possible completions for
16  *   a given input
17  * - some other methods to initialize, free, ...
18  *
19  * One basic example is the string node (ec_node_str). A node
20  * ec_node_str("foo") will match any token list starting with "foo",
21  * for example:
22  * - ["foo"]
23  * - ["foo", "bar", ...]
24  * But will not match:
25  * - []
26  * - ["bar", ...]
27  *
28  * A node ec_node_str("foo") will complete with "foo" if the input
29  * contains one token, with the same beginning than "foo":
30  * - [""]
31  * - ["f"]
32  * - ["fo"]
33  * - ["foo"]
34  * But it will not complete:
35  * - []
36  * - ["bar"]
37  * - ["f", ""]
38  * - ["", "f"]
39  *
40  * A node can have child nodes. For instance, a sequence node
41  * ec_node_seq(ec_node_str("foo"), ec_node_str("bar")) will match
42  * ["foo", "bar"].
43  */
44
45 #ifndef ECOLI_NODE_
46 #define ECOLI_NODE_
47
48 #include <sys/queue.h>
49 #include <sys/types.h>
50 #include <stdio.h>
51
52 /**
53  * Node has no identifier.
54  */
55 #define EC_NO_ID "no-id"
56
57 struct ec_node;
58 struct ec_pnode;
59 struct ec_comp;
60 struct ec_strvec;
61 struct ec_dict;
62 struct ec_config;
63 struct ec_config_schema;
64
65 /**
66  * Register a node type at library load.
67  *
68  * The node type is registered in a function that has the the
69  * constructor attribute: the function is called at library load.
70  *
71  * @param t
72  *   The name of the ec_node_type structure variable.
73  */
74 #define EC_NODE_TYPE_REGISTER(t)                                        \
75         static void ec_node_init_##t(void);                             \
76         static void __attribute__((constructor, used))                  \
77         ec_node_init_##t(void)                                          \
78         {                                                               \
79                 if (ec_node_type_register(&t) < 0)                      \
80                         fprintf(stderr,                                 \
81                                 "cannot register node type %s\n",       \
82                                 t.name);                                \
83         }
84
85 /**
86  * A list of node types.
87  */
88 TAILQ_HEAD(ec_node_type_list, ec_node_type);
89
90 /**
91  * Function type used to configure a node.
92  *
93  * The function pointer is not called directly, the helper
94  * @ec_node_set_config() should be used instead.
95  *
96  * @param node
97  *   The node to configure.
98  * @param config
99  *   The configuration to apply to the node.
100  * @return
101  *   0 on success, negative on error (errno is set).
102  */
103 typedef int (*ec_node_set_config_t)(struct ec_node *node,
104                                 const struct ec_config *config);
105
106 /**
107  * Parse a string vector using the given grammar tree.
108  *
109  * The function pointer is not called directly, the helpers @ec_parse(),
110  * ec_parse_strvec() or ec_parse_child() should be used instead.
111  *
112  * The implementation of this method for a node that manages children
113  * will call ec_parse_child(child, state, child_strvec).
114  *
115  * @param node
116  *   The root node of the grammar tree.
117  * @param state
118  *   A pointer to the leaf being parsed in the parsing tree. It can be
119  *   used by a node to retrieve information from the current parsing
120  *   tree. To get the root of the tree, @ec_pnode_get_root(state) should
121  *   be used.
122  * @param strvec
123  *   The string vector to be parsed.
124  * @return
125  *   On success, return the number of consumed items in the string vector
126  *   (can be 0) or EC_PARSE_NOMATCH if the node cannot parse the string
127  *   vector. On error, a negative value is returned and errno is set.
128  */
129 typedef int (*ec_parse_t)(const struct ec_node *node,
130                         struct ec_pnode *state,
131                         const struct ec_strvec *strvec);
132
133 /**
134  * Get completion items using the given grammar tree.
135  *
136  * The function pointer is not called directly, the helpers @ec_complete(),
137  * ec_complete_strvec() or ec_complete_child() should be used instead.
138  *
139  * This function completes the last element of the string vector.
140  * For instance, node.type->complete(node, comp, ["ls"]) will
141  * list all commands that starts with "ls", while
142  * node.type->complete(node, comp, ["ls", ""]) will list all
143  * possible values for the next argument.
144
145  * The implementation of this function is supposed to either:
146  * - call @ec_comp_add_item(node, comp, ...) for each completion item
147  *   that should be added to the list. This is done in terminal nodes,
148  *   for example in ec_node_str or ec_node_file.
149  * - call @ec_complete_child(child, comp, child_strvec) to let
150  *   the children nodes add their own completion. This is the
151  *   case of ec_node_or which trivially calls @ec_complete_child()
152  *   on all its children, and of ec_node_seq, which has to
153  *   do a more complex job (parsing strvec).
154  *
155  * A node that does not provide any method for the completion
156  * will fallback to ec_complete_unknown(): this helper returns
157  * a completion item of type EC_COMP_UNKNOWN, just to indicate
158  * that everything before the last element of the string vector
159  * has been parsed successfully, but we don't know how to
160  * complete the last element.
161  *
162  * @param node
163  *   The root node of the grammar tree.
164  * @param comp
165  *   The current list of completion items, to be filled by the
166  *   node.type->complete() method.
167  * @param strvec
168  *   The string vector to be completed.
169  * @return
170  *   0 on success, or a negative value on error (errno is set).
171  */
172 typedef int (*ec_complete_t)(const struct ec_node *node,
173                                 struct ec_comp *comp,
174                                 const struct ec_strvec *strvec);
175
176 /**
177  *
178  */
179 typedef const char * (*ec_node_desc_t)(const struct ec_node *);
180 typedef int (*ec_node_init_priv_t)(struct ec_node *);
181 typedef void (*ec_node_free_priv_t)(struct ec_node *);
182 typedef size_t (*ec_node_get_children_count_t)(const struct ec_node *);
183 typedef int (*ec_node_get_child_t)(const struct ec_node *,
184         size_t i, struct ec_node **child, unsigned int *refs);
185
186 /**
187  * A structure describing a node type.
188  */
189 struct ec_node_type {
190         TAILQ_ENTRY(ec_node_type) next;  /**< Next in list. */
191         const char *name;                /**< Node type name. */
192         /** Configuration schema array, must be terminated by a sentinel
193          *  (.type = EC_CONFIG_TYPE_NONE). */
194         const struct ec_config_schema *schema;
195         ec_node_set_config_t set_config; /* validate/ack a config change */
196         ec_parse_t parse;
197         ec_complete_t complete;
198         ec_node_desc_t desc;
199         size_t size;
200         ec_node_init_priv_t init_priv;
201         ec_node_free_priv_t free_priv;
202         ec_node_get_children_count_t get_children_count;
203         ec_node_get_child_t get_child;
204 };
205
206 /**
207  * Register a node type.
208  *
209  * @param type
210  *   A pointer to a ec_test structure describing the test
211  *   to be registered.
212  * @return
213  *   0 on success, negative value on error.
214  */
215 int ec_node_type_register(struct ec_node_type *type);
216
217 /**
218  * Lookup node type by name
219  *
220  * @param name
221  *   The name of the node type to search.
222  * @return
223  *   The node type if found, or NULL on error.
224  */
225 const struct ec_node_type *ec_node_type_lookup(const char *name);
226
227 /**
228  * Dump registered log types
229  */
230 void ec_node_type_dump(FILE *out);
231
232 /**
233  * Get the config schema of a node type.
234  */
235 const struct ec_config_schema *
236 ec_node_type_schema(const struct ec_node_type *type);
237
238 /**
239  * Get the name of a node type.
240  */
241 const char *
242 ec_node_type_name(const struct ec_node_type *type);
243
244 enum ec_node_free_state {
245         EC_NODE_FREE_STATE_NONE,
246         EC_NODE_FREE_STATE_TRAVERSED,
247         EC_NODE_FREE_STATE_FREEABLE,
248         EC_NODE_FREE_STATE_NOT_FREEABLE,
249         EC_NODE_FREE_STATE_FREEING,
250 };
251
252 /* create a new node when the type is known, typically called from the node
253  * code */
254 struct ec_node *ec_node_from_type(const struct ec_node_type *type, const char *id);
255
256 /* create a new node */
257 struct ec_node *ec_node(const char *typename, const char *id);
258
259 struct ec_node *ec_node_clone(struct ec_node *node);
260 void ec_node_free(struct ec_node *node);
261
262 /* set configuration of a node
263  * after a call to this function, the config is
264  * owned by the node and must not be used by the caller
265  * on error, the config is freed. */
266 int ec_node_set_config(struct ec_node *node, struct ec_config *config);
267
268 /* get the current node configuration. Return NULL if no configuration. */
269 const struct ec_config *ec_node_get_config(struct ec_node *node);
270
271 size_t ec_node_get_children_count(const struct ec_node *node);
272 int
273 ec_node_get_child(const struct ec_node *node, size_t i,
274         struct ec_node **child, unsigned int *refs);
275
276 /* XXX add more accessors */
277 const struct ec_node_type *ec_node_type(const struct ec_node *node);
278 struct ec_dict *ec_node_attrs(const struct ec_node *node);
279 const char *ec_node_id(const struct ec_node *node);
280 const char *ec_node_desc(const struct ec_node *node);
281
282 void ec_node_dump(FILE *out, const struct ec_node *node);
283 struct ec_node *ec_node_find(struct ec_node *node, const char *id);
284
285 /* check the type of a node */
286 int ec_node_check_type(const struct ec_node *node,
287                 const struct ec_node_type *type);
288
289 const char *ec_node_get_type_name(const struct ec_node *node);
290
291 /**
292  * Get the pointer to the node private area.
293  *
294  * @param node
295  *   The grammar node.
296  * @return
297  *   The pointer to the node private area.
298  */
299 void *ec_node_priv(const struct ec_node *node);
300
301 #endif
302
303  /** @} */