summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/Doc2
-rw-r--r--conf/cf-lex.l69
-rw-r--r--conf/conf.c110
-rw-r--r--conf/confbase.Y31
4 files changed, 212 insertions, 0 deletions
diff --git a/conf/Doc b/conf/Doc
index 7bda051b..5473badb 100644
--- a/conf/Doc
+++ b/conf/Doc
@@ -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"