summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/grecs/node.h2
-rw-r--r--include/grecs/tree.h8
-rw-r--r--include/grecs/value.h1
-rw-r--r--src/Make.am1
-rw-r--r--src/assert.c58
-rw-r--r--src/format.c22
-rw-r--r--src/tree.c63
-rw-r--r--tests/set.at4
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
@@ -32,13 +32,13 @@ typedef struct grecs_node {
grecs_locus_t locus;
struct grecs_node *up;
struct grecs_node *down;
struct grecs_node *next;
struct grecs_node *prev;
char *ident;
- grecs_locus_t idloc;
+ grecs_locus_t idloc; /* Location of the identifier */
union {
grecs_value_t *value;
grecs_symtab_ptr_t texttab;
} v;
} grecs_node_t;
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
@@ -64,8 +64,16 @@ grecs_match_buf_t grecs_match_buf_create(int argc, char **argv,
struct grecs_node *grecs_match_buf_first(struct grecs_match_buf *buf,
struct grecs_node *tree);
struct grecs_node *grecs_match_buf_get_node(grecs_match_buf_t buf);
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
@@ -41,12 +41,13 @@ typedef struct grecs_value {
(!(val) || \
((val)->type == GRECS_TYPE_STRING && (val)->v.string == NULL))
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);
int grecs_value_match(struct grecs_value *pat, struct grecs_value *b,
int flags);
#endif
diff --git a/src/Make.am b/src/Make.am
index 227973e..9fa7688 100644
--- a/src/Make.am
+++ b/src/Make.am
@@ -43,12 +43,13 @@ if GRECS_COND_JSON
GRECS_JSON = json-gram.y json-lex.l jsonfmt.c
GRECS_EXTRA_JSON = json-gram.h
endif
GRECS_SRC = \
asprintf.c\
+ assert.c\
cidr.c\
diag.c\
format.c\
grecs-gram.y\
grecs-lex.l\
ipstr.c\
diff --git a/src/assert.c b/src/assert.c
new file mode 100644
index 0000000..0577768
--- a/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
@@ -27,50 +27,50 @@
const char *
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:
case grecs_type_ushort:
case grecs_type_int:
case grecs_type_uint:
case grecs_type_long:
case grecs_type_ulong:
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?";
}
static void
format_level(unsigned level, FILE *stream)
diff --git a/src/tree.c b/src/tree.c
index e25c6a5..27a6f21 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -59,12 +59,25 @@ void
grecs_value_free(struct grecs_value *val)
{
grecs_value_free_content(val);
grecs_free(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)
{
struct grecs_node *np = grecs_zalloc(sizeof(*np));
np->type = type;
if (loc)
@@ -283,20 +296,38 @@ static struct grecs_keyword fake = {
fake_callback,
NULL,
&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;
}
return NULL;
}
@@ -912,27 +943,23 @@ nodeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
{
struct nodeproc_closure *clos = data;
struct grecs_keyword *kwp;
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);
break;
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;
case grecs_tree_recurse_post:
stmt_end(clos, node);
break;
@@ -1133,19 +1160,15 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
if (clos->sections)
clos->cursect = (struct grecs_keyword *)
grecs_list_pop(clos->sections);
} else {
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;
if (!(kwp->flags & GRECS_MULT) &&
node_reduce(node, kwp, clos->flags))
return grecs_tree_recurse_skip;
if (op == grecs_tree_recurse_pre) {
diff --git a/tests/set.at b/tests/set.at
index 7daad18..c1cb0b0 100644
--- a/tests/set.at
+++ b/tests/set.at
@@ -29,10 +29,10 @@ Program foo:
scalar = no
logging: 1/local1/(null)/0
Program bar:
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

Return to:

Send suggestions and report system problems to the System administrator.