Add documentation comments for new config code

This commit is contained in:
Andrew Bettison 2012-11-26 16:15:59 +10:30
parent 8479c52f54
commit 0091cf082b
2 changed files with 214 additions and 0 deletions

101
config.h
View File

@ -20,6 +20,107 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef __SERVALDNA_CONFIG_H
#define __SERVALDNA_CONFIG_H
/* This file defines the internal API to the configuration file. See "config_schema.h" for the
* definition of the configuration schema, which is used to generate these API components.
*
* Each STRUCT(foo) schema declaration produces the following data declaration:
*
* struct config_foo {
* TYPE NAME;
* ...
* };
*
* A C struct definition containing exactly one element per schema declaration inside the
* STRUCT..END_STRUCT block, in the defined order. The TYPE and NAME of each element depends
* on the schema declaration that produces it:
*
* ATOM(TYPE, bar, ...)
* NODE(TYPE, bar, ...)
*
* TYPE bar;
*
* STRING(SIZE, bar, ...)
*
* char bar[SIZE+1];
*
* SUB_STRUCT(NAME, bar, ...)
* NODE_STRUCT(NAME, bar, ...)
*
* struct config_NAME bar;
*
* Each ARRAY_*(SIZE, bar, ...) schema declaration produces the following data declaration:
*
* struct config_bar {
* unsigned ac;
* struct {
* char label[N]; // please discover N using sizeof()
* TYPE value;
* } av[SIZE];
* };
*
* A C struct definition containing a count 'ac' of the number of array elements [0..SIZE-1]
* and 'av' an array of element values, each one consisting of a label and the value itself,
* whose TYPE depends on the ARRAY_* declaration itself:
*
* ARRAY_ATOM(NAME, SIZE, TYPE, ...)
* ARRAY_NODE(NAME, SIZE, TYPE, ...)
*
* TYPE value;
*
* ARRAY_STRING(NAME, SIZE, STRINGSIZE, ...)
*
* char value[STRINGSIZE];
*
* ARRAY_STRUCT(NAME, SIZE, STRUCTNAME, ...)
*
* struct config_STRUCTNAME value;
*
* Each STRUCT(foo) and ARRAY_*(SIZE, foo, ...) schema declaration produces the following API
* functions:
*
* - int dfl_config_foo(struct config_foo *dest);
*
* A C function which sets the entire contents of the given C structure to its default values
* as defined in the schema. This will only return CFOK or CFERROR; see below.
*
* - int opt_config_foo(struct config_foo *dest, const struct cf_om_node *node);
*
* A C function which parses the given COM (configuration object model) and assigns the parsed
* result into the given C structure. See below for the return value.
*
* All parse functions assign the result of their parsing into the struct given in their 'dest'
* argument, and return a bitmask of the following flags:
*
* - CFERROR (all bits set, == -1) if an unrecoverable error occurrs (eg, malloc() fails); the
* result in *dest is undefined and may be malformed or inconsistent;
*
* - CFEMPTY if no items were encountered in the COM (ie, no array elements or no struct elements);
* the memory at *dest is unchanged;
*
* - CFARRAYOVERFLOW if the size of any array was exceeded; a valid result is produced and the
* overflowed array(s) are fully populated, arbitrarily omitting some elements that were found in
* the COM;
*
* - CFSTRINGFOVERFLOW if the size of any string element was exceeded, a valid result is produced
* but the overflowed string elements are unchanged -- those parts of *dest are not overwritten;
*
* - CFINCOMPLETE if any MANDATORY element was missing; a valid result is produced but the missing
* mandatory element(s) are unchanged -- those parts of *dest are not overwritten;
*
* - CFINVALID if any invalid configuration value was encountered, ie, any parse function returned
* CFINVALID in its return flags; a valid result is produced but the invalid elements are
* unchanged -- those parts of *dest are not overwritten;
*
* - CFSUB(CFxxx) if the STRUCT parser function encountered the error CFxxx when parsing a struct
* element, ie, a parse function returned CFxxx; a valid result is produced but some parts of
* *dest will not be overwritten;
*
* The special value CFOK is zero (no bits set); in this case a valid result is produced and all of
* *dest is overwritten (except unused array elements).
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
#include <stdint.h>
#include "constants.h"
#include "strbuf.h"

View File

@ -17,6 +17,119 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* This file contains definitions for the schema of the Serval DNA configuration file. See comments
* in "config.h" for a description of the internal configuration API.
*
* A configuration schema is set of nested structures and arrays. By convention, the top level, or
* root of the schema is called "main", but every structure and array has its own complete API which
* can be used by itself. So if there were two independent configuration files, both could be
* defined in this file, each with a conventional name for its own root element.
*
* To describe a configuration file that looks like this:
*
* some.thing.element1=integer
* some.thing.element2=string
* some.list.foo.element1=integer
* some.list.foo.element2=string
* some.list.bar.element1=integer
* some.list.bar.element2=string
* another_thing=http://my.host.com:1234/path/to/nowhere
*
* the following schema would do:
*
* STRUCT(happy)
* ATOM(int32_t, element1, 0, opt_int32_nonnegative,, "An integer >= 0")
* STRING(80, element2, "boo!", opt_str_nonempty, MANDATORY, "A non-empty string")
* END_STRUCT
*
* ARRAY_STRUCT(joy, 16, happy, "An array of integer-string pairs")
*
* STRUCT(love)
* SUB_STRUCT(happy, thing,)
* SUB_STRUCT(joy, list,)
* END_STRUCT
*
* STRUCT(main)
* SUB_STRUCT(love, some,)
* STRING(128, another_thing, "", opt_uri,, "URL; protocol://hostname[:port][/path]")
* END_STRUCT
*
* which would produce an API based on the following definitions (see "config.h" for more
* information):
*
* struct config_happy {
* int32_t element1;
* char element2[81];
* };
* struct config_joy {
* unsigned ac;
* struct {
* char label[N]; // please discover N using sizeof()
* struct config_happy value;
* } av[16];
* };
* struct config_love {
* struct config_happy thing;
* struct config_joy list;
* };
* struct config_main {
* struct config_love some;
* char another_thing[129];
* };
*
* A schema definition is composed from the following STRUCT and ARRAY definitions:
*
* STRUCT(name)
* ATOM(type, element, default, parsefunc, flags, comment)
* NODE(type, element, default, parsefunc, flags, comment)
* STRING(size, element, default, parsefunc, flags, comment)
* SUB_STRUCT(structname, element, flags)
* NODE_STRUCT(structname, element, parsefunc, flags)
* END_STRUCT
*
* ARRAY_ATOM(name, size, type, parsefunc, comment)
* ARRAY_STRING(name, size, parsefunc, comment)
* ARRAY_NODE(name, size, type, parsefunc, comment)
* ARRAY_STRUCT(name, size, structname, comment)
*
* The meanings of the parameters are:
*
* 'name'
* A label used to qualify this struct/array's API from the API components of other structs and
* arrays. This label does not appear anywhere in the config file itself; it is purely for
* internal code-related purposes.
* 'type'
* Only used for ATOM, NODE, ARRAY_ATOM and ARRAY_NODE declarations. Gives the C type of the
* element. For STRING and ARRAY_STRING, this is implicitly (const char *).
* 'structname'
* Only used for SUB_STRUCT, NODE_STRUCT and ARRAY_STRUCT declarations. Identifies a sub-
* structure by 'name' to nest in the enclosing struct or array.
* 'element'
* The name of the struct element and the key in the configuration file. This name does appear
* in the config file and also in the API, so that an option mamed "some.thing.element1" in the
* file is referred to as some.thing.element1 in the C code. Arrays are more complicated:
* "some.list.foo.element1" in the config file is referred to as some.list.av[n].value.element1
* in the C code, and some.list.ac gives the size of the some.list.av array.
* 'default'
* Only used for ATOM and NODE struct elements. Gives the default value for the element if
* absent from the config file.
* 'parsefunc'
* The function used to parse the value from the config file. The ATOM, STRING, ARRAY_ATOM and
* ARRAY_STRING parse functions take a string argument (const char *). The NODE, NODE_STRUCT
* and ARRAY_NODE parse functions take a pointer to a COM node (const struct cf_om_node).
* 'flags'
* A space-separated list of flags. At present only the MANDATORY flag is supported, which
* will cause parsing to fail if the given STRUCT element is not set in the config file. In
* the case of struct elements that are arrays, the config file must set at least one element
* of the array, or parsing fails.
* 'comment'
* A human-readable string describing the value of the configuration option. Must be
* informative enough to help users diagnose parse errors. Eg, "An integer" is not enough;
* better would be "Integer >= 0, number of seconds since Unix epoch".
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
STRUCT(log)
STRING(256, file, "", opt_absolute_path,, "Absolute path of log file")
ATOM(int, show_pid, 1, opt_boolean,, "If true, all log lines contain PID of logging process")