aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-06-05 16:42:37 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-06-05 16:52:58 +0300
commit806485a57fb37784e3e1789fce829a2bac390d99 (patch)
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')
-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
@@ -37,24 +37,25 @@ endif
if GRECS_COND_GIT_PARSER
GRECS_PARSER_GIT = git-parser.c
PARSER_DEFS += -DENABLE_GIT_PARSER
endif
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\
join.c\
lineacc.c\
list.c\
lookup.c\
mem.c\
opthelp.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
@@ -21,62 +21,62 @@
#include <wordsplit.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
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)
{
while (level--)
fprintf(stream, " ");
}
void
diff --git a/src/tree.c b/src/tree.c
index e25c6a5..27a6f21 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -53,24 +53,37 @@ grecs_value_free_content(struct grecs_value *val)
grecs_value_free(val->v.arg.v[i]);
free(val->v.arg.v);
}
}
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)
np->locus = *loc;
return np;
}
struct grecs_node *
grecs_node_create_points(enum grecs_node_type type,
@@ -277,32 +290,50 @@ static struct grecs_keyword fake = {
NULL,
NULL,
grecs_type_void,
GRECS_DFLT,
NULL,
0,
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;
}
static void *
target_ptr(struct grecs_keyword *kwp, char *base)
{
if (kwp->varptr)
base = (char*) kwp->varptr + kwp->offset;
else if (base)
@@ -906,39 +937,35 @@ stmt_end(struct nodeproc_closure *clos, struct grecs_node *node)
if (kwp)
kwp->callback_data = NULL;
}
static enum grecs_tree_recurse_res
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;
}
return grecs_tree_recurse_ok;
}
int
grecs_tree_process(struct grecs_node *node, struct grecs_keyword *kwd)
@@ -1127,31 +1154,27 @@ node_reduce(struct grecs_node *node, struct grecs_keyword *kwp, int flags)
static enum grecs_tree_recurse_res
reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
{
struct nodeproc_closure *clos = data;
if (op == grecs_tree_recurse_post) {
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) {
grecs_list_push(clos->sections, clos->cursect);
clos->cursect = kwp;
}
} else if (node_reduce(node, kwp, clos->flags))
return grecs_tree_recurse_skip;
}

Return to:

Send suggestions and report system problems to the System administrator.