mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 02:39:44 +00:00
Improve new config code, SORTED and NO_DUPLICATE flags
Config Object Model parser now returns bitmask result of CFxxx flags and only allocates root node if the config file is non-empty. Added emalloc_zero().
This commit is contained in:
parent
f42292ffc6
commit
4aac3637ed
73
conf_om.c
73
conf_om.c
@ -46,8 +46,10 @@ static const char *cf_find_keyend(const char *const key, const char *const fullk
|
||||
|
||||
static int cf_om_make_child(struct cf_om_node **const parentp, const char *const fullkey, const char *const key, const char *const keyend)
|
||||
{
|
||||
// Allocate parent node if it is not present.
|
||||
if (!*parentp && (*parentp = emalloc_zero(sizeof **parentp)) == NULL)
|
||||
return -1;
|
||||
size_t keylen = keyend - key;
|
||||
//DEBUGF("%s key=%s", __FUNCTION__, alloca_toprint(-1, key, keylen));
|
||||
int i = 0;
|
||||
struct cf_om_node *child;
|
||||
if ((*parentp)->nodc) {
|
||||
@ -75,10 +77,8 @@ static int cf_om_make_child(struct cf_om_node **const parentp, const char *const
|
||||
// At this point, i is the index where a new child should be inserted.
|
||||
assert(i >= 0);
|
||||
assert(i <= (*parentp)->nodc);
|
||||
child = emalloc(sizeof *child);
|
||||
if (child == NULL)
|
||||
if ((child = emalloc_zero(sizeof *child)) == NULL)
|
||||
return -1;
|
||||
memset(child, 0, sizeof *child);
|
||||
++(*parentp)->nodc;
|
||||
if ((*parentp)->nodc > NELS((*parentp)->nodv))
|
||||
*parentp = realloc(*parentp, sizeof(**parentp) + sizeof((*parentp)->nodv[0]) * ((*parentp)->nodc - NELS((*parentp)->nodv)));
|
||||
@ -105,31 +105,13 @@ int cf_get_child(const struct cf_om_node *parent, const char *key)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cf_free_node(struct cf_om_node *node)
|
||||
int cf_parse_to_om(const char *source, const char *buf, size_t len, struct cf_om_node **rootp)
|
||||
{
|
||||
while (node->nodc)
|
||||
cf_free_node(node->nodv[--node->nodc]);
|
||||
if (node->fullkey) {
|
||||
free((char *)node->fullkey);
|
||||
node->fullkey = node->key = NULL;
|
||||
}
|
||||
if (node->text) {
|
||||
free((char *)node->text);
|
||||
node->text = NULL;
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
|
||||
struct cf_om_node *cf_parse_to_om(const char *source, const char *buf, size_t len)
|
||||
{
|
||||
struct cf_om_node *root = emalloc(sizeof(struct cf_om_node));
|
||||
if (root == NULL)
|
||||
return NULL;
|
||||
memset(root, 0, sizeof *root);
|
||||
const char *end = buf + len;
|
||||
const char *line = buf;
|
||||
const char *nextline;
|
||||
unsigned lineno = 1;
|
||||
int result = CFOK;
|
||||
for (lineno = 1; line < end; line = nextline, ++lineno) {
|
||||
const char *lend = line;
|
||||
while (lend < end && *lend != '\n')
|
||||
@ -148,10 +130,11 @@ struct cf_om_node *cf_parse_to_om(const char *source, const char *buf, size_t le
|
||||
for (p = line; p < lend && *p != '='; ++p)
|
||||
;
|
||||
if (p == line || p == lend) {
|
||||
WARNF("%s:%u: malformed configuration line -- ignored", source, lineno);
|
||||
WARNF("%s:%u: malformed configuration line", source, lineno);
|
||||
result |= CFINVALID;
|
||||
continue;
|
||||
}
|
||||
struct cf_om_node **nodep = &root;
|
||||
struct cf_om_node **nodep = rootp;
|
||||
const char *fullkey = line;
|
||||
const char *fullkeyend = p;
|
||||
const char *key = fullkey;
|
||||
@ -162,31 +145,48 @@ struct cf_om_node *cf_parse_to_om(const char *source, const char *buf, size_t le
|
||||
nodep = &(*nodep)->nodv[nodi];
|
||||
}
|
||||
if (keyend == NULL) {
|
||||
WARNF("%s:%u: malformed configuration option %s -- ignored",
|
||||
WARNF("%s:%u: malformed configuration option %s",
|
||||
source, lineno, alloca_toprint(-1, fullkey, fullkeyend - fullkey)
|
||||
);
|
||||
result |= CFINVALID;
|
||||
continue;
|
||||
}
|
||||
if (nodi == -1)
|
||||
goto error; // out of memory
|
||||
return CFERROR; // out of memory
|
||||
struct cf_om_node *node = *nodep;
|
||||
if (node->text) {
|
||||
WARNF("%s:%u: duplicate configuration option %s -- ignored (original is at %s:%u)",
|
||||
WARNF("%s:%u: duplicate configuration option %s (original is at %s:%u)",
|
||||
source, lineno, alloca_toprint(-1, fullkey, fullkeyend - fullkey),
|
||||
node->source, node->line_number
|
||||
);
|
||||
result |= CFDUPLICATE;
|
||||
continue;
|
||||
}
|
||||
++p;
|
||||
if (!(node->text = strn_edup(p, lend - p)))
|
||||
break; // out of memory
|
||||
return CFERROR; // out of memory
|
||||
node->source = source;
|
||||
node->line_number = lineno;
|
||||
}
|
||||
return root;
|
||||
error:
|
||||
cf_free_node(root);
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
void cf_free_node(struct cf_om_node **nodep)
|
||||
{
|
||||
if (*nodep) {
|
||||
while ((*nodep)->nodc)
|
||||
cf_free_node(&(*nodep)->nodv[--(*nodep)->nodc]);
|
||||
if ((*nodep)->fullkey) {
|
||||
free((char *)(*nodep)->fullkey);
|
||||
(*nodep)->fullkey = (*nodep)->key = NULL;
|
||||
}
|
||||
if ((*nodep)->text) {
|
||||
free((char *)(*nodep)->text);
|
||||
(*nodep)->text = NULL;
|
||||
}
|
||||
free(*nodep);
|
||||
*nodep = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void cf_dump_node(const struct cf_om_node *node, int indent)
|
||||
@ -287,6 +287,7 @@ strbuf strbuf_cf_flags(strbuf sb, int flags)
|
||||
size_t n = strbuf_len(sb);
|
||||
static struct { int flag; const char *name; } flagdefs[] = {
|
||||
{ CFEMPTY, "CFEMPTY" },
|
||||
{ CFDUPLICATE, "CFDUPLICATE" },
|
||||
{ CFSTRINGOVERFLOW, "CFSTRINGOVERFLOW" },
|
||||
{ CFARRAYOVERFLOW, "CFARRAYOVERFLOW" },
|
||||
{ CFINCOMPLETE, "CFINCOMPLETE" },
|
||||
@ -329,12 +330,14 @@ strbuf strbuf_cf_flag_reason(strbuf sb, int flags)
|
||||
size_t n = strbuf_len(sb);
|
||||
static struct { int flag; const char *reason; } flagdefs[] = {
|
||||
{ CFEMPTY, "empty" },
|
||||
{ CFDUPLICATE, "duplicate element" },
|
||||
{ CFSTRINGOVERFLOW, "string overflow" },
|
||||
{ CFARRAYOVERFLOW, "array overflow" },
|
||||
{ CFINCOMPLETE, "incomplete" },
|
||||
{ CFINVALID, "invalid" },
|
||||
{ CFUNSUPPORTED, "not supported" },
|
||||
{ CFSUB(CFEMPTY), "contains empty element" },
|
||||
{ CFSUB(CFDUPLICATE), "contains element with duplicate" },
|
||||
{ CFSUB(CFSTRINGOVERFLOW), "contains string overflow" },
|
||||
{ CFSUB(CFARRAYOVERFLOW), "contains array overflow" },
|
||||
{ CFSUB(CFINCOMPLETE), "contains incomplete element" },
|
||||
@ -373,7 +376,7 @@ void _cf_warn_array_key(struct __sourceloc __whence, const struct cf_om_node *no
|
||||
{
|
||||
strbuf b = strbuf_alloca(180);
|
||||
strbuf_cf_flag_reason(b, reason);
|
||||
_cf_warn_node(__whence, node, NULL, "array label %s -- %s", alloca_str_toprint(node->key), strbuf_str(b));
|
||||
_cf_warn_node(__whence, node, NULL, "array key %s -- %s", alloca_str_toprint(node->key), strbuf_str(b));
|
||||
}
|
||||
|
||||
void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *node, int reason)
|
||||
|
35
conf_parse.c
35
conf_parse.c
@ -37,7 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define END_STRUCT \
|
||||
return CFOK; \
|
||||
}
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_dfl_config_##__name(struct config_##__name *a) { \
|
||||
a->ac = 0; \
|
||||
return CFOK; \
|
||||
@ -76,15 +76,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define SUB_STRUCT(__name, __element, __flags)
|
||||
#define NODE_STRUCT(__name, __element, __parser, __flags)
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
static int __cmp_config_##__name(const struct config_##__name##__element *a, const struct config_##__name##__element *b) { \
|
||||
__compare_func__config_##__name##__t *cmp = (NULL
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
,##__cmpfunc); \
|
||||
return cmp ? (*cmp)(&a->key, &b->key) : 0;
|
||||
return cmp ? (*cmp)(&a->key, &b->key) : memcmp(&a->key, &b->key, sizeof a->key);
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
,##__cmpfunc); \
|
||||
return cmp ? (*cmp)(a->key, b->key) : 0;
|
||||
return cmp ? (*cmp)(a->key, b->key) : strcmp(a->key, b->key);
|
||||
#define VALUE_ATOM(__type, __eltparser)
|
||||
#define VALUE_STRING(__strsize, __eltparser)
|
||||
#define VALUE_NODE(__type, __eltparser)
|
||||
@ -114,11 +114,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define __MANDATORY (1<<0)
|
||||
#define __TEXT (1<<1)
|
||||
#define __CHILDREN (1<<2)
|
||||
#define __SORTED (1<<3)
|
||||
#define __NO_DUPLICATES (1<<4)
|
||||
|
||||
// Schema flag symbols, to be used in the '__flags' macro arguments.
|
||||
#define MANDATORY |__MANDATORY
|
||||
#define USES_TEXT |__TEXT
|
||||
#define USES_CHILDREN |__CHILDREN
|
||||
#define SORTED |__SORTED
|
||||
#define NO_DUPLICATES |__NO_DUPLICATES
|
||||
|
||||
// Generate parsing functions, cf_opt_config_SECTION()
|
||||
#define STRUCT(__name, __validator...) \
|
||||
@ -182,9 +186,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
|
||||
__compare_func__config_##__name##__t *cmp = NULL; \
|
||||
int flags = (0 __flags); \
|
||||
int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \
|
||||
int (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \
|
||||
int result = CFOK; \
|
||||
@ -192,13 +196,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
for (n = 0, i = 0; i < node->nodc && n < NELS(array->av); ++i) { \
|
||||
const struct cf_om_node *child = node->nodv[i]; \
|
||||
int ret = CFEMPTY;
|
||||
#define __ARRAY_KEY(__parseexpr) \
|
||||
#define __ARRAY_KEY(__parseexpr, __cmpfunc...) \
|
||||
ret = (__parseexpr); \
|
||||
if (ret == CFERROR) \
|
||||
return CFERROR; \
|
||||
result |= ret & CF__SUBFLAGS; \
|
||||
ret &= CF__FLAGS; \
|
||||
result |= CFSUB(ret); \
|
||||
if (ret == CFOK && (flags & __NO_DUPLICATES)) { \
|
||||
int j; \
|
||||
for (j = 0; j < n; ++j) { \
|
||||
if ((*eltcmp)(&array->av[j], &array->av[n]) == 0) { \
|
||||
cf_warn_duplicate_node(child, NULL); \
|
||||
ret |= CFDUPLICATE; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (ret != CFOK) \
|
||||
cf_warn_array_key(child, ret);
|
||||
#define __ARRAY_VALUE(__parseexpr) \
|
||||
@ -223,7 +236,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
cf_warn_list_overflow(node->nodv[i]); \
|
||||
} \
|
||||
array->ac = n; \
|
||||
if (cmp) \
|
||||
if (flags & __SORTED) \
|
||||
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) eltcmp); \
|
||||
if (validator) \
|
||||
result = (*validator)(node, array, result); \
|
||||
@ -236,11 +249,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
return result; \
|
||||
}
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
__ARRAY_KEY(__eltparser(&array->av[n].key, child->key)) \
|
||||
cmp = (NULL, ##__cmpfunc);
|
||||
__ARRAY_KEY(__eltparser(&array->av[n].key, child->key), ##__cmpfunc)
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \
|
||||
__ARRAY_KEY(__eltparser(array->av[n].key, sizeof array->av[n].key, child->key)) \
|
||||
cmp = (NULL, ##__cmpfunc);
|
||||
__ARRAY_KEY(__eltparser(array->av[n].key, sizeof array->av[n].key, child->key), ##__cmpfunc)
|
||||
#define VALUE_ATOM(__type, __eltparser) \
|
||||
__ARRAY_VALUE(child->text ? __eltparser(&array->av[n].value, child->text) : CFEMPTY)
|
||||
#define VALUE_STRING(__strsize, __eltparser) \
|
||||
|
@ -246,7 +246,7 @@ int vld_argv(const struct cf_om_node *parent, struct config_argv *array, int res
|
||||
char labelkey[12];
|
||||
sprintf(labelkey, "%u", last_key);
|
||||
cf_warn_duplicate_node(parent, labelkey);
|
||||
result |= CFINVALID;
|
||||
result |= CFDUPLICATE;
|
||||
}
|
||||
while (++last_key < key && last_key <= sizeof(array->av)) {
|
||||
char labelkey[12];
|
||||
|
@ -50,7 +50,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* STRING(80, element2, "boo!", cf_opt_str_nonempty, MANDATORY, "A non-empty string")
|
||||
* END_STRUCT
|
||||
*
|
||||
* ARRAY(joy)
|
||||
* ARRAY(joy,)
|
||||
* KEY_STRING(3, happy, cf_opt_str)
|
||||
* VALUE_SUB_STRUCT(happy)
|
||||
* END_ARRAY(16)
|
||||
@ -104,7 +104,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* SUB_STRUCT(structname, element, flags)
|
||||
* NODE_STRUCT(structname, element, parsefunc, flags)
|
||||
*
|
||||
* ARRAY(name[, validatorfunc])
|
||||
* ARRAY(name, flags[, validatorfunc])
|
||||
* key-declaration
|
||||
* value-declaration
|
||||
* END_ARRAY(size)
|
||||
@ -199,7 +199,7 @@ STRUCT(mdp_iftype)
|
||||
ATOM(uint32_t, tick_ms, 0, cf_opt_uint32_nonzero,, "Tick interval for this interface type")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(mdp_iftypelist)
|
||||
ARRAY(mdp_iftypelist, NO_DUPLICATES)
|
||||
KEY_ATOM(short, cf_opt_interface_type, cmp_short)
|
||||
VALUE_SUB_STRUCT(mdp_iftype)
|
||||
END_ARRAY(5)
|
||||
@ -216,7 +216,7 @@ ATOM(uint16_t, remote_port,4130, cf_opt_port,, "Remote port number"
|
||||
ATOM(uint16_t, local_port, 4131, cf_opt_port,, "Local port number")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(argv, vld_argv)
|
||||
ARRAY(argv, SORTED NO_DUPLICATES, vld_argv)
|
||||
KEY_ATOM(unsigned short, cf_opt_ushort_nonzero, cmp_ushort)
|
||||
VALUE_STRING(128, cf_opt_str)
|
||||
END_ARRAY(16)
|
||||
@ -236,7 +236,7 @@ STRING(256, host, "", cf_opt_str_nonempty, MANDATORY, "Hos
|
||||
ATOM(uint16_t, port, RHIZOME_HTTP_PORT, cf_opt_port,, "Port number")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(peerlist)
|
||||
ARRAY(peerlist,)
|
||||
KEY_STRING(15, cf_opt_str)
|
||||
VALUE_NODE(struct config_rhizomepeer, cf_opt_rhizome_peer)
|
||||
END_ARRAY(10)
|
||||
@ -276,7 +276,7 @@ ATOM(struct in_addr, address, (struct in_addr){htonl(INADDR_NONE)}, cf
|
||||
ATOM(uint16_t, port, PORT_DNA, cf_opt_port,, "Port number")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(host_list)
|
||||
ARRAY(host_list, NO_DUPLICATES)
|
||||
KEY_ATOM(sid_t, cf_opt_sid, cmp_sid)
|
||||
VALUE_SUB_STRUCT(host)
|
||||
END_ARRAY(32)
|
||||
@ -290,7 +290,7 @@ ATOM(uint64_t, speed, 1000000, cf_opt_uint64_scaled,, "Speed i
|
||||
ATOM(uint32_t, mdp_tick_ms, 0, cf_opt_uint32_nonzero,, "Override MDP tick interval for this interface")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(interface_list)
|
||||
ARRAY(interface_list,)
|
||||
KEY_STRING(15, cf_opt_str)
|
||||
VALUE_SUB_STRUCT(network_interface)
|
||||
END_ARRAY(10)
|
||||
@ -306,5 +306,6 @@ SUB_STRUCT(dna, dna,)
|
||||
NODE(debugflags_t, debug, 0, cf_opt_debugflags, USES_CHILDREN, "Debug flags")
|
||||
SUB_STRUCT(rhizome, rhizome,)
|
||||
SUB_STRUCT(directory, directory,)
|
||||
SUB_STRUCT(olsr, olsr,)
|
||||
SUB_STRUCT(host_list, hosts,)
|
||||
END_STRUCT
|
||||
|
68
config.h
68
config.h
@ -98,7 +98,7 @@ 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.
|
||||
*
|
||||
* If a STRUCT(NAME, VALIDATOR) or ARRAY(NAME, VALIDATOR) schema declaration is given a
|
||||
* 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:
|
||||
*
|
||||
* - int VALIDATOR(struct config_NAME *dest, int orig_result);
|
||||
@ -140,12 +140,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* contains elements that are not defined in the STRUCT. This may indicate a typo in the name
|
||||
* of a config option, resulting in the intended option not being set.
|
||||
*
|
||||
* - CFDUPLICATE if a duplicate array entry was found. The result may be an empty array (in which
|
||||
* case CFEMPTY is also set), or an array that omits the duplicate element. It is not defined
|
||||
* which of the two conflicting elements will get omitted. Normal array parsing without a
|
||||
* validator function will return an empty array in the case of duplicate, but a validator
|
||||
* function may change this behaviour.
|
||||
*
|
||||
* - CFARRAYOVERFLOW if the size of any array was exceeded. The result in *dest may be empty (in
|
||||
* which case CFEMPTY is also set), or may contain elements parsed successfully from the COM (ie,
|
||||
* returned CFOK), omitting any that did not parse successfully (in which case other bits will be
|
||||
* set) and arbitrarily omitting others that did not fit (it is not defined which will be
|
||||
* omitted). Normal array parsing without a validator function will return an empty result in
|
||||
* the case of overflow, but a validator function may change this behaviour.
|
||||
* returned CFOK), omitting any that did not parse successfully (in which case the relevant
|
||||
* CFSUB() bits will be set) and arbitrarily omitting others that did not fit. It is not defined
|
||||
* which elements get omitted from an overflowed array. Normal array parsing without a validator
|
||||
* function will return an empty array in the case of overflow, but a validator function may
|
||||
* change this behaviour.
|
||||
*
|
||||
* - CFSTRINGFOVERFLOW if the size of any string element was exceeded. The result in *dest may be
|
||||
* unchanged or may contain a truncated string, depending on the parser that detected and
|
||||
@ -206,6 +213,25 @@ struct pattern_list {
|
||||
};
|
||||
#define PATTERN_LIST_EMPTY ((struct pattern_list){.patc = 0})
|
||||
|
||||
/* Return bit flags for config schema default cf_dfl_xxx() and parsing cf_opt_xxx() functions. */
|
||||
|
||||
#define CFERROR (~0) // all set
|
||||
#define CFOK 0
|
||||
#define CFEMPTY (1<<0)
|
||||
#define CFDUPLICATE (1<<1)
|
||||
#define CFARRAYOVERFLOW (1<<2)
|
||||
#define CFSTRINGOVERFLOW (1<<3)
|
||||
#define CFINCOMPLETE (1<<4)
|
||||
#define CFINVALID (1<<5)
|
||||
#define CFUNSUPPORTED (1<<6)
|
||||
#define CF__SUB_SHIFT 16
|
||||
#define CFSUB(f) ((f) << CF__SUB_SHIFT)
|
||||
#define CF__SUBFLAGS CFSUB(~0)
|
||||
#define CF__FLAGS (~0 & ~CF__SUBFLAGS)
|
||||
|
||||
strbuf strbuf_cf_flags(strbuf, int);
|
||||
strbuf strbuf_cf_flag_reason(strbuf sb, int flags);
|
||||
|
||||
/* The Configuration Object Model (COM). The config file is parsed into a tree of these structures
|
||||
* first, then those structures are passed as arguments to the schema parsing functions.
|
||||
*/
|
||||
@ -220,29 +246,11 @@ struct cf_om_node {
|
||||
struct cf_om_node *nodv[10]; // malloc()
|
||||
};
|
||||
|
||||
struct cf_om_node *cf_parse_to_om(const char *source, const char *buf, size_t len);
|
||||
int cf_parse_to_om(const char *source, const char *buf, size_t len, struct cf_om_node **rootp);
|
||||
int cf_get_child(const struct cf_om_node *parent, const char *key);
|
||||
void cf_free_node(struct cf_om_node *node);
|
||||
void cf_free_node(struct cf_om_node **nodep);
|
||||
void cf_dump_node(const struct cf_om_node *node, int indent);
|
||||
|
||||
/* Return bit flags for config schema default cf_dfl_xxx() and parsing cf_opt_xxx() functions. */
|
||||
|
||||
#define CFERROR (~0) // all set
|
||||
#define CFOK 0
|
||||
#define CFEMPTY (1<<0)
|
||||
#define CFARRAYOVERFLOW (1<<1)
|
||||
#define CFSTRINGOVERFLOW (1<<2)
|
||||
#define CFINCOMPLETE (1<<3)
|
||||
#define CFINVALID (1<<4)
|
||||
#define CFUNSUPPORTED (1<<5)
|
||||
#define CF__SUB_SHIFT 16
|
||||
#define CFSUB(f) ((f) << CF__SUB_SHIFT)
|
||||
#define CF__SUBFLAGS CFSUB(~0)
|
||||
#define CF__FLAGS (~0 & ~CF__SUBFLAGS)
|
||||
|
||||
strbuf strbuf_cf_flags(strbuf, int);
|
||||
strbuf strbuf_cf_flag_reason(strbuf sb, int flags);
|
||||
|
||||
/* Diagnostic functions for use in config schema parsing functions, cf_opt_xxx(). */
|
||||
|
||||
void _cf_warn_nodev(struct __sourceloc __whence, const struct cf_om_node *node, const char *key, const char *fmt, va_list ap);
|
||||
@ -290,7 +298,7 @@ void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *
|
||||
struct config_##__name __element;
|
||||
#define END_STRUCT \
|
||||
};
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
struct config_##__name { \
|
||||
unsigned ac; \
|
||||
struct config_##__name##__element {
|
||||
@ -338,7 +346,7 @@ void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *
|
||||
#define SUB_STRUCT(__name, __element, __flags)
|
||||
#define NODE_STRUCT(__name, __element, __parser, __flags)
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_dfl_config_##__name(struct config_##__name *a);
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...)
|
||||
#define KEY_STRING(__strsize, __eltparser, __cmpfunc...)
|
||||
@ -384,7 +392,7 @@ void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *
|
||||
#define NODE_STRUCT(__name, __element, __parser, __flags) \
|
||||
int __parser(struct config_##__name *, const struct cf_om_node *);
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
|
||||
__VALIDATOR(__name, ##__validator)
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
@ -429,7 +437,7 @@ void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *
|
||||
#define SUB_STRUCT(__name, __element, __flags)
|
||||
#define NODE_STRUCT(__name, __element, __parser, __flags)
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
typedef int __compare_func__config_##__name##__t
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
(const __type *, const __type *);
|
||||
@ -445,7 +453,7 @@ void _cf_warn_array_value(struct __sourceloc __whence, const struct cf_om_node *
|
||||
#undef ARRAY
|
||||
#undef KEY_ATOM
|
||||
#undef KEY_STRING
|
||||
#define ARRAY(__name, __validator...) \
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
__compare_func__config_##__name##__t __dummy__compare_func__config_##__name
|
||||
#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \
|
||||
,##__cmpfunc;
|
||||
|
@ -29,14 +29,16 @@ int main(int argc, char **argv)
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
||||
struct cf_om_node *root = cf_parse_to_om(argv[i], buf, st.st_size);
|
||||
struct cf_om_node *root = NULL;
|
||||
int ret = cf_parse_to_om(argv[i], buf, st.st_size, &root);
|
||||
close(fd);
|
||||
DEBUGF("ret = %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(128), ret)));
|
||||
//cf_dump_node(root, 0);
|
||||
struct config_main config;
|
||||
memset(&config, 0, sizeof config);
|
||||
cf_dfl_config_main(&config);
|
||||
int result = cf_opt_config_main(&config, root);
|
||||
cf_free_node(root);
|
||||
int result = root ? cf_opt_config_main(&config, root) : CFEMPTY;
|
||||
cf_free_node(&root);
|
||||
free(buf);
|
||||
DEBUGF("result = %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(128), result)));
|
||||
DEBUGF("config.log.file = %s", alloca_str_toprint(config.log.file));
|
||||
|
14
mem.c
14
mem.c
@ -20,16 +20,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include <string.h>
|
||||
#include "mem.h"
|
||||
|
||||
void *_emalloc(struct __sourceloc __whence, size_t len)
|
||||
void *_emalloc(struct __sourceloc __whence, size_t bytes)
|
||||
{
|
||||
char *new = malloc(len + 1);
|
||||
char *new = malloc(bytes);
|
||||
if (!new) {
|
||||
WHYF_perror("malloc(%lu)", (long)len);
|
||||
WHYF_perror("malloc(%lu)", (long)bytes);
|
||||
return NULL;
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
void *_emalloc_zero(struct __sourceloc __whence, size_t bytes)
|
||||
{
|
||||
char *new = _emalloc(__whence, bytes);
|
||||
if (new)
|
||||
memset(new, 0, bytes);
|
||||
return new;
|
||||
}
|
||||
|
||||
char *_strn_edup(struct __sourceloc __whence, const char *str, size_t len)
|
||||
{
|
||||
char *new = _emalloc(__whence, len + 1);
|
||||
|
8
mem.h
8
mem.h
@ -29,6 +29,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
void *_emalloc(struct __sourceloc, size_t bytes);
|
||||
|
||||
/* Equivalent to malloc(3) followed by memset(3) to zerofill, but logs an error
|
||||
* before returning NULL.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
void *_emalloc_zero(struct __sourceloc, size_t bytes);
|
||||
|
||||
/* Equivalent to strdup(3)/strndup(3), but logs an error before returning NULL.
|
||||
*
|
||||
* Why aren't these in str.h? Because str.c must not depend on log.h/log.c! str.c is used in link
|
||||
@ -40,6 +47,7 @@ char *_str_edup(struct __sourceloc, const char *str);
|
||||
char *_strn_edup(struct __sourceloc, const char *str, size_t len);
|
||||
|
||||
#define emalloc(bytes) _emalloc(__HERE__, (bytes))
|
||||
#define emalloc_zero(bytes) _emalloc_zero(__HERE__, (bytes))
|
||||
#define str_edup(str) _str_edup(__HERE__, (str))
|
||||
#define strn_edup(str, len) _strn_edup(__HERE__, (str), (len))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user