Improve config schema macros and log options

Add STRUCT_ASSIGN macro to config schema

Document STRUCT_DEFAULT and STRUCT_ASSIGN in block comments

Move 'log.file_xxx' options to 'log.file.xxx'
This commit is contained in:
Andrew Bettison 2013-04-05 14:07:31 +10:30
parent 60551df890
commit a822dca2fa
4 changed files with 258 additions and 75 deletions

92
conf.h
View File

@ -95,6 +95,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* function is used to parse each individual array element, and the parsed result is only
* appended to the array if it returns CFOK.
*
* - int cf_cmp_config_NAME(const struct config_NAME *a, const struct config_NAME *b);
*
* A C function that compares the two C structures, returning -1, 0 or +1 in a stable
* (invariant) fashion; successive calls for the same two structures will always return the
* same result. This defines a stable ordering over all possible structure values, and allows
* structures to be compared for equality.
*
* - int cf_fmt_config_NAME(struct cf_om_node **nodep, const struct config_NAME *src);
*
* A C function which decomposes the given C structure into a COM (configuration object model),
* suitable for re-parsing or for inspection. This provides a limited form of run-time
* reflection of configuration options. Each node in the generated COM has the 'line_number'
* field set to 0 if the node contains the option's default value, or 1 if the option's value
* differed from the default.
*
* If a STRUCT(NAME, VALIDATOR) or ARRAY(NAME, FLAGS, VALIDATOR) schema declaration is given a
* validator function, then the function must have the following signature:
*
@ -117,8 +132,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* there is no validator function, then cf_opt_config_NAME() will return an empty array (dest->ac
* == 0) in the case of CFARRAYOVERFLOW.
*
* 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:
* Each STRUCT_ASSIGN(NAME, SUPER) default declaration generates the following API function:
*
* - void cf_cpy_config_NAME(struct config_NAME *dest, struct config_SUPER *source);
*
* A C function which copies elements from 'source' into 'dest'. Any elements not defined in
* the STRUCT_ASSIGN...END_STRUCT_ASSIGN declaration are simply not copied, so the 'dest'
* structure should be initialised with known values prior to calling cf_cpy_config_NAME(), eg,
* by zero filling, or better still, with its default values using cf_dfl_config_NAME().
*
* All parse (cf_opt_) 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 occurs (eg, malloc() fails). The
* result in *dest is undefined and may be malformed or inconsistent.
@ -180,6 +204,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* 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).
*
* All format (cf_fmt_) functions return a bitmask of the following values:
*
* - CFERROR if an unrecoverable error occurs (eg, malloc() fails). The resulting COM is
* undefined, but can safely be freed using cf_om_free_node().
*
* - CFINVALID if an ATOM or STRING has an invalid value. This is only returned by ATOM and STRING
* format functions, not STRUCT or ARRAY functions, which will return CFSUB(CFINVALID) if any of
* their members is invalid.
*
* - CFEMPTY if an ATOM or STRING has an zero length but this is invalid.
*
* - CFSUB(CFxxx) if the format function (cf_fmt_) of any element of a sub-STRUCT or sub-ARRAY
* returned a CFxxx result. In the case of STRUCT, the failed elements are omitted from the output
* COM.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
@ -320,11 +359,14 @@ struct pattern_list {
struct config_##__name __element;
#define END_STRUCT \
};
#define STRUCT_ASSIGN(__substructname, __structname) \
struct __cf_unused_##__LINE__ {
#define END_STRUCT_ASSIGN \
};
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
struct config_##__name { \
@ -355,11 +397,12 @@ struct pattern_list {
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -371,28 +414,30 @@ struct pattern_list {
#undef VALUE_NODE_STRUCT
#undef END_ARRAY
// Generate config function prototypes, cf_dfl_config_NAME(), cf_sch_config_NAME().
// Generate config function prototypes, cf_dfl_config_NAME(), cf_sch_config_NAME(), cf_cpy_config_NAME().
#define STRUCT(__name, __validator...) \
int cf_dfl_config_##__name(struct config_##__name *s); \
int cf_dfl_config_##__name##_cf_(struct config_##__name *s); \
int cf_dfl_config_##__name(struct config_##__name *); \
int cf_dfl_config_##__name##_cf_(struct config_##__name *); \
int cf_sch_config_##__name(struct cf_om_node **parentp);
#define NODE(__type, __element, __default, __repr, __flags, __comment)
#define ATOM(__type, __element, __default, __repr, __flags, __comment)
#define STRING(__size, __element, __default, __repr, __flags, __comment)
#define SUB_STRUCT(__name, __element, __flags, __dfllabel...) \
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *s);
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *);
#define NODE_STRUCT(__name, __element, __repr, __flags, __dfllabel...) \
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *s);
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *);
#define END_STRUCT
#define STRUCT_ASSIGN(__substructname, __structname) \
void cf_cpy_config_##__substructname(struct config_##__substructname *, const struct config_##__structname *);
#define END_STRUCT_ASSIGN
#define STRUCT_DEFAULT(__name, __dfllabel) \
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *s);
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *);
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int cf_dfl_config_##__name(struct config_##__name *a); \
int cf_dfl_config_##__name(struct config_##__name *); \
int cf_sch_config_##__name(struct cf_om_node **parentp);
#define KEY_ATOM(__type, __keyrepr)
#define KEY_STRING(__strsize, __keyrepr)
@ -410,11 +455,12 @@ struct pattern_list {
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -459,11 +505,12 @@ struct pattern_list {
int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); \
int cf_cmp_##__repr(const struct config_##__structname *, const struct config_##__structname *);
#define END_STRUCT
#define STRUCT_ASSIGN(__substructname, __structname)
#define END_STRUCT_ASSIGN
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
@ -511,11 +558,12 @@ struct pattern_list {
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -535,11 +583,12 @@ struct pattern_list {
#define SUB_STRUCT(__name, __element, __flags, __dfllabel...)
#define NODE_STRUCT(__name, __element, __repr, __flags, __dfllabel...)
#define END_STRUCT
#define STRUCT_ASSIGN(__substructname, __structname)
#define END_STRUCT_ASSIGN
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int config_##__name##__get(const struct config_##__name *,
@ -561,11 +610,12 @@ struct pattern_list {
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM

View File

@ -40,16 +40,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define END_STRUCT \
return CFOK; \
}
#define STRUCT_ASSIGN(__substructname, __structname) \
__attribute__((unused)) static void __cf_unused_1_##__substructname(struct config_##__substructname *s) {
#define END_STRUCT_ASSIGN \
}
#define STRUCT_DEFAULT(__name, __dfllabel) \
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *s) {
int cf_dfl_config_##__name##_cf_##__dfllabel(struct config_##__name *s) { \
cf_dfl_config_##__name(s);
#define ATOM_DEFAULT(__element, __default) \
s->__element = (__default);
#define STRING_DEFAULT(__element, __default) \
s->__element = (__default);
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...) \
cf_dfl_config_##__name##_cf_##__dlflabel(&s->__element);
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel...) \
SUB_STRUCT_DEFAULT(__name, __element, ##__dfllabel)
#define END_STRUCT_DEFAULT \
return CFOK; \
}
@ -77,11 +80,70 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
#undef KEY_STRING
#undef VALUE_ATOM
#undef VALUE_STRING
#undef VALUE_NODE
#undef VALUE_SUB_STRUCT
#undef VALUE_NODE_STRUCT
#undef END_ARRAY
// Generate config assign function definitions, cf_cpy_config_NAME().
#define STRUCT(__name, __validator...) \
__attribute__((unused)) static void __cf_unused_2_##__name(struct config_##__name *dst, const struct config_##__name *src) {
#define END_STRUCT \
}
#define STRUCT_ASSIGN(__substructname, __structname) \
void cf_cpy_config_##__substructname(struct config_##__substructname *dst, const struct config_##__structname *src) {
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
dst->__element = src->__element;
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
dst->__element = src->__element;
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
strncpy(dst->__element, src->__element, (__size))[(__size)] = '\0';
#define SUB_STRUCT(__name, __element, __flags, __dlflabel...) \
dst->__element = src->__element;
#define NODE_STRUCT(__name, __element, __repr, __flags, __dfllabel...) \
dst->__element = src->__element;
#define END_STRUCT_ASSIGN \
}
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...)
#define KEY_ATOM(__type, __keyrepr)
#define KEY_STRING(__strsize, __keyrepr)
#define VALUE_ATOM(__type, __eltrepr)
#define VALUE_STRING(__strsize, __eltrepr)
#define VALUE_NODE(__type, __eltrepr)
#define VALUE_SUB_STRUCT(__structname, __dfllabel...)
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
#define END_ARRAY(__size)
#include "conf_schema.h"
#undef STRUCT
#undef NODE
#undef ATOM
#undef STRING
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -166,11 +228,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
result = (*validator)(node, strct, result); \
return result; \
}
#define STRUCT_ASSIGN(__substructname, __structname) \
__attribute__((unused)) static int __cf_unused_3_##__substructname(struct config_##__substructname *strct, const struct cf_om_node *node) { \
int result; \
char used[0];
#define END_STRUCT_ASSIGN \
return 0; \
}
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int cf_opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
@ -258,11 +326,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -284,11 +353,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define SUB_STRUCT(__name, __element, __flags, __dfllabel...)
#define NODE_STRUCT(__name, __element, __repr, __flags, __dfllabel...)
#define END_STRUCT
#define STRUCT_ASSIGN(__substructname, __structname)
#define END_STRUCT_ASSIGN
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int config_##__name##__get(const struct config_##__name *array,
@ -322,11 +392,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -374,11 +445,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define END_STRUCT \
return 0; \
}
#define STRUCT_ASSIGN(__substructname, __structname) \
__attribute__((unused)) static int __cf_unused_4_##__substructname(struct cf_om_node **rootp) { \
int i; \
struct cf_om_node **childp;
#define END_STRUCT_ASSIGN \
return 0; \
}
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int cf_sch_config_##__name(struct cf_om_node **rootp) { \
@ -416,11 +493,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -528,11 +606,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
cf_om_free_node(parentp); \
return result; \
}
#define STRUCT_ASSIGN(__substructname, __structname) \
__attribute__((unused)) static int __cf_unused_5_##__substructname(struct cf_om_node **parentp, const struct config_##__substructname *strct, const struct config_##__substructname *dflt) { \
int result; \
int ret;
#define END_STRUCT_ASSIGN \
return 0; \
}
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int cf_xfmt_config_##__name(struct cf_om_node **parentp, const struct config_##__name *array, const struct config_##__name *dflt) { \
@ -617,11 +701,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef __FMT_TEXT
#undef __FMT_NODE_START
#undef __FMT_NODE_END
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM
@ -658,11 +743,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define END_STRUCT \
return 0; \
}
#define STRUCT_ASSIGN(__substructname, __structname) \
__attribute__((unused)) static int __cf__unused_6_##__substructname(const struct config_##__substructname *a, const struct config_##__substructname *b) { \
int c;
#define END_STRUCT_ASSIGN \
return 0; \
}
#define STRUCT_DEFAULT(__name, __dfllabel)
#define ATOM_DEFAULT(__element, __default)
#define STRING_DEFAULT(__element, __default)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define NODE_STRUCT_DEFAULT(__name, __element, __dfllabel)
#define SUB_STRUCT_DEFAULT(__name, __element, __dfllabel...)
#define END_STRUCT_DEFAULT
#define ARRAY(__name, __flags, __validator...) \
int cf_cmp_config_##__name(const struct config_##__name *a, const struct config_##__name *b) { \
@ -702,11 +792,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef STRUCT_ASSIGN
#undef END_STRUCT_ASSIGN
#undef STRUCT_DEFAULT
#undef ATOM_DEFAULT
#undef STRING_DEFAULT
#undef SUB_STRUCT_DEFAULT
#undef NODE_STRUCT_DEFAULT
#undef END_STRUCT_DEFAULT
#undef ARRAY
#undef KEY_ATOM

View File

@ -90,7 +90,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* A schema definition is composed from the following STRUCT and ARRAY definitions:
*
* STRUCT(name[, validatorfunc])
* STRUCT(name [, validatorfunc])
* element-declaration
* element-declaration
* ...
@ -101,14 +101,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* ATOM(type, element, default, repr, flags, comment)
* NODE(type, element, default, repr, flags, comment)
* STRING(strlen, element, default, repr, flags, comment)
* SUB_STRUCT(structname, element, flags)
* NODE_STRUCT(structname, element, repr, flags)
* SUB_STRUCT(structname, element, flags [, default_label])
* NODE_STRUCT(structname, element, repr, flags [, default_label])
*
* ARRAY(name, flags[, validatorfunc])
* ARRAY(name, flags [, validatorfunc])
* key-declaration
* value-declaration
* END_ARRAY(size)
*
*
* where key-declaration is one of:
*
* KEY_ATOM(type, repr)
@ -122,6 +122,41 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* VALUE_SUB_STRUCT(structname)
* VALUE_NODE_STRUCT(structname, repr)
*
* For defining alternative STRUCT default settings:
*
* STRUCT_DEFAULT(name, default_label)
* default-declaration
* default-declaration
* ...
* END_STRUCT_DEFAULT
*
* where each default-declaration is one of:
*
* ATOM_DEFAULT(element, default)
* STRING_DEFAULT(element, default)
* SUB_STRUCT_DEFAULT(structname, element [, default_label])
*
* Every structure defined by STRUCT has its own, native default values as given by
* the 'default' parameter in each of its element declarations. The STRUCT_DEFAULT
* declaration defines a variation on the default values that can be used to give the
* structure alternative defaults when included as a SUB_STRUCT (or NODE_STRUCT) from
* within another structure. Not all the STRUCT's elements have to be defined within
* a STRUCT_DEFAULT definition; any omitted ones take the STRUCT's native default.
*
* For defining that one STRUCT can be treated as a subset of another:
*
* STRUCT_ASSIGN(substruct, superstruct)
* element-declaration
* element-declaration
* ...
* END_STRUCT_ASSIGN
*
* where element-declaration is exactly as for STRUCT(...) above.
*
* This generates a structure copy function that copies the given elements of 'substruct'
* into the equivalent elements of 'superstruct'; ie, both structures must have the same
* element names and types.
*
* The meanings of the parameters are:
*
* 'name'
@ -184,6 +219,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* 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".
* 'default_label'
* A label used to qualify an alternative STRUCT default set. These labels need only be unique
* for each given struct 'name', so different STRUCTs may re-use the same labels.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
@ -226,20 +264,31 @@ ATOM(bool_t, profiling, 0, boolean,, "")
ATOM(bool_t, externalblobs, 0, boolean,, "")
END_STRUCT
STRUCT(log_format)
ATOM(bool_t, show_pid, 1, boolean,, "If true, all log lines contain PID of logging process")
ATOM(bool_t, show_time, 1, boolean,, "If true, all log lines contain time stamp")
ATOM(int, level, LOG_LEVEL_DEBUG, log_level,, "Only log messages at and above this level of severity")
#define LOG_FORMAT_OPTIONS \
ATOM(bool_t, show_pid, 1, boolean,, "If true, all log lines contain PID of logging process") \
ATOM(bool_t, show_time, 1, boolean,, "If true, all log lines contain time stamp") \
ATOM(int, level, LOG_LEVEL_DEBUG, log_level,, "Only log messages at and above this level of severity") \
ATOM(bool_t, dump_config, 1, boolean,, "If true, current configuration is dumped into start of log")
STRUCT(log_format)
LOG_FORMAT_OPTIONS
END_STRUCT
STRUCT(log_format_file)
STRING(256, directory_path, "log", str_nonempty,, "Path of directory for log files, either absolute or relative to instance directory")
ATOM(unsigned short, rotate, 12, ushort,, "Number of log files to rotate, zero means no deletion")
ATOM(uint32_t, duration, 3600, uint32_time_interval,, "Time duration of each log file, zero means one file per invocation")
LOG_FORMAT_OPTIONS
END_STRUCT
STRUCT_ASSIGN(log_format, log_format_file)
LOG_FORMAT_OPTIONS
END_STRUCT_ASSIGN
STRUCT(log)
STRING(256, file_directory_path, "log", str_nonempty,, "Path of directory for log files, either absolute or relative to instance directory")
ATOM(unsigned short, file_rotate, 12, ushort,, "Number of log files to rotate, zero means no rotation")
ATOM(uint32_t, file_duration, 3600, uint32_time_interval,, "Time duration of each log file")
SUB_STRUCT(log_format, file,, full)
SUB_STRUCT(log_format, stderr,, important)
SUB_STRUCT(log_format, android,, android)
SUB_STRUCT(log_format_file, file,,)
SUB_STRUCT(log_format, stderr,, important)
SUB_STRUCT(log_format, android,, android)
END_STRUCT
STRUCT_DEFAULT(log_format, important)
@ -249,18 +298,8 @@ ATOM_DEFAULT(level, LOG_LEVEL_WARN)
ATOM_DEFAULT(dump_config, 0)
END_STRUCT_DEFAULT
STRUCT_DEFAULT(log_format, full)
ATOM_DEFAULT(show_pid, 1)
ATOM_DEFAULT(show_time, 1)
ATOM_DEFAULT(level, LOG_LEVEL_DEBUG)
ATOM_DEFAULT(dump_config, 1)
END_STRUCT_DEFAULT
STRUCT_DEFAULT(log_format, android)
ATOM_DEFAULT(show_pid, 0)
ATOM_DEFAULT(show_time, 1)
ATOM_DEFAULT(level, LOG_LEVEL_DEBUG)
ATOM_DEFAULT(dump_config, 1)
END_STRUCT_DEFAULT
STRUCT(server)

23
log.c
View File

@ -99,6 +99,7 @@ static void _open_log_file(_log_iterator *);
static void _rotate_log_file(_log_iterator *it);
static void _flush_log_file();
struct _log_state state_file;
struct config_log_format config_file;
time_t _log_file_start_time;
static char _log_file_buf[8192];
static struct strbuf _log_file_strbuf = STRUCT_STRBUF_EMPTY;
@ -140,7 +141,9 @@ static void _log_iterator_rewind(_log_iterator *it)
static void _log_iterator_advance_to_file(_log_iterator *it)
{
it->config = &config.log.file;
cf_dfl_config_log_format(&config_file);
cf_cpy_config_log_format(&config_file, &config.log.file);
it->config = &config_file;
it->state = &state_file;
}
@ -164,7 +167,7 @@ static int _log_iterator_advance(_log_iterator *it)
_log_iterator_advance_to_file(it);
return 1;
}
if (it->config == &config.log.file) {
if (it->config == &config_file) {
#ifdef ANDROID
_log_iterator_advance_to_android(it);
return 1;
@ -179,7 +182,7 @@ static int _log_iterator_advance(_log_iterator *it)
static int _log_enabled(_log_iterator *it)
{
if (it->config == &config.log.file) {
if (it->config == &config_file) {
_open_log_file(it); // puts initial INFO message(s) at head of log file
if (_log_file == NO_FILE)
return 0;
@ -207,7 +210,7 @@ static void _log_prefix_level(_log_iterator *it, int level)
static void _log_prefix(_log_iterator *it, int level)
{
if (it->config == &config.log.file) {
if (it->config == &config_file) {
if (strbuf_is_empty(&_log_file_strbuf))
strbuf_init(&_log_file_strbuf, _log_file_buf, sizeof _log_file_buf);
else if (strbuf_len(&_log_file_strbuf))
@ -294,7 +297,7 @@ static void _log_end_line(_log_iterator *it, int level)
static void _log_flush(_log_iterator *it)
{
if (it->config == &config.log.file) {
if (it->config == &config_file) {
_flush_log_file();
}
else if (it->config == &config.log.stderr) {
@ -421,7 +424,7 @@ static void _logs_printf_nl(int level, struct __sourceloc whence, const char *fm
const char *log_file_directory_path()
{
return config.log.file_directory_path;
return config.log.file.directory_path;
}
static void _compute_file_start_time(_log_iterator *it)
@ -430,8 +433,8 @@ static void _compute_file_start_time(_log_iterator *it)
assert(!cf_limbo);
assert(it->tv.tv_sec != 0);
it->file_start_time = it->tv.tv_sec;
if (config.log.file_duration)
it->file_start_time -= it->file_start_time % config.log.file_duration;
if (config.log.file.duration)
it->file_start_time -= it->file_start_time % config.log.file.duration;
}
}
@ -541,7 +544,7 @@ static void _open_log_file(_log_iterator *it)
}
}
closedir(d);
if (count <= config.log.file_rotate || !oldest.d_name[0])
if (count <= config.log.file.rotate || !oldest.d_name[0])
break;
strbuf b = strbuf_local(path, pathsiz);
strbuf_path_join(b, dir, oldest.d_name, NULL);
@ -562,7 +565,7 @@ static void _rotate_log_file(_log_iterator *it)
{
if (_log_file != NO_FILE && _log_file_path == _log_file_path_buf) {
assert(!cf_limbo);
if (config.log.file_duration) {
if (config.log.file.duration) {
_compute_file_start_time(it);
if (it->file_start_time != _log_file_start_time) {
// Close the current log file, which will cause _open_log_file() to open the next one.