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) (unidiff)
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
46 46
47GRECS_SRC = \ 47GRECS_SRC = \
48 asprintf.c\ 48 asprintf.c\
49 assert.c\
49 cidr.c\ 50 cidr.c\
50 diag.c\ 51 diag.c\
51 format.c\ 52 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 @@
1/* grecs - Gray's Extensible Configuration System
2 Copyright (C) 2007-2019 Sergey Poznyakoff
3
4 Grecs is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 Grecs is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with Grecs. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <errno.h>
21#include <grecs.h>
22
23int
24grecs_assert_value_type(const grecs_value_t *value, int type,
25 grecs_locus_t *refloc)
26{
27 if (GRECS_VALUE_EMPTY_P(value)) {
28 grecs_error(refloc, 0, _("expected %s"),
29 gettext(grecs_value_type_string(type)));
30 return 1;
31 }
32 if (value->type != type) {
33 grecs_error(&value->locus, 0, _("expected %s, but found %s"),
34 gettext(grecs_value_type_string(type)),
35 gettext(grecs_value_type_string(value->type)));
36 return 1;
37 }
38 return 0;
39}
40
41int
42grecs_assert_scalar_stmt(grecs_locus_t *locus, enum grecs_callback_command cmd)
43{
44 if (cmd != grecs_callback_set_value) {
45 grecs_error(locus, 0, _("unexpected block statement"));
46 return 1;
47 }
48 return 0;
49}
50
51int
52grecs_assert_node_value_type(enum grecs_callback_command cmd,
53 grecs_node_t *node, int type)
54{
55 return grecs_assert_scalar_stmt(&node->locus, cmd)
56 && grecs_assert_value_type(node->v.value, type,
57 &node->locus);
58}
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)
30{ 30{
31 switch (type) { 31 switch (type) {
32 case grecs_type_void: 32 case grecs_type_void:
33 return "void"; 33 return N_("void");
34 34
35 case grecs_type_string: 35 case grecs_type_string:
36 return "string"; 36 return N_("string");
37 37
38 case grecs_type_short: 38 case grecs_type_short:
39 case grecs_type_ushort: 39 case grecs_type_ushort:
@@ -43,31 +43,31 @@ grecs_data_type_string(enum grecs_data_type type)
43 case grecs_type_ulong: 43 case grecs_type_ulong:
44 case grecs_type_size: 44 case grecs_type_size:
45 /*FIXME case grecs_type_off:*/ 45 /*FIXME case grecs_type_off:*/
46 return "number"; 46 return N_("number");
47 47
48 case grecs_type_time: 48 case grecs_type_time:
49 return "time"; 49 return N_("time");
50 50
51 case grecs_type_bool: 51 case grecs_type_bool:
52 return "boolean"; 52 return N_("boolean");
53 53
54 case grecs_type_ipv4: 54 case grecs_type_ipv4:
55 return "IPv4"; 55 return N_("IPv4");
56 56
57 case grecs_type_cidr: 57 case grecs_type_cidr:
58 return "CIDR"; 58 return N_("CIDR");
59 59
60 case grecs_type_host: 60 case grecs_type_host:
61 return "hostname"; 61 return N_("hostname");
62 62
63 case grecs_type_sockaddr: 63 case grecs_type_sockaddr:
64 return "sockaddr"; 64 return N_("sockaddr");
65 65
66 case grecs_type_section: 66 case grecs_type_section:
67 return "section"; 67 return N_("section");
68 68
69 case grecs_type_null: 69 case grecs_type_null:
70 return "null"; 70 return N_("null");
71 } 71 }
72 return "UNKNOWN?"; 72 return "UNKNOWN?";
73} 73}
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)
62 grecs_free(val); 62 grecs_free(val);
63} 63}
64 64
65const char *
66grecs_value_type_string(int t)
67{
68 static const char *types[] = {
69 [GRECS_TYPE_STRING] = N_("string"),
70 [GRECS_TYPE_LIST] = N_("list"),
71 [GRECS_TYPE_ARRAY] = N_("one or more arguments")
72 };
73 if (t >= 0 && t < sizeof(types) / sizeof(types[0]))
74 return types[t];
75 return N_("unrecognized type; please report");
76}
77
65struct grecs_node * 78struct grecs_node *
66grecs_node_create(enum grecs_node_type type, grecs_locus_t *loc) 79grecs_node_create(enum grecs_node_type type, grecs_locus_t *loc)
67{ 80{
@@ -286,14 +299,32 @@ static struct grecs_keyword fake = {
286}; 299};
287 300
288static struct grecs_keyword * 301static struct grecs_keyword *
289find_keyword(struct grecs_keyword *cursect, const char *ident) 302find_keyword(struct grecs_keyword *cursect, grecs_node_t *node)
290{ 303{
291 struct grecs_keyword *kwp;
292
293 if (cursect && cursect->kwd && cursect != &fake) { 304 if (cursect && cursect->kwd && cursect != &fake) {
294 for (kwp = cursect->kwd; kwp->ident; kwp++) 305 struct grecs_keyword *found = NULL, *kwp;
295 if (strcmp(kwp->ident, ident) == 0) 306 char const *msg;
296 return kwp; 307
308 for (kwp = cursect->kwd; kwp->ident; kwp++) {
309 if (strcmp(kwp->ident, node->ident) == 0) {
310 found = kwp;
311 if (kwp->callback
312 || node->down
313 ? kwp->type == grecs_type_section
314 : kwp->type != grecs_type_section)
315 return kwp;
316 }
317 }
318 if (found) {
319 if (found->type == grecs_type_section) {
320 msg = N_("section keyword used as a scalar");
321 } else {
322 msg = N_("scalar keyword used as a section");
323 }
324 } else {
325 msg = N_("unknown keyword");
326 }
327 grecs_error(&node->idloc, 0, "%s", gettext(msg));
297 } else { 328 } else {
298 return &fake; 329 return &fake;
299 } 330 }
@@ -915,21 +946,17 @@ nodeproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
915 946
916 switch (op) { 947 switch (op) {
917 case grecs_tree_recurse_set: 948 case grecs_tree_recurse_set:
918 kwp = find_keyword(clos->cursect, node->ident); 949 kwp = find_keyword(clos->cursect, node);
919 if (!kwp) { 950 if (!kwp)
920 grecs_error(&node->idloc, 0, _("Unknown keyword"));
921 return grecs_tree_recurse_skip; 951 return grecs_tree_recurse_skip;
922 }
923 grecs_process_ident(kwp, node->v.value, CURRENT_BASE(clos), 952 grecs_process_ident(kwp, node->v.value, CURRENT_BASE(clos),
924 &node->idloc); 953 &node->idloc);
925 break; 954 break;
926 955
927 case grecs_tree_recurse_pre: 956 case grecs_tree_recurse_pre:
928 kwp = find_keyword(clos->cursect, node->ident); 957 kwp = find_keyword(clos->cursect, node);
929 if (!kwp) { 958 if (!kwp)
930 grecs_error(&node->locus, 0, _("Unknown keyword"));
931 return grecs_tree_recurse_skip; 959 return grecs_tree_recurse_skip;
932 }
933 stmt_begin(clos, kwp, node); 960 stmt_begin(clos, kwp, node);
934 break; 961 break;
935 962
@@ -1136,13 +1163,9 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
1136 } else { 1163 } else {
1137 struct grecs_keyword *kwp = NULL; 1164 struct grecs_keyword *kwp = NULL;
1138 if (clos->cursect) { 1165 if (clos->cursect) {
1139 kwp = find_keyword(clos->cursect, node->ident); 1166 kwp = find_keyword(clos->cursect, node);
1140 if (!kwp) { 1167 if (!kwp)
1141 grecs_error(&node->locus, 0,
1142 _("%s: unknown keyword"),
1143 node->ident);
1144 return grecs_tree_recurse_skip; 1168 return grecs_tree_recurse_skip;
1145 }
1146 if (kwp->flags & GRECS_INAC) 1169 if (kwp->flags & GRECS_INAC)
1147 return grecs_tree_recurse_skip; 1170 return grecs_tree_recurse_skip;
1148 if (!(kwp->flags & GRECS_MULT) && 1171 if (!(kwp->flags & GRECS_MULT) &&

Return to:

Send suggestions and report system problems to the System administrator.