aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-03 17:49:29 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-03 21:23:21 +0300
commit3d679b3df641f59fb81ca1651799f4e2965ed67e (patch)
tree5a614ee25cff44d015ee9e6f6920e2ba19379bba /src
parent24ec67c9f6375d34d88e79981ed8abbe15a78169 (diff)
downloadgrecs-3d679b3df641f59fb81ca1651799f4e2965ed67e.tar.gz
grecs-3d679b3df641f59fb81ca1651799f4e2965ed67e.tar.bz2
Switch to the two-layer model. Add testsuite.
The configuration file parser creates a syntax tree. This step does not require any knowledge about which keywords are allowed. The user can then either use that tree directly, or post-process it using parser tables. The latter approach is equivalent to previous versions of grecs.
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore4
-rw-r--r--src/Makefile.am3
-rw-r--r--src/diag.c73
-rw-r--r--src/format.c121
-rw-r--r--src/grecs-gram.y715
-rw-r--r--src/grecs.h86
-rw-r--r--src/lookup.c272
-rw-r--r--src/tree.c773
8 files changed, 1341 insertions, 706 deletions
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..7c38320
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,4 @@
1grecs-gram.c
2grecs-gram.h
3grecs-gram.output
4grecs-lex.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 759716b..0c2c444 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,14 +16,17 @@
16 16
17noinst_LIBRARIES=libgrecs.a 17noinst_LIBRARIES=libgrecs.a
18libgrecs_a_SOURCES = \ 18libgrecs_a_SOURCES = \
19 diag.c\
19 format.c\ 20 format.c\
20 grecs-gram.y\ 21 grecs-gram.y\
21 grecs-lex.l\ 22 grecs-lex.l\
22 list.c\ 23 list.c\
24 lookup.c\
23 mem.c\ 25 mem.c\
24 preproc.c\ 26 preproc.c\
25 symtab.c\ 27 symtab.c\
26 text.c\ 28 text.c\
29 tree.c\
27 grecs.h\ 30 grecs.h\
28 wordsplit.c\ 31 wordsplit.c\
29 wordsplit.h 32 wordsplit.h
diff --git a/src/diag.c b/src/diag.c
new file mode 100644
index 0000000..fcb8fd2
--- /dev/null
+++ b/src/diag.c
@@ -0,0 +1,73 @@
1/* grecs - Gray's Extensible Configuration System
2 Copyright (C) 2007-2011 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 <grecs.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <errno.h>
25
26static void
27default_print_diag(grecs_locus_t *locus, int err, int errcode, const char *msg)
28{
29 if (locus)
30 fprintf(stderr, "%s:%d: ", locus->file, locus->line);
31 if (!err)
32 fprintf(stderr, "warning: ");
33 fprintf(stderr, "%s", msg);
34 if (errcode)
35 fprintf(stderr, ": %s", strerror(errno));
36 fputc('\n', stderr);
37}
38
39void (*grecs_print_diag_fun)(grecs_locus_t *, int, int, const char *msg) =
40 default_print_diag;
41
42void
43grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...)
44{
45 va_list ap;
46 char *buf = NULL;
47 size_t size = 0;
48
49 va_start(ap, fmt);
50 if (grecs_vasprintf(&buf, &size, fmt, ap))
51 grecs_alloc_die();
52 va_end(ap);
53 grecs_print_diag_fun(locus, 0, errcode, buf);
54 free(buf);
55}
56
57void
58grecs_error(grecs_locus_t *locus, int errcode, const char *fmt, ...)
59{
60 va_list ap;
61 char *buf = NULL;
62 size_t size = 0;
63
64 va_start(ap, fmt);
65 if (grecs_vasprintf(&buf, &size, fmt, ap))
66 grecs_alloc_die();
67 va_end(ap);
68 grecs_print_diag_fun(locus, 1, errcode, buf);
69 free(buf);
70 grecs_error_count++;
71}
72
73
diff --git a/src/format.c b/src/format.c
index fc6c8d6..11b405a 100644
--- a/src/format.c
+++ b/src/format.c
@@ -24,7 +24,7 @@
24#include <string.h> 24#include <string.h>
25 25
26const char * 26const char *
27grecs_data_type_string (enum grecs_data_type type) 27grecs_data_type_string(enum grecs_data_type type)
28{ 28{
29 switch (type) { 29 switch (type) {
30 case grecs_type_void: 30 case grecs_type_void:
@@ -68,14 +68,14 @@ grecs_data_type_string (enum grecs_data_type type)
68} 68}
69 69
70static void 70static void
71format_level(FILE *stream, unsigned level) 71format_level(unsigned level, FILE *stream)
72{ 72{
73 while (level--) 73 while (level--)
74 fprintf(stream, " "); 74 fprintf(stream, " ");
75} 75}
76 76
77void 77void
78grecs_format_docstring(FILE *stream, const char *docstring, unsigned level) 78grecs_format_docstring(const char *docstring, unsigned level, FILE *stream)
79{ 79{
80 size_t len = strlen(docstring); 80 size_t len = strlen(docstring);
81 int width = 78 - level * 2; 81 int width = 78 - level * 2;
@@ -101,7 +101,7 @@ grecs_format_docstring(FILE *stream, const char *docstring, unsigned level)
101 if (seglen == 0 || *p == 0) 101 if (seglen == 0 || *p == 0)
102 seglen = p - docstring; 102 seglen = p - docstring;
103 103
104 format_level(stream, level); 104 format_level(level, stream);
105 fprintf(stream, "# "); 105 fprintf(stream, "# ");
106 fwrite(docstring, seglen, 1, stream); 106 fwrite(docstring, seglen, 1, stream);
107 fputc('\n', stream); 107 fputc('\n', stream);
@@ -119,14 +119,14 @@ grecs_format_docstring(FILE *stream, const char *docstring, unsigned level)
119} 119}
120 120
121void 121void
122grecs_format_simple_statement(FILE *stream, struct grecs_keyword *kwp, 122grecs_format_simple_statement(struct grecs_keyword *kwp, unsigned level,
123 unsigned level) 123 FILE *stream)
124{ 124{
125 const char *argstr; 125 const char *argstr;
126 126
127 if (kwp->docstring) 127 if (kwp->docstring)
128 grecs_format_docstring(stream, kwp->docstring, level); 128 grecs_format_docstring(kwp->docstring, level, stream);
129 format_level(stream, level); 129 format_level(level, stream);
130 130
131 if (kwp->argname) 131 if (kwp->argname)
132 argstr = kwp->argname; 132 argstr = kwp->argname;
@@ -136,7 +136,7 @@ grecs_format_simple_statement(FILE *stream, struct grecs_keyword *kwp,
136 if (strchr("<[", argstr[0])) 136 if (strchr("<[", argstr[0]))
137 fprintf(stream, "%s %s;\n", kwp->ident, gettext(argstr)); 137 fprintf(stream, "%s %s;\n", kwp->ident, gettext(argstr));
138 else if (strchr (argstr, ':')) 138 else if (strchr (argstr, ':'))
139 fprintf (stream, "%s <%s>;\n", kwp->ident, gettext(argstr)); 139 fprintf(stream, "%s <%s>;\n", kwp->ident, gettext(argstr));
140 else { 140 else {
141 fprintf(stream, "%s <%s: ", kwp->ident, gettext(argstr)); 141 fprintf(stream, "%s <%s: ", kwp->ident, gettext(argstr));
142 if (GRECS_IS_LIST(kwp->type)) 142 if (GRECS_IS_LIST(kwp->type))
@@ -151,34 +151,117 @@ grecs_format_simple_statement(FILE *stream, struct grecs_keyword *kwp,
151} 151}
152 152
153void 153void
154grecs_format_block_statement(FILE *stream, struct grecs_keyword *kwp, 154grecs_format_block_statement(struct grecs_keyword *kwp, unsigned level,
155 unsigned level) 155 FILE *stream)
156{ 156{
157 if (kwp->docstring) 157 if (kwp->docstring)
158 grecs_format_docstring(stream, kwp->docstring, level); 158 grecs_format_docstring(kwp->docstring, level, stream);
159 format_level(stream, level); 159 format_level(level, stream);
160 fprintf(stream, "%s", kwp->ident); 160 fprintf(stream, "%s", kwp->ident);
161 if (kwp->argname) 161 if (kwp->argname)
162 fprintf(stream, " <%s>", gettext(kwp->argname)); 162 fprintf(stream, " <%s>", gettext(kwp->argname));
163 fprintf(stream, " {\n"); 163 fprintf(stream, " {\n");
164 grecs_format_statement_array(stream, kwp->kwd, 0, level + 1); 164 grecs_format_statement_array(kwp->kwd, 0, level + 1, stream);
165 format_level(stream, level); 165 format_level(level, stream);
166 fprintf(stream, "}\n"); 166 fprintf(stream, "}\n");
167} 167}
168 168
169void 169void
170grecs_format_statement_array(FILE *stream, struct grecs_keyword *kwp, 170grecs_format_statement_array(struct grecs_keyword *kwp,
171 unsigned n, 171 unsigned n,
172 unsigned level) 172 unsigned level,
173 FILE *stream)
173{ 174{
174 for (; kwp->ident; kwp++, n++) { 175 for (; kwp->ident; kwp++, n++) {
175 if (n) 176 if (n)
176 fputc('\n', stream); 177 fputc('\n', stream);
177 if (kwp->type == grecs_type_section) 178 if (kwp->type == grecs_type_section)
178 grecs_format_block_statement(stream, kwp, level); 179 grecs_format_block_statement(kwp, level, stream);