Documentation.
This commit is contained in:
parent
899fc0abfe
commit
06607335ef
4 changed files with 212 additions and 0 deletions
2
conf/Doc
2
conf/Doc
|
@ -1,2 +1,4 @@
|
||||||
H Configuration
|
H Configuration
|
||||||
S conf.c
|
S conf.c
|
||||||
|
S cf-lex.l
|
||||||
|
S confbase.Y
|
||||||
|
|
|
@ -6,6 +6,24 @@
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* 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 */
|
#undef REJECT /* Avoid name clashes */
|
||||||
|
|
||||||
|
@ -230,6 +248,16 @@ cf_find_sym(byte *c, unsigned int h0)
|
||||||
return s;
|
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 *
|
struct symbol *
|
||||||
cf_find_symbol(byte *c)
|
cf_find_symbol(byte *c)
|
||||||
{
|
{
|
||||||
|
@ -257,6 +285,16 @@ cf_default_name(char *template, int *counter)
|
||||||
cf_error("Unable to generate default name");
|
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
|
void
|
||||||
cf_define_symbol(struct symbol *sym, int type, void *def)
|
cf_define_symbol(struct symbol *sym, int type, void *def)
|
||||||
{
|
{
|
||||||
|
@ -280,6 +318,13 @@ cf_lex_init_kh(void)
|
||||||
kw_hash_inited = 1;
|
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
|
void
|
||||||
cf_lex_init(int is_cli)
|
cf_lex_init(int is_cli)
|
||||||
{
|
{
|
||||||
|
@ -295,6 +340,16 @@ cf_lex_init(int is_cli)
|
||||||
conf_this_scope->active = 1;
|
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
|
void
|
||||||
cf_push_scope(struct symbol *sym)
|
cf_push_scope(struct symbol *sym)
|
||||||
{
|
{
|
||||||
|
@ -306,6 +361,13 @@ cf_push_scope(struct symbol *sym)
|
||||||
s->name = 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
|
void
|
||||||
cf_pop_scope(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 *
|
char *
|
||||||
cf_symbol_class_name(struct symbol *sym)
|
cf_symbol_class_name(struct symbol *sym)
|
||||||
{
|
{
|
||||||
|
|
110
conf/conf.c
110
conf/conf.c
|
@ -6,6 +6,37 @@
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* 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 <setjmp.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -29,6 +60,14 @@ static event *config_event;
|
||||||
int shutting_down;
|
int shutting_down;
|
||||||
bird_clock_t boot_time;
|
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 *
|
struct config *
|
||||||
config_alloc(byte *name)
|
config_alloc(byte *name)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +84,19 @@ config_alloc(byte *name)
|
||||||
return c;
|
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
|
int
|
||||||
config_parse(struct config *c)
|
config_parse(struct config *c)
|
||||||
{
|
{
|
||||||
|
@ -66,6 +118,13 @@ config_parse(struct config *c)
|
||||||
return 1;
|
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
|
int
|
||||||
cli_parse(struct config *c)
|
cli_parse(struct config *c)
|
||||||
{
|
{
|
||||||
|
@ -79,6 +138,13 @@ cli_parse(struct config *c)
|
||||||
return 1;
|
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
|
void
|
||||||
config_free(struct config *c)
|
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
|
int
|
||||||
config_commit(struct config *c)
|
config_commit(struct config *c)
|
||||||
{
|
{
|
||||||
|
@ -208,6 +295,12 @@ config_commit(struct config *c)
|
||||||
return CONF_PROGRESS;
|
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
|
void
|
||||||
order_shutdown(void)
|
order_shutdown(void)
|
||||||
{
|
{
|
||||||
|
@ -225,6 +318,14 @@ order_shutdown(void)
|
||||||
shutting_down = 1;
|
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
|
void
|
||||||
cf_error(char *msg, ...)
|
cf_error(char *msg, ...)
|
||||||
{
|
{
|
||||||
|
@ -239,6 +340,15 @@ cf_error(char *msg, ...)
|
||||||
longjmp(conf_jmpbuf, 1);
|
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 *
|
char *
|
||||||
cfg_strdup(char *c)
|
cfg_strdup(char *c)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,37 @@
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* 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
|
CF_HDR
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
|
|
Loading…
Reference in a new issue