Merge branch 'naf2-logging' into 'development'

This commit is contained in:
Andrew Bettison 2013-03-01 17:32:57 +10:30
commit 8771d6181b
9 changed files with 866 additions and 206 deletions

View File

@ -1140,8 +1140,10 @@ int app_config_schema(const struct cli_parsed *parsed, void *context)
if (create_serval_instance_dir() == -1)
return -1;
struct cf_om_node *root = NULL;
if (cf_sch_config_main(&root) == -1)
if (cf_sch_config_main(&root) == -1) {
cf_om_free_node(&root);
return -1;
}
struct cf_om_iterator it;
for (cf_om_iter_start(&it, root); it.node; cf_om_iter_next(&it))
if (it.node->text || it.node->nodc == 0) {
@ -1151,9 +1153,36 @@ int app_config_schema(const struct cli_parsed *parsed, void *context)
cli_puts(it.node->text);
cli_delim("\n");
}
cf_om_free_node(&root);
return 0;
}
int app_config_dump(const struct cli_parsed *parsed, void *context)
{
if (config.debug.verbose)
DEBUG_cli_parsed(parsed);
int full = 0 == cli_arg(parsed, "--full", NULL, NULL, NULL);
if (create_serval_instance_dir() == -1)
return -1;
struct cf_om_node *root = NULL;
int ret = cf_fmt_config_main(&root, &config);
if (ret == CFERROR) {
cf_om_free_node(&root);
return -1;
}
struct cf_om_iterator it;
for (cf_om_iter_start(&it, root); it.node; cf_om_iter_next(&it)) {
if (it.node->text && (full || it.node->line_number)) {
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;
}
int app_config_set(const struct cli_parsed *parsed, void *context)
{
if (config.debug.verbose)
@ -2349,7 +2378,9 @@ struct cli_schema command_line_options[]={
{app_trace,{"mdp","trace","<SID>",NULL},0,
"Trace through the network to the specified node via MDP."},
{app_config_schema,{"config","schema",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
"Dump configuration schema."},
"Display configuration schema."},
{app_config_dump,{"config","dump","[--full]",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
"Dump configuration settings."},
{app_config_set,{"config","set","<variable>","<value>","...",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
"Set and del specified configuration variables."},
{app_config_set,{"config","del","<variable>","...",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,

180
conf.h
View File

@ -238,6 +238,9 @@ int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char
const char *cf_om_get(const struct cf_om_node *root, const char *fullkey);
int cf_om_set(struct cf_om_node **nodep, const char *fullkey, const char *text);
int cf_om_add_child(struct cf_om_node **const parentp, const char *const key);
int cf_om_remove_null_child(struct cf_om_node **parentp, unsigned n);
int cf_om_remove_empty_child(struct cf_om_node **parentp, unsigned n);
void cf_om_remove_child(struct cf_om_node **parent, unsigned n);
void cf_om_free_node(struct cf_om_node **nodep);
void cf_om_dump_node(const struct cf_om_node *node, int indent);
int cf_om_match(const char *pattern, const struct cf_om_node *node);
@ -319,10 +322,10 @@ struct pattern_list {
struct config_##__name { \
unsigned ac; \
struct config_##__name##__element {
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
__type key;
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
char key[(__strsize) + 1];
#define KEY_ATOM(__type, __keyrepr) \
__type key; // key must be first element in struct
#define KEY_STRING(__strsize, __keyrepr) \
char key[(__strsize) + 1]; // key must be first element in struct
#define VALUE_ATOM(__type, __eltrepr) \
__type value;
#define VALUE_STRING(__strsize, __eltrepr) \
@ -367,8 +370,8 @@ struct pattern_list {
#define ARRAY(__name, __flags, __validator...) \
int cf_dfl_config_##__name(struct config_##__name *a); \
int cf_sch_config_##__name(struct cf_om_node **parentp);
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...)
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...)
#define KEY_ATOM(__type, __keyrepr)
#define KEY_STRING(__strsize, __keyrepr)
#define VALUE_ATOM(__type, __eltrepr)
#define VALUE_STRING(__strsize, __eltrepr)
#define VALUE_NODE(__type, __eltrepr)
@ -393,46 +396,71 @@ struct pattern_list {
#undef VALUE_NODE_STRUCT
#undef END_ARRAY
// Generate config parser function prototypes.
// Generate config parser function prototypes: cf_opt_REPR(), cf_fmt_REPR(), cf_cmp_REPR()
#define __VALIDATOR(__name, __validator...) \
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;
#define STRUCT(__name, __validator...) \
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
int cf_fmt_config_##__name(struct cf_om_node **, const struct config_##__name *); \
int cf_cmp_config_##__name(const struct config_##__name *, const struct config_##__name *); \
__VALIDATOR(__name, ##__validator)
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
int cf_opt_##__repr(__type *, const struct cf_om_node *); \
char * cf_fmt_##__repr(const __type *);
int cf_fmt_##__repr(struct cf_om_node **, const __type *); \
int cf_cmp_##__repr(const __type *, const __type *);
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
int cf_opt_##__repr(__type *, const char *); \
char * cf_fmt_##__repr(const __type *);
int cf_fmt_##__repr(const char **, const __type *); \
int cf_cmp_##__repr(const __type *, const __type *);
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
int cf_opt_##__repr(char *, size_t, const char *); \
char * cf_fmt_##__repr(const char *);
#define SUB_STRUCT(__name, __element, __flags) \
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
struct cf_om_node * cf_fmt_config_##__name(struct config_##__name *);
#define NODE_STRUCT(__name, __element, __repr, __flags) \
int cf_opt_##__repr(struct config_##__name *, const struct cf_om_node *); \
struct cf_om_node * cf_fmt_##__repr(struct config_##__name *);
int cf_fmt_##__repr(const char **, const char *); \
int cf_cmp_##__repr(const char *, const char *);
#define SUB_STRUCT(__structname, __element, __flags) \
int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *); \
int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); \
int cf_cmp_config_##__structname(const struct config_##__structname *, const struct config_##__structname *);
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
SUB_STRUCT(__structname, __element, __flags) \
int cf_opt_##__repr(struct config_##__structname *, const struct cf_om_node *); \
int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); \
int cf_cmp_##__repr(const struct config_##__structname *, const struct config_##__structname *);
#define END_STRUCT
#define ARRAY(__name, __flags, __validator...) \
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
int cf_fmt_config_##__name(struct cf_om_node **, const struct config_##__name *); \
int cf_cmp_config_##__name(const struct config_##__name *, const struct config_##__name *); \
__VALIDATOR(__name, ##__validator)
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
int cf_opt_##__keyrepr(__type *, const char *);
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
int cf_opt_##__keyrepr(char *, size_t, const char *);
#define KEY_ATOM(__type, __keyrepr) \
int cf_opt_##__keyrepr(__type *, const char *); \
int cf_fmt_##__keyrepr(const char **, const __type *); \
int cf_cmp_##__keyrepr(const __type *, const __type *);
#define KEY_STRING(__strsize, __keyrepr) \
int cf_opt_##__keyrepr(char *, size_t, const char *); \
int cf_fmt_##__keyrepr(const char **, const char *); \
int cf_cmp_##__keyrepr(const char *, const char *);
#define VALUE_ATOM(__type, __eltrepr) \
int cf_opt_##__eltrepr(__type *, const char *);
int cf_opt_##__eltrepr(__type *, const char *); \
int cf_fmt_##__eltrepr(const char **, const __type *); \
int cf_cmp_##__eltrepr(const __type *, const __type *);
#define VALUE_STRING(__strsize, __eltrepr) \
int cf_opt_##__eltrepr(char *, size_t, const char *);
int cf_opt_##__eltrepr(char *, size_t, const char *); \
int cf_fmt_##__eltrepr(const char **, const char *); \
int cf_cmp_##__eltrepr(const char *, const char *);
#define VALUE_NODE(__type, __eltrepr) \
int cf_opt_##__eltrepr(__type *, const struct cf_om_node *);
int cf_opt_##__eltrepr(__type *, const struct cf_om_node *); \
int cf_fmt_##__eltrepr(struct cf_om_node **, const __type *); \
int cf_cmp_##__eltrepr(const __type *, const __type *);
#define VALUE_SUB_STRUCT(__structname) \
int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *);
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
int cf_opt_##__eltrepr(struct config_##__structname *, const struct cf_om_node *);
int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *); \
int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); \
int cf_cmp_config_##__structname(const struct config_##__structname *, const struct config_##__structname *);
#define VALUE_NODE_STRUCT(__structname, __repr) \
VALUE_SUB_STRUCT(__structname) \
int cf_opt_##__repr(struct config_##__structname *, const struct cf_om_node *); \
int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); \
int cf_cmp_##__repr(const struct config_##__structname *, const struct config_##__structname *);
#define END_ARRAY(__size)
#include "conf_schema.h"
#undef __VALIDATOR
@ -453,54 +481,6 @@ struct pattern_list {
#undef VALUE_NODE_STRUCT
#undef END_ARRAY
// Generate config array key comparison function prototypes.
#define STRUCT(__name, __validator...)
#define NODE(__type, __element, __default, __repr, __flags, __comment)
#define ATOM(__type, __element, __default, __repr, __flags, __comment)
#define STRING(__size, __element, __default, __repr, __flags, __comment)
#define SUB_STRUCT(__name, __element, __flags)
#define NODE_STRUCT(__name, __element, __repr, __flags)
#define END_STRUCT
#define ARRAY(__name, __flags, __validator...) \
typedef int __compare_func__config_##__name##__t
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
(const __type *, const __type *);
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
(const char *, const char *);
#define VALUE_ATOM(__type, __eltrepr)
#define VALUE_STRING(__strsize, __eltrepr)
#define VALUE_NODE(__type, __eltrepr)
#define VALUE_SUB_STRUCT(__structname)
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
#define END_ARRAY(__size)
#include "conf_schema.h"
#undef ARRAY
#undef KEY_ATOM
#undef KEY_STRING
#define ARRAY(__name, __flags, __validator...) \
__compare_func__config_##__name##__t __dummy__compare_func__config_##__name
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
,##__cmpfunc;
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
,##__cmpfunc;
#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
// Generate config array search-by-key function prototypes.
#define STRUCT(__name, __validator...)
#define NODE(__type, __element, __default, __repr, __flags, __comment)
@ -511,9 +491,9 @@ struct pattern_list {
#define END_STRUCT
#define ARRAY(__name, __flags, __validator...) \
int config_##__name##__get(const struct config_##__name *,
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
#define KEY_ATOM(__type, __keyrepr) \
const __type *);
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
#define KEY_STRING(__strsize, __keyrepr) \
const char *);
#define VALUE_ATOM(__type, __eltrepr)
#define VALUE_STRING(__strsize, __eltrepr)
@ -540,28 +520,72 @@ struct pattern_list {
#undef END_ARRAY
int cf_opt_char_boolean(char *booleanp, const char *text);
int cf_fmt_char_boolean(const char **, const char *booleanp);
int cf_opt_int_boolean(int *booleanp, const char *text);
int cf_fmt_int_boolean(const char **, const int *booleanp);
int cf_opt_absolute_path(char *str, size_t len, const char *text);
int cf_fmt_absolute_path(const char **, const char *path);
int cf_opt_rhizome_peer(struct config_rhizome_peer *, const struct cf_om_node *node);
int cf_fmt_rhizome_peer(struct cf_om_node **, const struct config_rhizome_peer *);
int cf_opt_rhizome_peer_from_uri(struct config_rhizome_peer *, const char *uri);
int cf_opt_str(char *str, size_t len, const char *text);
int cf_fmt_str(const char **, const char *str);
int cf_opt_str_nonempty(char *str, size_t len, const char *text);
int cf_fmt_str_nonempty(const char **, const char *str);
int cf_opt_int(int *intp, const char *text);
int cf_fmt_int(const char **, const int *intp);
int cf_opt_uint16(uint16_t *intp, const char *text);
int cf_fmt_int16(const char **, const int16_t *intp);
int cf_opt_uint16_nonzero(uint16_t *intp, const char *text);
int cf_fmt_int16_nonzero(const char **, const uint16_t *intp);
int cf_opt_int32_nonneg(int32_t *intp, const char *text);
int cf_fmt_int32_nonneg(const char **, const int32_t *intp);
int cf_opt_uint32_nonzero(uint32_t *intp, const char *text);
int cf_fmt_uint32_nonzero(const char **, const uint32_t *intp);
int cf_opt_uint64_scaled(uint64_t *intp, const char *text);
int cf_fmt_uint64_scaled(const char **, const uint64_t *intp);
int cf_opt_protocol(char *str, size_t len, const char *text);
int cf_fmt_protocol(const char **, const char *str);
int cf_opt_in_addr(struct in_addr *addrp, const char *text);
int cf_fmt_in_addr(const char **, const struct in_addr *addrp);
int cf_opt_sid(sid_t *sidp, const char *text);
int cf_fmt_sid(const char **, const sid_t *sidp);
int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text);
int cf_fmt_rhizome_bk(const char **, const rhizome_bk_t *bkp);
int cf_opt_interface_type(short *typep, const char *text);
int cf_fmt_interface_type(const char **, const short *typep);
int cf_opt_pattern_list(struct pattern_list *listp, const char *text);
int cf_fmt_pattern_list(const char **, const struct pattern_list *listp);
int cf_opt_network_interface(struct config_network_interface *nifp, const struct cf_om_node *node);
int cf_fmt_network_interface(struct cf_om_node **, const struct config_network_interface *nifp);
int cf_opt_interface_list(struct config_interface_list *listp, const struct cf_om_node *node);
int cf_opt_socket_type(int *typep, const char *text);
int cf_opt_encapsulation(int *typep, const char *text);
int cf_fmt_interface_list(struct cf_om_node **, const struct config_interface_list *listp);
int cf_opt_socket_type(short *typep, const char *text);
int cf_fmt_socket_type(const char **, const short *typep);
int cf_opt_encapsulation(short *encapp, const char *text);
int cf_fmt_encapsulation(const char **, const short *encapp);
extern int cf_limbo;
extern struct config_main config;

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;
}
@ -191,6 +191,35 @@ int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char
return -1;
}
int cf_om_remove_null_child(struct cf_om_node **parentp, unsigned n)
{
assert(n < (*parentp)->nodc);
if ((*parentp)->nodv[n] == NULL) {
cf_om_remove_child(parentp, n);
return 1;
}
return 0;
}
int cf_om_remove_empty_child(struct cf_om_node **parentp, unsigned n)
{
assert(n < (*parentp)->nodc);
if ((*parentp)->nodv[n] && (*parentp)->nodv[n]->text == NULL && (*parentp)->nodv[n]->nodc == 0) {
cf_om_remove_child(parentp, n);
return 1;
}
return 0;
}
void cf_om_remove_child(struct cf_om_node **parentp, unsigned n)
{
assert(n < (*parentp)->nodc);
cf_om_free_node(&(*parentp)->nodv[n]);
--(*parentp)->nodc;
for (; n < (*parentp)->nodc; ++n)
(*parentp)->nodv[n] = (*parentp)->nodv[n+1];
}
int cf_om_parse(const char *source, const char *buf, size_t len, struct cf_om_node **rootp)
{
const char *end = buf + len;
@ -261,6 +290,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) {
@ -418,8 +448,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

@ -42,8 +42,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
a->ac = 0; \
return CFOK; \
}
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...)
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...)
#define KEY_ATOM(__type, __keyrepr)
#define KEY_STRING(__strsize, __keyrepr)
#define VALUE_ATOM(__type, __eltrepr)
#define VALUE_STRING(__strsize, __eltrepr)
#define VALUE_NODE(__type, __eltrepr)
@ -68,60 +68,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef VALUE_NODE_STRUCT
#undef END_ARRAY
// Generate array element comparison functions.
#define STRUCT(__name, __validator...)
#define NODE(__type, __element, __default, __repr, __flags, __comment)
#define ATOM(__type, __element, __default, __repr, __flags, __comment)
#define STRING(__size, __element, __default, __repr, __flags, __comment)
#define SUB_STRUCT(__name, __element, __flags)
#define NODE_STRUCT(__name, __element, __repr, __flags)
#define END_STRUCT
#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, __keyrepr, __cmpfunc...) \
,##__cmpfunc); \
return cmp ? (*cmp)(&a->key, &b->key) : memcmp(&a->key, &b->key, sizeof a->key);
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
,##__cmpfunc); \
return cmp ? (*cmp)(a->key, b->key) : strcmp(a->key, b->key);
#define VALUE_ATOM(__type, __eltrepr)
#define VALUE_STRING(__strsize, __eltrepr)
#define VALUE_NODE(__type, __eltrepr)
#define VALUE_SUB_STRUCT(__structname)
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
#define END_ARRAY(__size) \
}
#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
// Schema item flags.
#define __MANDATORY (1<<0)
#define __TEXT (1<<1)
#define __CHILDREN (1<<2)
#define __SORTED (1<<3)
#define __NO_DUPLICATES (1<<4)
#define __NO_DUPLICATES (1<<3)
// 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()
@ -188,14 +144,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define ARRAY(__name, __flags, __validator...) \
int cf_opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
int flags = (0 __flags); \
int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \
int (*keycmp)(const void *, const void *) = NULL; \
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;
#define __ARRAY_KEY(__parseexpr, __cmpfunc...) \
#define __ARRAY_KEY(__parseexpr, __cmpfunc, __cmpfuncargs) \
keycmp = (int (*)(const void *, const void *)) __cmpfunc; \
ret = (__parseexpr); \
if (ret == CFERROR) \
return CFERROR; \
@ -205,7 +162,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
if (ret == CFOK && (flags & __NO_DUPLICATES)) { \
int j; \
for (j = 0; j < n; ++j) { \
if ((*eltcmp)(&array->av[j], &array->av[n]) == 0) { \
if (__cmpfunc __cmpfuncargs == 0) { \
cf_warn_duplicate_node(child, NULL); \
ret |= CFDUPLICATE; \
} \
@ -237,8 +194,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
cf_warn_list_overflow(node->nodv[i]); \
} \
array->ac = n; \
if (flags & __SORTED) \
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) eltcmp); \
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) keycmp); \
if (validator) \
result = (*validator)(node, array, result); \
if (result & ~CFEMPTY) { \
@ -249,10 +205,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
result |= CFEMPTY; \
return result; \
}
#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 KEY_ATOM(__type, __keyrepr) \
__ARRAY_KEY(cf_opt_##__keyrepr(&array->av[n].key, child->key), cf_cmp_##__keyrepr, (&array->av[j].key, &array->av[n].key))
#define KEY_STRING(__strsize, __keyrepr) \
__ARRAY_KEY(cf_opt_##__keyrepr(array->av[n].key, sizeof array->av[n].key, child->key), cf_cmp_##__keyrepr, (&array->av[j].key[0], &array->av[n].key[0]))
#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) \
@ -279,6 +235,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.
@ -291,21 +249,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define END_STRUCT
#define ARRAY(__name, __flags, __validator...) \
int config_##__name##__get(const struct config_##__name *array,
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
#define KEY_ATOM(__type, __keyrepr) \
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) \
if ((cf_cmp_##__keyrepr(key, &array->av[i].key)) == 0) \
return i; \
return -1; \
}
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
#define KEY_STRING(__strsize, __keyrepr) \
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) \
if ((cf_cmp_##__keyrepr(&key[0], &array->av[i].key[0])) == 0) \
return i; \
return -1; \
}
@ -373,9 +329,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
int cf_sch_config_##__name(struct cf_om_node **rootp) { \
int i; \
struct cf_om_node **childp;
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
#define KEY_ATOM(__type, __keyrepr) \
__ADD_CHILD(rootp, "[" #__keyrepr "]")
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
#define KEY_STRING(__strsize, __keyrepr) \
__ADD_CHILD(rootp, "[" #__keyrepr "]")
#define VALUE_ATOM(__type, __eltrepr) \
__ATOM(childp, "(" #__eltrepr ")")
@ -415,3 +371,231 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#undef VALUE_NODE_STRUCT
#undef END_ARRAY
// 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) { \
int result = CFOK; \
int ret;
#define __FMT_TEXT(__repr, __eltname, __eltexpr, __defaultvar) \
const char *text = NULL; \
ret = cf_fmt_##__repr(&text, __eltexpr); \
if (ret == CFOK) { \
int n; \
if (text == NULL) { \
WHY("cf_fmt_" #__repr "() returned CFOK but text=NULL"); \
ret = CFERROR; \
} else if ((n = cf_om_add_child(parentp, __eltname)) == -1) { \
ret = CFERROR; \
} else { \
(*parentp)->nodv[n]->text = text; \
(*parentp)->nodv[n]->line_number = is_default ? 0 : 1; \
text = NULL; \
} \
} else if (ret == CFERROR || !is_default) \
WARNF("cf_fmt_" #__repr "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
if (text) { \
free((char *)text); \
text = NULL; \
} \
if (ret == CFERROR) \
return CFERROR; \
else if (ret != CFOK && !is_default) \
result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS);
#define __FMT_NODE(__fmtfunc, __element) \
{ \
int n = cf_om_add_child(parentp, #__element); \
if (n == -1) \
ret = CFERROR; \
else { \
ret = __fmtfunc(&(*parentp)->nodv[n], &strct->__element); \
cf_om_remove_null_child(parentp, n); \
if (ret != CFOK) \
WARNF(#__fmtfunc "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
if (n < (*parentp)->nodc && cf_om_remove_empty_child(parentp, n)) { \
WHYF(#__fmtfunc "() returned empty node at n=%d", n); \
ret = CFERROR; \
} \
} \
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) \
__FMT_NODE(cf_fmt_##__repr, __element)
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
{ \
__type dfl = __default; \
int is_default = cf_cmp_##__repr(&strct->__element, &dfl) == 0; \
__FMT_TEXT(__repr, #__element, &strct->__element, __default) \
}
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
{ \
int is_default = cf_cmp_##__repr(&strct->__element[0], __default) == 0; \
__FMT_TEXT(__repr, #__element, &strct->__element[0], __default) \
}
#define SUB_STRUCT(__structname, __element, __flags) \
__FMT_NODE(cf_fmt_config_##__structname, __element)
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
__FMT_NODE(cf_fmt_##__repr, __element)
#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) { \
int result = CFOK; \
int i; \
for (i = 0; i < array->ac; ++i) {
#define __ARRAY_KEY(__keyfunc, __keyexpr) \
const char *key = NULL; \
int ret = __keyfunc(&key, __keyexpr); \
int n = -1; \
if (ret != CFOK) { \
WARNF(#__keyfunc "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
} else if (key == NULL) { \
WHY(#__keyfunc "() returned CFOK but key=NULL"); \
ret = CFERROR; \
} else { \
n = cf_om_add_child(parentp, key); \
if (n == -1) \
ret = CFERROR; \
} \
if (key) { \
free((char *)key); \
key = NULL; \
} \
if (ret == CFOK) {
#define __ARRAY_VALUE(__valuefunc) \
cf_om_remove_null_child(parentp, n); \
if (ret != CFOK) \
WARNF(#__valuefunc "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
if (n < (*parentp)->nodc && cf_om_remove_empty_child(parentp, n)) { \
WHYF(#__valuefunc "() returned empty node at n=%d", n); \
ret = CFERROR; \
}
#define __ARRAY_TEXT(__valuefunc, __eltexpr) \
ret = __valuefunc(&(*parentp)->nodv[n]->text, __eltexpr); \
__ARRAY_VALUE(__valuefunc)
#define __ARRAY_NODE(__valuefunc, __eltexpr) \
ret = __valuefunc(&(*parentp)->nodv[n], __eltexpr); \
__ARRAY_VALUE(__valuefunc)
#define END_ARRAY(__size) \
} \
if (ret == CFERROR) \
return CFERROR; \
else if (ret != CFOK) \
result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS); \
} \
if ((*parentp)->nodc == 0) \
cf_om_free_node(parentp); \
return result; \
}
#define KEY_ATOM(__type, __keyrepr) \
__ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key);
#define KEY_STRING(__strsize, __keyrepr) \
__ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key[0]);
#define VALUE_ATOM(__type, __eltrepr) \
__ARRAY_TEXT(cf_fmt_##__eltrepr, &array->av[i].value)
#define VALUE_STRING(__strsize, __eltrepr) \
__ARRAY_TEXT(cf_fmt_##__eltrepr, &array->av[i].value[0])
#define VALUE_NODE(__type, __eltrepr) \
__ARRAY_NODE(cf_fmt_##__eltrepr, &array->av[i].value)
#define VALUE_SUB_STRUCT(__structname) \
__ARRAY_NODE(cf_fmt_config_##__structname, &array->av[i].value)
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
__ARRAY_NODE(cf_fmt_##__eltrepr, &array->av[i].value)
#include "conf_schema.h"
#undef STRUCT
#undef NODE
#undef ATOM
#undef STRING
#undef SUB_STRUCT
#undef NODE_STRUCT
#undef END_STRUCT
#undef __FMT_TEXT
#undef __FMT_NODE
#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 __ARRAY_KEY
#undef __ARRAY_TEXT
#undef __ARRAY_NODE
#undef __ARRAY_VALUE
#undef END_ARRAY
// Generate comparison functions, cf_cmp_config_SECTION()
#define STRUCT(__name, __validator...) \
int cf_cmp_config_##__name(const struct config_##__name *a, const struct config_##__name *b) { \
int c;
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \
return c;
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \
return c;
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
if ((c = cf_cmp_##__repr(&a->__element[0], &b->__element[0]))) \
return c;
#define SUB_STRUCT(__structname, __element, __flags) \
if ((c = cf_cmp_config_##__structname(&a->__element, &b->__element))) \
return c;
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \
return c;
#define END_STRUCT \
return 0; \
}
#define ARRAY(__name, __flags, __validator...) \
int cf_cmp_config_##__name(const struct config_##__name *a, const struct config_##__name *b) { \
int c; \
int i; \
for (i = 0; i < a->ac && i < b->ac; ++i) {
#define KEY_ATOM(__type, __keyrepr) \
if ((c = cf_cmp_##__keyrepr(&a->av[i].key, &b->av[i].key))) \
return c;
#define KEY_STRING(__strsize, __keyrepr) \
if ((c = cf_cmp_##__keyrepr(&a->av[i].key[0], &b->av[i].key[0]))) \
return c;
#define VALUE_ATOM(__type, __eltrepr) \
if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \
return c;
#define VALUE_STRING(__strsize, __eltrepr) \
if ((c = cf_cmp_##__eltrepr(&a->av[i].value[0], &b->av[i].value[0]))) \
return c;
#define VALUE_NODE(__type, __eltrepr) \
if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \
return c;
#define VALUE_SUB_STRUCT(__structname) \
if ((c = cf_cmp_config_##__structname(&a->av[i].value, &b->av[i].value))) \
return c;
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \
return c;
#define END_ARRAY(__size) \
} \
return (a->ac < b->ac) ? -1 : (a->ac > b->ac) ? 1 : 0; \
}
#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

View File

@ -45,6 +45,24 @@ int cf_opt_char_boolean(char *booleanp, const char *text)
return CFINVALID;
}
int cf_fmt_char_boolean(const char **textp, const char *booleanp)
{
if (*booleanp == 1) {
*textp = str_edup("true");
return CFOK;
}
else if (*booleanp == 0) {
*textp = str_edup("false");
return CFOK;
}
return CFINVALID;
}
int cf_cmp_char_boolean(const char *a, const char *b)
{
return !*a && *b ? -1 : *a && !*b ? 1 : 0;
}
int cf_opt_int_boolean(int *booleanp, const char *text)
{
char b;
@ -54,6 +72,24 @@ int cf_opt_int_boolean(int *booleanp, const char *text)
return ret;
}
int cf_fmt_int_boolean(const char **textp, const int *booleanp)
{
if (*booleanp == 1) {
*textp = str_edup("true");
return CFOK;
}
else if (*booleanp == 0) {
*textp = str_edup("false");
return CFOK;
}
return CFINVALID;
}
int cf_cmp_int_boolean(const int *a, const int *b)
{
return !*a && *b ? -1 : *a && !*b ? 1 : 0;
}
int cf_opt_absolute_path(char *str, size_t len, const char *text)
{
if (text[0] != '/')
@ -65,6 +101,19 @@ int cf_opt_absolute_path(char *str, size_t len, const char *text)
return CFOK;
}
int cf_fmt_absolute_path(const char **textp, const char *str)
{
if (str[0] != '/')
return CFINVALID;
*textp = str_edup(str);
return CFOK;
}
int cf_cmp_absolute_path(const char *a, const char *b)
{
return strcmp(a, b);
}
int cf_opt_protocol(char *str, size_t len, const char *text)
{
if (!str_is_uri_scheme(text))
@ -76,6 +125,19 @@ int cf_opt_protocol(char *str, size_t len, const char *text)
return CFOK;
}
int cf_fmt_protocol(const char **textp, const char *str)
{
if (!str_is_uri_scheme(str))
return CFINVALID;
*textp = str_edup(str);
return CFOK;
}
int cf_cmp_protocol(const char *a, const char *b)
{
return strcmp(a, b);
}
int cf_opt_rhizome_peer(struct config_rhizome_peer *rpeer, const struct cf_om_node *node)
{
if (!node->text)
@ -87,6 +149,16 @@ int cf_opt_rhizome_peer(struct config_rhizome_peer *rpeer, const struct cf_om_no
return cf_opt_rhizome_peer_from_uri(rpeer, node->text);
}
int cf_fmt_rhizome_peer(struct cf_om_node **parentp, const struct config_rhizome_peer *rpeer)
{
return cf_fmt_config_rhizome_peer(parentp, rpeer);
}
int cf_cmp_rhizome_peer(const struct config_rhizome_peer *a, const struct config_rhizome_peer *b)
{
return cf_cmp_config_rhizome_peer(a, b);
}
int cf_opt_rhizome_peer_from_uri(struct config_rhizome_peer *rpeer, const char *text)
{
const char *protocol;
@ -129,6 +201,17 @@ int cf_opt_str(char *str, size_t len, const char *text)
return CFOK;
}
int cf_fmt_str(const char **textp, const char *str)
{
*textp = str_edup(str);
return CFOK;
}
int cf_cmp_str(const char *a, const char *b)
{
return strcmp(a, b);
}
int cf_opt_str_nonempty(char *str, size_t len, const char *text)
{
if (!text[0])
@ -136,6 +219,19 @@ int cf_opt_str_nonempty(char *str, size_t len, const char *text)
return cf_opt_str(str, len, text);
}
int cf_fmt_str_nonempty(const char **textp, const char *str)
{
if (!str[0])
return CFINVALID;
*textp = str_edup(str);
return CFOK;
}
int cf_cmp_str_nonempty(const char *a, const char *b)
{
return strcmp(a, b);
}
int cf_opt_int(int *intp, const char *text)
{
const char *end = text;
@ -146,6 +242,19 @@ int cf_opt_int(int *intp, const char *text)
return CFOK;
}
int cf_fmt_int(const char **textp, const int *intp)
{
char buf[22];
sprintf(buf, "%d", *intp);
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_int(const int *a, const int *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cf_opt_uint(unsigned int *uintp, const char *text)
{
const char *end = text;
@ -156,6 +265,19 @@ int cf_opt_uint(unsigned int *uintp, const char *text)
return CFOK;
}
int cf_fmt_uint(const char **textp, const unsigned int *uintp)
{
char buf[22];
sprintf(buf, "%u", *uintp);
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_uint(const unsigned int *a, const unsigned int *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cf_opt_int32_nonneg(int32_t *intp, const char *text)
{
const char *end = text;
@ -166,6 +288,44 @@ int cf_opt_int32_nonneg(int32_t *intp, const char *text)
return CFOK;
}
static int cf_fmt_int32(const char **textp, const int32_t *intp)
{
char buf[12];
sprintf(buf, "%d", *intp);
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_int32(const int32_t *a, const int32_t *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
static int cf_fmt_uint32(const char **textp, const uint32_t *uintp)
{
char buf[12];
sprintf(buf, "%u", *uintp);
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_uint32(const uint32_t *a, const uint32_t *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cf_fmt_int32_nonneg(const char **textp, const int32_t *intp)
{
if (*intp < 0)
return CFINVALID;
return cf_fmt_int32(textp, intp);
}
int cf_cmp_int32_nonneg(const int32_t *a, const int32_t *b)
{
return cf_cmp_int32(a, b);
}
int cf_opt_uint32_nonzero(uint32_t *intp, const char *text)
{
const char *end = text;
@ -176,6 +336,18 @@ int cf_opt_uint32_nonzero(uint32_t *intp, const char *text)
return CFOK;
}
int cf_fmt_uint32_nonzero(const char **textp, const uint32_t *uintp)
{
if (*uintp == 0)
return CFINVALID;
return cf_fmt_uint32(textp, uintp);
}
int cf_cmp_uint32_nonzero(const uint32_t *a, const uint32_t *b)
{
return cf_cmp_uint32(a, b);
}
int cf_opt_uint64_scaled(uint64_t *intp, const char *text)
{
uint64_t result;
@ -186,6 +358,20 @@ int cf_opt_uint64_scaled(uint64_t *intp, const char *text)
return CFOK;
}
int cf_fmt_uint64_scaled(const char **textp, const uint64_t *uintp)
{
char buf[25];
int n = uint64_scaled_to_str(buf, sizeof buf, *uintp);
assert(n != 0);
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_uint64_scaled(const uint64_t *a, const uint64_t *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cf_opt_ushort_nonzero(unsigned short *ushortp, const char *text)
{
uint32_t ui;
@ -195,19 +381,34 @@ int cf_opt_ushort_nonzero(unsigned short *ushortp, const char *text)
return CFOK;
}
int cmp_short(const short *a, const short *b)
int cf_fmt_ushort(const char **textp, const unsigned short *ushortp)
{
char buf[12];
sprintf(buf, "%u", (unsigned int) *ushortp);
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_ushort(const unsigned short *a, const unsigned short *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cmp_ushort(const unsigned short *a, const unsigned short *b)
int cf_fmt_ushort_nonzero(const char **textp, const unsigned short *ushortp)
{
if (*ushortp == 0)
return CFINVALID;
return cf_fmt_ushort(textp, ushortp);
}
int cf_cmp_short(const short *a, const short *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cmp_sid(const sid_t *a, const sid_t *b)
int cf_cmp_ushort_nonzero(const unsigned short *a, const unsigned short *b)
{
return memcmp(a->binary, b->binary, sizeof a->binary);
return cf_cmp_ushort(a, b);
}
int vld_argv(const struct cf_om_node *parent, struct config_argv *array, int result)
@ -255,7 +456,18 @@ int cf_opt_in_addr(struct in_addr *addrp, const char *text)
return CFOK;
}
int cf_opt_uint16(uint16_t *intp, const char *text)
int cf_fmt_in_addr(const char **textp, const struct in_addr *addrp)
{
*textp = str_edup(inet_ntoa(*addrp));
return CFOK;
}
int cf_cmp_in_addr(const struct in_addr *a, const struct in_addr *b)
{
return memcmp(a, b, sizeof(struct in_addr));
}
int cf_opt_uint16(uint16_t *uintp, const char *text)
{
uint16_t ui = 0;
const char *p;
@ -267,19 +479,44 @@ int cf_opt_uint16(uint16_t *intp, const char *text)
}
if (*p)
return CFINVALID;
*intp = ui;
*uintp = ui;
return CFOK;
}
int cf_opt_uint16_nonzero(uint16_t *intp, const char *text)
int cf_fmt_uint16(const char **textp, const uint16_t *uintp)
{
char buf[12];
sprintf(buf, "%u", (unsigned int) *uintp);
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_uint16(const uint16_t *a, const uint16_t *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cf_opt_uint16_nonzero(uint16_t *uintp, const char *text)
{
uint16_t ui;
if (cf_opt_uint16(&ui, text) != CFOK || ui == 0)
return CFINVALID;
*intp = ui;
*uintp = ui;
return CFOK;
}
int cf_fmt_uint16_nonzero(const char **textp, const uint16_t *uintp)
{
if (*uintp == 0)
return CFINVALID;
return cf_fmt_uint16(textp, uintp);
}
int cf_cmp_uint16_nonzero(const uint16_t *a, const uint16_t *b)
{
return cf_cmp_uint16(a, b);
}
int cf_opt_sid(sid_t *sidp, const char *text)
{
if (!str_is_subscriber_id(text))
@ -289,6 +526,17 @@ int cf_opt_sid(sid_t *sidp, const char *text)
return CFOK;
}
int cf_fmt_sid(const char **textp, const sid_t *sidp)
{
*textp = str_edup(alloca_tohex_sid_t(*sidp));
return CFOK;
}
int cf_cmp_sid(const sid_t *a, const sid_t *b)
{
return memcmp(a->binary, b->binary, sizeof a->binary);
}
int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text)
{
if (!rhizome_str_is_bundle_key(text))
@ -298,6 +546,17 @@ int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text)
return CFOK;
}
int cf_fmt_rhizome_bk(const char **textp, const rhizome_bk_t *bkp)
{
*textp = str_edup(alloca_tohex_rhizome_bk_t(*bkp));
return CFOK;
}
int cf_cmp_rhizome_bk(const rhizome_bk_t *a, const rhizome_bk_t *b)
{
return memcmp(a, b, sizeof a->binary);
}
int cf_opt_interface_type(short *typep, const char *text)
{
if (strcasecmp(text, "ethernet") == 0) {
@ -319,7 +578,27 @@ int cf_opt_interface_type(short *typep, const char *text)
return CFINVALID;
}
int cf_opt_socket_type(int *typep, const char *text)
int cf_fmt_interface_type(const char **textp, const short *typep)
{
const char *t = NULL;
switch (*typep) {
case OVERLAY_INTERFACE_ETHERNET: t = "ethernet"; break;
case OVERLAY_INTERFACE_WIFI: t = "wifi"; break;
case OVERLAY_INTERFACE_PACKETRADIO: t = "catear"; break;
case OVERLAY_INTERFACE_UNKNOWN: t = "other"; break;
}
if (!t)
return CFINVALID;
*textp = str_edup(t);
return CFOK;
}
int cf_cmp_interface_type(const short *a, const short *b)
{
return *a < *b ? -1 : *a > *b ? 1 : 0;
}
int cf_opt_socket_type(short *typep, const char *text)
{
if (strcasecmp(text, "dgram") == 0) {
*typep = SOCK_DGRAM;
@ -336,19 +615,56 @@ int cf_opt_socket_type(int *typep, const char *text)
return CFINVALID;
}
int cf_opt_encapsulation(int *typep, const char *text)
int cf_fmt_socket_type(const char **textp, const short *typep)
{
const char *t = NULL;
switch (*typep) {
case SOCK_DGRAM: t = "dgram"; break;
case SOCK_STREAM: t = "stream"; break;
case SOCK_FILE: t = "file"; break;
}
if (!t)
return CFINVALID;
*textp = str_edup(t);
return CFOK;
}
int cf_cmp_socket_type(const short *a, const short *b)
{
return cf_cmp_short(a, b);
}
int cf_opt_encapsulation(short *encapp, const char *text)
{
if (strcasecmp(text, "overlay") == 0) {
*typep = ENCAP_OVERLAY;
*encapp = ENCAP_OVERLAY;
return CFOK;
}
if (strcasecmp(text, "single") == 0) {
*typep = ENCAP_SINGLE;
*encapp = ENCAP_SINGLE;
return CFOK;
}
return CFINVALID;
}
int cf_fmt_encapsulation(const char **textp, const short *encapp)
{
const char *t = NULL;
switch (*encapp) {
case ENCAP_OVERLAY: t = "overlay"; break;
case ENCAP_SINGLE: t = "single"; break;
}
if (!t)
return CFINVALID;
*textp = str_edup(t);
return CFOK;
}
int cf_cmp_encapsulation(const short *a, const short *b)
{
return cf_cmp_short(a, b);
}
int cf_opt_pattern_list(struct pattern_list *listp, const char *text)
{
struct pattern_list list;
@ -370,10 +686,46 @@ int cf_opt_pattern_list(struct pattern_list *listp, const char *text)
word = p;
}
assert(word == NULL);
if (list.patc == 0)
return CFEMPTY;
*listp = list;
return CFOK;
}
int cf_fmt_pattern_list(const char **textp, const struct pattern_list *listp)
{
if (listp->patc == 0)
return CFEMPTY;
char buf[sizeof listp->patv];
char *bufp = buf;
unsigned i;
for (i = 0; i < listp->patc; ++i) {
if (bufp != buf)
*bufp++ = ',';
const char *patvp = listp->patv[i];
const char *npatvp = listp->patv[i + 1];
while (bufp < &buf[sizeof buf - 1] && patvp < npatvp && (*bufp = *patvp))
++bufp, ++patvp;
if (patvp >= npatvp)
return CFINVALID;
assert(bufp < &buf[sizeof buf - 1]);
}
*bufp = '\0';
DEBUGF("buf=%s", alloca_toprint(-1, buf, sizeof buf));
*textp = str_edup(buf);
return CFOK;
}
int cf_cmp_pattern_list(const struct pattern_list *a, const struct pattern_list *b)
{
unsigned i;
for (i = 0; i < a->patc && i < b->patc; ++i) {
int c = strcmp(a->patv[i], b->patv[i]);
if (c)
return c;
}
return (a->patc < b->patc) ? -1 : (a->patc > b->patc) ? 1 : 0;
}
/* Config parse function. Implements the original form of the 'interfaces' config option. Parses a
* single text string of the form:
@ -427,11 +779,11 @@ static int cf_opt_network_interface_legacy(struct config_network_interface *nifp
nif.match.patc = 0;
nif.socket_type = SOCK_FILE;
} else {
int star = (strchr(name, '*') != NULL) ? 1 : 0;
if (len + star >= sizeof(nif.match.patv[0]))
int addstar = strnchr(name, len, '*') == NULL ? 1 : 0;
if (len + addstar >= sizeof(nif.match.patv[0]))
return CFSTRINGOVERFLOW;
strncpy(nif.match.patv[0], name, len)[len + star] = '\0';
if (star)
strncpy(nif.match.patv[0], name, len)[len + addstar] = '\0';
if (addstar)
nif.match.patv[0][len] = '*';
nif.match.patc = 1;
nif.socket_type = SOCK_DGRAM;
@ -490,6 +842,16 @@ int cf_opt_network_interface(struct config_network_interface *nifp, const struct
return cf_opt_network_interface_legacy(nifp, node->text);
}
int cf_fmt_network_interface(struct cf_om_node **parentp, const struct config_network_interface *nifp)
{
return cf_fmt_config_network_interface(parentp, nifp);
}
int cf_cmp_network_interface(const struct config_network_interface *a, const struct config_network_interface *b)
{
return cf_cmp_config_network_interface(a, b);
}
int vld_network_interface(const struct cf_om_node *parent, struct config_network_interface *nifp, int result)
{
if (nifp->match.patc != 0 && nifp->file[0]) {
@ -500,7 +862,6 @@ int vld_network_interface(const struct cf_om_node *parent, struct config_network
cf_warn_incompatible(parent->nodv[nodei_match], parent->nodv[nodei_file]);
return result | CFSUB(CFINCOMPATIBLE);
}
if (nifp->socket_type == SOCK_UNSPECIFIED) {
if (nifp->match.patc != 0)
nifp->socket_type = SOCK_DGRAM;
@ -511,7 +872,6 @@ int vld_network_interface(const struct cf_om_node *parent, struct config_network
return result | CFINCOMPLETE;
}
} else {
if (nifp->socket_type == SOCK_DGRAM && nifp->file[0]){
int nodei_socket_type = cf_om_get_child(parent, "socket_type", NULL);
int nodei_file = cf_om_get_child(parent, "file", NULL);
@ -520,13 +880,11 @@ int vld_network_interface(const struct cf_om_node *parent, struct config_network
cf_warn_incompatible(parent->nodv[nodei_socket_type], parent->nodv[nodei_file]);
return result | CFSUB(CFINCOMPATIBLE);
}
if (nifp->socket_type != SOCK_DGRAM && !nifp->file[0]){
cf_warn_missing_node(parent, "file");
return result | CFSUB(CFINCOMPATIBLE);
}
}
return result;
}
@ -592,3 +950,13 @@ bye:
result |= CFEMPTY;
return result;
}
int cf_fmt_interface_list(struct cf_om_node **parentp, const struct config_interface_list *listp)
{
return cf_fmt_config_interface_list(parentp, listp);
}
int cf_cmp_interface_list(const struct config_interface_list *a, const struct config_interface_list *b)
{
return cf_cmp_config_interface_list(a, b);
}

View File

@ -46,7 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* the following schema would do:
*
* STRUCT(happy)
* ATOM(int32_t, element1, 0, int32_nonnegative,, "An integer >= 0")
* ATOM(int32_t, element1, 0, int32_nonneg,, "An integer >= 0")
* STRING(80, element2, "boo!", str_nonempty, MANDATORY, "A non-empty string")
* END_STRUCT
*
@ -111,8 +111,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* where key-declaration is one of:
*
* KEY_ATOM(type, repr[, comparefunc])
* KEY_STRING(strlen, repr[, comparefunc])
* KEY_ATOM(type, repr)
* KEY_STRING(strlen, repr)
*
* and value-declaration is one of:
*
@ -149,24 +149,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* Only used for ATOM and NODE struct elements. Gives the default value for the element if
* absent from the config file.
* 'repr'
* The string representation. This name specifies a pair of functions, <repr> and
* cf_fmt_<repr> that convert the given 'type' from and to a string respectively:
* - The <repr> functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and
* The string representation. This name specifies a trio of functions, cf_opt_<repr>(),
* cf_fmt_<repr>() and cf_cmp_<repr>():
* - The cf_opt_<repr>() functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and
* VALUE_STRING take a (const char *) argument pointing to nul-terminated text. The
* <repr> functions for NODE and VALUE_NODE take a pointer to a COM node (const
* struct cf_om_node *), and are responsible for parsing the node's text and all of its
* descendents (children).
* - Each cf_fmt_<repr> function is the inverse of <repr>. The cf_fmt_<repr>
* functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and VALUE_STRING all take a
* pointer to a const 'type', and return a malloc()ed nul-terminated string which, if passed
* to <repr>(), would produce the same original value. If the value is invalid
* (outside the legal range) or malloc() fails, then cf_fmt_<repr> returns NULL. The
* cf_fmt_<repr> functions for NODE and VALUE_NODE take a pointer to a const 'type' and
* return a pointer to a malloc()ed COM node (struct cf_om_node *) which, if passed to
* <repr> would produce the same original value.
* 'comparefunc'
* A function used to sort an array after all elements have been parsed, and before being
* validated (see below).
* - Each cf_fmt_<repr>() function is the inverse of cf_opt_<repr>. The cf_fmt_<repr>
* functions for ATOM, KEY_ATOM, KEY_STRING, VALUE_ATOM and VALUE_STRING all take a pointer
* to a const 'type', and produce a malloc()ed nul-terminated string which, if passed to
* cf_opt_<repr>(), would produce the same original value. If the value is invalid (outside
* the legal range) then cf_fmt_<repr> returns CFINVALID or CFEMPTY. The cf_fmt_<repr>
* functions for NODE and VALUE_NODE take a pointer to a const 'type' and produce a
* malloc()ed COM node (struct cf_om_node *) which, if passed to cf_opt_<repr> would produce
* the same original value.
* - Each cf_cmp_<repr>() function compares two values of the given 'type' and returns -1, 0
* or 1 to indicate the natural ordering of the values. These functions are used to detect
* when config elements have their default values, to avoid calling cf_fmt_<repr>(). They
* are also used to sort array keys.
* 'validatorfunc'
* A function that is called after the struct/array is fully parsed and populated. This
* function can perform validation checks on the whole struct/array that cannot be performed by
@ -239,16 +240,16 @@ END_STRUCT
STRUCT(monitor)
STRING(256, socket, DEFAULT_MONITOR_SOCKET_NAME, str_nonempty,, "Name of socket for monitor interface")
ATOM(int, uid, -1, int,, "Allowed UID for monitor socket client")
ATOM(uint32_t, uid, 0, uint32_nonzero,, "Allowed UID for monitor socket client")
END_STRUCT
STRUCT(mdp_iftype)
ATOM(uint32_t, tick_ms, -1, uint32_nonzero,, "Tick interval for this interface type")
ATOM(int, packet_interval, -1, int,, "Minimum interval between packets in microseconds")
ATOM(int32_t, packet_interval, -1, int32_nonneg,, "Minimum interval between packets in microseconds")
END_STRUCT
ARRAY(mdp_iftypelist, NO_DUPLICATES)
KEY_ATOM(short, interface_type, cmp_short)
KEY_ATOM(short, interface_type)
VALUE_SUB_STRUCT(mdp_iftype)
END_ARRAY(5)
@ -263,8 +264,8 @@ ATOM(uint16_t, remote_port,4130, uint16_nonzero,, "Remote port numb
ATOM(uint16_t, local_port, 4131, uint16_nonzero,, "Local port number")
END_STRUCT
ARRAY(argv, SORTED NO_DUPLICATES, vld_argv)
KEY_ATOM(unsigned short, ushort_nonzero, cmp_ushort)
ARRAY(argv, NO_DUPLICATES, vld_argv)
KEY_ATOM(unsigned short, ushort_nonzero)
VALUE_STRING(128, str)
END_ARRAY(16)
@ -346,15 +347,15 @@ ATOM(uint16_t, port, PORT_DNA, uint16_nonzero,, "Port number"
END_STRUCT
ARRAY(host_list, NO_DUPLICATES)
KEY_ATOM(sid_t, sid, cmp_sid)
KEY_ATOM(sid_t, sid)
VALUE_SUB_STRUCT(host)
END_ARRAY(32)
STRUCT(network_interface, vld_network_interface)
ATOM(int, exclude, 0, int_boolean,, "If true, do not use matching interfaces")
ATOM(struct pattern_list, match, PATTERN_LIST_EMPTY, pattern_list,, "Names that match network interface")
ATOM(int, socket_type, SOCK_UNSPECIFIED, socket_type,, "Type of network socket")
ATOM(int, encapsulation, ENCAP_OVERLAY, encapsulation,, "Type of packet encapsulation")
ATOM(short, socket_type, SOCK_UNSPECIFIED, socket_type,, "Type of network socket")
ATOM(short, encapsulation, ENCAP_OVERLAY, encapsulation,, "Type of packet encapsulation")
STRING(256, file, "", str_nonempty,, "Path of interface file, absolute or relative to server.interface_path")
ATOM(struct in_addr, dummy_address, hton_in_addr(INADDR_LOOPBACK), in_addr,, "Dummy interface address")
ATOM(struct in_addr, dummy_netmask, hton_in_addr(0xFFFFFF00), in_addr,, "Dummy interface netmask")
@ -362,14 +363,14 @@ ATOM(uint16_t, port, PORT_DNA, uint16_nonzero,, "Port number
ATOM(char, drop_broadcasts, 0, char_boolean,, "If true, drop all incoming broadcast packets")
ATOM(char, drop_unicasts, 0, char_boolean,, "If true, drop all incoming unicast packets")
ATOM(short, type, OVERLAY_INTERFACE_WIFI, interface_type,, "Type of network interface")
ATOM(int, packet_interval, -1, int,, "Minimum interval between packets in microseconds")
ATOM(int, mdp_tick_ms, -1, int32_nonneg,, "Override MDP tick interval for this interface")
ATOM(int32_t, packet_interval, -1, int32_nonneg,, "Minimum interval between packets in microseconds")
ATOM(int32_t, mdp_tick_ms, -1, int32_nonneg,, "Override MDP tick interval for this interface")
ATOM(char, send_broadcasts, 1, char_boolean,, "If false, don't send any broadcast packets")
ATOM(char, default_route, 0, char_boolean,, "If true, use this interface as a default route")
ATOM(char, prefer_unicast, 0, char_boolean,, "If true, send unicast data as unicast IP packets if available")
END_STRUCT
ARRAY(interface_list, SORTED NO_DUPLICATES)
ARRAY(interface_list, NO_DUPLICATES)
KEY_ATOM(unsigned, uint)
VALUE_NODE_STRUCT(network_interface, network_interface)
END_ARRAY(10)

View File

@ -61,6 +61,8 @@ __RHIZOME_INLINE int rhizome_is_bk_none(const rhizome_bk_t *bk) {
return is_all_matching(bk->binary, sizeof bk->binary, 0);
}
#define alloca_tohex_rhizome_bk_t(bk) alloca_tohex((bk).binary, sizeof (*(rhizome_bk_t*)0).binary)
extern time_ms_t rhizome_voice_timeout;
#define RHIZOME_PRIORITY_HIGHEST RHIZOME_PRIORITY_SERVAL_CORE

11
str.c
View File

@ -88,6 +88,17 @@ char *str_toupper_inplace(char *str)
return str;
}
const char *strnchr(const char *s, size_t n, char c)
{
for (; n; --n, ++s) {
if (*s == c)
return s;
if (!*s)
break;
}
return NULL;
}
int str_startswith(const char *str, const char *substring, const char **afterp)
{
while (*substring && *substring == *str)

7
str.h
View File

@ -86,6 +86,13 @@ size_t str_fromprint(unsigned char *dst, const char *src);
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca((dstlen) == -1 ? toprint_len((const char *)(buf),(len), "``") + 1 : (dstlen)), (dstlen), (const char *)(buf), (len), "``")
#define alloca_str_toprint(str) toprint_str((char *)alloca(toprint_str_len(str, "``") + 1), -1, (str), "``")
/* Like strchr(3), but only looks for 'c' in the first 'n' characters of 's', stopping at the first
* nul char in 's'.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
const char *strnchr(const char *s, size_t n, char c);
/* Check if a given nul-terminated string 'str' starts with a given nul-terminated sub-string. If
* so, return 1 and, if afterp is not NULL, set *afterp to point to the character in 'str'
* immediately following the substring. Otherwise return 0.