aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
@@ -26,25 +26,25 @@ enum grecs_node_type {
grecs_node_stmt,
grecs_node_block
};
typedef struct grecs_node {
enum grecs_node_type type;
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;
void grecs_node_free(struct grecs_node *node);
struct grecs_node *grecs_node_create(enum grecs_node_type type,
grecs_locus_t *loc);
struct grecs_node *grecs_node_create_points(enum grecs_node_type type,
struct grecs_locus_point beg,
struct grecs_locus_point end);
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
@@ -58,14 +58,22 @@ struct grecs_node *grecs_match_first(struct grecs_node *tree,
const char *pattern,
grecs_match_buf_t *buf);
struct grecs_node *grecs_match_next(struct grecs_match_buf *buf);
void grecs_match_buf_free(struct grecs_match_buf *buf);
grecs_match_buf_t grecs_match_buf_create(int argc, char **argv,
struct grecs_value **labelv);
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
@@ -35,18 +35,19 @@ typedef struct grecs_value {
struct grecs_value **v;
} arg;
} v;
} grecs_value_t;
#define GRECS_VALUE_EMPTY_P(val) \
(!(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
@@ -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;
}
diff --git a/tests/set.at b/tests/set.at
index 7daad18..c1cb0b0 100644
--- a/tests/set.at
+++ b/tests/set.at
@@ -23,16 +23,16 @@ sed 's|^.*/gcf1.conf||' err >&2],
[Global settings:
scalar = yes
listvar = "a" "2" "b" "c"
logging: 1/mail/(null)/0
Programs configured: 2
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.