summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile.am2
-rw-r--r--am/grecs.m47
-rwxr-xr-xbuild-aux/yyrename92
-rw-r--r--configure.ac2
-rw-r--r--doc/GRECS_SETUP.38
-rw-r--r--doc/grecs_parse.38
-rw-r--r--src/.gitignore4
-rw-r--r--src/Make.am19
-rw-r--r--src/asprintf.c85
-rw-r--r--src/grecs-gram.y80
-rw-r--r--src/grecs-lex.l133
-rw-r--r--src/grecs.h35
-rw-r--r--src/lineacc.c82
-rw-r--r--src/meta1-gram.y217
-rw-r--r--src/meta1-lex.l114
-rw-r--r--src/parser.c60
-rw-r--r--src/txtacc.c187
-rw-r--r--src/wordsplit.c2
-rw-r--r--src/yygrecs.h28
-rw-r--r--src/yytrans20
20 files changed, 944 insertions, 241 deletions
diff --git a/Makefile.am b/Makefile.am
index d614a25..0696c72 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,7 @@
16 16
17ACLOCAL_AMFLAGS = -I am 17ACLOCAL_AMFLAGS = -I am
18SUBDIRS=. src @GRECS_TESTDIR@ @GRECS_DOCDIR@ 18SUBDIRS=. src @GRECS_TESTDIR@ @GRECS_DOCDIR@
19EXTRA_DIST=@GRECS_BUILD_AUX@ gitid.h 19EXTRA_DIST=build-aux/yyrename @GRECS_BUILD_AUX@ gitid.h
20 20
21noinst_HEADERS = gitid.h 21noinst_HEADERS = gitid.h
22BUILT_SOURCES = gitid.h README 22BUILT_SOURCES = gitid.h README
diff --git a/am/grecs.m4 b/am/grecs.m4
index 0d1b03d..8f4868b 100644
--- a/am/grecs.m4
+++ b/am/grecs.m4
@@ -148,7 +148,11 @@ AC_DEFUN([GRECS_SETUP],[
148 GRECS_BUILD_AUX="build-aux/getopt.m4" 148 GRECS_BUILD_AUX="build-aux/getopt.m4"
149 ]) 149 ])
150 _GRECS_IF_OPTION_SET([git2chg],[GRECS_BUILD_AUX="$GRECS_BUILD_AUX build-aux/git2chg.awk"]) 150 _GRECS_IF_OPTION_SET([git2chg],[GRECS_BUILD_AUX="$GRECS_BUILD_AUX build-aux/git2chg.awk"])
151 151 AM_CONDITIONAL([GRECS_COND_META1_PARSER],
152 _GRECS_OPTION_SWITCH([parser-meta1],[true],
153 [all-parsers],[true],
154 [false]))
155
152 AC_SUBST([GRECS_SRCDIR],$1) 156 AC_SUBST([GRECS_SRCDIR],$1)
153 AC_SUBST([GRECS_BUILD_AUX]) 157 AC_SUBST([GRECS_BUILD_AUX])
154 AC_SUBST([GRECS_INCLUDES]) 158 AC_SUBST([GRECS_INCLUDES])
@@ -160,6 +164,7 @@ AC_DEFUN([GRECS_SETUP],[
160 AC_SUBST([GRECS_README]) 164 AC_SUBST([GRECS_README])
161 AC_SUBST([GRECS_INCLUDES],['-I$(top_srcdir)/]grecsdir[src]') 165 AC_SUBST([GRECS_INCLUDES],['-I$(top_srcdir)/]grecsdir[src]')
162 AC_SUBST([GRECS_HOST_PROJECT_INCLUDES]) 166 AC_SUBST([GRECS_HOST_PROJECT_INCLUDES])
167
163 _GRECS_OPTION_SWITCH([install],[ 168 _GRECS_OPTION_SWITCH([install],[
164 LT_INIT 169 LT_INIT
165 GRECS_LDADD=['$(top_builddir)/]grecsdir[src/libgrecs.la'] 170 GRECS_LDADD=['$(top_builddir)/]grecsdir[src/libgrecs.la']
diff --git a/build-aux/yyrename b/build-aux/yyrename
new file mode 100755
index 0000000..5e7b1db
--- a/dev/null
+++ b/build-aux/yyrename
@@ -0,0 +1,92 @@
1#! /bin/sh
2# Rename yy.* identifiers to avoid name clashes. This file is part of Grecs.
3# Copyright (C) 2011 Sergey Poznyakoff
4#
5# Grecs is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3, or (at your option)
8# any later version.
9#
10# Grecs is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Grecs. If not, see <http://www.gnu.org/licenses/>.
17
18# Usage: yyrename [-f OUTFILE [OUTFILE...]] COMMAND INFILE
19# Makefile.am:
20# LEXCOMPILE = yyrename -f $(LEX_OUTPUT_ROOT).c \
21# '$(LEX) $(LFLAGS) $(AM_LFLAGS)'
22# YACCCOMPILE = yyrename '$(YACC) $(YFLAGS) $(AM_YFLAGS)'
23#
24# This script runs COMMAND with INFILE as its argument and scans
25# OUTFILEs for identifiers starting with 'yy'. These identifiers
26# are renamed by replacing 'yy' with the selected prefix.
27#
28# The prefix is looked up in the file yytrans, located in the INFILE's
29# directory. If this file does not exist, the prefix is constructed
30# by concatenating the string 'grecs_' and the ``root name''. The root
31# name is build by removing '-lex.l' or '-gram.y' from the base name.
32# If the latter does not end in any of these, the root name
33# is constructed by removing the suffix from the base name.
34#
35# The yytrans file is a line-oriented lookup table. Empty lines are
36# ignored, usual UNIX comment lines are honored. The remaining lines
37# must consist of two words separated by any amount of whitespace.
38# The first word is a look-up key, the second one provides a translation
39# (yy replacement) for that key.
40#
41# Two look-ups are tried: first the base name and then the root name.
42# If both result in a non-empty replacement, the former is preferred
43# over the latter.
44#
45# The -f option supplies a list of output file names generated by COMMAND.
46# If not supplied, the following defaults are used: y.tab.c and y.tab.h, if
47# INFILE ends in '.y', and yy.lex.c, if it ends in '.l'. If INFILE does not
48# end in any of these suffixes, error is reported.
49#
50# BUGS: Any occurrence of 'yy' is replaced, not only 'yy' prefixes.
51#
52case $1 in
53-f) files=$2
54 shift
55 shift
56esac
57
58base=`expr "$2" : '.*/\(.*\)\.[ly]'`
59dir=`dirname "$2"`
60case $2 in
61*.y) test -z "$files" && files="y.tab.c y.tab.h"
62 root=`expr "$2" : '.*/\(.*\)-gram\.y'`;;
63*.l) test -z "$files" && files=lex.yy.c
64 root=`expr "$2" : '.*/\(.*\)-lex\.l'`;;
65*) if test -z "$files"; then
66 echo >&2 "$0: suffix unknown, files must be given (use -f)"
67 exit 1
68 fi
69 root=$base
70esac
71
72if test -f $dir/yytrans; then
73 pfx=`awk '
74{ sub(/#.*$/,"") }
75NF == 2 && $1=="'$base'" { exact=$2 }
76NF == 2 && $1=="'$root'" { root=$2 }
77{ next }
78END { print exact ? exact : root ? root : "" }' $dir/yytrans`
79else
80 pfx=
81fi
82if test -z "$pfx"; then
83 pfx=grecs_`echo $root | tr .- __`
84fi
85
86eval $* || exit $?
87
88for file in $files
89do
90 mv $file ${file}.tmp
91 sed "s/yy/$pfx/g" ${file}.tmp > $file
92done
diff --git a/configure.ac b/configure.ac
index 980c713..816de11 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,6 +37,6 @@ AC_HEADER_STDC
37 37
38# Grecs subsystem 38# Grecs subsystem
39 39
40GRECS_SETUP(., [install tests git2chg]) 40GRECS_SETUP(., [install tests git2chg all-parsers])
41 41
42AC_OUTPUT 42AC_OUTPUT
diff --git a/doc/GRECS_SETUP.3 b/doc/GRECS_SETUP.3
index c24399e..13b568e 100644
--- a/doc/GRECS_SETUP.3
+++ b/doc/GRECS_SETUP.3
@@ -14,7 +14,7 @@
14.\" You should have received a copy of the GNU General Public License 14.\" You should have received a copy of the GNU General Public License
15.\" along with Grecs. If not, see <http://www.gnu.org/licenses/>. 15.\" along with Grecs. If not, see <http://www.gnu.org/licenses/>.
16.\" 16.\"
17.TH GRECS_SETUP 3 "May 8, 2011" "GRECS" "Grecs User Reference" 17.TH GRECS_SETUP 3 "May 15, 2011" "GRECS" "Grecs User Reference"
18.SH NAME 18.SH NAME
19GRECS_SETUP \- Initialize \fBgrecs\fR submodule. 19GRECS_SETUP \- Initialize \fBgrecs\fR submodule.
20.SH SYNOPSIS 20.SH SYNOPSIS
@@ -44,6 +44,12 @@ The
44argument is a space-separated list of options. The following options 44argument is a space-separated list of options. The following options
45are understood: 45are understood:
46.TP 46.TP
47.B all-parsers
48Compile all available parsers.
49.TP
50.B parser-meta1
51Build the parser for MeTA1 configuration files.
52.TP
47.B no-preproc 53.B no-preproc
48Disable the use of preprocessor. 54Disable the use of preprocessor.
49.TP 55.TP
diff --git a/doc/grecs_parse.3 b/doc/grecs_parse.3
index 2abc417..dff6759 100644
--- a/doc/grecs_parse.3
+++ b/doc/grecs_parse.3
@@ -149,13 +149,11 @@ screen:
149int 149int
150main(int argc, char **argv) 150main(int argc, char **argv)
151{ 151{
152 struct grecs_node *tree, *node; 152 struct grecs_node *tree;
153 153
154 tree = grecs_parse(argv[1]); 154 tree = grecs_parse(argv[1]);
155 for (node = tree; node; node = node->next) { 155 grecs_format_node(tree, GRECS_NODE_FLAG_DEFAULT, stdout);
156 grecs_format_node(node, GRECS_NODE_FLAG_DEFAULT, stdout); 156 fputc('\\n', stdout);
157 fputc('\n', stdout);
158 }
159 grecs_tree_free(tree); 157 grecs_tree_free(tree);
160 exit(0); 158 exit(0);
161} 159}
diff --git a/src/.gitignore b/src/.gitignore
index 9ef1b57..feb5040 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -2,6 +2,10 @@ grecs-gram.c
2grecs-gram.h 2grecs-gram.h
3grecs-gram.output 3grecs-gram.output
4grecs-lex.c 4grecs-lex.c
5meta1-gram.c
6meta1-gram.h
7meta1-gram.output
8meta1-lex.c
5Make-inst.in 9Make-inst.in
6Make-shared.in 10Make-shared.in
7Make-static.in 11Make-static.in
diff --git a/src/Make.am b/src/Make.am
index 915e6c4..60c0f06 100644
--- a/src/Make.am
+++ b/src/Make.am
@@ -14,26 +14,36 @@
14# You should have received a copy of the GNU General Public License 14# You should have received a copy of the GNU General Public License
15# along with Grecs. If not, see <http://www.gnu.org/licenses/>. 15# along with Grecs. If not, see <http://www.gnu.org/licenses/>.
16 16
17if GRECS_COND_META1_PARSER
18 GRECS_PARSER_META1 = meta1-gram.y meta1-lex.l
19 GRECS_EXTRA_META1 = meta1-gram.h
20endif
21
17GRECS_SRC = \ 22GRECS_SRC = \
23 asprintf.c\
18 diag.c\ 24 diag.c\
19 format.c\ 25 format.c\
20 grecs-gram.y\ 26 grecs-gram.y\
21 grecs-lex.l\ 27 grecs-lex.l\
22 join.c\ 28 join.c\
29 lineacc.c\
23 list.c\ 30 list.c\
24 lookup.c\ 31 lookup.c\
25 mem.c\ 32 mem.c\
33 parser.c\
26 preproc.c\ 34 preproc.c\
27 sort.c\ 35 sort.c\
28 symtab.c\ 36 symtab.c\
29 text.c\ 37 text.c\
30 tree.c\ 38 tree.c\
39 txtacc.c\
31 version.c\ 40 version.c\
32 wordsplit.c 41 wordsplit.c\
42 $(GRECS_PARSER_META1)
33 43
34noinst_HEADERS = yygrecs.h 44noinst_HEADERS =
35 45
36EXTRA_DIST=grecs-gram.h $(PP_SETUP_FILE) Make.am Make-inst.am Make-shared.am Make-static.am 46EXTRA_DIST=grecs-gram.h $(GRECS_EXTRA_META1) $(PP_SETUP_FILE) Make.am Make-inst.am Make-shared.am Make-static.am
37 47
38INCLUDES = -I$(srcdir) -I$(top_srcdir)/@GRECS_SUBDIR@ @GRECS_INCLUDES@ @GRECS_HOST_PROJECT_INCLUDES@ 48INCLUDES = -I$(srcdir) -I$(top_srcdir)/@GRECS_SUBDIR@ @GRECS_INCLUDES@ @GRECS_HOST_PROJECT_INCLUDES@
39AM_YFLAGS = -dtv 49AM_YFLAGS = -dtv
@@ -41,3 +51,6 @@ AM_LFLAGS = -d
41 51
42incdir=$(pkgdatadir)/$(VERSION)/include 52incdir=$(pkgdatadir)/$(VERSION)/include
43inc_DATA = $(PP_SETUP_FILE) 53inc_DATA = $(PP_SETUP_FILE)
54
55LEXCOMPILE = $(top_srcdir)/@GRECS_SUBDIR@/build-aux/yyrename '$(LEX) $(LFLAGS) $(AM_LFLAGS)'
56YACCCOMPILE = $(top_srcdir)/@GRECS_SUBDIR@/build-aux/yyrename '$(YACC) $(YFLAGS) $(AM_YFLAGS)' \ No newline at end of file
diff --git a/src/asprintf.c b/src/asprintf.c
new file mode 100644
index 0000000..d493fcb
--- a/dev/null
+++ b/src/asprintf.c
@@ -0,0 +1,85 @@
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 <stdlib.h>
21#include <string.h>
22#include <errno.h>
23#include "grecs.h"
24
25int
26grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap)
27{
28 char *buf = *pbuf;
29 size_t buflen = *psize;
30 int rc = 0;
31
32 if (!buf) {
33 if (buflen == 0)
34 buflen = 512; /* Initial allocation */
35
36 buf = calloc(1, buflen);
37 if (buf == NULL)
38 return ENOMEM;
39 }
40
41 for (;;) {
42 ssize_t n = vsnprintf(buf, buflen, fmt, ap);
43 if (n < 0 || n >= buflen || !memchr(buf, '\0', n + 1)) {
44 char *newbuf;
45 size_t newlen = buflen * 2;
46 if (newlen < buflen) {
47 rc = ENOMEM;
48 break;
49 }
50 newbuf = realloc(buf, newlen);
51 if (newbuf == NULL) {
52 rc = ENOMEM;
53 break;
54 }
55 buflen = newlen;
56 buf = newbuf;
57 } else
58 break;
59 }
60
61 if (rc) {
62 if (!*pbuf) {
63 /* We made first allocation, now free it */
64 free(buf);
65 buf = NULL;
66 buflen = 0;
67 }
68 }
69
70 *pbuf = buf;
71 *psize = buflen;
72 return rc;
73}
74
75int
76grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...)
77{
78 int rc;
79 va_list ap;
80
81 va_start(ap, fmt);
82 rc = grecs_vasprintf(pbuf, psize, fmt, ap);
83 va_end(ap);
84 return rc;
85}
diff --git a/src/grecs-gram.y b/src/grecs-gram.y
index 9f8d000..3452074 100644
--- a/src/grecs-gram.y
+++ b/src/grecs-gram.y
@@ -18,7 +18,6 @@
18#ifdef HAVE_CONFIG_H 18#ifdef HAVE_CONFIG_H
19# include <config.h> 19# include <config.h>
20#endif 20#endif
21#include "yygrecs.h"
22#include <grecs.h> 21#include <grecs.h>
23#include <grecs-gram.h> 22#include <grecs-gram.h>
24#include <stdlib.h> 23#include <stdlib.h>
@@ -26,11 +25,10 @@
26#include <string.h> 25#include <string.h>
27#include <errno.h> 26#include <errno.h>
28 27
29static struct grecs_node *parse_tree; 28int yylex(void);
30int grecs_error_count; 29int yyerror(char *s);
31
32int grecs_default_port = 0;
33 30
31static struct grecs_node *parse_tree;
34%} 32%}
35 33
36%union { 34%union {
@@ -239,74 +237,13 @@ yyerror(char *s)
239 return 0; 237 return 0;
240} 238}
241 239
242int
243grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap)
244{
245 char *buf = *pbuf;
246 size_t buflen = *psize;
247 int rc = 0;
248
249 if (!buf) {
250 if (buflen == 0)
251 buflen = 512; /* Initial allocation */
252
253 buf = calloc(1, buflen);
254 if (buf == NULL)
255 return ENOMEM;
256 }
257
258 for (;;) {
259 ssize_t n = vsnprintf(buf, buflen, fmt, ap);
260 if (n < 0 || n >= buflen || !memchr(buf, '\0', n + 1)) {
261 char *newbuf;
262 size_t newlen = buflen * 2;
263 if (newlen < buflen) {
264 rc = ENOMEM;
265 break;
266 }
267 newbuf = realloc(buf, newlen);
268 if (newbuf == NULL) {
269 rc = ENOMEM;
270 break;
271 }
272 buflen = newlen;
273 buf = newbuf;
274 } else
275 break;
276 }
277
278 if (rc) {
279 if (!*pbuf) {
280 /* We made first allocation, now free it */
281 free(buf);
282 buf = NULL;
283 buflen = 0;
284 }
285 }
286
287 *pbuf = buf;
288 *psize = buflen;
289 return rc;
290}
291
292int
293grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...)
294{
295 int rc;
296 va_list ap;
297
298 va_start(ap, fmt);
299 rc = grecs_vasprintf(pbuf, psize, fmt, ap);
300 va_end(ap);
301 return rc;
302}
303
304struct grecs_node * 240struct grecs_node *
305grecs_parse(const char *name) 241grecs_grecs_parser(const char *name, int traceflags)
306{ 242{
307 int rc; 243 int rc;
308 if (grecs_lex_begin(name)) 244 if (grecs_lex_begin(name, traceflags & GRECS_TRACE_LEX))
309 return NULL; 245 return NULL;
246 yydebug = traceflags & GRECS_TRACE_GRAM;
310 parse_tree = NULL; 247 parse_tree = NULL;
311 rc = yyparse(); 248 rc = yyparse();
312 if (grecs_error_count) 249 if (grecs_error_count)
@@ -319,11 +256,6 @@ grecs_parse(const char *name)
319 return parse_tree; 256 return parse_tree;
320} 257}
321 258
322void
323grecs_gram_trace(int n)
324{
325 yydebug = n;
326}
327 259
328 260
329 261
diff --git a/src/grecs-lex.l b/src/grecs-lex.l
index 4d491fe..84ee858 100644
--- a/src/grecs-lex.l
+++ b/src/grecs-lex.l
@@ -3,7 +3,6 @@
3#ifdef HAVE_CONFIG_H 3#ifdef HAVE_CONFIG_H
4# include <config.h> 4# include <config.h>
5#endif 5#endif
6#include "yygrecs.h"
7} 6}
8%{ 7%{
9/* grecs - Gray's Extensible Configuration System 8/* grecs - Gray's Extensible Configuration System
@@ -48,12 +47,9 @@ grecs_locus_t grecs_current_locus; /* Input file location */
48*/ 47*/
49static size_t xlines; 48static size_t xlines;
50 49
51static struct grecs_list *line_acc;
52
53static void multiline_begin(char *); 50static void multiline_begin(char *);
54static void multiline_add(char *); 51static void multiline_add(char *);
55static char *multiline_strip_tabs(char *text); 52static char *multiline_strip_tabs(char *text);
56static void line_add_unescape_last(char *text, size_t len);
57static int ident(void); 53static int ident(void);
58static int isemptystr(int off); 54static int isemptystr(int off);
59 55
@@ -113,9 +109,10 @@ P [1-9][0-9]*
113\"[^\\"\n]*\\. | 109\"[^\\"\n]*\\. |
114\"[^\\"\n]*\\\n { BEGIN(STR); 110\"[^\\"\n]*\\\n { BEGIN(STR);
115 grecs_line_begin(); 111 grecs_line_begin();
116 line_add_unescape_last(yytext + 1, yyleng - 1); } 112 grecs_line_acc_grow_unescape_last(yytext + 1,
113 yyleng - 1); }
117<STR>[^\\"\n]*\\. | 114<STR>[^\\"\n]*\\. |
118<STR>\"[^\\"\n]*\\\n { line_add_unescape_last(yytext, yyleng); } 115<STR>\"[^\\"\n]*\\\n { grecs_line_acc_grow_unescape_last(yytext, yyleng); }
119<STR>[^\\"\n]*\" { BEGIN(INITIAL); 116<STR>[^\\"\n]*\" { BEGIN(INITIAL);
120 if (yyleng > 1) 117 if (yyleng > 1)
121 grecs_line_add(yytext, yyleng - 1); 118 grecs_line_add(yytext, yyleng - 1);
@@ -170,20 +167,12 @@ yywrap()
170 return 1; 167 return 1;
171} 168}
172 169
173static void
174line_acc_free_entry(void *ptr)
175{
176 grecs_free(ptr);
177}
178
179int 170int
180grecs_lex_begin(const char *name) 171grecs_lex_begin(const char *name, int trace)
181{ 172{
182 if (yy_flex_debug > 0) 173 yy_flex_debug = trace;
183 yy_flex_debug = 0;
184 174
185 line_acc = grecs_list_create(); 175 grecs_line_acc_create();
186 line_acc->free_entry = line_acc_free_entry;
187 176
188 if (grecs_preprocessor) { 177 if (grecs_preprocessor) {
189 int fd; 178 int fd;
@@ -211,7 +200,7 @@ grecs_lex_begin(const char *name)
211void 200void
212grecs_lex_end(int err) 201grecs_lex_end(int err)
213{ 202{
214 grecs_list_clear(line_acc); 203 grecs_line_acc_free();
215} 204}
216 205
217static int 206static int
@@ -239,95 +228,21 @@ multiline_strip_tabs(char *text)
239 return text; 228 return text;
240} 229}
241 230
242static int
243unquote_char(int c)
244{
245 static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
246
247 char *p;
248
249 for (p = quote_transtab; *p; p += 2) {
250 if (*p == c)
251 return p[1];
252 }
253 return -1;
254}
255
256struct line_acc_entry
257{
258 size_t size;
259};
260#define line_acc_ptr(entry) (char*)(entry + 1)
261
262static void
263line_acc_add_string(const char *str, size_t len)
264{
265 struct line_acc_entry *ent = grecs_malloc(sizeof(*ent) + len + 1);
266 char *p = line_acc_ptr(ent);
267 memcpy(p, str, len);
268 p[len] = 0;
269 ent->size = len;
270 grecs_list_append(line_acc, ent);
271}
272
273static void
274line_acc_add_char(int c)
275{
276 char t = c;
277 line_acc_add_string(&t, 1);
278}
279
280static void
281list_acc_unescape_char(int c)
282{
283 if (c != '\n') {
284 int t = unquote_char(c);
285 if (t != -1)
286 line_acc_add_char(t);
287 else {
288 grecs_warning(&grecs_current_locus, 0,
289 _("unknown escape sequence '\\%c'"),
290 c);
291 line_acc_add_char(c);
292 }
293 }
294}
295
296void
297grecs_line_add(const char *text, size_t len)
298{
299 line_acc_add_string(text, len);
300}
301
302/* Same, but unescapes the last character from yytext */
303static void
304line_add_unescape_last(char *text, size_t len)
305{
306 line_acc_add_string(text, len - 2);
307 list_acc_unescape_char(text[len - 1]);
308}
309
310static void 231static void
311multiline_add(char *s) 232multiline_add(char *s)
312{ 233{
313 if (multiline_unescape) { 234 if (multiline_unescape) {
314 for (; *s; s++){ 235 for (; *s; s++){
315 if (*s == '\\') { 236 if (*s == '\\') {
316 list_acc_unescape_char(s[1]); 237 grecs_line_acc_grow_char_unescape(s[1]);
317 ++s; 238 ++s;
318 } else 239 } else
319 line_acc_add_char(*s); 240 grecs_line_acc_grow_char(*s);
320 } 241 }
321 } else 242 } else
322 grecs_line_add(s, strlen(s)); 243 grecs_line_add(s, strlen(s));
323} 244}
324 245
325void
326grecs_line_begin()
327{
328 /* FIXME: nothing so far. Maybe prepare stk by calling obstack_finish? */
329}
330
331static int 246static int
332is_tab(char c) 247is_tab(char c)
333{ 248{
@@ -374,30 +289,6 @@ multiline_begin(char *p)
374 grecs_line_begin(); 289 grecs_line_begin();
375} 290}
376 291
377char *
378grecs_line_finish()
379{
380 struct grecs_list_entry *ep;
381 size_t size = 0;
382 char *str, *p;
383
384 for (ep = line_acc->head; ep; ep = ep->next) {
385 struct line_acc_entry *ent = ep->data;
386 size += ent->size;
387 }
388
389 str = grecs_malloc(size + 1);
390 for (ep = line_acc->head, p = str; ep; ep = ep->next) {
391 struct line_acc_entry *ent = ep->data;
392 char *str = line_acc_ptr(ent);
393 memcpy(p, str, ent->size);
394 p += ent->size;
395 }
396 *p = 0;
397 grecs_list_clear(line_acc);
398 return str;
399}
400
401static int 292static int
402ident() 293ident()
403{ 294{
@@ -416,12 +307,6 @@ ident()
416 return IDENT; 307 return IDENT;
417} 308}
418 309
419void
420grecs_lex_trace(int n)
421{
422 yy_flex_debug = -n;
423}
424
425grecs_value_t * 310grecs_value_t *
426grecs_value_ptr_from_static(grecs_value_t *input) 311grecs_value_ptr_from_static(grecs_value_t *input)
427{ 312{
diff --git a/src/grecs.h b/src/grecs.h
index 61a915b..ff47698 100644
--- a/src/grecs.h
+++ b/src/grecs.h
@@ -198,18 +198,39 @@ void grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...)
198 __attribute__ ((__format__ (__printf__, 3, 4))); 198 __attribute__ ((__format__ (__printf__, 3, 4)));
199void grecs_error(grecs_locus_t *locus, int errcode, const char *fmt, ...) 199void grecs_error(grecs_locus_t *locus, int errcode, const char *fmt, ...)
200 __attribute__ ((__format__ (__printf__, 3, 4))); 200 __attribute__ ((__format__ (__printf__, 3, 4)));
201
202
203extern int grecs_trace_flags;
204
205#define GRECS_TRACE_GRAM 0x01
206#define GRECS_TRACE_LEX 0x02
201void grecs_gram_trace(int n); 207void grecs_gram_trace(int n);
202void grecs_lex_trace(int n); 208void grecs_lex_trace(int n);
209
203 210
204int grecs_lex_begin(const char*); 211int grecs_lex_begin(const char*, int);
205void grecs_lex_end(int err); 212void grecs_lex_end(int err);
206struct grecs_node *grecs_parse(const char *name); 213struct grecs_node *grecs_parse(const char *name);
214
215extern struct grecs_node *(*grecs_parser_fun)(const char *name, int trace);
216
217/* Parsers: */
218struct grecs_node *grecs_grecs_parser(const char *name, int traceflags);
219struct grecs_node *grecs_meta1_parser(const char *name, int traceflags);
207 220
221
208struct grecs_list *_grecs_simple_list_create(int dispose); 222struct grecs_list *_grecs_simple_list_create(int dispose);
209struct grecs_list *grecs_value_list_create(void); 223struct grecs_list *grecs_value_list_create(void);
210 224
225void grecs_line_acc_create(void);
226void grecs_line_acc_free(void);
227void grecs_line_acc_grow_char(int c);
228void grecs_line_acc_grow_char_unescape(int c);
229void grecs_line_acc_grow(const char *text, size_t len);
230void grecs_line_acc_grow_unescape_last(char *text, size_t len);
231
211void grecs_line_begin(void); 232void grecs_line_begin(void);
212void grecs_line_add(const char *text, size_t len); 233#define grecs_line_add grecs_line_acc_grow
213char *grecs_line_finish(void); 234char *grecs_line_finish(void);
214 235
215extern int grecs_string_convert(void *target, enum grecs_data_type type, 236extern int grecs_string_convert(void *target, enum grecs_data_type type,
@@ -295,6 +316,13 @@ void grecs_list_add(struct grecs_list *dst, struct grecs_list *src);
295int grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap); 316int grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap);
296int grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...); 317int grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...);
297 318
319#define GRECS_TXTACC_BUFSIZE 1024
320struct grecs_txtacc *grecs_txtacc_create(void);
321void grecs_txtacc_free(struct grecs_txtacc *acc);
322void grecs_txtacc_grow(struct grecs_txtacc *acc, const char *buf, size_t size);
323char *grecs_txtacc_finish(struct grecs_txtacc *acc, int steal);
324void grecs_txtacc_free_string(struct grecs_txtacc *acc, char *str);
325
298struct grecs_symtab; 326struct grecs_symtab;
299 327
300struct grecs_syment { 328struct grecs_syment {
@@ -363,6 +391,9 @@ struct grecs_node *grecs_match_next(struct grecs_match_buf *buf);
363void grecs_match_buf_free(struct grecs_match_buf *buf); 391void grecs_match_buf_free(struct grecs_match_buf *buf);
364 392
365int grecs_value_eq(struct grecs_value *a, struct grecs_value *b); 393int grecs_value_eq(struct grecs_value *a, struct grecs_value *b);
394int grecs_value_match(struct grecs_value *pat, struct grecs_value *b,
395 int flags);
396
366struct grecs_node *grecs_find_node(struct grecs_node *node, const char *path); 397struct grecs_node *grecs_find_node(struct grecs_node *node, const char *path);
367 398
368struct grecs_node *grecs_node_from_path(const char *path, const char *value); 399struct grecs_node *grecs_node_from_path(const char *path, const char *value);
diff --git a/src/lineacc.c b/src/lineacc.c
new file mode 100644
index 0000000..a3f4836
--- a/dev/null
+++ b/src/lineacc.c
@@ -0,0 +1,82 @@
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 <wordsplit.h>
22
23static struct grecs_txtacc *line_acc;
24
25void
26grecs_line_acc_create()
27{
28 line_acc = grecs_txtacc_create();
29}
30
31void
32grecs_line_acc_free()
33{
34 grecs_txtacc_free(line_acc);
35 line_acc = NULL;
36}
37
38void
39grecs_line_acc_grow_char(int c)
40{
41 char t = c;
42 grecs_txtacc_grow(line_acc, &t, 1);
43}
44
45void
46grecs_line_acc_grow_char_unescape(int c)
47{
48 if (c != '\n')
49 grecs_line_acc_grow_char(wordsplit_c_unquote_char(c));
50}
51
52void
53grecs_line_acc_grow(const char *text, size_t len)
54{
55 grecs_txtacc_grow(line_acc, text, len);
56}
57
58/* Same, but unescapes the last character from text */
59void
60grecs_line_acc_grow_unescape_last(char *text, size_t len)
61{
62 grecs_txtacc_grow(line_acc, text, len - 2);
63 grecs_line_acc_grow_char_unescape(text[len - 1]);
64}
65
66void
67grecs_line_begin()
68{
69 if (!line_acc)
70 grecs_line_acc_create();
71}
72
73char *
74grecs_line_finish()
75{
76 grecs_line_acc_grow_char(0);
77 return grecs_txtacc_finish(line_acc, 1);
78}
79
80
81
82
diff --git a/src/meta1-gram.y b/src/meta1-gram.y
new file mode 100644
index 0000000..8ddcbfb
--- a/dev/null
+++ b/src/meta1-gram.y
@@ -0,0 +1,217 @@
1%{
2/* MeTA1 configuration parser for Grecs.
3 Copyright (C) 2007-2011 Sergey Poznyakoff
4
5 Grecs is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3 of the License, or (at your
8 option) any later version.
9
10 Grecs is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with Grecs. If not, see <http://www.gnu.org/licenses/>. */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21#include <errno.h>
22#include <string.h>
23#include "grecs.h"
24
25int yylex(void);
26int yyerror(char *s);
27
28static struct grecs_node *parse_tree;
29 extern int yy_flex_debug;
30%}
31
32%union {
33 struct {
34 grecs_locus_t locus;
35 char *string;
36 } ident;
37 char *string;
38 grecs_value_t svalue, *pvalue;
39 struct grecs_list *list;
40 struct { struct grecs_node *head, *tail; } node_list;
41 struct grecs_node *node;
42}
43
44%token <ident> META1_IDENT
45%token <string> META1_STRING
46%type <node> stmt simple block
47%type <node_list> stmtlist
48%type <pvalue> tag value
49%type <string> string slist
50%type <list> slist0
51%type <list> values list
52%%
53
54input : stmtlist
55 {
56 parse_tree = grecs_node_create(grecs_node_root,
57 &grecs_current_locus);
58 parse_tree->v.texttab = grecs_text_table();
59 grecs_node_bind(parse_tree, $1.head, 1);
60 }
61 ;
62
63stmtlist: stmt
64 {
65 $$.head = $$.tail = $1;
66 }
67 | stmtlist stmt
68 {
69 grecs_node_bind($1.tail, $2, 0);
70 }
71 ;
72
73stmt : simple
74 | block
75 ;
76
77simple : META1_IDENT '=' value opt_sc
78 {
79 $$ = grecs_node_create(grecs_node_stmt,
80 &$1.locus);
81 $$->ident = $1.string;
82 $$->v.value = $3;
83 }
84 ;
85
86block : META1_IDENT tag '{' stmtlist '}' opt_sc
87 {
88 $$ = grecs_node_create(grecs_node_block,
89 &$1.locus);
90 $$->ident = $1.string;
91 $$->v.value = $2;
92 grecs_node_bind($$, $4.head, 1);
93 }
94 ;
95
96tag : /* empty */
97 {
98 $$ = NULL;
99 }
100 | META1_IDENT
101 {
102 $$ = grecs_malloc(sizeof($$[0]));
103 $$->type = GRECS_TYPE_STRING;
104 $$->v.string = $1.string;
105 }
106 ;
107
108value : string
109 {
110 $$ = grecs_malloc(sizeof($$[0]));
111 $$->type = GRECS_TYPE_STRING;
112 $$->v.string = $1;
113 }
114 | list
115 {
116 $$ = grecs_malloc(sizeof($$[0]));
117 $$->type = GRECS_TYPE_LIST;
118 $$->v.list = $1;
119 }
120 ;
121
122string : META1_IDENT
123 {
124 $$ = $1.string;
125 }
126 | slist
127 ;
128
129slist : slist0
130 {
131 struct grecs_list_entry *ep;
132
133 grecs_line_begin();
134 for (ep = $1->head; ep; ep = ep->next) {
135 grecs_line_add(ep->data, strlen(ep->data));
136 free(ep->data);
137 ep->data = NULL;
138 }
139 $$ = grecs_line_finish();
140 grecs_list_free($1);
141 }
142
143slist0 : META1_STRING
144 {
145 $$ = grecs_list_create();
146 grecs_list_append($$, $1);
147 }
148 | slist0 META1_STRING
149 {
150 grecs_list_append($1, $2);
151 $$ = $1;
152 }
153 ;
154
155list : '{' values '}'
156 {
157 $$ = $2;
158 }
159 | '{' values ',' '}'
160 {
161 $$ = $2;
162 }
163 ;
164
165values : value
166 {
167 $$ = grecs_value_list_create();
168 grecs_list_append($$, $1);
169 }
170 | values ',' value
171 {
172 grecs_list_append($1, $3);
173 $$ = $1;
174 }
175 ;
176
177opt_sc : /* empty */
178 | ';'
179 ;
180
181%%
182int
183yyerror(char *s)
184{
185 grecs_error(&grecs_current_locus, 0, "%s", s);
186 return 0;
187}
188
189struct grecs_node *
190grecs_meta1_parser(const char *name, int traceflags)
191{
192 int rc;
193 FILE *fp;
194
195 fp = fopen(name, "r");
196 if (!fp) {
197 grecs_error(NULL, errno, _("Cannot open `%s'"), name);
198 return NULL;
199 }
200 yyset_in(fp);
201
202 yy_flex_debug = traceflags & GRECS_TRACE_LEX;
203 yydebug = traceflags & GRECS_TRACE_GRAM;
204 parse_tree = NULL;
205 grecs_line_acc_create();
206 rc = yyparse();
207 fclose(fp);
208 if (grecs_error_count)
209 rc = 1;
210 grecs_line_acc_free();
211 if (rc) {
212 grecs_tree_free(parse_tree);
213 parse_tree = NULL;
214 }
215 return parse_tree;
216}
217
diff --git a/src/meta1-lex.l b/src/meta1-lex.l
new file mode 100644
index 0000000..cb2931d
--- a/dev/null
+++ b/src/meta1-lex.l
@@ -0,0 +1,114 @@
1/* MeTA1 configuration lexer for Grecs. -*- c -*- */
2%top {
3/* MeTA1 configuration lexer for Grecs.
4 Copyright (C) 2007-2011 Sergey Poznyakoff
5
6 Grecs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3 of the License, or (at your
9 option) any later version.
10
11 Grecs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with Grecs. If not, see <http://www.gnu.org/licenses/>. */
18
19/* This file implements a lexical analyzer for MeTA1 main configuration file.
20 */
21
22#ifndef HAVE_CONFIG_H
23# include <config.h>
24#endif
25#include "grecs.h"
26#include "meta1-gram.h"
27#include <ctype.h>
28}
29
30%{
31static int yywrap(void);
32 static void meta1_line_add_unescape_hex(const char *text, size_t len);
33%}
34
35%x COMMENT STR
36X [0-9a-fA-F]
37%%
38 /* C-style comments */
39"/*" BEGIN (COMMENT);
40<COMMENT>[^*\n]* /* eat anything that's not a '*' */
41<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
42<COMMENT>\n ++grecs_current_locus.line;
43<COMMENT>"*"+"/" BEGIN (INITIAL);
44 /* End-of-line comments */
45#.*\n { grecs_current_locus.line++; }
46#.* /* end-of-file comment */;
47 /* Number */
480[xX]{X}+ |
490[0-7]+ |
50[1-9][0-9]+ { grecs_line_begin();
51 grecs_line_add(yytext, yyleng);
52 yylval.string = grecs_line_finish();
53 return META1_STRING; }
54 /* Identifiers (unquoted strings) */
55[a-zA-Z0-9_\./:\*-]+ { grecs_line_begin();
56 grecs_line_add(yytext, yyleng);
57 yylval.ident.locus = grecs_current_locus;
58 yylval.ident.string = grecs_line_finish();
59 return META1_IDENT; }
60 /* Quoted strings */
61\"[^\\"\n]*\" { grecs_line_begin();
62 grecs_line_add(yytext + 1, yyleng - 2);
63 yylval.string = grecs_line_finish();
64 return META1_STRING; }
65\"[^\\"\n]*\\x{X}{1,2} { BEGIN(STR);
66 grecs_line_begin();
67 meta1_line_add_unescape_hex(yytext + 1, yyleng - 1);
68 }
69\"[^\\"\n]*\\. { BEGIN(STR);
70 grecs_line_begin();
71 grecs_line_acc_grow_unescape_last(yytext + 1,
72 yyleng - 1); }
73<STR>[^\\"\n]*\\x{X}{1,2} { meta1_line_add_unescape_hex(yytext, yyleng); }
74<STR>[^\\"\n]*\\. { grecs_line_acc_grow_unescape_last(yytext, yyleng); }
75<STR>[^\\"\n]*\" { BEGIN(INITIAL);
76 if (yyleng > 1)
77 grecs_line_add(yytext, yyleng - 1);
78 yylval.string = grecs_line_finish();
79 return META1_STRING; }
80<STR>[^\\"\n]*\n { BEGIN(INITIAL);
81 grecs_error(&grecs_current_locus, 0,
82 _("newline in a string"));
83 grecs_line_add (yytext, yyleng - 1);
84 yylval.string = grecs_line_finish ();
85 return META1_STRING; }
86 /* Other tokens */
87[ \t\f][ \t\f]* ;
88\n { grecs_current_locus.line++; }
89[,;{}=] return yytext[0];
90. { grecs_error(&grecs_current_locus, 0,
91 (isascii(yytext[0]) && isprint(yytext[0])) ?
92 _("stray character %c") :
93 _("stray character \\%03o"),
94 (unsigned char) yytext[0]); }
95%%
96
97int
98yywrap()
99{
100 return 1;
101}
102
103static void
104meta1_line_add_unescape_hex(const char *text, size_t len)
105{
106 for (; text[len-1] != 'x' && len > 0; len--)
107 ;
108 grecs_line_acc_grow(text, len - 2);
109 grecs_line_acc_grow_char((char) strtoul (text + len, NULL, 16));
110}
111
112
113
114
diff --git a/src/parser.c b/src/parser.c
new file mode 100644
index 0000000..6f84bd8
--- a/dev/null
+++ b/src/parser.c
@@ -0,0 +1,60 @@
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 <stdlib.h>
21#include <string.h>
22#include <errno.h>
23#include "grecs.h"
24
25int grecs_error_count;
26int grecs_default_port = 0;
27
28int grecs_trace_flags = 0;
29
30#ifndef GRECS_DEFAULT_PARSER
31# define GRECS_DEFAULT_PARSER grecs_grecs_parser
32#endif
33
34struct grecs_node *(*grecs_parser_fun)(const char *name, int trace) =
35 GRECS_DEFAULT_PARSER;
36
37void
38grecs_gram_trace(int n)
39{
40 if (n)
41 grecs_trace_flags |= GRECS_TRACE_GRAM;
42 else
43 grecs_trace_flags &= ~GRECS_TRACE_GRAM;
44}
45
46void
47grecs_lex_trace(int n)
48{
49 if (n)
50 grecs_trace_flags |= GRECS_TRACE_LEX;
51 else
52 grecs_trace_flags &= ~GRECS_TRACE_LEX;
53}
54
55struct grecs_node *
56grecs_parse(const char *name)
57{
58 grecs_error_count = 0;
59 return grecs_parser_fun(name, grecs_trace_flags);
60}
diff --git a/src/txtacc.c b/src/txtacc.c
new file mode 100644
index 0000000..ff13e42
--- a/dev/null
+++ b/src/txtacc.c
@@ -0,0 +1,187 @@
1/* wydawca - automatic release submission daemon
2 Copyright (C) 2007, 2009-2011 Sergey Poznyakoff
3
4 Wydawca 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 Wydawca 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 wydawca. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <string.h>
21#include "grecs.h"
22
23struct grecs_txtacc_entry
24{
25 char *buf; /* Text buffer */
26 size_t size; /* Buffer size */
27 size_t len; /* Actual number of bytes in buffer */
28};
29#define TXTACC_BUFSIZE 1024
30#define grecs_txtacc_entry_freesize(e) ((e)->size - (e)->len)
31
32struct grecs_txtacc
33{
34 struct grecs_list *cur; /* Current build list */
35 struct grecs_list *mem; /* List of already allocated elements */
36};
37
38static struct grecs_txtacc_entry *
39grecs_txtacc_alloc_entry(struct grecs_list *list, size_t size)
40{
41 struct grecs_txtacc_entry *p = grecs_malloc(sizeof (*p));
42 p->buf = grecs_malloc(size);
43 p->size = size;
44 p->len = 0;
45 grecs_list_append(list, p);
46 return p;
47}
48
49static struct grecs_txtacc_entry *
50grecs_txtacc_cur_entry(struct grecs_txtacc *acc)
51{
52 struct grecs_txtacc_entry *ent;
53
54 if (grecs_list_size(acc->cur) == 0)
55 return grecs_txtacc_alloc_entry(acc->cur,
56 GRECS_TXTACC_BUFSIZE);
57 ent = acc->cur->tail->data;
58 if (grecs_txtacc_entry_freesize(ent) == 0)
59 ent = grecs_txtacc_alloc_entry(acc->cur,
60 GRECS_TXTACC_BUFSIZE);
61 return ent;
62}
63
64static void
65grecs_txtacc_entry_append(struct grecs_txtacc_entry *ent,
66 const char *p, size_t size)
67{
68 memcpy(ent->buf + ent->len, p, size);
69 ent->len += size;
70}
71
72static void
73grecs_txtacc_entry_tailor(struct grecs_txtacc_entry *ent)
74{
75 if (ent->size > ent->len) {
76 char *p = realloc(ent->buf, ent->len);
77 if (!p)
78 return;
79 ent->buf = p;
80 ent->size = ent->len;
81 }
82}
83
84static void
85grecs_txtacc_entry_free(void *p)
86{
87 if (p) {
88 struct grecs_txtacc_entry *ent = p;
89 free(ent->buf);
90 free(ent);
91 }
92}
93
94struct grecs_txtacc *
95grecs_txtacc_create()
96{
97 struct grecs_txtacc *acc = grecs_malloc(sizeof (*acc));
98 acc->cur = grecs_list_create();
99 acc->cur->free_entry = grecs_txtacc_entry_free;
100 acc->mem = grecs_list_create();
101 acc->mem->free_entry = grecs_txtacc_entry_free;
102 return acc;
103}
104
105void
106grecs_txtacc_free(struct grecs_txtacc *acc)
107{
108 grecs_list_free (acc->cur);
109 grecs_list_free (acc->mem);
110 free (acc);
111}
112
113void
114grecs_txtacc_grow(struct grecs_txtacc *acc, const char *buf, size_t size)
115{
116 while (size) {
117 struct grecs_txtacc_entry *ent = grecs_txtacc_cur_entry(acc);
118 size_t rest = grecs_txtacc_entry_freesize(ent);
119 if (rest > size)
120 rest = size;
121 grecs_txtacc_entry_append(ent, buf, rest);
122 buf += rest;
123 size -= rest;
124 }
125}
126
127char *
128grecs_txtacc_finish(struct grecs_txtacc *acc, int steal)
129{
130 struct grecs_list_entry *ep;
131 struct grecs_txtacc_entry *txtent;
132 size_t size;
133 char *p;
134
135 switch (grecs_list_size(acc->cur)) {
136 case 0:
137 return NULL;
138
139 case 1:
140 txtent = acc->cur->head->data;
141 acc->cur->head->data = NULL;
142 grecs_txtacc_entry_tailor(txtent);
143 grecs_list_append(acc->mem, txtent);
144 break;
145
146 default:
147 size = 0;
148 for (ep = acc->cur->head; ep; ep = ep->next) {
149 txtent = ep->data;
150 size += txtent->len;
151 }
152
153 txtent = grecs_txtacc_alloc_entry(acc->mem, size);
154 for (ep = acc->cur->head; ep; ep = ep->next) {
155 struct grecs_txtacc_entry *tp = ep->data;
156 grecs_txtacc_entry_append(txtent, tp->buf, tp->len);
157 }
158 }
159
160 grecs_list_clear(acc->cur);
161 p = txtent->buf;
162 if (steal) {
163 grecs_list_remove_tail(acc->mem);
164 free(txtent);
165 }
166 return p;
167}
168
169void
170grecs_txtacc_free_string(struct grecs_txtacc *acc, char *str)
171{
172 struct grecs_list_entry *ep;
173 for (ep = acc->mem->head; ep; ep = ep->next) {
174 struct grecs_txtacc_entry *tp = ep->data;
175 if (tp->buf == str) {
176 grecs_list_remove_entry(acc->mem, ep);
177 grecs_free(tp->buf);
178 return;
179 }
180 }
181}
182
183void
184grecs_txtacc_clear(struct grecs_txtacc *acc)
185{
186 grecs_list_clear(acc->cur);
187}
diff --git a/src/wordsplit.c b/src/wordsplit.c
index 662a1e1..c51be0a 100644
--- a/src/wordsplit.c
+++ b/src/wordsplit.c
@@ -1139,7 +1139,7 @@ scan_word (struct wordsplit *wsp, size_t start)
1139 return _WRDS_OK; 1139 return _WRDS_OK;
1140} 1140}
1141 1141
1142static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\tv\v"; 1142static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
1143 1143
1144int 1144int
1145wordsplit_c_unquote_char (int c) 1145wordsplit_c_unquote_char (int c)
diff --git a/src/yygrecs.h b/src/yygrecs.h
deleted file mode 100644
index 1b3bf31..0000000
--- a/src/yygrecs.h
+++ b/dev/null
@@ -1,28 +0,0 @@
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#define yyparse grecs_yyparse
18 #define yylex grecs_yylex
19 #define yyerror grecs_yyerror
20 #define yynerrs grecs_yynerrs
21 #define yylval grecs_yylval
22 #define yylloc grecs_yylloc
23 #define yychar grecs_yychar
24#define yydebug grecs_yydebug
25#define yy_flex_debug grecs_yy_flex_debug
26
27int yylex(void);
28int yyerror(char *s);
diff --git a/src/yytrans b/src/yytrans
new file mode 100644
index 0000000..d78fe26
--- a/dev/null
+++ b/src/yytrans
@@ -0,0 +1,20 @@
1# Identifier translation table for Grecs.
2# Copyright (C) 2011 Sergey Poznyakoff
3#
4# Grecs is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3, or (at your option)
7# 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
15# along with Grecs. If not, see <http://www.gnu.org/licenses/>.
16#
17# See build-aux/yyrename for a description of this file.
18
19 grecs grecs_yy
20 meta1 grecs_meta1_yy

Return to:

Send suggestions and report system problems to the System administrator.