2012-11-29 05:37:34 +00:00
|
|
|
/*
|
|
|
|
Serval DNA configuration
|
|
|
|
Copyright (C) 2012 Serval Project Inc.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
2012-11-29 06:14:06 +00:00
|
|
|
#include "log.h"
|
2012-12-04 03:42:28 +00:00
|
|
|
#include "conf.h"
|
2012-11-29 05:37:34 +00:00
|
|
|
|
|
|
|
// Generate config set-default function definitions, cf_dfl_config_NAME().
|
|
|
|
#define STRUCT(__name, __validator...) \
|
|
|
|
int cf_dfl_config_##__name(struct config_##__name *s) {
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
|
2012-11-29 05:37:34 +00:00
|
|
|
s->__element = (__default);
|
2013-02-25 06:53:44 +00:00
|
|
|
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
|
2012-11-29 05:37:34 +00:00
|
|
|
s->__element = (__default);
|
2013-02-25 06:53:44 +00:00
|
|
|
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
|
2012-11-29 05:37:34 +00:00
|
|
|
strncpy(s->__element, (__default), (__size))[(__size)] = '\0';
|
|
|
|
#define SUB_STRUCT(__name, __element, __flags) \
|
|
|
|
cf_dfl_config_##__name(&s->__element);
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE_STRUCT(__name, __element, __repr, __flags) \
|
2012-11-29 05:37:34 +00:00
|
|
|
cf_dfl_config_##__name(&s->__element);
|
|
|
|
#define END_STRUCT \
|
|
|
|
return CFOK; \
|
|
|
|
}
|
2012-11-30 02:02:30 +00:00
|
|
|
#define ARRAY(__name, __flags, __validator...) \
|
2012-11-29 05:37:34 +00:00
|
|
|
int cf_dfl_config_##__name(struct config_##__name *a) { \
|
|
|
|
a->ac = 0; \
|
|
|
|
return CFOK; \
|
|
|
|
}
|
2013-02-25 06:53:44 +00:00
|
|
|
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...)
|
|
|
|
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...)
|
|
|
|
#define VALUE_ATOM(__type, __eltrepr)
|
|
|
|
#define VALUE_STRING(__strsize, __eltrepr)
|
|
|
|
#define VALUE_NODE(__type, __eltrepr)
|
2012-11-29 05:37:34 +00:00
|
|
|
#define VALUE_SUB_STRUCT(__structname)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
|
2012-11-29 05:37:34 +00:00
|
|
|
#define END_ARRAY(__size)
|
2012-11-29 05:42:03 +00:00
|
|
|
#include "conf_schema.h"
|
2012-11-29 05:37:34 +00:00
|
|
|
#undef STRUCT
|
|
|
|
#undef NODE
|
|
|
|
#undef ATOM
|
|
|
|
#undef STRING
|
|
|
|
#undef SUB_STRUCT
|
|
|
|
#undef NODE_STRUCT
|
|
|
|
#undef END_STRUCT
|
|
|
|
#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 array element comparison functions.
|
|
|
|
#define STRUCT(__name, __validator...)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE(__type, __element, __default, __repr, __flags, __comment)
|
|
|
|
#define ATOM(__type, __element, __default, __repr, __flags, __comment)
|
|
|
|
#define STRING(__size, __element, __default, __repr, __flags, __comment)
|
2012-11-29 05:37:34 +00:00
|
|
|
#define SUB_STRUCT(__name, __element, __flags)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE_STRUCT(__name, __element, __repr, __flags)
|
2012-11-29 05:37:34 +00:00
|
|
|
#define END_STRUCT
|
2012-11-30 02:02:30 +00:00
|
|
|
#define ARRAY(__name, __flags, __validator...) \
|
2012-11-29 05:37:34 +00:00
|
|
|
static int __cmp_config_##__name(const struct config_##__name##__element *a, const struct config_##__name##__element *b) { \
|
|
|
|
__compare_func__config_##__name##__t *cmp = (NULL
|
2013-02-25 06:53:44 +00:00
|
|
|
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
2012-11-29 05:37:34 +00:00
|
|
|
,##__cmpfunc); \
|
2012-11-30 02:02:30 +00:00
|
|
|
return cmp ? (*cmp)(&a->key, &b->key) : memcmp(&a->key, &b->key, sizeof a->key);
|
2013-02-25 06:53:44 +00:00
|
|
|
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
2012-11-29 05:37:34 +00:00
|
|
|
,##__cmpfunc); \
|
2012-11-30 02:02:30 +00:00
|
|
|
return cmp ? (*cmp)(a->key, b->key) : strcmp(a->key, b->key);
|
2013-02-25 06:53:44 +00:00
|
|
|
#define VALUE_ATOM(__type, __eltrepr)
|
|
|
|
#define VALUE_STRING(__strsize, __eltrepr)
|
|
|
|
#define VALUE_NODE(__type, __eltrepr)
|
2012-11-29 05:37:34 +00:00
|
|
|
#define VALUE_SUB_STRUCT(__structname)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
|
2012-11-29 05:37:34 +00:00
|
|
|
#define END_ARRAY(__size) \
|
|
|
|
}
|
2012-11-29 05:42:03 +00:00
|
|
|
#include "conf_schema.h"
|
2012-11-29 05:37:34 +00:00
|
|
|
#undef STRUCT
|
|
|
|
#undef NODE
|
|
|
|
#undef ATOM
|
|
|
|
#undef STRING
|
|
|
|
#undef SUB_STRUCT
|
|
|
|
#undef NODE_STRUCT
|
|
|
|
#undef END_STRUCT
|
|
|
|
#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
|
|
|
|
|
|
|
|
// Schema item flags.
|
|
|
|
#define __MANDATORY (1<<0)
|
|
|
|
#define __TEXT (1<<1)
|
|
|
|
#define __CHILDREN (1<<2)
|
2012-11-30 02:02:30 +00:00
|
|
|
#define __SORTED (1<<3)
|
|
|
|
#define __NO_DUPLICATES (1<<4)
|
2012-11-29 05:37:34 +00:00
|
|
|
|
|
|
|
// Schema flag symbols, to be used in the '__flags' macro arguments.
|
|
|
|
#define MANDATORY |__MANDATORY
|
|
|
|
#define USES_TEXT |__TEXT
|
|
|
|
#define USES_CHILDREN |__CHILDREN
|
2012-11-30 02:02:30 +00:00
|
|
|
#define SORTED |__SORTED
|
|
|
|
#define NO_DUPLICATES |__NO_DUPLICATES
|
2012-11-29 05:37:34 +00:00
|
|
|
|
|
|
|
// Generate parsing functions, cf_opt_config_SECTION()
|
|
|
|
#define STRUCT(__name, __validator...) \
|
|
|
|
int cf_opt_config_##__name(struct config_##__name *strct, const struct cf_om_node *node) { \
|
|
|
|
int (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \
|
|
|
|
int result = CFEMPTY; \
|
|
|
|
char used[node->nodc]; \
|
|
|
|
memset(used, 0, node->nodc * sizeof used[0]);
|
|
|
|
#define __ITEM(__element, __flags, __parseexpr) \
|
|
|
|
{ \
|
2012-12-04 03:42:28 +00:00
|
|
|
int i = cf_om_get_child(node, #__element, NULL); \
|
2012-11-29 05:37:34 +00:00
|
|
|
const struct cf_om_node *child = (i != -1) ? node->nodv[i] : NULL; \
|
|
|
|
int ret = CFEMPTY; \
|
|
|
|
if (child) { \
|
|
|
|
used[i] |= (__flags); \
|
|
|
|
ret = (__parseexpr); \
|
|
|
|
if (ret == CFERROR) \
|
|
|
|
return CFERROR; \
|
|
|
|
} \
|
|
|
|
result |= ret & CF__SUBFLAGS; \
|
|
|
|
ret &= CF__FLAGS; \
|
|
|
|
if (!(ret & CFEMPTY)) \
|
|
|
|
result &= ~CFEMPTY; \
|
|
|
|
else if ((__flags) & __MANDATORY) { \
|
|
|
|
cf_warn_missing_node(node, #__element); \
|
|
|
|
result |= CFINCOMPLETE; \
|
|
|
|
} \
|
|
|
|
if (ret & ~CFEMPTY) { \
|
|
|
|
assert(child != NULL); \
|
|
|
|
if (child->text) \
|
|
|
|
cf_warn_node_value(child, ret); \
|
|
|
|
result |= CFSUB(ret); \
|
|
|
|
} \
|
|
|
|
}
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
|
|
|
|
__ITEM(__element, 0 __flags, cf_opt_##__repr(&strct->__element, child))
|
|
|
|
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
|
|
|
|
__ITEM(__element, ((0 __flags)|__TEXT)&~__CHILDREN, child->text ? cf_opt_##__repr(&strct->__element, child->text) : CFEMPTY)
|
|
|
|
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
|
|
|
|
__ITEM(__element, ((0 __flags)|__TEXT)&~__CHILDREN, child->text ? cf_opt_##__repr(strct->__element, (__size) + 1, child->text) : CFEMPTY)
|
2012-11-29 05:37:34 +00:00
|
|
|
#define SUB_STRUCT(__name, __element, __flags) \
|
|
|
|
__ITEM(__element, (0 __flags)|__CHILDREN, cf_opt_config_##__name(&strct->__element, child))
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE_STRUCT(__name, __element, __repr, __flags) \
|
|
|
|
__ITEM(__element, (0 __flags)|__TEXT|__CHILDREN, cf_opt_##__repr(&strct->__element, child))
|
2012-11-29 05:37:34 +00:00
|
|
|
#define END_STRUCT \
|
|
|
|
{ \
|
|
|
|
int i; \
|
|
|
|
for (i = 0; i < node->nodc; ++i) { \
|
|
|
|
if (node->nodv[i]->text && !(used[i] & __TEXT)) { \
|
|
|
|
cf_warn_unsupported_node(node->nodv[i]); \
|
|
|
|
result |= CFSUB(CFUNSUPPORTED); \
|
|
|
|
} \
|
|
|
|
if (node->nodv[i]->nodc && !(used[i] & __CHILDREN)) { \
|
|
|
|
cf_warn_unsupported_children(node->nodv[i]); \
|
|
|
|
result |= CFSUB(CFUNSUPPORTED); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
if (validator) \
|
|
|
|
result = (*validator)(node, strct, result); \
|
|
|
|
return result; \
|
|
|
|
}
|
2012-11-30 02:02:30 +00:00
|
|
|
#define ARRAY(__name, __flags, __validator...) \
|
2012-11-29 05:37:34 +00:00
|
|
|
int cf_opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
|
2012-11-30 02:02:30 +00:00
|
|
|
int flags = (0 __flags); \
|
2012-11-29 05:37:34 +00:00
|
|
|
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; \
|
|
|
|
int i, n; \
|
|
|
|
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;
|
2012-11-30 02:02:30 +00:00
|
|
|
#define __ARRAY_KEY(__parseexpr, __cmpfunc...) \
|
2012-11-29 05:37:34 +00:00
|
|
|
ret = (__parseexpr); \
|
|
|
|
if (ret == CFERROR) \
|
|
|
|
return CFERROR; \
|
|
|
|
result |= ret & CF__SUBFLAGS; \
|
|
|
|
ret &= CF__FLAGS; \
|
|
|
|
result |= CFSUB(ret); \
|
2012-11-30 02:02:30 +00:00
|
|
|
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; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
2012-11-29 05:37:34 +00:00
|
|
|
if (ret != CFOK) \
|
|
|
|
cf_warn_array_key(child, ret);
|
2012-12-10 03:33:46 +00:00
|
|
|
#define __ARRAY_VALUE(__dflexpr, __parseexpr) \
|
2012-11-29 05:37:34 +00:00
|
|
|
if (ret == CFOK) { \
|
2012-12-10 03:33:46 +00:00
|
|
|
ret = (__dflexpr); \
|
|
|
|
if (ret == CFOK) \
|
|
|
|
ret = (__parseexpr); \
|
2012-11-29 05:37:34 +00:00
|
|
|
if (ret == CFERROR) \
|
|
|
|
return CFERROR; \
|
|
|
|
result |= ret & CF__SUBFLAGS; \
|
|
|
|
ret &= CF__FLAGS; \
|
|
|
|
result |= CFSUB(ret); \
|
|
|
|
if (ret == CFOK) \
|
|
|
|
++n; \
|
|
|
|
else \
|
|
|
|
cf_warn_array_value(child, ret); \
|
|
|
|
}
|
|
|
|
#define END_ARRAY(__size) \
|
|
|
|
} \
|
|
|
|
if (i < node->nodc) { \
|
|
|
|
assert(n == NELS(array->av)); \
|
|
|
|
result |= CFARRAYOVERFLOW; \
|
|
|
|
for (; i < node->nodc; ++i) \
|
|
|
|
cf_warn_list_overflow(node->nodv[i]); \
|
|
|
|
} \
|
|
|
|
array->ac = n; \
|
2012-11-30 02:02:30 +00:00
|
|
|
if (flags & __SORTED) \
|
2012-11-29 05:37:34 +00:00
|
|
|
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) eltcmp); \
|
|
|
|
if (validator) \
|
|
|
|
result = (*validator)(node, array, result); \
|
|
|
|
if (result & ~CFEMPTY) { \
|
|
|
|
cf_warn_no_array(node, result); \
|
|
|
|
array->ac = 0; \
|
|
|
|
} \
|
|
|
|
if (array->ac == 0) \
|
|
|
|
result |= CFEMPTY; \
|
|
|
|
return result; \
|
|
|
|
}
|
2013-02-25 06:53:44 +00:00
|
|
|
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
|
|
|
__ARRAY_KEY(cf_opt_##__keyrepr(&array->av[n].key, child->key), ##__cmpfunc)
|
|
|
|
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
|
|
|
__ARRAY_KEY(cf_opt_##__keyrepr(array->av[n].key, sizeof array->av[n].key, child->key), ##__cmpfunc)
|
|
|
|
#define VALUE_ATOM(__type, __eltrepr) \
|
|
|
|
__ARRAY_VALUE(CFOK, child->text ? cf_opt_##__eltrepr(&array->av[n].value, child->text) : CFEMPTY)
|
|
|
|
#define VALUE_STRING(__strsize, __eltrepr) \
|
|
|
|
__ARRAY_VALUE(CFOK, child->text ? cf_opt_##__eltrepr(array->av[n].value, sizeof array->av[n].value, child->text) : CFEMPTY)
|
|
|
|
#define VALUE_NODE(__type, __eltrepr) \
|
|
|
|
__ARRAY_VALUE(CFOK, cf_opt_##__eltrepr(&array->av[n].value, child))
|
2012-11-29 05:37:34 +00:00
|
|
|
#define VALUE_SUB_STRUCT(__structname) \
|
2012-12-10 03:33:46 +00:00
|
|
|
__ARRAY_VALUE(cf_dfl_config_##__structname(&array->av[n].value), cf_opt_config_##__structname(&array->av[n].value, child))
|
2013-02-25 06:53:44 +00:00
|
|
|
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
|
|
|
|
__ARRAY_VALUE(cf_dfl_config_##__structname(&array->av[n].value), cf_opt_##__eltrepr(&array->av[n].value, child))
|
2012-11-29 05:42:03 +00:00
|
|
|
#include "conf_schema.h"
|
2012-12-04 03:42:28 +00:00
|
|
|
#undef STRUCT
|
|
|
|
#undef NODE
|
|
|
|
#undef ATOM
|
|
|
|
#undef STRING
|
|
|
|
#undef SUB_STRUCT
|
|
|
|
#undef NODE_STRUCT
|
|
|
|
#undef END_STRUCT
|
|
|
|
#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
|
2012-11-29 05:37:34 +00:00
|
|
|
|
2012-12-04 03:42:28 +00:00
|
|
|
// Generate config array search-by-key functions.
|
|
|
|
#define STRUCT(__name, __validator...)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE(__type, __element, __default, __repr, __flags, __comment)
|
|
|
|
#define ATOM(__type, __element, __default, __repr, __flags, __comment)
|
|
|
|
#define STRING(__size, __element, __default, __repr, __flags, __comment)
|
2012-12-04 03:42:28 +00:00
|
|
|
#define SUB_STRUCT(__name, __element, __flags)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE_STRUCT(__name, __element, __repr, __flags)
|
2012-12-04 03:42:28 +00:00
|
|
|
#define END_STRUCT
|
|
|
|
#define ARRAY(__name, __flags, __validator...) \
|
|
|
|
int config_##__name##__get(const struct config_##__name *array,
|
2013-02-25 06:53:44 +00:00
|
|
|
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
2012-12-04 03:42:28 +00:00
|
|
|
const __type *key) { \
|
|
|
|
int (*cmp)(const __type *, const __type *) = (NULL, ##__cmpfunc); \
|
|
|
|
int i; \
|
|
|
|
for (i = 0; i < array->ac; ++i) \
|
|
|
|
if ((cmp ? (*cmp)(key, &array->av[i].key) : memcmp(key, &array->av[i].key, sizeof *key)) == 0) \
|
|
|
|
return i; \
|
|
|
|
return -1; \
|
|
|
|
}
|
2013-02-25 06:53:44 +00:00
|
|
|
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
2012-12-04 03:42:28 +00:00
|
|
|
const char *key) { \
|
|
|
|
int (*cmp)(const char *, const char *) = (NULL, ##__cmpfunc); \
|
|
|
|
int i; \
|
|
|
|
for (i = 0; i < array->ac; ++i) \
|
|
|
|
if ((cmp ? (*cmp)(key, array->av[i].key) : strcmp(key, array->av[i].key)) == 0) \
|
|
|
|
return i; \
|
|
|
|
return -1; \
|
|
|
|
}
|
2013-02-25 06:53:44 +00:00
|
|
|
#define VALUE_ATOM(__type, __eltrepr)
|
|
|
|
#define VALUE_STRING(__strsize, __eltrepr)
|
|
|
|
#define VALUE_NODE(__type, __eltrepr)
|
2012-12-04 03:42:28 +00:00
|
|
|
#define VALUE_SUB_STRUCT(__structname)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
|
2012-12-04 03:42:28 +00:00
|
|
|
#define END_ARRAY(__size)
|
|
|
|
#include "conf_schema.h"
|
2012-11-29 05:37:34 +00:00
|
|
|
#undef STRUCT
|
|
|
|
#undef NODE
|
|
|
|
#undef ATOM
|
|
|
|
#undef STRING
|
|
|
|
#undef SUB_STRUCT
|
|
|
|
#undef NODE_STRUCT
|
|
|
|
#undef END_STRUCT
|
|
|
|
#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
|
2012-12-04 03:42:28 +00:00
|
|
|
|
2012-12-06 07:24:30 +00:00
|
|
|
// Generate config schema dump functions, cf_sch_config_NAME().
|
|
|
|
#define STRUCT(__name, __validator...) \
|
|
|
|
int cf_sch_config_##__name(struct cf_om_node **rootp) { \
|
|
|
|
int i; \
|
|
|
|
struct cf_om_node **childp;
|
2012-12-07 00:27:05 +00:00
|
|
|
#define __ADD_CHILD(nodep, __elementstr) \
|
|
|
|
if ((i = cf_om_add_child(nodep, __elementstr)) == -1) \
|
2012-12-06 07:24:30 +00:00
|
|
|
return -1; \
|
2012-12-07 00:27:05 +00:00
|
|
|
childp = &(*nodep)->nodv[i];
|
|
|
|
#define __ATOM(nodep, __text) \
|
|
|
|
if (((*nodep)->text = str_edup(__text)) == NULL) \
|
2012-12-06 07:24:30 +00:00
|
|
|
return -1;
|
2012-12-07 00:27:05 +00:00
|
|
|
#define __STRUCT(nodep, __structname) \
|
|
|
|
if (cf_sch_config_##__structname(nodep) == -1) \
|
2012-12-06 07:24:30 +00:00
|
|
|
return -1;
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
|
2012-12-07 00:27:05 +00:00
|
|
|
__ADD_CHILD(rootp, #__element) \
|
2013-02-25 06:53:44 +00:00
|
|
|
__ATOM(childp, "(" #__repr ")") \
|
|
|
|
__ADD_CHILD(childp, "(" #__repr ")") \
|
|
|
|
__ATOM(childp, "(" #__repr ")")
|
|
|
|
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
|
2012-12-07 00:27:05 +00:00
|
|
|
__ADD_CHILD(rootp, #__element) \
|
2013-02-25 06:53:44 +00:00
|
|
|
__ATOM(childp, "(" #__repr ")")
|
|
|
|
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
|
2012-12-07 00:27:05 +00:00
|
|
|
__ADD_CHILD(rootp, #__element) \
|
2013-02-25 06:53:44 +00:00
|
|
|
__ATOM(childp, "(" #__repr ")")
|
2012-12-06 07:24:30 +00:00
|
|
|
#define SUB_STRUCT(__structname, __element, __flags) \
|
2012-12-07 00:27:05 +00:00
|
|
|
__ADD_CHILD(rootp, #__element) \
|
|
|
|
__STRUCT(childp, __structname)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
|
2012-12-07 00:27:05 +00:00
|
|
|
__ADD_CHILD(rootp, #__element) \
|
2013-02-25 06:53:44 +00:00
|
|
|
__ATOM(childp, "(" #__repr ")") \
|
2012-12-07 00:27:05 +00:00
|
|
|
__STRUCT(childp, __structname)
|
2012-12-06 07:24:30 +00:00
|
|
|
#define END_STRUCT \
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
#define ARRAY(__name, __flags, __validator...) \
|
|
|
|
int cf_sch_config_##__name(struct cf_om_node **rootp) { \
|
|
|
|
int i; \
|
|
|
|
struct cf_om_node **childp;
|
2013-02-25 06:53:44 +00:00
|
|
|
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
|
|
|
__ADD_CHILD(rootp, "[" #__keyrepr "]")
|
|
|
|
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
|
|
|
__ADD_CHILD(rootp, "[" #__keyrepr "]")
|
|
|
|
#define VALUE_ATOM(__type, __eltrepr) \
|
|
|
|
__ATOM(childp, "(" #__eltrepr ")")
|
|
|
|
#define VALUE_STRING(__strsize, __eltrepr) \
|
|
|
|
__ATOM(childp, "(" #__eltrepr ")")
|
|
|
|
#define VALUE_NODE(__type, __eltrepr) \
|
|
|
|
__ATOM(childp, "(" #__eltrepr ")") \
|
|
|
|
__ADD_CHILD(childp, "(" #__eltrepr ")") \
|
|
|
|
__ATOM(childp, "(" #__eltrepr ")")
|
2012-12-06 07:24:30 +00:00
|
|
|
#define VALUE_SUB_STRUCT(__structname) \
|
2012-12-07 00:27:05 +00:00
|
|
|
__STRUCT(childp, __structname)
|
2013-02-25 06:53:44 +00:00
|
|
|
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
|
|
|
|
__ATOM(childp, "(" #__eltrepr ")") \
|
2012-12-07 00:27:05 +00:00
|
|
|
__STRUCT(childp, __structname)
|
|
|
|
|
2012-12-06 07:24:30 +00:00
|
|
|
#define END_ARRAY(__size) \
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
#include "conf_schema.h"
|
|
|
|
#undef __ADD_CHILD
|
|
|
|
#undef __ATOM
|
|
|
|
#undef __STRUCT
|
|
|
|
#undef STRUCT
|
|
|
|
#undef NODE
|
|
|
|
#undef ATOM
|
|
|
|
#undef STRING
|
|
|
|
#undef SUB_STRUCT
|
|
|
|
#undef NODE_STRUCT
|
|
|
|
#undef END_STRUCT
|
|
|
|
#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
|
|
|
|
|
2013-02-26 07:39:08 +00:00
|
|
|
// Generate formatting functions, cf_fmt_config_SECTION()
|
|
|
|
#define STRUCT(__name, __validator...) \
|
|
|
|
int cf_fmt_config_##__name(struct cf_om_node **parentp, const struct config_##__name *strct) { \
|
|
|
|
DEBUGF("STRUCT(" #__name ", " #__validator ")"); \
|
|
|
|
int result = CFOK; \
|
|
|
|
int ret;
|
|
|
|
#define __HANDLE_TEXT(__elementstr) \
|
|
|
|
WHYF(" ret=%s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
|
|
|
|
if (ret == CFOK) { \
|
|
|
|
int n; \
|
|
|
|
if (text == NULL) { \
|
|
|
|
WHY(" text=NULL"); \
|
|
|
|
ret = CFERROR; \
|
|
|
|
} else if ((n = cf_om_add_child(parentp, __elementstr)) == -1) { \
|
|
|
|
WHY(" cf_om_add_child() returned -1"); \
|
|
|
|
ret = CFERROR; \
|
|
|
|
} else { \
|
|
|
|
(*parentp)->nodv[n]->text = text; \
|
|
|
|
text = NULL; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
if (text) { \
|
|
|
|
free((char *)text); \
|
|
|
|
text = NULL; \
|
|
|
|
}
|
|
|
|
#define __HANDLE_RET \
|
|
|
|
if (ret == CFERROR) \
|
|
|
|
return CFERROR; \
|
|
|
|
else if (ret != CFOK) \
|
|
|
|
result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS);
|
|
|
|
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
|
|
|
|
DEBUGF(" NODE(" #__type ", " #__element ", " #__repr ")"); \
|
|
|
|
ret = cf_fmt_##__repr(parentp, &strct->__element); \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
|
|
|
|
DEBUGF(" ATOM(" #__type ", " #__element ", " #__repr ")"); \
|
|
|
|
{ \
|
|
|
|
const char *text = NULL; \
|
|
|
|
ret = cf_fmt_##__repr(&text, &strct->__element);\
|
|
|
|
__HANDLE_TEXT(#__element) \
|
|
|
|
__HANDLE_RET \
|
|
|
|
}
|
|
|
|
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
|
|
|
|
DEBUGF(" STRING(" #__size ", " #__element ", " #__repr ")"); \
|
|
|
|
{ \
|
|
|
|
const char *text = NULL; \
|
|
|
|
ret = cf_fmt_##__repr(&text, &strct->__element[0]);\
|
|
|
|
__HANDLE_TEXT(#__element) \
|
|
|
|
__HANDLE_RET \
|
|
|
|
}
|
|
|
|
#define SUB_STRUCT(__structname, __element, __flags) \
|
|
|
|
DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ")"); \
|
|
|
|
ret = cf_fmt_config_##__structname(parentp, &strct->__element); \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
|
|
|
|
DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ", " #__repr ")"); \
|
|
|
|
ret = cf_fmt_##__repr(parentp, &strct->__element); \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define END_STRUCT \
|
|
|
|
if ((*parentp)->nodc == 0) \
|
|
|
|
cf_om_free_node(parentp); \
|
|
|
|
return result; \
|
|
|
|
}
|
|
|
|
#define ARRAY(__name, __flags, __validator...) \
|
|
|
|
int cf_fmt_config_##__name(struct cf_om_node **parentp, const struct config_##__name *array) { \
|
|
|
|
DEBUGF("ARRAY(" #__name ", " #__flags ", " #__validator ")"); \
|
|
|
|
int flags = (0 __flags); \
|
|
|
|
int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \
|
|
|
|
int result = CFOK; \
|
|
|
|
int i; \
|
|
|
|
for (i = 0; i < array->ac; ++i) { \
|
|
|
|
int ret; \
|
|
|
|
const char *key = NULL; \
|
|
|
|
int n = -1; \
|
|
|
|
struct cf_om_node *child = NULL;
|
|
|
|
#define __HANDLE_KEY \
|
|
|
|
if (key == NULL) \
|
|
|
|
ret = CFERROR; \
|
|
|
|
if (ret == CFOK) { \
|
|
|
|
if ((n = cf_om_add_child(parentp, key)) == -1) \
|
|
|
|
ret = CFERROR; \
|
|
|
|
else \
|
|
|
|
child = (*parentp)->nodv[n]; \
|
|
|
|
} \
|
|
|
|
if (key) { \
|
|
|
|
free((char *)key); \
|
|
|
|
key = NULL; \
|
|
|
|
} \
|
|
|
|
if (!child) \
|
|
|
|
continue;
|
|
|
|
#define __HANDLE_VALUE \
|
|
|
|
if (child->text == NULL) \
|
|
|
|
ret = CFERROR;
|
|
|
|
#define END_ARRAY(__size) \
|
|
|
|
if (child && child->nodc == 0) \
|
|
|
|
cf_om_remove_child(parentp, n); \
|
|
|
|
} \
|
|
|
|
if ((*parentp)->nodc == 0) \
|
|
|
|
cf_om_free_node(parentp); \
|
|
|
|
return result; \
|
|
|
|
}
|
|
|
|
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
|
|
|
DEBUGF(" KEY_ATOM(" #__type ", " #__keyrepr ", " #__cmpfunc ")"); \
|
|
|
|
ret = cf_fmt_##__keyrepr(&key, &array->av[i].key); \
|
|
|
|
__HANDLE_KEY \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
|
|
|
DEBUGF(" KEY_STRING(" #__strsize ", " #__keyrepr ", " #__cmpfunc ")"); \
|
|
|
|
ret = cf_fmt_##__keyrepr(&key, &array->av[i].key[0]); \
|
|
|
|
__HANDLE_KEY \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define VALUE_ATOM(__type, __eltrepr) \
|
|
|
|
DEBUGF(" VALUE_ATOM(" #__type ", " #__eltrepr ")"); \
|
|
|
|
ret = cf_fmt_##__eltrepr(&child->text, &array->av[i].value); \
|
|
|
|
__HANDLE_VALUE \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define VALUE_STRING(__strsize, __eltrepr) \
|
|
|
|
DEBUGF(" VALUE_STRING(" #__strsize ", " #__eltrepr ")"); \
|
|
|
|
ret = cf_fmt_##__eltrepr(&child->text, &array->av[i].value[0]); \
|
|
|
|
__HANDLE_VALUE \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define VALUE_NODE(__type, __eltrepr) \
|
|
|
|
DEBUGF(" VALUE_NODE(" #__type ", " #__eltrepr ")"); \
|
|
|
|
ret = cf_fmt_##__eltrepr(&child, &array->av[i].value); \
|
|
|
|
__HANDLE_VALUE \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define VALUE_SUB_STRUCT(__structname) \
|
|
|
|
DEBUGF(" VALUE_SUB_STRUCT(" #__structname ")"); \
|
|
|
|
ret = cf_fmt_config_##__structname(&child, &array->av[i].value); \
|
|
|
|
__HANDLE_VALUE \
|
|
|
|
__HANDLE_RET
|
|
|
|
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
|
|
|
|
DEBUGF(" VALUE_NODE_STRUCT(" #__structname ", " #__eltrepr ")"); \
|
|
|
|
ret = cf_fmt_##__eltrepr(&child, &array->av[i].value); \
|
|
|
|
__HANDLE_VALUE \
|
|
|
|
__HANDLE_RET
|
|
|
|
#include "conf_schema.h"
|
|
|
|
#undef STRUCT
|
|
|
|
#undef NODE
|
|
|
|
#undef ATOM
|
|
|
|
#undef STRING
|
|
|
|
#undef SUB_STRUCT
|
|
|
|
#undef NODE_STRUCT
|
|
|
|
#undef END_STRUCT
|
|
|
|
#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
|
|
|
|
|