Improve new "config dump" command

No more SEGV.  Omits invalid (default) values.  Logs unconditional DEBUG
output, to be removed before merging into development.  Still missing
cf_cmp_ functions to prune out default values.

Improved config Object Model iterator logic to barf on internal NULL
nodes.
This commit is contained in:
Andrew Bettison 2013-02-27 16:26:07 +10:30
parent 14b859616e
commit 46eeacb823
3 changed files with 77 additions and 82 deletions

View File

@ -1170,13 +1170,15 @@ int app_config_dump(const struct cli_parsed *parsed, void *context)
return -1; return -1;
} }
struct cf_om_iterator it; struct cf_om_iterator it;
for (cf_om_iter_start(&it, root); it.node; cf_om_iter_next(&it)) for (cf_om_iter_start(&it, root); it.node; cf_om_iter_next(&it)) {
//DEBUGF("%s text=%s nodc=%d", it.node->fullkey, alloca_str_toprint(it.node->text), it.node->nodc);
if (it.node->text) { if (it.node->text) {
cli_puts(it.node->fullkey); cli_puts(it.node->fullkey);
cli_delim("="); cli_delim("=");
cli_puts(it.node->text); cli_puts(it.node->text);
cli_delim("\n"); cli_delim("\n");
} }
}
cf_om_free_node(&root); cf_om_free_node(&root);
return ret == CFOK ? 0 : 1; return ret == CFOK ? 0 : 1;
} }

View File

@ -148,6 +148,11 @@ static int cf_om_make_child(struct cf_om_node **const parentp, const char *const
assert(i <= (*parentp)->nodc); assert(i <= (*parentp)->nodc);
if ((child = emalloc_zero(sizeof *child)) == NULL) if ((child = emalloc_zero(sizeof *child)) == NULL)
return -1; return -1;
if (!(child->fullkey = strn_edup(fullkey, keyend - fullkey))) {
free(child);
return -1;
}
child->key = child->fullkey + (key - fullkey);
++(*parentp)->nodc; ++(*parentp)->nodc;
if ((*parentp)->nodc > NELS((*parentp)->nodv)) if ((*parentp)->nodc > NELS((*parentp)->nodv))
*parentp = realloc(*parentp, sizeof(**parentp) + sizeof((*parentp)->nodv[0]) * ((*parentp)->nodc - NELS((*parentp)->nodv))); *parentp = realloc(*parentp, sizeof(**parentp) + sizeof((*parentp)->nodv[0]) * ((*parentp)->nodc - NELS((*parentp)->nodv)));
@ -155,11 +160,6 @@ static int cf_om_make_child(struct cf_om_node **const parentp, const char *const
for (j = (*parentp)->nodc - 1; j > i; --j) for (j = (*parentp)->nodc - 1; j > i; --j)
(*parentp)->nodv[j] = (*parentp)->nodv[j-1]; (*parentp)->nodv[j] = (*parentp)->nodv[j-1];
(*parentp)->nodv[i] = child; (*parentp)->nodv[i] = child;
if (!(child->fullkey = strn_edup(fullkey, keyend - fullkey))) {
free(child);
return -1;
}
child->key = child->fullkey + (key - fullkey);
//DEBUGF(" insert i=%d", i); //DEBUGF(" insert i=%d", i);
return i; return i;
} }
@ -193,7 +193,7 @@ int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char
void cf_om_remove_child(struct cf_om_node **parentp, unsigned n) void cf_om_remove_child(struct cf_om_node **parentp, unsigned n)
{ {
if (n < (*parentp)->nodc && (*parentp)->nodv[n]) { if (n < (*parentp)->nodc) {
cf_om_free_node(&(*parentp)->nodv[n]); cf_om_free_node(&(*parentp)->nodv[n]);
--(*parentp)->nodc; --(*parentp)->nodc;
for (; n < (*parentp)->nodc; ++n) for (; n < (*parentp)->nodc; ++n)
@ -271,6 +271,7 @@ int cf_om_parse(const char *source, const char *buf, size_t len, struct cf_om_no
void cf_om_free_node(struct cf_om_node **nodep) void cf_om_free_node(struct cf_om_node **nodep)
{ {
if (*nodep) { if (*nodep) {
//DEBUGF("%s text=%s nodc=%d", (*nodep)->fullkey, alloca_str_toprint((*nodep)->text), (*nodep)->nodc);
while ((*nodep)->nodc) while ((*nodep)->nodc)
cf_om_free_node(&(*nodep)->nodv[--(*nodep)->nodc]); cf_om_free_node(&(*nodep)->nodv[--(*nodep)->nodc]);
if ((*nodep)->fullkey) { if ((*nodep)->fullkey) {
@ -428,8 +429,10 @@ int cf_om_iter_next(struct cf_om_iterator *it)
int i = it->stack[it->sp].index++; int i = it->stack[it->sp].index++;
if (i < parent->nodc) { if (i < parent->nodc) {
it->node = parent->nodv[i]; it->node = parent->nodv[i];
if (it->node == NULL)
return WHY("null node");
if (it->sp >= NELS(it->stack)) if (it->sp >= NELS(it->stack))
return -1; return WHY("stack overflow");
++it->sp; ++it->sp;
it->stack[it->sp].node = it->node; it->stack[it->sp].node = it->node;
it->stack[it->sp].index = 0; it->stack[it->sp].index = 0;

View File

@ -1,4 +1,4 @@
/* /*
Serval DNA configuration Serval DNA configuration
Copyright (C) 2012 Serval Project Inc. Copyright (C) 2012 Serval Project Inc.
@ -279,6 +279,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef VALUE_NODE #undef VALUE_NODE
#undef VALUE_SUB_STRUCT #undef VALUE_SUB_STRUCT
#undef VALUE_NODE_STRUCT #undef VALUE_NODE_STRUCT
#undef __ARRAY_KEY
#undef __ARRAY_VALUE
#undef END_ARRAY #undef END_ARRAY
// Generate config array search-by-key functions. // Generate config array search-by-key functions.
@ -421,24 +423,46 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
DEBUGF("STRUCT(" #__name ", " #__validator ")"); \ DEBUGF("STRUCT(" #__name ", " #__validator ")"); \
int result = CFOK; \ int result = CFOK; \
int ret; int ret;
#define __HANDLE_TEXT(__elementstr) \ #define __FMT_TEXT(__fmtfunc, __eltname, __eltexpr) \
WHYF(" ret=%s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \ { \
if (ret == CFOK) { \ const char *text = NULL; \
int n; \ ret = __fmtfunc(&text, __eltexpr); \
if (text == NULL) { \ if (ret != CFOK) \
WHY(" text=NULL"); \ WHYF(" ret=%s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
ret = CFERROR; \ if (ret == CFOK) { \
} else if ((n = cf_om_add_child(parentp, __elementstr)) == -1) { \ int n; \
WHY(" cf_om_add_child() returned -1"); \ if (text == NULL) { \
ret = CFERROR; \ WHY(" text=NULL"); \
} else { \ ret = CFERROR; \
(*parentp)->nodv[n]->text = text; \ } else if ((n = cf_om_add_child(parentp, __eltname)) == -1) { \
WHY(" cf_om_add_child() returned -1"); \
ret = CFERROR; \
} else { \
(*parentp)->nodv[n]->text = text; \
text = NULL; \
DEBUGF(" %s text=%s", (*parentp)->nodv[n]->fullkey, alloca_str_toprint((*parentp)->nodv[n]->text)); \
} \
} \
if (text) { \
free((char *)text); \
text = NULL; \ text = NULL; \
} \ } \
} \ __HANDLE_RET \
if (text) { \ }
free((char *)text); \ #define __FMT_NODE(__fmtfunc, __element) \
text = NULL; \ { \
int n = cf_om_add_child(parentp, #__element); \
ret = (n != -1) ? __fmtfunc(&(*parentp)->nodv[n], &strct->__element) : CFERROR; \
if (ret != CFOK) \
WHYF(" ret=%s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
__REMOVE_EMPTY \
__HANDLE_RET \
}
#define __REMOVE_EMPTY \
if (n != -1 && ((*parentp)->nodv[n] == NULL || ((*parentp)->nodv[n]->text == NULL && (*parentp)->nodv[n]->nodc == 0))) { \
WHYF(" child n=%d empty", n); \
cf_om_remove_child(parentp, n); \
ret |= CFEMPTY; \
} }
#define __HANDLE_RET \ #define __HANDLE_RET \
if (ret == CFERROR) \ if (ret == CFERROR) \
@ -447,32 +471,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS); result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS);
#define NODE(__type, __element, __default, __repr, __flags, __comment) \ #define NODE(__type, __element, __default, __repr, __flags, __comment) \
DEBUGF(" NODE(" #__type ", " #__element ", " #__repr ")"); \ DEBUGF(" NODE(" #__type ", " #__element ", " #__repr ")"); \
ret = cf_fmt_##__repr(parentp, &strct->__element); \ __FMT_NODE(cf_fmt_##__repr, __element)
__HANDLE_RET
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \ #define ATOM(__type, __element, __default, __repr, __flags, __comment) \
DEBUGF(" ATOM(" #__type ", " #__element ", " #__repr ")"); \ DEBUGF(" ATOM(" #__type ", " #__element ", " #__repr ")"); \
{ \ __FMT_TEXT(cf_fmt_##__repr, #__element, &strct->__element)
const char *text = NULL; \
ret = cf_fmt_##__repr(&text, &strct->__element);\
__HANDLE_TEXT(#__element) \
__HANDLE_RET \
}
#define STRING(__size, __element, __default, __repr, __flags, __comment) \ #define STRING(__size, __element, __default, __repr, __flags, __comment) \
DEBUGF(" STRING(" #__size ", " #__element ", " #__repr ")"); \ DEBUGF(" STRING(" #__size ", " #__element ", " #__repr ")"); \
{ \ __FMT_TEXT(cf_fmt_##__repr, #__element, &strct->__element[0])
const char *text = NULL; \
ret = cf_fmt_##__repr(&text, &strct->__element[0]);\
__HANDLE_TEXT(#__element) \
__HANDLE_RET \
}
#define SUB_STRUCT(__structname, __element, __flags) \ #define SUB_STRUCT(__structname, __element, __flags) \
DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ")"); \ DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ")"); \
ret = cf_fmt_config_##__structname(parentp, &strct->__element); \ __FMT_NODE(cf_fmt_config_##__structname, __element)
__HANDLE_RET
#define NODE_STRUCT(__structname, __element, __repr, __flags) \ #define NODE_STRUCT(__structname, __element, __repr, __flags) \
DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ", " #__repr ")"); \ DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ", " #__repr ")"); \
ret = cf_fmt_##__repr(parentp, &strct->__element); \ __FMT_NODE(cf_fmt_##__repr, __element)
__HANDLE_RET
#define END_STRUCT \ #define END_STRUCT \
if ((*parentp)->nodc == 0) \ if ((*parentp)->nodc == 0) \
cf_om_free_node(parentp); \ cf_om_free_node(parentp); \
@ -485,32 +496,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \ int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \
int result = CFOK; \ int result = CFOK; \
int i; \ int i; \
for (i = 0; i < array->ac; ++i) { \ for (i = 0; i < array->ac; ++i) {
int ret; \ #define __ARRAY_KEY(__keyfunc, __keyexpr) \
const char *key = NULL; \ const char *key = NULL; \
int n = -1; \ int ret = __keyfunc(&key, __keyexpr); \
struct cf_om_node *child = NULL;
#define __HANDLE_KEY \
if (key == NULL) \ if (key == NULL) \
ret = CFERROR; \ ret = CFERROR; \
if (ret == CFOK) { \ int n = ret == CFOK ? cf_om_add_child(parentp, key) : -1; \
if ((n = cf_om_add_child(parentp, key)) == -1) \
ret = CFERROR; \
else \
child = (*parentp)->nodv[n]; \
} \
if (key) { \ if (key) { \
free((char *)key); \ free((char *)key); \
key = NULL; \ key = NULL; \
} \ } \
if (!child) \ if (n == -1) { \
continue; result |= CFSUB(CFINVALID); \
#define __HANDLE_VALUE \ continue; \
if (child->text == NULL) \ }
ret = CFERROR;
#define END_ARRAY(__size) \ #define END_ARRAY(__size) \
if (child && child->nodc == 0) \ __REMOVE_EMPTY \
cf_om_remove_child(parentp, n); \ __HANDLE_RET \
} \ } \
if ((*parentp)->nodc == 0) \ if ((*parentp)->nodc == 0) \
cf_om_free_node(parentp); \ cf_om_free_node(parentp); \
@ -518,39 +521,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
} }
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \ #define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
DEBUGF(" KEY_ATOM(" #__type ", " #__keyrepr ", " #__cmpfunc ")"); \ DEBUGF(" KEY_ATOM(" #__type ", " #__keyrepr ", " #__cmpfunc ")"); \
ret = cf_fmt_##__keyrepr(&key, &array->av[i].key); \ __ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key);
__HANDLE_KEY \
__HANDLE_RET
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \ #define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
DEBUGF(" KEY_STRING(" #__strsize ", " #__keyrepr ", " #__cmpfunc ")"); \ DEBUGF(" KEY_STRING(" #__strsize ", " #__keyrepr ", " #__cmpfunc ")"); \
ret = cf_fmt_##__keyrepr(&key, &array->av[i].key[0]); \ __ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key[0]);
__HANDLE_KEY \
__HANDLE_RET
#define VALUE_ATOM(__type, __eltrepr) \ #define VALUE_ATOM(__type, __eltrepr) \
DEBUGF(" VALUE_ATOM(" #__type ", " #__eltrepr ")"); \ DEBUGF(" VALUE_ATOM(" #__type ", " #__eltrepr ")"); \
ret = cf_fmt_##__eltrepr(&child->text, &array->av[i].value); \ ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n]->text, &array->av[i].value);
__HANDLE_VALUE \
__HANDLE_RET
#define VALUE_STRING(__strsize, __eltrepr) \ #define VALUE_STRING(__strsize, __eltrepr) \
DEBUGF(" VALUE_STRING(" #__strsize ", " #__eltrepr ")"); \ DEBUGF(" VALUE_STRING(" #__strsize ", " #__eltrepr ")"); \
ret = cf_fmt_##__eltrepr(&child->text, &array->av[i].value[0]); \ ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n]->text, &array->av[i].value[0]);
__HANDLE_VALUE \
__HANDLE_RET
#define VALUE_NODE(__type, __eltrepr) \ #define VALUE_NODE(__type, __eltrepr) \
DEBUGF(" VALUE_NODE(" #__type ", " #__eltrepr ")"); \ DEBUGF(" VALUE_NODE(" #__type ", " #__eltrepr ")"); \
ret = cf_fmt_##__eltrepr(&child, &array->av[i].value); \ ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n], &array->av[i].value);
__HANDLE_VALUE \
__HANDLE_RET
#define VALUE_SUB_STRUCT(__structname) \ #define VALUE_SUB_STRUCT(__structname) \
DEBUGF(" VALUE_SUB_STRUCT(" #__structname ")"); \ DEBUGF(" VALUE_SUB_STRUCT(" #__structname ")"); \
ret = cf_fmt_config_##__structname(&child, &array->av[i].value); \ ret = cf_fmt_config_##__structname(&(*parentp)->nodv[n], &array->av[i].value);
__HANDLE_VALUE \
__HANDLE_RET
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \ #define VALUE_NODE_STRUCT(__structname, __eltrepr) \
DEBUGF(" VALUE_NODE_STRUCT(" #__structname ", " #__eltrepr ")"); \ DEBUGF(" VALUE_NODE_STRUCT(" #__structname ", " #__eltrepr ")"); \
ret = cf_fmt_##__eltrepr(&child, &array->av[i].value); \ ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n], &array->av[i].value);
__HANDLE_VALUE \
__HANDLE_RET
#include "conf_schema.h" #include "conf_schema.h"
#undef STRUCT #undef STRUCT
#undef NODE #undef NODE
@ -567,5 +556,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef VALUE_NODE #undef VALUE_NODE
#undef VALUE_SUB_STRUCT #undef VALUE_SUB_STRUCT
#undef VALUE_NODE_STRUCT #undef VALUE_NODE_STRUCT
#undef __ARRAY_KEY
#undef END_ARRAY #undef END_ARRAY