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;
}
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) {
cli_puts(it.node->fullkey);
cli_delim("=");
cli_puts(it.node->text);
cli_delim("\n");
}
}
cf_om_free_node(&root);
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);
if ((child = emalloc_zero(sizeof *child)) == NULL)
return -1;
if (!(child->fullkey = strn_edup(fullkey, keyend - fullkey))) {
free(child);
return -1;
}
child->key = child->fullkey + (key - fullkey);
++(*parentp)->nodc;
if ((*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)
(*parentp)->nodv[j] = (*parentp)->nodv[j-1];
(*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);
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)
{
if (n < (*parentp)->nodc && (*parentp)->nodv[n]) {
if (n < (*parentp)->nodc) {
cf_om_free_node(&(*parentp)->nodv[n]);
--(*parentp)->nodc;
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)
{
if (*nodep) {
//DEBUGF("%s text=%s nodc=%d", (*nodep)->fullkey, alloca_str_toprint((*nodep)->text), (*nodep)->nodc);
while ((*nodep)->nodc)
cf_om_free_node(&(*nodep)->nodv[--(*nodep)->nodc]);
if ((*nodep)->fullkey) {
@ -428,8 +429,10 @@ int cf_om_iter_next(struct cf_om_iterator *it)
int i = it->stack[it->sp].index++;
if (i < parent->nodc) {
it->node = parent->nodv[i];
if (it->node == NULL)
return WHY("null node");
if (it->sp >= NELS(it->stack))
return -1;
return WHY("stack overflow");
++it->sp;
it->stack[it->sp].node = it->node;
it->stack[it->sp].index = 0;

View File

@ -279,6 +279,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef VALUE_NODE
#undef VALUE_SUB_STRUCT
#undef VALUE_NODE_STRUCT
#undef __ARRAY_KEY
#undef __ARRAY_VALUE
#undef END_ARRAY
// 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 ")"); \
int result = CFOK; \
int ret;
#define __HANDLE_TEXT(__elementstr) \
#define __FMT_TEXT(__fmtfunc, __eltname, __eltexpr) \
{ \
const char *text = NULL; \
ret = __fmtfunc(&text, __eltexpr); \
if (ret != CFOK) \
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) { \
} 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; \
} \
__HANDLE_RET \
}
#define __FMT_NODE(__fmtfunc, __element) \
{ \
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 \
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);
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
DEBUGF(" NODE(" #__type ", " #__element ", " #__repr ")"); \
ret = cf_fmt_##__repr(parentp, &strct->__element); \
__HANDLE_RET
__FMT_NODE(cf_fmt_##__repr, __element)
#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 \
}
__FMT_TEXT(cf_fmt_##__repr, #__element, &strct->__element)
#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 \
}
__FMT_TEXT(cf_fmt_##__repr, #__element, &strct->__element[0])
#define SUB_STRUCT(__structname, __element, __flags) \
DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ")"); \
ret = cf_fmt_config_##__structname(parentp, &strct->__element); \
__HANDLE_RET
__FMT_NODE(cf_fmt_config_##__structname, __element)
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
DEBUGF(" SUB_STRUCT(" #__structname ", " #__element ", " #__repr ")"); \
ret = cf_fmt_##__repr(parentp, &strct->__element); \
__HANDLE_RET
__FMT_NODE(cf_fmt_##__repr, __element)
#define END_STRUCT \
if ((*parentp)->nodc == 0) \
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 result = CFOK; \
int i; \
for (i = 0; i < array->ac; ++i) { \
int ret; \
for (i = 0; i < array->ac; ++i) {
#define __ARRAY_KEY(__keyfunc, __keyexpr) \
const char *key = NULL; \
int n = -1; \
struct cf_om_node *child = NULL;
#define __HANDLE_KEY \
int ret = __keyfunc(&key, __keyexpr); \
if (key == NULL) \
ret = CFERROR; \
if (ret == CFOK) { \
if ((n = cf_om_add_child(parentp, key)) == -1) \
ret = CFERROR; \
else \
child = (*parentp)->nodv[n]; \
} \
int n = ret == CFOK ? cf_om_add_child(parentp, key) : -1; \
if (key) { \
free((char *)key); \
key = NULL; \
} \
if (!child) \
continue;
#define __HANDLE_VALUE \
if (child->text == NULL) \
ret = CFERROR;
if (n == -1) { \
result |= CFSUB(CFINVALID); \
continue; \
}
#define END_ARRAY(__size) \
if (child && child->nodc == 0) \
cf_om_remove_child(parentp, n); \
__REMOVE_EMPTY \
__HANDLE_RET \
} \
if ((*parentp)->nodc == 0) \
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...) \
DEBUGF(" KEY_ATOM(" #__type ", " #__keyrepr ", " #__cmpfunc ")"); \
ret = cf_fmt_##__keyrepr(&key, &array->av[i].key); \
__HANDLE_KEY \
__HANDLE_RET
__ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key);
#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
__ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key[0]);
#define VALUE_ATOM(__type, __eltrepr) \
DEBUGF(" VALUE_ATOM(" #__type ", " #__eltrepr ")"); \
ret = cf_fmt_##__eltrepr(&child->text, &array->av[i].value); \
__HANDLE_VALUE \
__HANDLE_RET
ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n]->text, &array->av[i].value);
#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
ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n]->text, &array->av[i].value[0]);
#define VALUE_NODE(__type, __eltrepr) \
DEBUGF(" VALUE_NODE(" #__type ", " #__eltrepr ")"); \
ret = cf_fmt_##__eltrepr(&child, &array->av[i].value); \
__HANDLE_VALUE \
__HANDLE_RET
ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n], &array->av[i].value);
#define VALUE_SUB_STRUCT(__structname) \
DEBUGF(" VALUE_SUB_STRUCT(" #__structname ")"); \
ret = cf_fmt_config_##__structname(&child, &array->av[i].value); \
__HANDLE_VALUE \
__HANDLE_RET
ret = cf_fmt_config_##__structname(&(*parentp)->nodv[n], &array->av[i].value);
#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
ret = cf_fmt_##__eltrepr(&(*parentp)->nodv[n], &array->av[i].value);
#include "conf_schema.h"
#undef STRUCT
#undef NODE
@ -567,5 +556,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef VALUE_NODE
#undef VALUE_SUB_STRUCT
#undef VALUE_NODE_STRUCT
#undef __ARRAY_KEY
#undef END_ARRAY