diff options
-rw-r--r-- | conf/Doc | 2 | ||||
-rw-r--r-- | conf/cf-lex.l | 69 | ||||
-rw-r--r-- | conf/conf.c | 110 | ||||
-rw-r--r-- | conf/confbase.Y | 31 |
4 files changed, 212 insertions, 0 deletions
@@ -1,2 +1,4 @@ H Configuration S conf.c +S cf-lex.l +S confbase.Y diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 27ea86eb..e7cb2c8a 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -6,6 +6,24 @@ * Can be freely distributed and used under the terms of the GNU GPL. */ +/** + * DOC: Lexical analyser + * + * The lexical analyser used for configuration files and CLI commands + * is generated using the |flex| tool accompanied with a couple of + * functions maintaining the hash tables containing information about + * symbols and keywords. + * + * Each symbol is represented by a &symbol structure containing name + * of the symbol, its scope, symbol class (%SYM_PROTO for a name of a protocol, + * %SYM_NUMBER for a numeric constant etc.) and class dependent data. + * When an unknown symbol is encountered, it's automatically added to the + * symbol table with class %SYM_VOID. + * + * The keyword tables are generated from the grammar templates + * using the |gen_keywords.m4| script. + */ + %{ #undef REJECT /* Avoid name clashes */ @@ -230,6 +248,16 @@ cf_find_sym(byte *c, unsigned int h0) return s; } +/** + * cf_find_symbol - find a symbol by name + * @c: symbol name + * + * This functions searches the symbol table for a symbol of given + * name. First it examines the current scope, then the second recent + * one and so on until it either finds the symbol and returns a pointer + * to its &symbol structure or reaches the end of the scope chain + * and returns %NULL to signify no match. + */ struct symbol * cf_find_symbol(byte *c) { @@ -257,6 +285,16 @@ cf_default_name(char *template, int *counter) cf_error("Unable to generate default name"); } +/** + * cf_define_symbol - define meaning of a symbol + * @sym: symbol to be defined + * @type: symbol class to assign + * @def: class dependent data + * + * This function takes a symbol, checks whether it's really + * an undefined one (else it raises an error) and assigns the + * given class and definition to it. + */ void cf_define_symbol(struct symbol *sym, int type, void *def) { @@ -280,6 +318,13 @@ cf_lex_init_kh(void) kw_hash_inited = 1; } +/** + * cf_lex_init - initialize the lexer + * @is_cli: true if we're going to parse CLI command, false for configuration + * + * cf_lex_init() initializes the lexical analyser and prepares it for + * parsing of a new input. + */ void cf_lex_init(int is_cli) { @@ -295,6 +340,16 @@ cf_lex_init(int is_cli) conf_this_scope->active = 1; } +/** + * cf_push_scope - enter new scope + * @sym: symbol representing scope name + * + * If we want to enter a new scope to process declarations inside + * a nested block, we can just call cf_push_scope() to push a new + * scope onto the scope stack which will cause all new symbols to be + * defined in this scope and all existing symbols to be sought for + * in all scopes stored on the stack. + */ void cf_push_scope(struct symbol *sym) { @@ -306,6 +361,13 @@ cf_push_scope(struct symbol *sym) s->name = sym; } +/** + * cf_pop_scope - leave a scope + * + * cf_pop_scope() pops the topmost scope from the scope stack, + * leaving all its symbols in the symbol table, but making them + * invisible to the rest of the config. + */ void cf_pop_scope(void) { @@ -332,6 +394,13 @@ cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos) } } +/** + * cf_symbol_class_name - get name of a symbol class + * @sym: symbol + * + * This function returns a string representing the class + * of the given symbol. + */ char * cf_symbol_class_name(struct symbol *sym) { diff --git a/conf/conf.c b/conf/conf.c index dd716424..e2a003d3 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -6,6 +6,37 @@ * Can be freely distributed and used under the terms of the GNU GPL. */ +/** + * DOC: Configuration manager + * + * Configuration of BIRD is complex, but straightforward. There exist three + * modules taking care of the configuration: config manager (which takes care + * of storage of config information and controls switching between configs), + * lexical analyser and parser. + * + * The configuration manager stores each config as a &config structure + * accompanied by a linear pool from which all information associated + * with the config and pointed to by the &config structure is allocated. + * + * There can exist up four different configurations at one time: an active + * one (pointed to by @config), configuration we are just switching from + * (@old_config), one queued for the next reconfiguration (@future_config; + * if it's non-%NULL and the user wants to reconfigure once again, we just + * free the previous queued config and replace it with the new one) and + * finally a config being parsed (@new_config). + * + * Loading of new configuration is very simple: just call config_alloc() + * to get a new &config structure, then use config_parse() to parse a + * configuration file and fill all information in the structure + * and finally ask the config manager to switch to the new + * config by calling config_commit(). + * + * CLI commands are parsed in a very similar way -- there is also a stripped-down + * &config structure associated with them and they are lexed and parsed by the + * same functions, only a special fake token is prepended before the command + * text to make the parser recognize only the rules corresponding to CLI commands. + */ + #include <setjmp.h> #include <stdarg.h> @@ -29,6 +60,14 @@ static event *config_event; int shutting_down; bird_clock_t boot_time; +/** + * config_alloc - allocate a new configuration + * @name: name of the config + * + * This function creates new &config structure, attaches a resource + * pool and a linear memory pool to it and makes it available for + * further use. Returns a pointer to the structure. + */ struct config * config_alloc(byte *name) { @@ -45,6 +84,19 @@ config_alloc(byte *name) return c; } +/** + * config_parse - parse a configuration + * @c: configuration + * + * config_parse() reads input by calling a hook function pointed to + * by @cf_read_hook and parses it according to the configuration + * grammar. It also calls all the preconfig and postconfig hooks + * before resp. after parsing. + * + * Result: 1 if the config has been parsed successfully, 0 if any + * error has occured (such as anybody calling cf_error()) and + * the @err_msg field has been set to the error message. + */ int config_parse(struct config *c) { @@ -66,6 +118,13 @@ config_parse(struct config *c) return 1; } +/** + * cli_parse - parse a CLI command + * @c: temporary config structure + * + * cli_parse() is similar to config_parse(), but instead of a configuration, + * it parses a CLI command. See the CLI module for more information. + */ int cli_parse(struct config *c) { @@ -79,6 +138,13 @@ cli_parse(struct config *c) return 1; } +/** + * config_free - free a configuration + * @c: configuration to be freed + * + * This function takes a &config structure and frees all resources + * associated with it. + */ void config_free(struct config *c) { @@ -169,6 +235,27 @@ config_done(void *unused) } } +/** + * config_commit - commit a configuration + * @c: new configuration + * + * When a configuration is parsed and prepared for use, the + * config_commit() function starts the process of reconfiguration. + * It checks whether there is already a reconfiguration in progress + * in which case it just queues the new config for later processing. + * Else it notifies all modules about the new configuration by calling + * their commit() functions which can either accept it immediately + * or call config_add_obstacle() to report that they need some time + * to complete the reconfiguration. After all such obstacles are removed + * using config_del_obstacle(), the old configuration is freed and + * everything runs according to the new one. + * + * Result: %CONF_DONE if the configuration has been accepted immediately, + * %CONF_PROGRESS if it will take some time to switch to it, %CONF_QUEUED + * if it's been queued due to another reconfiguration being in progress now + * or %CONF_SHUTDOWN if BIRD is in shutdown mode and no new configurations + * are accepted. + */ int config_commit(struct config *c) { @@ -208,6 +295,12 @@ config_commit(struct config *c) return CONF_PROGRESS; } +/** + * order_shutdown - order BIRD shutdown + * + * This function initiates shutdown of BIRD. It's accomplished by asking + * for switching to an empty configuration. + */ void order_shutdown(void) { @@ -225,6 +318,14 @@ order_shutdown(void) shutting_down = 1; } +/** + * cf_error - report a configuration error + * @msg: printf-like format string + * + * cf_error() can be called during execution of config_parse(), that is + * from the parser, a preconfig hook or a postconfig hook, to report an + * error in the configuration. + */ void cf_error(char *msg, ...) { @@ -239,6 +340,15 @@ cf_error(char *msg, ...) longjmp(conf_jmpbuf, 1); } +/** + * cfg_strdup - copy a string to config memory + * @c: string to copy + * + * cfg_strdup() creates a new copy of the string in the memory + * pool associated with the configuration being currently parsed. + * It's often used when a string literal occurs in the configuration + * and we want to preserve it for further use. + */ char * cfg_strdup(char *c) { diff --git a/conf/confbase.Y b/conf/confbase.Y index 5da84b1e..1b18a979 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -6,6 +6,37 @@ * Can be freely distributed and used under the terms of the GNU GPL. */ +/** + * DOC: Parser + * + * Both the configuration and CLI commands are analysed using a syntax + * driven parser generated by the |bison| tool from a grammar which + * is constructed from information gathered from grammar snippets by + * the |gen_parser.m4| script. + * + * Grammar snippets are files (usually with extension |.Y|) contributed + * by various BIRD modules to provide information about syntax of their + * configuration and their CLI commands. Each snipped consists of several + * section, each of them starting with a special keyword: |CF_HDR| for + * a list of |#include| directives needed by the C code, |CF_DEFINES| + * for a list of C declarations, |CF_DECLS| for |bison| declarations + * including keyword definitions specified as |CF_KEYWORDS|, |CF_GRAMMAR| + * for the grammar rules, |CF_CODE| for auxillary C code and finally + * |CF_END| at the end of the snippet. + * + * To create references between the snippets, it's possible to define + * multi-part rules by utilizing the |CF_ADDTO| macro which adds a new + * alternative to a multi-part rule. + * + * CLI commands are defined using a |CF_CLI| macro. Its parameters are: + * the list of keywords determining the command, the list of paramaters, + * help text for the parameters and help text for the command. + * + * Values of |enum| filter types can be defined using |CF_ENUM| with + * the following parameters: name of filter type, prefix common for all + * literals of this type, names of all the possible values. + */ + CF_HDR #include "nest/bird.h" |