Improve new config prototype code

Implement dna.helper.argv array label validation.

Ignore comment lines starting with '#'.
This commit is contained in:
Andrew Bettison 2012-11-28 17:54:19 +10:30
parent 8e8a3b1ea2
commit af6a912a1f
2 changed files with 79 additions and 30 deletions

View File

@ -302,7 +302,7 @@ struct cf_om_node {
// Generate parser function prototypes. // Generate parser function prototypes.
#define __VALIDATOR(__name, __validator...) \ #define __VALIDATOR(__name, __validator...) \
typedef int __validator_func__config_##__name##__t(struct config_##__name *, int); \ typedef int __validator_func__config_##__name##__t(const struct cf_om_node *, struct config_##__name *, int); \
__validator_func__config_##__name##__t __dummy__validator_func__config_##__name, ##__validator; __validator_func__config_##__name##__t __dummy__validator_func__config_##__name, ##__validator;
#define STRUCT(__name, __validator...) \ #define STRUCT(__name, __validator...) \
int opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \ int opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \

View File

@ -145,6 +145,8 @@ struct cf_om_node *parse_config(const char *source, const char *buf, size_t len)
if (lend > line && lend[-1] == '\r') if (lend > line && lend[-1] == '\r')
--lend; --lend;
//DEBUGF("lineno=%u %s", lineno, alloca_toprint(-1, line, lend - line)); //DEBUGF("lineno=%u %s", lineno, alloca_toprint(-1, line, lend - line));
if (line[0] == '#')
continue; // skip comment lines
const char *p; const char *p;
for (p = line; p < lend && isspace(*p); ++p) for (p = line; p < lend && isspace(*p); ++p)
; ;
@ -221,7 +223,7 @@ int get_child(const struct cf_om_node *parent, const char *key)
return -1; return -1;
} }
void warn_node(const char *file, unsigned line, const struct cf_om_node *node, const char *fmt, ...) void warn_nodev(const char *file, unsigned line, const struct cf_om_node *node, const char *key, const char *fmt, va_list ap)
{ {
strbuf b = strbuf_alloca(1024); strbuf b = strbuf_alloca(1024);
if (node) { if (node) {
@ -229,20 +231,44 @@ void warn_node(const char *file, unsigned line, const struct cf_om_node *node, c
strbuf_sprintf(b, "%s:%u: ", node->source, node->line_number); strbuf_sprintf(b, "%s:%u: ", node->source, node->line_number);
strbuf_puts(b, "configuration option \""); strbuf_puts(b, "configuration option \"");
strbuf_puts(b, node->fullkey); strbuf_puts(b, node->fullkey);
strbuf_puts(b, "\": "); if (key && key[0]) {
strbuf_putc(b, '.');
strbuf_puts(b, key);
} }
strbuf_puts(b, "\" ");
}
strbuf_vsprintf(b, fmt, ap);
_WARNF("%s:%u %s", file, line, strbuf_str(b));
}
void warn_childrenv(const char *file, unsigned line, const struct cf_om_node *parent, const char *fmt, va_list ap)
{
int i;
for (i = 0; i < parent->nodc; ++i) {
warn_nodev(file, line, parent->nodv[i], NULL, fmt, ap);
warn_childrenv(file, line, parent->nodv[i], fmt, ap);
}
}
void warn_node(const char *file, unsigned line, const struct cf_om_node *node, const char *key, const char *fmt, ...)
{
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
strbuf_vsprintf(b, fmt, ap); warn_nodev(file, line, node, key, fmt, ap);
va_end(ap);
}
void warn_children(const char *file, unsigned line, const struct cf_om_node *node, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
warn_childrenv(file, line, node, fmt, ap);
va_end(ap); va_end(ap);
_WARNF("%s:%u %s", file, line, strbuf_str(b));
} }
void missing_node(const struct cf_om_node *parent, const char *key) void missing_node(const struct cf_om_node *parent, const char *key)
{ {
WARNF("missing configuration option %s%s%s", warn_node(__FILE__, __LINE__, parent, key, "is missing");
parent->fullkey ? parent->fullkey : "", parent->fullkey ? "." : "", key
);
} }
strbuf strbuf_cf_flags(strbuf sb, int flags) strbuf strbuf_cf_flags(strbuf sb, int flags)
@ -287,8 +313,6 @@ strbuf strbuf_cf_flags(strbuf sb, int flags)
return sb; return sb;
} }
strbuf strbuf_cf_flag_reason(strbuf sb, int flags) strbuf strbuf_cf_flag_reason(strbuf sb, int flags)
{ {
if (flags == CFERROR) if (flags == CFERROR)
@ -322,16 +346,23 @@ strbuf strbuf_cf_flag_reason(strbuf sb, int flags)
return sb; return sb;
} }
void warn_ignoring_value(const struct cf_om_node *node, int reason) void warn_node_value(const struct cf_om_node *node, int reason)
{ {
strbuf b = strbuf_alloca(180); strbuf b = strbuf_alloca(180);
strbuf_cf_flag_reason(b, reason); strbuf_cf_flag_reason(b, reason);
warn_node(__FILE__, __LINE__, node, "ignoring value %s -- %s", alloca_str(node->text), strbuf_str(b)); warn_node(__FILE__, __LINE__, node, NULL, "value %s %s", alloca_str(node->text), strbuf_str(b));
}
void warn_no_array(const struct cf_om_node *node, int reason)
{
strbuf b = strbuf_alloca(180);
strbuf_cf_flag_reason(b, reason);
warn_node(__FILE__, __LINE__, node, NULL, "array discarded -- %s", strbuf_str(b));
} }
void warn_unsupported_node(const struct cf_om_node *node) void warn_unsupported_node(const struct cf_om_node *node)
{ {
warn_node(__FILE__, __LINE__, node, "not supported"); warn_node(__FILE__, __LINE__, node, NULL, "not supported");
} }
void warn_unsupported_children(const struct cf_om_node *parent) void warn_unsupported_children(const struct cf_om_node *parent)
@ -346,9 +377,7 @@ void warn_unsupported_children(const struct cf_om_node *parent)
void ignore_node(const struct cf_om_node *node, const char *msg) void ignore_node(const struct cf_om_node *node, const char *msg)
{ {
warn_node(__FILE__, __LINE__, node, "ignoring%s%s", warn_node(__FILE__, __LINE__, node, NULL, "ignoring%s%s", msg && msg[0] ? " -- " : "", msg ? msg : "");
msg && msg[0] ? " -- " : "", msg ? msg : ""
);
} }
void ignore_tree(const struct cf_om_node *node, const char *msg); void ignore_tree(const struct cf_om_node *node, const char *msg);
@ -369,19 +398,19 @@ void ignore_tree(const struct cf_om_node *node, const char *msg)
void warn_list_overflow(const struct cf_om_node *node) void warn_list_overflow(const struct cf_om_node *node)
{ {
ignore_children(node, "list overflow"); warn_children(__FILE__, __LINE__, node, "list overflow");
} }
void spurious_children(const struct cf_om_node *parent) void spurious_children(const struct cf_om_node *parent)
{ {
ignore_children(parent, "spurious"); warn_children(__FILE__, __LINE__, parent, "spurious");
} }
void warn_array_label(const struct cf_om_node *node, int reason) void warn_array_label(const struct cf_om_node *node, int reason)
{ {
strbuf b = strbuf_alloca(180); strbuf b = strbuf_alloca(180);
strbuf_cf_flag_reason(b, reason); strbuf_cf_flag_reason(b, reason);
warn_node(__FILE__, __LINE__, node, "array label %s -- %s", alloca_str(node->key), strbuf_str(b)); warn_node(__FILE__, __LINE__, node, NULL, "array label %s -- %s", alloca_str(node->key), strbuf_str(b));
} }
void warn_array_value(const struct cf_om_node *node, int reason) void warn_array_value(const struct cf_om_node *node, int reason)
@ -389,9 +418,9 @@ void warn_array_value(const struct cf_om_node *node, int reason)
strbuf b = strbuf_alloca(180); strbuf b = strbuf_alloca(180);
strbuf_cf_flag_reason(b, reason); strbuf_cf_flag_reason(b, reason);
if (node->text) if (node->text)
warn_node(__FILE__, __LINE__, node, "array value %s -- %s", alloca_str(node->text), strbuf_str(b)); warn_node(__FILE__, __LINE__, node, NULL, "array value %s -- %s", alloca_str(node->text), strbuf_str(b));
else else
warn_node(__FILE__, __LINE__, node, "array element -- %s", strbuf_str(b)); warn_node(__FILE__, __LINE__, node, NULL, "array element -- %s", strbuf_str(b));
} }
int opt_boolean(int *booleanp, const char *text); int opt_boolean(int *booleanp, const char *text);
@ -507,7 +536,7 @@ int opt_debugflags(debugflags_t *flagsp, const struct cf_om_node *node)
} }
break; break;
default: default:
warn_ignoring_value(child, ret); warn_node_value(child, ret);
result |= ret; result |= ret;
break; break;
} }
@ -626,10 +655,27 @@ int opt_argv_label(char *str, size_t len, const char *text)
return CFOK; return CFOK;
} }
int vld_argv(struct config_argv *array, int result) int cmp_atoi(const char *a, const char *b)
{
int ai = atoi(a);
int bi = atoi(b);
return ai < bi ? -1 : ai > bi ? 1 : 0;
}
int vld_argv(const struct cf_om_node *parent, struct config_argv *array, int result)
{ {
int i; int i;
int last_label = -1;
for (i = 0; i < array->ac; ++i) { for (i = 0; i < array->ac; ++i) {
int label = atoi(array->av[i].label);
assert(label >= 1);
while (last_label != -1 && ++last_label < label && last_label <= sizeof(array->av)) {
char labelkey[12];
sprintf(labelkey, "%u", last_label);
missing_node(parent, labelkey);
result |= CFINCOMPLETE;
}
last_label = label;
} }
return result; return result;
} }
@ -857,7 +903,7 @@ int opt_interface_list(struct config_interface_list *listp, const struct cf_om_n
++n; ++n;
break; break;
default: default:
warn_node(__FILE__, __LINE__, node, "ignoring invalid interface rule %s", alloca_str(buf)); \ warn_node(__FILE__, __LINE__, node, NULL, "invalid interface rule %s", alloca_str(buf)); \
result |= CFSUB(ret); result |= CFSUB(ret);
break; break;
} }
@ -900,7 +946,7 @@ void warn_list_overflow(const struct cf_om_node *node);
// Generate parsing functions, opt_config_SECTION() // Generate parsing functions, opt_config_SECTION()
#define STRUCT(__name, __validator...) \ #define STRUCT(__name, __validator...) \
int opt_config_##__name(struct config_##__name *strct, const struct cf_om_node *node) { \ int opt_config_##__name(struct config_##__name *strct, const struct cf_om_node *node) { \
int (*validator)(struct config_##__name *, int) = (NULL, ##__validator); \ int (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \
int result = CFEMPTY; \ int result = CFEMPTY; \
char used[node->nodc]; \ char used[node->nodc]; \
memset(used, 0, node->nodc * sizeof used[0]); memset(used, 0, node->nodc * sizeof used[0]);
@ -926,7 +972,7 @@ void warn_list_overflow(const struct cf_om_node *node);
if (ret & ~CFEMPTY) { \ if (ret & ~CFEMPTY) { \
assert(child != NULL); \ assert(child != NULL); \
if (child->text) \ if (child->text) \
warn_ignoring_value(child, ret); \ warn_node_value(child, ret); \
result |= CFSUB(ret); \ result |= CFSUB(ret); \
} \ } \
} }
@ -955,13 +1001,13 @@ void warn_list_overflow(const struct cf_om_node *node);
} \ } \
} \ } \
if (validator) \ if (validator) \
result = (*validator)(strct, result); \ result = (*validator)(node, strct, result); \
return result; \ return result; \
} }
#define __ARRAY(__name, __lblparser, __parseexpr, __validator...) \ #define __ARRAY(__name, __lblparser, __parseexpr, __validator...) \
int opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \ int opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
int (*validator)(struct config_##__name *, int) = (NULL, ##__validator); \ int (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \
int result = CFOK; \ int result = CFOK; \
int i, n; \ int i, n; \
for (n = 0, i = 0; i < node->nodc && n < NELS(array->av); ++i) { \ for (n = 0, i = 0; i < node->nodc && n < NELS(array->av); ++i) { \
@ -971,6 +1017,7 @@ void warn_list_overflow(const struct cf_om_node *node);
return CFERROR; \ return CFERROR; \
result |= ret & CF__SUBFLAGS; \ result |= ret & CF__SUBFLAGS; \
ret &= CF__FLAGS; \ ret &= CF__FLAGS; \
result |= CFSUB(ret); \
if (ret != CFOK) \ if (ret != CFOK) \
warn_array_label(child, ret); \ warn_array_label(child, ret); \
else { \ else { \
@ -994,9 +1041,11 @@ void warn_list_overflow(const struct cf_om_node *node);
} \ } \
array->ac = n; \ array->ac = n; \
if (validator) \ if (validator) \
result = (*validator)(array, result); \ result = (*validator)(node, array, result); \
else if (result & CFARRAYOVERFLOW) \ if (result & ~CFEMPTY) { \
warn_no_array(node, result); \
array->ac = 0; \ array->ac = 0; \
} \
if (array->ac == 0) \ if (array->ac == 0) \
result |= CFEMPTY; \ result |= CFEMPTY; \
return result; \ return result; \