2 * Copyright (c) 2013, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Confizery configuration node
32 * This module provides functions related to configuration nodes. A
33 * configuration node is a structure that stores a part of the
34 * information of the configuration tree. For instance, a "config" or
35 * "menuconfig" option is stored in a configuration node structure.
37 * It contains among other fields the name of the node (CONFIG_XYZ),
38 * the prompt and the help. Each node references its parent and a list
39 * of children as some nodes can contains some other nodes (menu, if,
40 * choice, ...). It also contains the default values, the user value,
41 * and the effective value of the node. Some nodes have no values (if,
45 #ifndef _CFZY_CONFNODE_H_
46 #define _CFZY_CONFNODE_H_
50 #include "cfzy_confnode_ops.h"
51 #include "cfzy_conftree_parser.h"
54 #define CFZY_F_IS_DIR 0x0001 /**< node can contain other nodes */
55 #define CFZY_F_NO_SET_DEPS 0x0002 /**< does not support the "requires" attribute */
56 #define CFZY_F_NO_SET_PROMPT 0x0004 /**< does not support the "prompt" attribute */
57 #define CFZY_F_NO_SET_DEFAULT 0x0008 /**< does not support the "default" attribute */
58 #define CFZY_F_IS_ROOT 0x0010 /**< the root node */
59 #define CFZY_F_VAL_IS_BOOL 0x0020 /**< value is a boolean */
60 #define CFZY_F_INVISIBLE 0x0040 /**< never seen from cmdline (like the IF node) */
61 #define CFZY_F_NO_NAME 0x0080 /**< node has no name (if, comments, ...) */
62 #define CFZY_F_NO_SET_VALUE 0x0100 /**< user cannot set value (if, comments, ...) */
63 #define CFZY_F_QUOTE_VAL 0x0200 /**< quote value */
64 #define CFZY_F_DOTCONF_SHOW_TITLE 0x0400 /**< show title as a comment in dotconfig file */
69 * Structure storing a conditional default value
71 struct cfzy_confnode_defvalue {
72 struct cfzy_expr *expr; /**< expression (condition) */
73 char *val; /**< value */
77 * List of cfzy_node, used to chain children together
79 TAILQ_HEAD(cfzy_confnode_list, cfzy_confnode);
82 * This structure defines a configuration node in the configration
83 * tree, for instance a "menu" entry, or a "bool" entry.
85 struct cfzy_confnode {
86 /* pointer to other nodes in conf tree */
87 struct cfzy_confnode *parent; /**< pointer to parent */
88 struct cfzy_confnode_list children; /**< list of children */
89 TAILQ_ENTRY(cfzy_confnode) child_next; /**< next in children list */
90 struct cfzy_conftree *conftree; /**< back pointer to conftree */
93 char *name; /**< node name (dynamic alloc) */
94 char *prompt; /**< node prompt (dynamic alloc) */
95 char *help; /**< node help (dynamic alloc) */
96 unsigned flags; /**< node flags */
97 struct cfzy_list_head *expr_deps; /**< list of prereq expressions */
99 /* where it was parsed */
100 char *filename; /**< name of conftree file */
101 int linenum; /**< line where node was declared */
103 /* specific to a node type */
104 const struct cfzy_confnode_ops *ops; /**< specific ops on node */
108 char *default_value; /**< default value for this node */
109 struct cfzy_list_head *default_val_list; /* conditional default vals */
110 char *user_value; /**< value wanted by the user */
111 char *effective_value; /**< real value, taking care of deps */
112 char *old_user_value; /**< saved user value */
113 char *old_effective_value; /**< saved effective value */
115 /* allow to chain this node in a priority ordered list */
116 TAILQ_ENTRY(cfzy_confnode) prio_next; /**< next in ordered list */
117 int in_prio_list; /**< true if present in prio list */
119 struct cfzy_list_head *node_deps; /**< list of nodes that must be
120 * evaluated before this one */
124 * Get the name of a node
129 * pointer to the node name (hosted in the node structure)
131 static inline const char *cfzy_confnode_name(const struct cfzy_confnode *n)
139 * Allocate a new node
141 * Allocate a new empty node, with no specific ops.
146 * the allocated configuration node, or NULL on error
148 struct cfzy_confnode *cfzy_confnode_alloc(struct cfzy_conftree *conftree);
151 * Free the node given as argument, and all its associated data
153 * This function will free the children of the nodes, then the node
154 * itself, first by calling the specific function n->ops->free() if
155 * defined, then by doing the generic operations.
160 void cfzy_confnode_free(struct cfzy_confnode *n);
163 * Get the prerequisites for this node
165 * Return the list of nodes required to evaluate the value of the
166 * given node. Indeed, each node has a 'expr_deps' field storing a
167 * list of expressions and a list of default value associated to
168 * expressions. This function returns the list of all nodes referenced
169 * in these expressions and all the ancestor nodes.
171 * The returned list must be freed by the user with
172 * cfzy_list_free(list, NULL).
177 * list of nodes, or NULL on error
179 struct cfzy_list_head *
180 cfzy_confnode_get_deplist(const struct cfzy_confnode *n);
183 * Add a conditional default value to a node
188 * value to be used as default value
190 * condition string to enable the default value
192 * 0 on success, negative on error
194 int cfzy_confnode_add_defval(struct cfzy_confnode *n, const char *val,
195 const char *expr_buf);
198 * Parse a line of configuration tree file, expecting an attribute
200 * This function first tries to match specific node attributes, using
201 * the specific operation n->ops->add_attr() if registered. Then it
202 * tries to match generic attributes (prompt, requires, default).
204 * This function is internal to the confizery library (called by the
205 * configuration tree parser).
210 * list of tokens for this line
212 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
213 * is not an attribute for this node, ERROR on error
215 enum cfzy_parse_return
216 cfzy_confnode_add_attr(struct cfzy_confnode *n,
217 const struct cfzy_token_list *tklist);
220 * Write .config-like configuration in a file
222 * Write in a file the configuration values of this node and its
223 * descendants. The format of this file is like .config: it can be
224 * sourced by a shell or a Makefile.
226 * The function calls the specific node operation
227 * n->ops->dotconfig_write() if defined. Else, it uses the defaut
228 * behavior, which varies depending on node flags.
230 * This function is internal and is called by the public function
231 * cfzy_dotconfig_write().
236 * open file with write permissions where config will be written
238 * 0 on success, negative on error
240 int cfzy_confnode_dotconfig_write(const struct cfzy_confnode *n, FILE *f);
243 * Write the configuration in a C header file
245 * Write in a file the configuration values of this node and its
246 * descendants. The format of this file is a C header, so it can be
247 * included by a C application.
249 * The function calls the specific node operation
250 * n->ops->c_hdr_write() if defined. Else, it uses the defaut
251 * behavior, which varies depending on node flags.
253 * This function is internal and is called by the public function
254 * cfzy_c_hdr_write().
259 * open file with write permissions where config will be written
261 * 0 on success, negative on error
263 int cfzy_confnode_c_hdr_write(const struct cfzy_confnode *n, FILE *f);
266 * Return a string identifying the node type
268 * The function calls the specific node operation
269 * n->ops->get_type_str().
271 * The returned string points to static memory and contains the type
272 * of the node (ex: "config", "menuconfig", "choice", ...)
277 * pointer to a node type string
279 const char *cfzy_confnode_get_type_str(const struct cfzy_confnode *n);
282 * Return the boolean value of the node given the string value
284 * Convert the string value given as parameter to a boolean value. It
285 * calls the specific node operation n->ops->str2bool() if
286 * defined. Else, it uses the defaut behavior: return 0 for value=NULL
287 * or 1 for any other value.
289 * The specific function (if defined) can also return a negative value
290 * to indicate that the given value is not valid for this node.
295 * string containing the value
297 * the boolean value (0 or 1) if the string value is valid,
300 int cfzy_confnode_str2bool(const struct cfzy_confnode *n, const char *value);
303 * Get the path of the node
308 * buffer where the path should be written
310 * length of the buffer
312 * 0 on success, negative on error
314 int cfzy_confnode_path(const struct cfzy_confnode *n, char *buf, int len);
317 #define CFZY_DUMP_MODE_MINIMAL 0x0
318 #define CFZY_DUMP_MODE_STANDARD 0x1
319 #define CFZY_DUMP_MODE_FULL 0x2
320 #define CFZY_DUMP_MODE_FULL_RECURSIVE 0x3
323 * Dump a human-readable configuration in a file
325 * Write in a file the structure fields of this node and its
331 * open file with write permissions where configuration will be written
333 * behavior of dump (CFZY_DUMP_MODE_MINIMAL, CFZY_DUMP_MODE_STANDARD, ...)
335 * 0 on success, negative on error
337 int cfzy_confnode_dump(const struct cfzy_confnode *n, FILE *f, int mode);
340 * Check prerequisites for a node
343 * configuration node to be checked
345 * 0 if a parent node is disabled or if a prerequisite expression is
346 * false, 1 if node can be enable. On error, return -1.
348 int cfzy_confnode_check_deps(struct cfzy_confnode *n);
351 * Evaluate the effective value of a node
353 * Set the new value of n->effective_value, assuming all prerequisites
354 * are already evaluated. This function is used as a callback by
355 * cfzy_expr_parse() when parsing an expression for
356 * cfzy_confnode_evaluate().
361 * 0 on success, negative on error
363 int cfzy_confnode_evaluate(struct cfzy_confnode *n);
366 * Get the boolean value of a node, given its name
368 * Return the effective value of a node (assuming it has been
369 * evaluated previously).
372 * configuration node name
376 * the boolean value (0 or 1) if the string value is valid,
379 int cfzy_confnode_get_boolvalue(const char *name,
380 const struct cfzy_conftree *conftree);
383 * Set user value of a configuration node
385 * To set the user value of a node, the user must not access to the
386 * field directly but use this function. Indeed, a node may want to do
387 * a specific operation (like a check, or modifying children nodes)
388 * stored in n->ops->set_uservalue().
393 * value to be set as user value
395 * 0 on success, negative on error
397 int cfzy_confnode_set_uservalue(struct cfzy_confnode *n, const char *value);
400 * Create a new root node
405 * a pointer to the configuration node, or NULL on error
407 struct cfzy_confnode *cfzy_confnode_root_new(struct cfzy_conftree *conftree);
410 * Parse a line of configuration tree file, expecting new choice node
415 * list of tokens for this line
417 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
418 * is not an attribute for this node, ERROR on error
420 enum cfzy_parse_return
421 cfzy_confnode_choice_new(struct cfzy_confnode *n,
422 const struct cfzy_token_list *tklist);
424 * Parse a line of configuration tree file, expecting new choiceconfig node
429 * list of tokens for this line
431 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
432 * is not an attribute for this node, ERROR on error
434 enum cfzy_parse_return
435 cfzy_confnode_choiceconfig_new(struct cfzy_confnode *n,
436 const struct cfzy_token_list *tklist);
439 * Parse a line of configuration tree file, expecting new comment node
444 * list of tokens for this line
446 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
447 * is not an attribute for this node, ERROR on error
449 enum cfzy_parse_return
450 cfzy_confnode_comment_new(struct cfzy_confnode *n,
451 const struct cfzy_token_list *tklist);
454 * Parse a line of configuration tree file, expecting new config node
459 * list of tokens for this line
461 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
462 * is not an attribute for this node, ERROR on error
464 enum cfzy_parse_return
465 cfzy_confnode_config_new(struct cfzy_confnode *n,
466 const struct cfzy_token_list *tklist);
469 * Parse a line of configuration tree file, expecting new if node
474 * list of tokens for this line
476 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
477 * is not an attribute for this node, ERROR on error
479 enum cfzy_parse_return
480 cfzy_confnode_if_new(struct cfzy_confnode *n,
481 const struct cfzy_token_list *tklist);
484 * Parse a line of configuration tree file, expecting new intconfig node
489 * list of tokens for this line
491 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
492 * is not an attribute for this node, ERROR on error
494 enum cfzy_parse_return
495 cfzy_confnode_intconfig_new(struct cfzy_confnode *n,
496 const struct cfzy_token_list *tklist);
499 * Parse a line of configuration tree file, expecting new menu node
504 * list of tokens for this line
506 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
507 * is not an attribute for this node, ERROR on error
509 enum cfzy_parse_return
510 cfzy_confnode_menu_new(struct cfzy_confnode *n,
511 const struct cfzy_token_list *tklist);
514 * Parse a line of configuration tree file, expecting new menuconfig node
519 * list of tokens for this line
521 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
522 * is not an attribute for this node, ERROR on error
524 enum cfzy_parse_return
525 cfzy_confnode_menuconfig_new(struct cfzy_confnode *n,
526 const struct cfzy_token_list *tklist);
529 * Parse a line of configuration tree file, expecting new strconfig node
534 * list of tokens for this line
536 * SUCCESS if it matches an attribute of this node, NO_MATCH if the line
537 * is not an attribute for this node, ERROR on error
539 enum cfzy_parse_return
540 cfzy_confnode_strconfig_new(struct cfzy_confnode *n,
541 const struct cfzy_token_list *tklist);
544 * Close the node beeing parsed
546 * Some nodes can contains other nodes (menu, menuconfig, ...). When
547 * the parser has finished to parse the descendants of the node, it
548 * calls this function to close the node. This can trigger some
549 * specific operations (like checks) if the node type registers a
550 * n->ops->close(). If no specific function is registered, it does
553 * This function is internal to the confizery library (called by the
554 * configuration tree parser).
559 * 0 on success, negative on error
561 int cfzy_confnode_close(struct cfzy_confnode *n);
564 #endif /* _CFZY_CONFNODE_H_ */