summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org>2019-06-05 13:42:37 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-06-05 13:52:58 (GMT)
commit806485a57fb37784e3e1789fce829a2bac390d99 (patch) (side-by-side diff)
tree963e02852aa0203c912b9947eec0211e8661bc82 /src
parentf7b04cc09b26a7e1342170129dacf896f50f98b2 (diff)
downloadgrecs-806485a57fb37784e3e1789fce829a2bac390d99.tar.gz
grecs-806485a57fb37784e3e1789fce829a2bac390d99.tar.bz2
Fix syntax checking of compound vs. scalar statements. Add assertion functions.
Up to now the parser incorrectly accepted the use of compound statement keyword in scalar context, unless the keyword description had non NULL value in the callback field. This change fixes it. It also defines several assertion functions for use inm callbacks. * src/tree.c (grecs_value_type_string): New function. (find_keyword): Take into account node type. (nodeproc,reduceproc): Leave error reporting to find_keyword. * tests/set.at: Change expected error string. * include/grecs/tree.h (grecs_assert_value_type) (grecs_assert_scalar_stmt) (grecs_assert_node_value_type): New protos. * include/grecs/value.h (grecs_value_type_string): New proto. * src/Make.am: Add assert.c * src/assert.c: New file. * src/format.c (grecs_data_type_string): Add i18n markers to the returned strings.
Diffstat (limited to 'src') (more/less context) (ignore whitespace changes)
-rw-r--r--src/Make.am1
-rw-r--r--src/assert.c58
-rw-r--r--src/format.c22
-rw-r--r--src/tree.c63
4 files changed, 113 insertions, 31 deletions
diff --git a/src/Make.am b/src/Make.am
index 227973e..9fa7688 100644
--- a/src/Make.am
+++ b/src/Make.am
@@ -46,6 +46,7 @@ endif
GRECS_SRC = \
asprintf.c\
+ assert.c\
cidr.c\
diag.c\
format.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
@@ -30,10 +30,10 @@ 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:
@@ -43,31 +43,31 @@ grecs_data_type_string(enum grecs_data_type type)
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?";
}
diff --git a/src/tree.c b/src/tree.c
index e25c6a5..27a6f21 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -62,6 +62,19 @@ grecs_value_free(struct grecs_value *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)
{
@@ -286,14 +299,32 @@ 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;
}
@@ -915,21 +946,17 @@ 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);
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;
@@ -1136,13 +1163,9 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
} 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) &&

Return to:

Send suggestions and report system problems to the System administrator.