diff options
-rw-r--r-- | include/grecs/node.h | 2 | ||||
-rw-r--r-- | include/grecs/tree.h | 8 | ||||
-rw-r--r-- | include/grecs/value.h | 1 | ||||
-rw-r--r-- | src/Make.am | 1 | ||||
-rw-r--r-- | src/assert.c | 58 | ||||
-rw-r--r-- | src/format.c | 22 | ||||
-rw-r--r-- | src/tree.c | 63 | ||||
-rw-r--r-- | tests/set.at | 4 |
8 files changed, 125 insertions, 34 deletions
diff --git a/include/grecs/node.h b/include/grecs/node.h index 2d879ad..752b002 100644 --- a/include/grecs/node.h +++ b/include/grecs/node.h @@ -36,5 +36,5 @@ typedef struct grecs_node { struct grecs_node *prev; char *ident; - grecs_locus_t idloc; + grecs_locus_t idloc; /* Location of the identifier */ union { grecs_value_t *value; diff --git a/include/grecs/tree.h b/include/grecs/tree.h index 2fb26dd..f13a74b 100644 --- a/include/grecs/tree.h +++ b/include/grecs/tree.h @@ -68,4 +68,12 @@ size_t grecs_match_buf_get_args(grecs_match_buf_t buf, char ***argv); struct grecs_node *grecs_match_buf_get_root(grecs_match_buf_t buf); void grecs_match_buf_set_root(grecs_match_buf_t buf, struct grecs_node *root); + +/* Assertions */ +int grecs_assert_value_type(const grecs_value_t *value, int type, + grecs_locus_t *refloc); +int grecs_assert_scalar_stmt(grecs_locus_t *locus, + enum grecs_callback_command cmd); +int grecs_assert_node_value_type(enum grecs_callback_command cmd, + grecs_node_t *node, int type); #endif diff --git a/include/grecs/value.h b/include/grecs/value.h index 8cd2800..480db9d 100644 --- a/include/grecs/value.h +++ b/include/grecs/value.h @@ -45,4 +45,5 @@ void grecs_value_free(struct grecs_value *val); void grecs_value_free_content(struct grecs_value *val); grecs_value_t *grecs_value_ptr_from_static(grecs_value_t *input); +const char *grecs_value_type_string(int t); int grecs_value_eq(struct grecs_value *a, struct grecs_value *b); diff --git a/src/Make.am b/src/Make.am index 227973e..9fa7688 100644 --- a/src/Make.am +++ b/src/Make.am @@ -47,4 +47,5 @@ endif GRECS_SRC = \ asprintf.c\ + assert.c\ cidr.c\ diag.c\ diff --git a/src/assert.c b/src/assert.c new file mode 100644 index 0000000..0577768 --- /dev/null +++ b/src/assert.c @@ -0,0 +1,58 @@ +/* grecs - Gray's Extensible Configuration System + Copyright (C) 2007-2019 Sergey Poznyakoff + + Grecs 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 3 of the License, or (at your + option) any later version. + + Grecs 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 Grecs. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <errno.h> +#include <grecs.h> + +int +grecs_assert_value_type(const grecs_value_t *value, int type, + grecs_locus_t *refloc) +{ + if (GRECS_VALUE_EMPTY_P(value)) { + grecs_error(refloc, 0, _("expected %s"), + gettext(grecs_value_type_string(type))); + return 1; + } + if (value->type != type) { + grecs_error(&value->locus, 0, _("expected %s, but found %s"), + gettext(grecs_value_type_string(type)), + gettext(grecs_value_type_string(value->type))); + return 1; + } + return 0; +} + +int +grecs_assert_scalar_stmt(grecs_locus_t *locus, enum grecs_callback_command cmd) +{ + if (cmd != grecs_callback_set_value) { + grecs_error(locus, 0, _("unexpected block statement")); + return 1; + } + return 0; +} + +int +grecs_assert_node_value_type(enum grecs_callback_command cmd, + grecs_node_t *node, int type) +{ + return grecs_assert_scalar_stmt(&node->locus, cmd) + && grecs_assert_value_type(node->v.value, type, + &node->locus); +} diff --git a/src/format.c b/src/format.c index af87329..d7cdb0f 100644 --- a/src/format.c +++ b/src/format.c @@ -31,8 +31,8 @@ grecs_data_type_string(enum grecs_data_type type) switch (type) { case grecs_type_void: - return "void"; + return N_("void"); case grecs_type_string: - return "string"; + return N_("string"); case grecs_type_short: @@ -44,29 +44,29 @@ grecs_data_type_string(enum grecs_data_type type) case grecs_type_size: /*FIXME case grecs_type_off:*/ - return "number"; + return N_("number"); case grecs_type_time: - return "time"; + return N_("time"); case grecs_type_bool: - return "boolean"; + return N_("boolean"); case grecs_type_ipv4: - return "IPv4"; + return N_("IPv4"); case grecs_type_cidr: - return "CIDR"; + return N_("CIDR"); case grecs_type_host: - return "hostname"; + return N_("hostname"); case grecs_type_sockaddr: - return "sockaddr"; + return N_("sockaddr"); case grecs_type_section: - return "section"; + return N_("section"); case grecs_type_null: - return "null"; + return N_("null"); } return "UNKNOWN?"; @@ -63,4 +63,17 @@ grecs_value_free(struct grecs_value *val) } +const char * +grecs_value_type_string(int t) +{ + static const char *types[] = { + [GRECS_TYPE_STRING] = N_("string"), + [GRECS_TYPE_LIST] = N_("list"), + [GRECS_TYPE_ARRAY] = N_("one or more arguments") + }; + if (t >= 0 && t < sizeof(types) / sizeof(types[0])) + return types[t]; + return N_("unrecognized type; please report"); +} + struct grecs_node * grecs_node_create(enum grecs_node_type type, grecs_locus_t *loc) @@ -287,12 +300,30 @@ static struct grecs_keyword fake = { static struct grecs_keyword * -find_keyword(struct grecs_keyword *cursect, const char *ident) +find_keyword(struct grecs_keyword *cursect, grecs_node_t *node) { - struct grecs_keyword *kwp; - if (cursect && cursect->kwd && cursect != &fake) { - for (kwp = cursect->kwd; kwp->ident; kwp++) - if (strcmp(kwp->ident, ident) == 0) - return kwp; + struct grecs_keyword *found = NULL, *kwp; + char const *msg; + + for (kwp = cursect->kwd; kwp->ident; kwp++) { + if (strcmp(kwp->ident, node->ident) == 0) { + found = kwp; + if (kwp->callback + || node->down + ? kwp->type == grecs_type_section + : kwp->type != grecs_type_section) + return kwp; + } + } + if (found) { + if (found->type == grecs_type_section) { + msg = N_("section keyword used as a scalar"); + } else { + msg = N_("scalar keyword used as a section"); + } + } else { + msg = N_("unknown keyword"); + } + grecs_error(&node->idloc, 0, "%s", gettext(msg)); } else { return &fake; @@ -916,9 +947,7 @@ nodeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data) switch (op) { case grecs_tree_recurse_set: - kwp = find_keyword(clos->cursect, node->ident); - if (!kwp) { - grecs_error(&node->idloc, 0, _("Unknown keyword")); + kwp = find_keyword(clos->cursect, node); + if (!kwp) return grecs_tree_recurse_skip; - } grecs_process_ident(kwp, node->v.value, CURRENT_BASE(clos), &node->idloc); @@ -926,9 +955,7 @@ nodeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data) case grecs_tree_recurse_pre: - kwp = find_keyword(clos->cursect, node->ident); - if (!kwp) { - grecs_error(&node->locus, 0, _("Unknown keyword")); + kwp = find_keyword(clos->cursect, node); + if (!kwp) return grecs_tree_recurse_skip; - } stmt_begin(clos, kwp, node); break; @@ -1137,11 +1164,7 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data) struct grecs_keyword *kwp = NULL; if (clos->cursect) { - kwp = find_keyword(clos->cursect, node->ident); - if (!kwp) { - grecs_error(&node->locus, 0, - _("%s: unknown keyword"), - node->ident); + kwp = find_keyword(clos->cursect, node); + if (!kwp) return grecs_tree_recurse_skip; - } if (kwp->flags & GRECS_INAC) return grecs_tree_recurse_skip; diff --git a/tests/set.at b/tests/set.at index 7daad18..c1cb0b0 100644 --- a/tests/set.at +++ b/tests/set.at @@ -33,6 +33,6 @@ scalar = 25 logging: 0/local2/baz/0 ], -[:25.1-8: Unknown keyword +[:25.1-8: unknown keyword ]) -AT_CLEANUP
\ No newline at end of file +AT_CLEANUP |