summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--.gitignore4
-rw-r--r--.gitmodules3
-rw-r--r--Makefile.am22
-rw-r--r--README-hacking35
-rw-r--r--bootstrap.conf7
-rw-r--r--configure.ac46
-rw-r--r--gconf/.gitignore4
-rw-r--r--gconf/Makefile.am17
-rw-r--r--gconf/gconf-format.c200
-rw-r--r--gconf/gconf-gram.y891
-rw-r--r--gconf/gconf-lex.l476
-rw-r--r--gconf/gconf-preproc.c728
-rw-r--r--gconf/gconf-text.c73
-rw-r--r--gconf/gconf.h163
-rw-r--r--gconf/gnulib.modules14
-rw-r--r--gconf/wordsplit.c568
-rw-r--r--gconf/wordsplit.h88
m---------grecs0
-rw-r--r--src/Makefile.am4
-rw-r--r--src/cmdline.opt18
-rw-r--r--src/config.c476
-rw-r--r--src/diskio.c8
-rw-r--r--src/tcpwrap.c22
-rw-r--r--src/wydawca.c10
-rw-r--r--src/wydawca.h14
-rw-r--r--tests/Makefile.am4
26 files changed, 320 insertions, 3575 deletions
diff --git a/.gitignore b/.gitignore
index 5e9c566..4c9b75d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
1*.a
2*.o
1*.tar.* 3*.tar.*
2*~ 4*~
3*.o
4*.a
5.bootstrap 5.bootstrap
6.deps 6.deps
7.emacs.desktop 7.emacs.desktop
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..fea8f96
--- a/dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
1[submodule "grecs"]
2 path = grecs
3 url = git://git.gnu.org.ua/grecs.git
diff --git a/Makefile.am b/Makefile.am
index 1eac948..743b2be 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,34 +14,16 @@
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 wydawca. If not, see <http://www.gnu.org/licenses/>. 15# along with wydawca. If not, see <http://www.gnu.org/licenses/>.
16 16
17ACLOCAL_AMFLAGS = -I m4 17ACLOCAL_AMFLAGS = -I m4 -I grecs/am
18AUTOMAKE_OPTIONS = gnu 1.8.5 18AUTOMAKE_OPTIONS = gnu 1.8.5
19 19
20SUBDIRS=gnu gconf src doc etc tests 20SUBDIRS=gnu grecs src doc etc tests
21 21
22# We never remove files from the configuration directory 22# We never remove files from the configuration directory
23distuninstallcheck_listfiles = \ 23distuninstallcheck_listfiles = \
24 find $(prefix) -type f -not -path '$(sysconfdir)/*' 24 find $(prefix) -type f -not -path '$(sysconfdir)/*'
25 25
26gen_start_date = 2009-01-25 26gen_start_date = 2009-01-25
27.PHONY: make-ChangeLog
28make-ChangeLog:
29 if test -d .git; then \
30 $(top_srcdir)/build-aux/gitlog-to-changelog \
31 --since=$(gen_start_date) | \
32 sed '/<unknown>$$/d' | fmt -s > $(distdir)/cl-t; \
33 cat ChangeLog.svn | sed '/^Local Variables:/,/^End:/d'\
34 >> $(distdir)/cl-t; \
35 echo "Local Variables:" >> $(distdir)/cl-t; \
36 echo "mode: change-log" >> $(distdir)/cl-t; \
37 echo "version-control: never" >> $(distdir)/cl-t; \
38 echo "buffer-read-only: t" >> $(distdir)/cl-t; \
39 echo "End:" >> $(distdir)/cl-t; \
40 rm -f $(distdir)/ChangeLog; \
41 mv $(distdir)/cl-t $(distdir)/ChangeLog; \
42 fi
43
44dist-hook: make-ChangeLog
45 27
46.PHONY: ChangeLog 28.PHONY: ChangeLog
47ChangeLog: 29ChangeLog:
diff --git a/README-hacking b/README-hacking
index 19b957a..a746607 100644
--- a/README-hacking
+++ b/README-hacking
@@ -1,44 +1,59 @@
1These notes intend to help people working on the SVN version of 1These notes intend to help people working on the Git version of
2this package. See end of this file for the copying conditions. 2this package. See end of this file for the copying conditions.
3 3
4* Requirements 4* Requirements
5 5
6You need the following packages to build the SVN version of Wydawca. I do 6You need the following packages to build the Git version of Wydawca. I do
7not make any efforts to accommodate older versions of these packages, 7not make any efforts to accommodate older versions of these packages,
8so please make sure that you have the latest stable version. 8so please make sure that you have the latest stable version.
9 9
10- Automake <http://www.gnu.org/software/automake/> 10- Automake <http://www.gnu.org/software/automake/>
11- Autoconf <http://www.gnu.org/software/autoconf/> 11- Autoconf <http://www.gnu.org/software/autoconf/>
12- Bison <http://www.gnu.org/software/bison/> 12- Bison <http://www.gnu.org/software/bison/>
13- Git <http://git.or.cz>
13- Gnulib <http://www.gnu.org/software/gnulib/> 14- Gnulib <http://www.gnu.org/software/gnulib/>
15- Grecs <http://puszcza.gnu.org.ua/projects/grecs>
14- Flex <http://flex.sourceforge.net/> 16- Flex <http://flex.sourceforge.net/>
15- M4 <http://www.gnu.org/software/m4/> 17- M4 <http://www.gnu.org/software/m4/>
16- Mailutils <http://www.gnu.org/software/mailutils/> 18- Mailutils <http://www.gnu.org/software/mailutils/>
17- Subversion <http://subversion.tigris.org/>
18- Texinfo <http://www.gnu.org/software/texinfo> 19- Texinfo <http://www.gnu.org/software/texinfo>
19 20
20* Bootstrapping 21* Bootstrapping
21 22
22Obviously, if you are reading these notes, you did manage to check out 23Obviously, if you are reading these notes, you did manage to clone
23the source tree from SVN. The next step is to create the configuration 24the source tree from the Git repository. The next step is to create
24framework: 25the configuration framework:
25 26
261. Change to the source tree directory 271. Change to the source tree directory
27 28
28 $ cd wydawca 29 $ cd wydawca
29 30
302. Run `bootstrap' pointing the --gnulib-srcdir option to the location 312. Run `bootstrap':
31of the local directory where gnulib sources reside, e.g.:
32 32
33 ./bootstrap --gnulib-srcdir=/usr/src/gnulib 33 ./bootstrap
34 34
35Once done, proceed as described in the file README (section 35Once done, proceed as described in the file README (section
36`Installation'). 36`Installation').
37 37
38Normally you will have to run bootstrap only once. However, if you
39intend to hack on Wydawca, you might need to run it again later. In
40this case, you will probably want to save some time and bandwidth by
41avoiding downloading the same files again. If so, create in the Wydawca
42root directory the file named `.bootstrap' with the following
43contents:
44
45 --gnulib-srcdir=$HOME/gnulib
46
47Replace `$HOME/gnulib' with the actual directory where the Gnulib
48sources reside.
49
50For more information about `bootstrap', run `bootstrap --help'.
51
52
38 53
39* Copyright information 54* Copyright information
40 55
41 Copyright (C) 2007 Sergey Poznyakoff 56 Copyright (C) 2007, 2009 Sergey Poznyakoff
42 57
43 Permission is granted to anyone to make or distribute verbatim copies 58 Permission is granted to anyone to make or distribute verbatim copies
44 of this document as received, in any medium, provided that the 59 of this document as received, in any medium, provided that the
diff --git a/bootstrap.conf b/bootstrap.conf
index 6119189..fde2671 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -21,6 +21,11 @@ gnulib_mk=Makefile.am
21 21
22test -d $source_base || mkdir -p $source_base 22test -d $source_base || mkdir -p $source_base
23 23
24if git config submodule.grecs.url >/dev/null; then : ; else
25 git submodule init || exit $?
26 git submodule update || exit $?
27fi
28
24# We don't need these modules, even though gnulib-tool mistakenly 29# We don't need these modules, even though gnulib-tool mistakenly
25# includes them because of gettext dependencies. 30# includes them because of gettext dependencies.
26avoided_gnulib_modules=' 31avoided_gnulib_modules='
@@ -29,7 +34,7 @@ avoided_gnulib_modules='
29' 34'
30 35
31# gnulib modules used by this package. 36# gnulib modules used by this package.
32gnulib_modules="`grep -h '^[^#]' gnulib.modules gconf/gnulib.modules | sort | uniq`" 37gnulib_modules="`grep -h '^[^#]' gnulib.modules grecs/gnulib.modules | sort | uniq`"
33 38
34# Additional xgettext options to use. Use "\\\newline" to break lines. 39# Additional xgettext options to use. Use "\\\newline" to break lines.
35XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\ 40XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
diff --git a/configure.ac b/configure.ac
index 604ccc4..48e1252 100644
--- a/configure.ac
+++ b/configure.ac
@@ -106,48 +106,9 @@ fi
106if test "$status_tcpwrap" = yes; then 106if test "$status_tcpwrap" = yes; then
107 AC_DEFINE_UNQUOTED([WITH_LIBWRAP],1,[Defined if compiling with libwrap]) 107 AC_DEFINE_UNQUOTED([WITH_LIBWRAP],1,[Defined if compiling with libwrap])
108fi 108fi
109
110 # **********************
111# Preprocessor
112 # **********************
113AC_ARG_WITH([preprocessor],
114 AC_HELP_STRING([--without-preprocessor],
115 [do not use external preprocessor]),
116 [
117case "${withval}" in
118yes) use_ext_pp=yes ;;
119no) use_ext_pp=no ;;
120*) AC_MSG_ERROR(bad value ${withval} for --with-preprocessor) ;;
121esac],[use_ext_pp=yes])
122
123if test $use_ext_pp != no; then
124 # Check for default preprocessor
125 AC_ARG_VAR([DEFAULT_PREPROCESSOR],
126 [Set default preprocessor name])
127 if test -z "$DEFAULT_PREPROCESSOR" ; then
128 DEFAULT_PREPROCESSOR="m4 -s"
129 fi
130
131 save_PATH=$PATH
132 PREPROC_OPTIONS=`echo $DEFAULT_PREPROCESSOR | sed -n 's/[[^ ]][[^ ]]* //p'`
133 case "$DEFAULT_PREPROCESSOR" in
134 /*) PATH=`expr $DEFAULT_PREPROCESSOR : '\(.*\)/.*'`:$PATH
135 DEFAULT_PREPROCESSOR=`expr $DEFAULT_PREPROCESSOR : '.*/\(.*\)'`;;
136 esac
137 AC_PATH_PROG(PPBIN, $DEFAULT_PREPROCESSOR)
138 DEFAULT_PREPROCESSOR=$PPBIN
139 if test -n "$DEFAULT_PREPROCESSOR"; then
140 DEFAULT_PREPROCESSOR="$DEFAULT_PREPROCESSOR $PREPROC_OPTIONS"
141 case $PPBIN in
142 *m4) AC_SUBST(PP_SETUP_FILE,'pp-setup');; # Install default pp-setup
143 esac
144 fi
145 PATH=$save_PATH
146 DEFAULT_PREPROCESSOR="\\\"$DEFAULT_PREPROCESSOR\\\""
147else
148 DEFAULT_PREPROCESSOR=NULL
149fi
150 109
110# Grecs subsystem
111GRECS_SETUP
151 112
152AH_BOTTOM([ 113AH_BOTTOM([
153#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) 114#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
@@ -172,7 +133,8 @@ fi
172AC_CONFIG_FILES([Makefile 133AC_CONFIG_FILES([Makefile
173 doc/Makefile 134 doc/Makefile
174 gnu/Makefile 135 gnu/Makefile
175 gconf/Makefile 136 grecs/Makefile
137 grecs/src/Makefile
176 src/Makefile 138 src/Makefile
177 etc/Makefile]) 139 etc/Makefile])
178 140
diff --git a/gconf/.gitignore b/gconf/.gitignore
deleted file mode 100644
index 42c88b2..0000000
--- a/gconf/.gitignore
+++ b/dev/null
@@ -1,4 +0,0 @@
1gconf-gram.c
2gconf-gram.h
3gconf-gram.output
4gconf-lex.c
diff --git a/gconf/Makefile.am b/gconf/Makefile.am
deleted file mode 100644
index afe06b0..0000000
--- a/gconf/Makefile.am
+++ b/dev/null
@@ -1,17 +0,0 @@
1noinst_LIBRARIES=libgconf.a
2libgconf_a_SOURCES = \
3 gconf-format.c\
4 gconf-gram.y\
5 gconf-lex.l\
6 gconf-preproc.c\
7 gconf-text.c\
8 gconf.h\
9 wordsplit.c\
10 wordsplit.h
11
12EXTRA_DIST=gconf-gram.h
13
14INCLUDES = -I$(top_srcdir)/gnu -I../gnu
15AM_YFLAGS = -dtv
16AM_LFLAGS = -dvp
17
diff --git a/gconf/gconf-format.c b/gconf/gconf-format.c
deleted file mode 100644
index ea8a808..0000000
--- a/gconf/gconf-format.c
+++ b/dev/null
@@ -1,200 +0,0 @@
1/* gconf - General purpose configuration parser.
2 Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <gconf.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <ctype.h>
24#include <string.h>
25
26#if ENABLE_NLS
27# include "gettext.h"
28#else
29# define gettext(s) s
30#endif
31
32#define _(s) gettext (s)
33#define N_(s) s
34
35const char *
36gconf_data_type_string (enum gconf_data_type type)
37{
38 switch (type)
39 {
40 case gconf_type_void:
41 return "void";
42
43 case gconf_type_string:
44 return "string";
45
46 case gconf_type_short:
47 case gconf_type_ushort:
48 case gconf_type_int:
49 case gconf_type_uint:
50 case gconf_type_long:
51 case gconf_type_ulong:
52 case gconf_type_size:
53/* case gconf_type_off:*/
54 case gconf_type_uintmax:
55 case gconf_type_intmax:
56 return "number";
57
58 case gconf_type_time:
59 return "time";
60
61 case gconf_type_bool:
62 return "boolean";
63
64 case gconf_type_ipv4:
65 return "IPv4";
66
67 case gconf_type_cidr:
68 return "CIDR";
69
70 case gconf_type_host:
71 return "hostname";
72
73 case gconf_type_sockaddr:
74 return "sock-addr";
75
76 case gconf_type_section:
77 return "section";
78 }
79 return "UNKNOWN?";
80}
81
82static void
83format_level (FILE *stream, unsigned level)
84{
85 while (level--)
86 fprintf (stream, " ");
87}
88
89void
90gconf_format_docstring (FILE *stream, const char *docstring, unsigned level)
91{
92 size_t len = strlen (docstring);
93 int width = 78 - level * 2;
94
95 if (width < 0)
96 {
97 width = 78;
98 level = 0;
99 }
100
101 while (len)
102 {
103 size_t seglen;
104 const char *p;
105
106 for (seglen = 0, p = docstring; p < docstring + width && *p; p++)
107 {
108 if (*p == '\n')
109 {
110 seglen = p - docstring;
111 break;
112 }
113 if (isspace (*p))
114 seglen = p - docstring;
115 }
116 if (seglen == 0 || *p == 0)
117 seglen = p - docstring;
118
119 format_level (stream, level);
120 fprintf (stream, "# ");
121 fwrite (docstring, seglen, 1, stream);
122 fputc ('\n', stream);
123 len -= seglen;
124 docstring += seglen;
125 if (*docstring == '\n')
126 {
127 docstring++;
128 len--;
129 }
130 else
131 while (*docstring && isspace (*docstring))
132 {
133 docstring++;
134 len--;
135 }
136 }
137}
138
139void
140gconf_format_simple_statement (FILE *stream, struct gconf_keyword *kwp,
141 unsigned level)
142{
143 const char *argstr;
144
145 if (kwp->docstring)
146 gconf_format_docstring (stream, kwp->docstring, level);
147 format_level (stream, level);
148
149 if (kwp->argname)
150 argstr = kwp->argname;
151 else
152 argstr = N_("arg");
153
154 if (strchr ("<[", argstr[0]))
155 fprintf (stream, "%s %s;\n", kwp->ident, gettext (argstr));
156 else if (strchr (argstr, ':'))
157 fprintf (stream, "%s <%s>;\n", kwp->ident, gettext (argstr));
158 else
159 {
160 fprintf (stream, "%s <%s: ", kwp->ident, gettext (argstr));
161 if (GCONF_IS_LIST (kwp->type))
162 fprintf (stream, "list of %s",
163 gettext (gconf_data_type_string (GCONF_TYPE (kwp->type))));
164 else
165 fprintf (stream, "%s", gettext (gconf_data_type_string (kwp->type)));
166 fprintf (stream, ">;\n");
167 }
168}
169
170void
171gconf_format_block_statement (FILE *stream, struct gconf_keyword *kwp,
172 unsigned level)
173{
174 if (kwp->docstring)
175 gconf_format_docstring (stream, kwp->docstring, level);
176 format_level (stream, level);
177 fprintf (stream, "%s", kwp->ident);
178 if (kwp->argname)
179 fprintf (stream, " <%s>", gettext (kwp->argname));
180 fprintf (stream, " {\n");
181 gconf_format_statement_array (stream, kwp->kwd, 0, level + 1);
182 format_level (stream, level);
183 fprintf (stream, "}\n");
184}
185
186void
187gconf_format_statement_array (FILE *stream, struct gconf_keyword *kwp,
188 unsigned n,
189 unsigned level)
190{
191 for (; kwp->ident; kwp++, n++)
192 {
193 if (n)
194 fputc ('\n', stream);
195 if (kwp->type == gconf_type_section)
196 gconf_format_block_statement (stream, kwp, level);
197 else
198 gconf_format_simple_statement (stream, kwp, level);
199 }
200}
diff --git a/gconf/gconf-gram.y b/gconf/gconf-gram.y
deleted file mode 100644
index c2d833b..0000000
--- a/gconf/gconf-gram.y
+++ b/dev/null
@@ -1,891 +0,0 @@
1%{
2/* gconf - General purpose configuration parser.
3 Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
4
5 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
17
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21#include <gconf.h>
22#include <gconf-gram.h>
23#include <stdlib.h>
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/time.h>
27#include <sys/un.h>
28#include <netinet/in.h>
29#include <arpa/inet.h>
30#include <netdb.h>
31
32#include <xalloc.h>
33#include <inttypes.h>
34
35#if ENABLE_NLS
36# include "gettext.h"
37# define _(msgid) gettext (msgid)
38#else
39# define _(msgid) msgid
40#endif
41
42typedef union
43{
44 struct sockaddr s;
45 struct sockaddr_in s_in;
46 struct sockaddr_un s_un;
47} sockaddr_union_t;
48
49static struct gconf_keyword config_keywords;
50static struct gconf_keyword *cursect;
51static gl_list_t sections;
52int gconf_error_count;
53
54int gconf_default_port = 0;
55
56static void *target_ptr(struct gconf_keyword *kwp);
57static void stmt_begin(struct gconf_keyword *kwp, gconf_value_t tag);
58static void stmt_end(struct gconf_keyword *kwp);
59static struct gconf_keyword *find_keyword(const char *ident);
60
61static void process_ident(struct gconf_keyword *kwp, gconf_value_t *value);
62static gl_list_t simple_list_create (bool dispose);
63%}
64
65%union {
66 char *string;
67 gconf_value_t value;
68 gl_list_t list;
69 struct gconf_keyword *kw;
70}
71
72%token <string> IDENT STRING QSTRING MSTRING
73%type <string> string slist
74%type <list> slist0
75%type <value> value tag vallist
76%type <list> values list vlist
77%type <kw> ident
78
79%%
80
81input : stmtlist
82 ;
83
84stmtlist: stmt
85 | stmtlist stmt
86 ;
87
88stmt : simple
89 | block
90 ;
91
92simple : ident vallist ';'
93 {
94 process_ident($1, &$2);
95 }
96 ;
97
98block : ident tag { stmt_begin($<kw>1, $<value>2); } '{' stmtlist '}' opt_sc
99 {
100 stmt_end($1);
101 }
102 ;
103
104ident : IDENT
105 {
106 $$ = find_keyword($1);
107 if (!$$)
108 gconf_error(&gconf_current_locus, 0, _("Unknown keyword"));
109 }
110 ;
111
112tag : /* empty */
113 {
114 $$.type = GCONF_TYPE_STRING;
115 $$.v.string = NULL;
116 }
117 | value
118 ;
119
120vallist : vlist
121 {
122 size_t n;
123
124 if ((n = gl_list_size ($1)) == 1)
125 {
126 $$ = *(gconf_value_t *)gl_list_get_at ($1, 0);
127 }
128 else
129 {
130 size_t i;
131
132 $$.type = GCONF_TYPE_ARRAY;
133 $$.v.arg.c = n;
134 $$.v.arg.v = xcalloc (n, sizeof ($$.v.arg.v[0]));
135 for (i = 0; i < n; i++)
136 $$.v.arg.v[i] = *(gconf_value_t *)gl_list_get_at ($1, i);
137 }
138 gl_list_free ($1);
139 }
140 ;
141
142vlist : value
143 {
144 $$ = simple_list_create (false);
145 gl_list_add_last ($$, gconf_value_dup (&$1));
146 }
147 | vlist value
148 {
149 gl_list_add_last ($1, gconf_value_dup (&$2));
150 }
151 ;
152
153value : string
154 {
155 $$.type = GCONF_TYPE_STRING;
156 $$.v.string = $1;
157 }
158 | list
159 {
160 $$.type = GCONF_TYPE_LIST;
161 $$.v.list = $1;
162 }
163 | MSTRING
164 {
165 $$.type = GCONF_TYPE_STRING;
166 $$.v.string = $1;
167 }
168 ;
169
170string : STRING
171 | IDENT
172 | slist
173 ;
174
175slist : slist0
176 {
177 const void *p;
178 gl_list_iterator_t itr = gl_list_iterator ($1);
179
180 gconf_line_begin ();
181 while (gl_list_iterator_next (&itr, &p, NULL))
182 gconf_line_add (p, strlen (p));
183 $$ = gconf_line_finish ();
184 gl_list_iterator_free (&itr);
185 gl_list_free ($1);
186 }
187 ;
188
189slist0 : QSTRING
190 {
191 $$ = simple_list_create (false);
192 gl_list_add_last ($$, $1);
193 }
194 | slist0 QSTRING
195 {
196 gl_list_add_last ($1, $2);
197 $$ = $1;
198 }
199 ;
200
201list : '(' ')'
202 {
203 $$ = NULL;
204 }
205 | '(' values ')'
206 {
207 $$ = $2;
208 }
209 | '(' values ',' ')'
210 {
211 $$ = $2;
212 }
213 ;
214
215values : value
216 {
217 $$ = simple_list_create (true);
218 gl_list_add_last ($$, gconf_value_dup (&$1));
219 }
220 | values ',' value
221 {
222 gl_list_add_last ($1, gconf_value_dup (&$3));
223 $$ = $1;
224 }
225 ;
226
227opt_sc : /* empty */
228 | ';'
229 ;
230
231%%
232
233int
234yyerror(char *s)
235{
236 gconf_error (&gconf_current_locus, 0, "%s", s);
237 return 0;
238}
239
240static void
241listel_dispose(const void *el)
242{
243 free((void*)el);
244}
245
246static gl_list_t
247simple_list_create (bool dispose)
248{
249 return gl_list_create_empty(&gl_linked_list_implementation,
250 NULL,
251 NULL,
252 dispose ? listel_dispose : NULL,
253 false);
254}
255
256
257void
258gconf_warning(gconf_locus_t *locus, int errcode, const char *fmt, ...)
259{
260 va_list ap;
261 char *buf = NULL;
262
263 va_start (ap, fmt);
264 vasprintf (&buf, fmt, ap);
265 va_end (ap);
266 gconf_print_diag (locus, 0, errcode, buf);
267 free(buf);
268}
269
270void
271gconf_error (gconf_locus_t *locus, int errcode, const char *fmt, ...)
272{
273 va_list ap;
274 char *buf = NULL;
275
276 va_start (ap, fmt);
277 vasprintf (&buf, fmt, ap);
278 va_end (ap);
279 gconf_print_diag (locus, 1, errcode, buf);
280 free (buf);
281 gconf_error_count++;
282}
283
284void
285gconf_set_keywords (struct gconf_keyword *kwd)
286{
287 config_keywords.kwd = kwd;
288}
289
290int
291gconf_parse (const char *name)
292{
293 int rc;
294 if (gconf_lex_begin (name))
295 return 1;
296 cursect = &config_keywords;
297 if (sections)
298 {
299 gl_list_free (sections);
300 sections = NULL;
301 }
302 rc = yyparse ();
303 gconf_lex_end ();
304 if (gconf_error_count)
305 rc = 1;
306 return rc;
307}
308
309void
310gconf_gram_trace (int n)
311{
312 yydebug = n;
313}
314
315
316
317static void *
318target_ptr (struct gconf_keyword *kwp)
319{
320 char *base;
321
322 if (kwp->varptr)
323 base = (char*) kwp->varptr + kwp->offset;
324 else if (cursect && cursect->callback_data)
325 base = (char*) cursect->callback_data + kwp->offset;
326 else
327 base = NULL;
328 return base;
329}
330
331static int
332fake_callback (enum gconf_callback_command cmd,
333 gconf_locus_t *locus,
334 void *varptr,
335 gconf_value_t *value,
336 void *cb_data)
337{
338 return 0;
339}
340
341static struct gconf_keyword fake = {
342 "*",
343 NULL,
344 NULL,
345 gconf_type_void,
346 NULL,
347 0,
348 fake_callback,
349 NULL,
350 &fake
351};
352
353static void
354stmt_begin (struct gconf_keyword *kwp, gconf_value_t tag)
355{
356 void *target;
357
358 if (!sections)
359 sections = simple_list_create (false);
360 gl_list_add_first (sections, cursect);
361 if (kwp)
362 {
363 target = target_ptr (kwp);
364 cursect = kwp;
365 if (kwp->callback && kwp->callback (gconf_callback_section_begin,
366 &gconf_current_locus, /* FIXME */
367 target,
368 &tag,
369 &kwp->callback_data))
370 cursect = &fake;
371 }
372 else
373 /* install "ignore-all" section */
374 cursect = kwp;
375}
376
377static void
378stmt_end (struct gconf_keyword *kwp)
379{
380 gconf_callback_fn callback = NULL;
381 void *dataptr = NULL;
382
383 if (cursect && cursect->callback)
384 {
385 callback = cursect->callback;
386 dataptr = &cursect->callback_data;
387 }
388
389 if (gl_list_size (sections) == 0)
390 abort ();
391 cursect = (struct gconf_keyword *) gl_list_get_at (sections, 0);
392 gl_list_remove_at (sections, 0);
393 if (callback)
394 callback (gconf_callback_section_end,
395 &gconf_current_locus, /* FIXME */
396 kwp ? target_ptr(kwp) : NULL,
397 NULL,
398 dataptr);
399
400}
401
402static struct gconf_keyword *
403find_keyword (const char *ident)
404{
405 struct gconf_keyword *kwp;
406
407 if (cursect && cursect != &fake)
408 {
409 for (kwp = cursect->kwd; kwp->ident; kwp++)
410 if (strcmp (kwp->ident, ident) == 0)
411 return kwp;
412 }
413 else
414 {
415 return &fake;
416 }
417 return NULL;
418}
419
420static int
421string_to_signed (intmax_t *sval, const char *string,
422 intmax_t minval, intmax_t maxval)
423{
424 intmax_t t;
425 char *p;
426
427 t = strtoimax (string, &p, 0);
428 if (*p)
429 {
430 gconf_error (&gconf_current_locus, 0, _("cannot convert `%s' to number"),
431 string);
432 return 1;
433 }
434 else if (t < minval || t > maxval)
435 {
436 gconf_error (&gconf_current_locus, 0,
437 _("%s: value out of allowed range %"PRIiMAX"..%"PRIiMAX),
438 string, minval, maxval);
439 return 1;
440 }
441 *sval = t;
442 return 0;
443}
444
445static int
446string_to_unsigned (uintmax_t *sval, const char *string, uintmax_t maxval,
447 gconf_locus_t *loc)
448{
449 uintmax_t t;
450 char *p;
451
452 t = strtoumax (string, &p, 0);
453 if (*p)
454 {
455 gconf_error (loc, 0, _("cannot convert `%s' to number"),
456 string);
457 return 1;
458 }
459 else if (t > maxval)
460 {
461 gconf_error (loc, 0,
462 _("%s: value out of allowed range 0..%"PRIuMAX),
463 string, maxval);
464 return 1;
465 }
466 *sval = t;
467 return 0;
468}
469
470static int
471string_to_bool (const char *string, int *pval)
472{
473 if (strcmp (string, "yes") == 0
474 || strcmp (string, "true") == 0
475 || strcmp (string, "t") == 0
476 || strcmp (string, "1") == 0)
477 *pval = 1;
478 else if (strcmp (string, "no") == 0
479 || strcmp (string, "false") == 0
480 || strcmp (string, "nil") == 0
481 || strcmp (string, "0") == 0)
482 *pval = 0;
483 else
484 {
485 gconf_error (&gconf_current_locus, 0,
486 _("%s: not a valid boolean value"),
487 string);
488 return 1;
489 }
490 return 0;
491}
492
493static int
494string_to_host (struct in_addr *in, const char *string)
495{
496 if (inet_aton (string, in) == 0)
497 {
498 struct hostent *hp;
499
500 hp = gethostbyname (string);
501 if (hp == NULL)
502 return 1;
503 memcpy (in, hp->h_addr, sizeof (struct in_addr));
504 }
505 return 0;
506}
507
508static int
509string_to_sockaddr (struct gconf_sockaddr *sp, const char *string)
510{
511 if (string[0] == '/')
512 {
513 struct sockaddr_un s_un;
514 if (strlen (string) >= sizeof (s_un.sun_path))
515 {
516 gconf_error (&gconf_current_locus, 0,
517 _("%s: UNIX socket name too long"),
518 string);
519 return 1;
520 }
521 s_un.sun_family = AF_UNIX;
522 strcpy (s_un.sun_path, string);
523 sp->len = sizeof (s_un);
524 sp->sa = xmalloc (sp->len);
525 memcpy (sp->sa, &s_un, sp->len);
526 }
527 else
528 {
529 char *p = strchr (string, ':');
530 size_t len;
531 struct sockaddr_in sa;
532
533 sa.sin_family = AF_INET;
534 if (p)
535 len = p - string;
536 else
537 len = strlen (string);
538
539 if (len == 0)
540 sa.sin_addr.s_addr = INADDR_ANY;
541 else
542 {
543 char *host = xmalloc (len + 1);
544 memcpy (host, string, len);
545 host[len] = 0;
546
547 if (string_to_host (&sa.sin_addr, host))
548 {
549 gconf_error (&gconf_current_locus, 0,
550 _("%s: not a valid IP address or hostname"),
551 host);
552 free (host);
553 return 1;
554 }
555 free (host);
556 }
557
558 if (p)
559 {
560 struct servent *serv;
561
562 p++;
563 serv = getservbyname (p, "tcp");
564 if (serv != NULL)
565 sa.sin_port = serv->s_port;
566 else
567 {
568 unsigned long l;
569 char *q;
570
571 /* Not in services, maybe a number? */
572 l = strtoul (p, &q, 0);
573
574 if (*q || l > USHRT_MAX)
575 {
576 gconf_error (&gconf_current_locus, 0,
577 _("%s: not a valid port number"), p);
578 return 1;
579 }
580 sa.sin_port = htons (l);
581 }
582 }
583 else if (gconf_default_port)
584 sa.sin_port = gconf_default_port;
585 else
586 {
587 gconf_error (&gconf_current_locus, 0, _("missing port number"));
588 return 1;
589 }
590 sp->len = sizeof (sa);
591 sp->sa = xmalloc (sp->len);
592 memcpy (sp->sa, &sa, sp->len);
593 }
594 return 0;
595}
596
597int
598gconf_string_convert (void *target, enum gconf_data_type type,
599 const char *string)
600{
601 uintmax_t uval;
602 intmax_t sval;
603
604 switch (type)
605 {
606 case gconf_type_void:
607 abort ();
608
609 case gconf_type_string:
610 *(const char**)target = string;
611 break;
612
613 case gconf_type_short:
614 if (string_to_signed (&sval, string, SHRT_MIN, SHRT_MAX) == 0)
615 *(short*)target = sval;
616 else
617 return 1;
618 break;
619
620 case gconf_type_ushort:
621 if (string_to_unsigned (&uval, string, USHRT_MAX, &gconf_current_locus) == 0)
622 *(unsigned short*)target = uval;
623 else
624 return 1;
625 break;
626
627 case gconf_type_bool:
628 return string_to_bool (string, (int*)target);
629
630 case gconf_type_int:
631 if (string_to_signed (&sval, string, INT_MIN, INT_MAX) == 0)
632 *(int*)target = sval;
633 else
634 return 1;
635 break;
636
637 case gconf_type_uint:
638 if (string_to_unsigned (&uval, string, UINT_MAX, &gconf_current_locus) == 0)
639 *(unsigned int*)target = uval;
640 else
641 return 1;
642 break;
643
644 case gconf_type_long:
645 if (string_to_signed (&sval, string, LONG_MIN, LONG_MAX) == 0)
646 *(long*)target = sval;
647 else
648 return 1;
649 break;
650
651 case gconf_type_ulong:
652 if (string_to_unsigned (&uval, string, ULONG_MAX, &gconf_current_locus) == 0)
653 *(unsigned long*)target = uval;
654 else
655 return 1;
656 break;
657
658 case gconf_type_size:
659 if (string_to_unsigned (&uval, string, SIZE_MAX, &gconf_current_locus) == 0)
660 *(size_t*)target = uval;
661 else
662 return 1;
663 break;
664
665 case gconf_type_intmax:
666 return string_to_signed ((intmax_t*)target, string,
667 INTMAX_MIN, INTMAX_MAX);
668
669 case gconf_type_uintmax:
670 return string_to_unsigned ((uintmax_t*)target, string, UINTMAX_MAX,
671 &gconf_current_locus);
672
673 case gconf_type_time:
674 /*FIXME: Use getdate */
675 if (string_to_unsigned (&uval, string, (time_t)-1, &gconf_current_locus) == 0)
676 *(time_t*)target = uval;
677 else
678 return 1;
679 break;
680
681 case gconf_type_ipv4:
682 if (inet_aton (string, (struct in_addr *)target))
683 {
684 gconf_error (&gconf_current_locus, 0, _("%s: not a valid IP address"), string);
685 return 1;
686 }
687 break;
688
689 case gconf_type_host:
690 if (string_to_host ((struct in_addr *)target, string))
691 {
692 gconf_error (&gconf_current_locus, 0,
693 _("%s: not a valid IP address or hostname"), string);
694 return 1;
695 }
696 break;
697
698 case gconf_type_sockaddr:
699 return string_to_sockaddr ((struct gconf_sockaddr *)target, string);
700
701 /* FIXME: */
702 case gconf_type_cidr:
703 gconf_error (&gconf_current_locus, 0, _("INTERNAL ERROR at %s:%d"), __FILE__,
704 __LINE__);
705 abort();
706
707 case gconf_type_section:
708 gconf_error (&gconf_current_locus, 0,
709 _("Invalid use of block statement"));
710 return 1;
711 }
712 return 0;
713}
714
715struct gconf_prop
716{
717 size_t size;
718 gl_listelement_equals_fn eqfn;
719};
720
721static bool
722string_eq (const void *elt1, const void *elt2)
723{
724 return strcmp ((const char *)elt1, (const char *)elt2) == 0;
725}
726
727#define __gconf_name_cat__(a,b) a ## b
728#define NUMEQ(type) __gconf_name_cat__(type,_eq)
729 #define __DECL_NUMEQ(type,ctype) \
730 static bool \
731 NUMEQ(type) (const void *elt1, const void *elt2)\
732 { \
733 return memcmp (elt1, elt2, sizeof (ctype)) == 0;\
734 }
735#define DECL_NUMEQ(type) __DECL_NUMEQ(type,type)
736
737DECL_NUMEQ(short)
738DECL_NUMEQ(int)
739DECL_NUMEQ(long)
740DECL_NUMEQ(size_t)
741DECL_NUMEQ(uintmax_t)
742DECL_NUMEQ(intmax_t)
743DECL_NUMEQ(time_t)
744__DECL_NUMEQ(in_addr, struct in_addr)
745__DECL_NUMEQ(gconf_sockaddr, struct gconf_sockaddr)
746
747struct gconf_prop gconf_prop_tab[] = {
748 { 0, NULL }, /* gconf_type_void */
749 { sizeof (char*), string_eq }, /* gconf_type_string */
750 { sizeof (short), NUMEQ (short) }, /* gconf_type_short */
751 { sizeof (unsigned short), NUMEQ (short) }, /* gconf_type_ushort */
752 { sizeof (int), NUMEQ (int) }, /* gconf_type_int */
753 { sizeof (unsigned int), NUMEQ (int) }, /* gconf_type_uint */
754 { sizeof (long), NUMEQ (long) }, /* gconf_type_long */
755 { sizeof (unsigned long), NUMEQ (long) }, /* gconf_type_ulong */
756 { sizeof (size_t), NUMEQ (size_t) }, /* gconf_type_size */
757 /* gconf_type_off,*/
758 { sizeof (uintmax_t), NUMEQ (uintmax_t) }, /* gconf_type_uintmax */
759 { sizeof (intmax_t), NUMEQ (intmax_t) }, /* gconf_type_intmax */
760 { sizeof (time_t), NUMEQ (time_t) }, /* gconf_type_time */
761 { sizeof (int), NUMEQ (int) }, /* gconf_type_bool */
762 { sizeof (struct in_addr), NUMEQ (in_addr) }, /* gconf_type_ipv4 */
763 { 0, NULL }, /* FIXME: gconf_type_cidr */
764 { sizeof (struct in_addr), NUMEQ (in_addr) }, /* gconf_type_host */
765 { sizeof (struct gconf_sockaddr), NUMEQ (gconf_sockaddr) },
766 /* gconf_type_sockaddr */
767 { 0, NULL } /* gconf_type_section */
768};
769#define gconf_prop_count \
770 (sizeof (gconf_prop_tab) / sizeof (gconf_prop_tab[0]))
771
772static void
773process_ident (struct gconf_keyword *kwp, gconf_value_t *value)
774{
775 void *target;
776
777 if (!kwp)
778 return;
779
780 target = target_ptr (kwp);
781
782 if (kwp->callback)
783 kwp->callback (gconf_callback_set_value,
784 &gconf_current_locus, /* FIXME */
785 target,
786 value,
787 &kwp->callback_data);
788 else if (value->type == GCONF_TYPE_ARRAY)
789 {
790 gconf_error (&gconf_current_locus, 0,
791 _("too many arguments to `%s'; missing semicolon?"),
792 kwp->ident);
793 return;
794 }
795 else if (value->type == GCONF_TYPE_LIST)
796 {
797 if (GCONF_IS_LIST (kwp->type))
798 {
799 gl_list_iterator_t itr = gl_list_iterator (value->v.list);
800 enum gconf_data_type type = GCONF_TYPE (kwp->type);
801 int num = 1;
802 const void *p;
803 gl_list_t list;
804 size_t size;
805
806 if (type >= gconf_prop_count
807 || (size = gconf_prop_tab[type].size) == 0)
808 {
809 gconf_error (&gconf_current_locus, 0,
810 _("INTERNAL ERROR at %s:%d: "
811 "unhandled data type %d"),
812 __FILE__, __LINE__, type);
813 abort ();
814 }
815
816 list = gl_list_create_empty (&gl_linked_list_implementation,
817 gconf_prop_tab[type].eqfn,
818 NULL,
819 listel_dispose,
820 false);
821
822 while (gl_list_iterator_next (&itr, &p, NULL))
823 {
824 const gconf_value_t *vp = p;
825
826 if (vp->type != GCONF_TYPE_STRING)
827 gconf_error (&gconf_current_locus, 0,
828 _("%s: incompatible data type in list item #%d"),
829 kwp->ident, num);
830 else if (type == gconf_type_string)
831 gl_list_add_last (list, vp->v.string);
832 else
833 {
834 void *ptr = xmalloc (size);
835 if (gconf_string_convert (ptr, type, vp->v.string) == 0)
836 gl_list_add_last (list, ptr);
837 else
838 free (ptr);
839 }
840 }
841 gl_list_iterator_free (&itr);
842 *(gl_list_t*)target = list;
843 }
844 else
845 {
846 gconf_error (&gconf_current_locus, 0,
847 _("incompatible data type for `%s'"),
848 kwp->ident);
849 return;
850 }
851 }
852 else if (GCONF_IS_LIST (kwp->type))
853 {
854 gl_list_t list;
855 enum gconf_data_type type = GCONF_TYPE (kwp->type);
856 size_t size;
857 void *ptr;
858
859 if (type >= gconf_prop_count
860 || (size = gconf_prop_tab[type].size) == 0)
861 {
862 gconf_error (&gconf_current_locus, 0,
863 _("INTERNAL ERROR at %s:%d: unhandled data type %d"),
864 __FILE__, __LINE__, type);
865 abort();
866 }
867
868 list = gl_list_create_empty (&gl_linked_list_implementation,
869 gconf_prop_tab[type].eqfn,
870 NULL,
871 listel_dispose,
872 false);
873 if (type == gconf_type_string)
874 gl_list_add_last (list, value->v.string);
875 else
876 {
877 ptr = xmalloc (size);
878 if (gconf_string_convert (ptr, type, value->v.string))
879 {
880 free (ptr);
881 gl_list_free (list);
882 return;
883 }
884 gl_list_add_last (list, ptr);
885 }
886 *(gl_list_t*)target = list;
887 }
888 else
889 gconf_string_convert (target, GCONF_TYPE (kwp->type), value->v.string);
890}
891
diff --git a/gconf/gconf-lex.l b/gconf/gconf-lex.l
deleted file mode 100644
index 1379640..0000000
--- a/gconf/gconf-lex.l
+++ b/dev/null
@@ -1,476 +0,0 @@
1/* gconf - General purpose configuration parser. -*- c -*- */
2%{
3/* gconf - General purpose configuration parser.
4 Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
5
6 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22#include <gconf.h>
23#include <gconf-gram.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <ctype.h>
27#include <stdlib.h>
28#include <errno.h>
29
30#define obstack_chunk_alloc malloc
31#define obstack_chunk_free free
32#include <obstack.h>
33#include <xalloc.h>
34#include <wordsplit.h>
35
36#if ENABLE_NLS
37# include "gettext.h"
38# define _(msgid) gettext (msgid)
39#else
40# define _(msgid) msgid
41#endif
42
43static char *multiline_delimiter;
44static size_t multiline_delimiter_len;
45static int multiline_unescape; /* Unescape here-document contents */
46static int (*char_to_strip) (char); /* Strip matching characters of each
47 here-document line */
48
49gconf_locus_t gconf_current_locus; /* Input file location */
50/* Line correction. Equals to the number of #line directives inserted into
51 the input by the preprocessor instance. The external preprocessor, if
52 any, counts these as input lines and therefore the line numbers in *its*
53 #line directives are offset by the value of XLINES.
54
55 Uff, running two preprocessors is confusing...
56*/
57static size_t xlines;
58static struct obstack stk;
59
60static void multiline_begin (char *);
61static void multiline_add (char *);
62static char *multiline_strip_tabs (char *text);
63static void line_add_unescape_last (char *text, size_t len);
64static int ident (void);
65static int isemptystr (int off);
66
67static void parse_line (char *text, gconf_locus_t *ploc, size_t *pxlines);
68static void parse_line_cpp (char *text, gconf_locus_t *ploc, size_t *pxlines);
69
70#undef YY_INPUT
71 #define YY_INPUT(buf,result,max_size) \
72 do \
73 { \
74 if (gconf_preprocessor) \
75 result = fread (buf, 1, max_size, yyin); \
76 else \
77 result = gconf_preproc_fill_buffer(buf, max_size); \
78 } \
79 while (0)
80
81%}
82
83
84%x COMMENT ML STR
85
86WS [ \t\f][ \t\f]*
87ID [a-zA-Z_][a-zA-Z_0-9-]+
88P [1-9][0-9]*
89
90%%
91 /* C-style comments */
92"/*" BEGIN (COMMENT);
93<COMMENT>[^*\n]* /* eat anything that's not a '*' */
94<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
95<COMMENT>\n ++gconf_current_locus.line;
96<COMMENT>"*"+"/" BEGIN (INITIAL);
97 /* Line directive */
98^[ \t]*#[ \t]*{P}[ \t]+\".*\".*\n { parse_line_cpp (yytext,
99 &gconf_current_locus,
100 &xlines); }
101^[ \t]*#[ \t]*line[ \t].*\n { parse_line (yytext, &gconf_current_locus,
102 &xlines); }
103 /* End-of-line comments */
104#.*\n { gconf_current_locus.line++; }
105#.* /* end-of-file comment */;
106"//".*\n { gconf_current_locus.line++; }
107"//".* /* end-of-file comment */;
108 /* Identifiers */
109<INITIAL>{ID} return ident ();
110 /* Strings */
111[a-zA-Z0-9_\.\*/:@-]+ { gconf_line_begin ();
112 gconf_line_add (yytext, yyleng);
113 yylval.string = gconf_line_finish ();
114 return STRING; }
115 /* Quoted strings */
116\"[^\\"\n]*\" { gconf_line_begin ();
117 gconf_line_add (yytext + 1, yyleng - 2);
118 yylval.string = gconf_line_finish ();
119 return QSTRING; }
120\"[^\\"\n]*\\. |
121\"[^\\"\n]*\\\n { BEGIN (STR);
122 gconf_line_begin ();
123 line_add_unescape_last (yytext + 1, yyleng - 1); }
124<STR>[^\\"\n]*\\. |
125<STR>\"[^\\"\n]*\\\n { line_add_unescape_last (yytext, yyleng); }
126<STR>[^\\"\n]*\" { BEGIN(INITIAL);
127 if (yyleng > 1)
128 gconf_line_add (yytext, yyleng - 1);
129 yylval.string = gconf_line_finish ();
130 return QSTRING; }
131 /* Multiline strings */
132"<<"(-" "?)?\\?{ID}[ \t]*#.*\n |
133"<<"(-" "?)?\\?{ID}[ \t]*"//".*\n |
134"<<"(-" "?)?\\?{ID}[ \t]*\n |
135"<<"(-" "?)?\"{ID}\"[ \t]*#.*\n |
136"<<"(-" "?)?\"{ID}\"[ \t]*"//".*\n |
137"<<"(-" "?)?\"{ID}\"[ \t]*\n {
138 BEGIN (ML);
139 multiline_begin (yytext+2);
140 gconf_current_locus.line++; }
141 /* Ignore m4 line statements */
142<ML>^"#line ".*\n { gconf_current_locus.line++; }
143<ML>.*\n { char *p = multiline_strip_tabs (yytext);
144
145 if (!strncmp (p, multiline_delimiter, multiline_delimiter_len)
146 && isemptystr (p + multiline_delimiter_len - yytext))
147 {
148 free (multiline_delimiter);
149 multiline_delimiter = NULL;
150 BEGIN (INITIAL);
151 yylval.string = gconf_line_finish ();
152 return MSTRING;
153 }
154 gconf_current_locus.line++;
155 multiline_add (p); }
156{WS} ;
157 /* Other tokens */
158\n { gconf_current_locus.line++; }
159[,;{}()] return yytext[0];
160. { if (isascii (yytext[0]) && isprint (yytext[0]))
161 gconf_error (&gconf_current_locus, 0, _("stray character %c"), yytext[0]);
162 else
163 gconf_error (&gconf_current_locus, 0, _("stray character \\%03o"),
164 (unsigned char) yytext[0]); }
165%%
166
167pid_t gconf_preproc_pid;
168
169int
170yywrap ()
171{
172 if (yyin)
173 gconf_preproc_extrn_shutdown (gconf_preproc_pid);
174 else
175 gconf_preproc_done ();
176 gconf_current_locus.file = NULL;
177 return 1;
178}
179
180int
181gconf_lex_begin (const char *name)
182{
183 if (yy_flex_debug > 0)
184 yy_flex_debug = 0;
185 obstack_init (&stk);
186 if (gconf_preprocessor)
187 {
188 int fd;
189
190 fd = open (name, O_RDONLY);
191 if (fd == -1)
192 {
193 gconf_error (NULL, errno, _("Cannot open `%s'"), name);
194 return 1;
195 }
196 close (fd);
197
198 yyin = gconf_preproc_extrn_start (name, &gconf_preproc_pid);
199 if (!yyin)
200 {
201 gconf_error (NULL, errno,
202 _("Unable to start external preprocessor `%s'"),
203 gconf_preprocessor);
204 return 1;
205 }
206 }
207 else
208 return gconf_preproc_init (name);
209
210 return 0;
211}
212
213void
214gconf_lex_end ()
215{
216}
217
218static int
219isemptystr (int off)
220{
221 for (; yytext[off] && isspace (yytext[off]); off++)
222 ;
223 if (yytext[off] == ';')
224 {
225 int i;
226 for (i = off + 1; yytext[i]; i++)
227 if (!isspace (yytext[i]))
228 return 0;
229 yyless (off);
230 return 1;
231 }
232 return yytext[off] == 0;
233}
234
235char *
236multiline_strip_tabs (char *text)
237{
238 if (char_to_strip)
239 for (; *text && char_to_strip (*text); text++)
240 ;
241 return text;
242}
243
244static int
245unquote_char (int c)
246{
247 static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
248
249 char *p;
250
251 for (p = quote_transtab; *p; p += 2)
252 {
253 if (*p == c)
254 return p[1];
255 }
256 return -1;
257}
258
259static void
260unescape_to_obstack (int c)
261{
262 if (c != '\n')
263 {
264 int t = unquote_char (c);
265 if (t != -1)
266 obstack_1grow (&stk, t);
267 else
268 {
269 gconf_warning(&gconf_current_locus, 0,
270 _("unknown escape sequence '\\%c'"),
271 c);
272 obstack_1grow (&stk, c);
273 }
274 }
275}
276
277void
278gconf_line_add (const char *text, size_t len)
279{
280 obstack_grow (&stk, text, len);
281}
282
283/* Same, but unescapes the last character from yytext */
284static void
285line_add_unescape_last (char *text, size_t len)
286{
287 obstack_grow (&stk, text, len - 2);
288 unescape_to_obstack (text[len - 1]);
289}
290
291static void
292multiline_add (char *s)
293{
294 if (multiline_unescape)
295 {
296 for (; *s; s++)
297 {
298 if (*s == '\\')
299 {
300 unescape_to_obstack (s[1]);
301 ++s;
302 }
303 else
304 obstack_1grow (&stk, *s);
305 }
306 }
307 else
308 gconf_line_add (s, strlen (s));
309}
310
311void
312gconf_line_begin ()
313{
314 /* FIXME: nothing so far. Maybe prepare stk by calling obstack_finish? */
315}
316
317static int
318is_tab (char c)
319{
320 return c == '\t';
321}
322
323static int
324is_ws (char c)
325{
326 return c == '\t' || c == ' ';
327}
328
329void
330multiline_begin (char *p)
331{
332 if (*p == '-')
333 {
334 if (*++p == ' ')
335 {
336 char_to_strip = is_ws;
337 p++;
338 }
339 else
340 char_to_strip = is_tab;
341 }
342 else
343 char_to_strip = NULL;
344 if (*p == '\\')
345 {
346 p++;
347 multiline_unescape = 0;
348 }
349 else if (*p == '"')
350 {
351 char *q;
352
353 p++;
354 multiline_unescape = 0;
355 q = strchr (p, '"');
356 multiline_delimiter_len = q - p;
357 }
358 else
359 {
360 multiline_delimiter_len = strcspn (p, " \t");
361 multiline_unescape = 1;
362 }
363
364 /* Remove trailing newline */
365 multiline_delimiter_len--;
366 multiline_delimiter = xmalloc (multiline_delimiter_len + 1);
367 memcpy (multiline_delimiter, p, multiline_delimiter_len);
368 multiline_delimiter[multiline_delimiter_len] = 0;
369 gconf_line_begin ();
370}
371
372char *
373gconf_line_finish ()
374{
375 obstack_1grow (&stk, 0);
376 return obstack_finish (&stk);
377}
378
379static int
380ident ()
381{
382 char *p;
383
384 for (p = yytext; *p && isspace (*p); p++)
385 ;
386 obstack_grow (&stk, p, strlen (p));
387 obstack_1grow (&stk, 0);
388 yylval.string = obstack_finish (&stk);
389 return IDENT;
390}
391
392void
393gconf_lex_trace (int n)
394{
395 yy_flex_debug = -n;
396}
397
398gconf_value_t *
399gconf_value_dup(gconf_value_t *input)
400{
401 gconf_value_t *ptr = obstack_alloc (&stk, sizeof (*ptr));
402 *ptr = *input;
403 return ptr;
404}
405
406
407static int
408assign_locus (gconf_locus_t *ploc, char *name, char *line, size_t *pxlines)
409{
410 char *p;
411
412 if (name)
413 {
414 if (pxlines && (!ploc->file || strcmp(name, ploc->file)))
415 *pxlines = 0;
416 ploc->file = gconf_install_text (name);
417 }
418 ploc->line = strtoul (line, &p, 10) - (pxlines ? *pxlines : 0);
419 return *p != 0;
420}
421
422static void
423parse_line (char *text, gconf_locus_t *ploc, size_t *pxlines)
424{
425 int rc = 1;
426 struct wordsplit ws;
427
428 if (wordsplit (text, &ws, WRDSF_DEFFLAGS))
429 gconf_error (ploc, 0, _("cannot parse #line line"));
430 else
431 {
432 if (ws.ws_wordc == 2)
433 rc = assign_locus (ploc, NULL, ws.ws_wordv[1], pxlines);
434 else if (ws.ws_wordc == 3)
435 rc = assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], pxlines);
436 else if (ws.ws_wordc == 4)
437 {
438 rc = assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], 0);
439 if (rc == 0)
440 {
441 char *p;
442 unsigned long x = strtoul (ws.ws_wordv[3], &p, 10);
443 rc = *p != 0;
444 if (rc == 0)
445 *pxlines = x;
446 }
447 }
448 else
449 gconf_error (ploc, 0, _("invalid #line statement"));
450
451 if (rc)
452 gconf_error (ploc, 0, _("malformed #line statement"));
453 wordsplit_free (&ws);
454 }
455}
456
457static void
458parse_line_cpp (char *text, gconf_locus_t *ploc, size_t *pxlines)
459{
460 struct wordsplit ws;
461
462 if (wordsplit (text, &ws, WRDSF_DEFFLAGS))
463 {
464 gconf_error (ploc, 0, _("cannot parse #line line"));
465 return;
466 }
467 else if (ws.ws_wordc < 3)
468 gconf_error (ploc, 0, _("invalid #line statement"));
469 else
470 {
471 if (assign_locus (ploc, ws.ws_wordv[2], ws.ws_wordv[1], pxlines))
472 gconf_error (ploc, 0, _("malformed #line statement"));
473 }
474 wordsplit_free (&ws);
475}
476
diff --git a/gconf/gconf-preproc.c b/gconf/gconf-preproc.c
deleted file mode 100644
index 5bd0a95..0000000
--- a/gconf/gconf-preproc.c
+++ b/dev/null
@@ -1,728 +0,0 @@
1/* gconf - General purpose configuration parser.
2 Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <gconf.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <sys/wait.h>
24#include <ctype.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <stdarg.h>
28#include <string.h>
29#include <errno.h>
30
31#include <xalloc.h>
32#include <hash.h>
33#include <gl_linked_list.h>
34#include <inttostr.h>
35#include <wordsplit.h>
36
37#if ENABLE_NLS
38# include "gettext.h"
39# define _(msgid) gettext (msgid)
40#else
41# define _(msgid) msgid
42#endif
43
44bool gconf_log_to_stderr = true;
45void (*gconf_log_setup_hook) () = NULL;
46
47struct input_file_ident
48{
49 ino_t i_node;
50 dev_t device;
51};
52
53struct buffer_ctx
54{
55 struct buffer_ctx *prev;/* Pointer to previous context */
56 gconf_locus_t locus; /* Current input location */
57 size_t namelen; /* Length of the file name */
58 size_t xlines; /* Number of #line directives output so far */
59 struct input_file_ident id;
60 FILE *infile;
61};
62
63extern int yy_flex_debug;
64static struct buffer_ctx *context_stack;
65
66#define INFILE context_stack->infile
67#define LOCUS context_stack->locus
68
69static char *linebuf;
70static size_t bufsize;
71static char *putback_buffer;
72static size_t putback_size;
73static size_t putback_max;
74
75static int push_source (const char *name, int once);
76static int pop_source (void);
77static int parse_include (const char *text, int once);
78
79static void
80putback (const char *str)
81{
82 size_t len;
83
84 if (!*str)
85 return;
86 len = strlen (str) + 1;
87 if (len > putback_max)
88 {
89 putback_max = len;
90 putback_buffer = xrealloc (putback_buffer, putback_max);
91 }
92 strcpy (putback_buffer, str);
93 putback_size = len - 1;
94}
95
96/* Compute the size of the line
97
98 #line NNN "FILENAME"
99*/
100static size_t
101pp_line_stmt_size ()
102{
103 char lbuf[INT_BUFSIZE_BOUND(uintmax_t)];
104 char xbuf[INT_BUFSIZE_BOUND(uintmax_t)];
105 char *lp, *xp;
106
107 lp = umaxtostr (LOCUS.line, lbuf);
108 xp = umaxtostr (context_stack->xlines + 1, xbuf);
109 if (context_stack->namelen == 0)
110 context_stack->namelen = strlen (LOCUS.file);
111 /* "#line " is 6 chars, two more spaces, two quotes and a linefeed
112 make another 5, summa facit 11 */
113 return 11 + strlen (lp) + strlen (xp) + context_stack->namelen;
114}
115
116static void
117pp_line_stmt ()
118{
119 char *p;
120 size_t ls_size = pp_line_stmt_size ();
121 size_t pb_size = putback_size + ls_size + 1;
122
123 if (pb_size > putback_max)
124 {
125 putback_max = pb_size;
126 putback_buffer = xrealloc (putback_buffer, putback_max);
127 }
128
129 p = putback_buffer + putback_size;
130 context_stack->xlines++;
131 snprintf (p, putback_max - putback_size,
132 "#line %lu \"%s\" %lu\n",
133 (unsigned long) LOCUS.line,
134 LOCUS.file, (unsigned long) context_stack->xlines);
135 putback_size += ls_size;
136}
137
138 #define STRMATCH(p, len, s) (len >= sizeof(s) \
139 && memcmp (p, s, sizeof(s) - 1) == 0 \
140 && isspace(p[sizeof(s) - 1]))
141
142static int
143next_line ()
144{
145 ssize_t rc;
146
147 do
148 {
149 if (putback_size)
150 {
151 if (putback_size + 1 > bufsize)
152 {
153 bufsize = putback_size + 1;
154 linebuf = xrealloc (linebuf, bufsize);
155 }
156 strcpy (linebuf, putback_buffer);
157 rc = putback_size;
158 putback_size = 0;
159 }
160 else if (!context_stack)
161 return 0;
162 else
163 rc = getline (&linebuf, &bufsize, INFILE);
164 }
165 while (rc == -1 && pop_source () == 0);
166 return rc;
167}
168
169size_t
170gconf_preproc_fill_buffer (char *buf, size_t size)
171{
172 size_t bufsize = size;
173
174 while (next_line () > 0)
175 {
176 char *p;
177 size_t len;
178 int is_line = 0;
179
180 for (p = linebuf; *p && isspace (*p); p++)
181 ;
182 if (*p == '#')
183 {
184 size_t l;
185 for (p++; *p && isspace (*p); p++)
186 ;
187 l = strlen (p);
188 if (STRMATCH (p, l, "include_once"))
189 {
190 if (parse_include (linebuf, 1))
191 putback ("/*include_once*/\n");
192 continue;
193 }
194 else if (STRMATCH (p, l, "include"))
195 {
196 if (parse_include (linebuf, 0))
197 putback ("/*include*/\n");
198 continue;
199 }
200 else if (STRMATCH (p, l, "line"))
201 is_line = 1;
202 }
203
204 len = strlen (linebuf);
205
206 if (len > size)
207 len = size;
208
209 memcpy (buf, linebuf, len);
210 buf += len;
211 size -= len;
212
213 if (size == 0)
214 {
215 putback (linebuf + len);
216 break;
217 }
218
219 if (!is_line && len > 0 && linebuf[len - 1] == '\n')
220 LOCUS.line++;
221 }
222 return bufsize - size;
223}
224
225#define STAT_ID_EQ(st,id) ((id).i_node == (st).st_ino \
226 && (id).device == (st).st_dev)
227
228static struct buffer_ctx *
229ctx_lookup (struct stat *st)
230{
231 struct buffer_ctx *ctx;
232
233 if (!context_stack)
234 return NULL;
235
236 for (ctx = context_stack->prev; ctx; ctx = ctx->prev)
237 if (STAT_ID_EQ (*st, ctx->id))
238 break;
239 return ctx;
240}
241
242const char *gconf_preprocessor = NULL;
243static gl_list_t include_path;
244static gl_list_t std_include_path;
245
246struct file_data
247{
248 const char *name;
249 size_t namelen;
250 char *buf;
251 size_t buflen;
252 int found;
253};
254
255static int
256pp_list_find (gl_list_t list, struct file_data *dptr)
257{
258 const void *p;
259 gl_list_iterator_t itr = gl_list_iterator (list);
260
261 while (!dptr->found && gl_list_iterator_next (&itr, &p, NULL))
262 {
263 const char *dir = p;
264 size_t size = strlen (dir) + 1 + dptr->namelen + 1;
265 if (size > dptr->buflen)
266 {
267 dptr->buflen = size;
268 dptr->buf = xrealloc (dptr->buf, dptr->buflen);
269 }
270 strcpy (dptr->buf, dir);
271 strcat (dptr->buf, "/");
272 strcat (dptr->buf, dptr->name);
273 dptr->found = access (dptr->buf, F_OK) == 0;
274 }
275 gl_list_iterator_free (&itr);
276 return dptr->found;
277}
278
279gl_list_t
280pp_list_create ()
281{
282 return gl_list_create_empty(&gl_linked_list_implementation,
283 NULL,
284 NULL,
285 NULL,
286 false);
287}
288
289void
290gconf_include_path_setup_v (char **dirs)
291{
292 if (!include_path)
293 include_path = pp_list_create ();
294 std_include_path = pp_list_create ();
295 if (dirs)
296 {
297 int i;
298 for (i = 0; dirs[i]; i++)
299 /* FIXME: Element never freed */
300 gl_list_add_last (std_include_path, xstrdup (dirs[i]));
301 }
302}
303
304void
305gconf_include_path_setup (const char *dir, ...)
306{
307 const char *p;
308 char **argv = NULL;
309 size_t argc = 0;
310 size_t argi = 0;
311 va_list ap;
312
313 va_start (ap, dir);
314 p = dir;
315 while (1)
316 {
317 if (argi == argc)
318 {
319 if (argc == 0)
320 argc = 16;
321 argv = x2nrealloc (argv, &argc, sizeof (argv[0]));
322 }
323 argv[argi++] = (char*) p;
324 if (!p)
325 break;
326 p = va_arg (ap, const char*);
327 }
328 gconf_include_path_setup_v (argv);
329 free (argv);
330 va_end (ap);
331}
332
333void
334gconf_preproc_add_include_dir (char *dir)
335{
336 if (!include_path)
337 include_path = pp_list_create ();
338 gl_list_add_last (include_path, dir);
339}
340
341static Hash_table *incl_sources;
342
343/* Calculate the hash of a struct input_file_ident. */
344static size_t
345incl_hasher (void const *data, unsigned n_buckets)
346{
347 const struct input_file_ident *id = data;
348 return (id->i_node + id->device) % n_buckets;
349}
350
351/* Compare two input_file_idents for equality. */
352static bool
353incl_compare (void const *data1, void const *data2)
354{
355 const struct input_file_ident *id1 = data1;
356 const struct input_file_ident *id2 = data2;
357 return id1->device == id2->device && id1->i_node == id2->i_node;
358}
359
360static void
361incl_free (void *data)
362{
363 free (data);
364}
365
366static int
367source_lookup (struct stat *st)
368{
369 struct input_file_ident *sample = xmalloc (sizeof (*sample)), *id;
370
371 sample->i_node = st->st_ino;
372 sample->device = st->st_dev;
373
374 if (!((incl_sources
375 || (incl_sources = hash_initialize (0, 0,
376 incl_hasher,
377 incl_compare,
378 incl_free)))
379 && (id = hash_insert (incl_sources, sample))))
380 xalloc_die ();
381
382 if (id != sample)
383 {
384 free (sample);
385 return 1; /* Found */
386 }
387 return 0;
388}
389
390
391static int
392push_source (const char *name, int once)
393{
394 FILE *fp;
395 struct buffer_ctx *ctx;
396 struct stat st;
397 int rc = stat (name, &st);
398
399 if (context_stack)
400 {
401 if (rc)
402 {
403 gconf_error (&LOCUS, errno, _("Cannot stat `%s'"), name);
404 return 1;
405 }
406
407 if (LOCUS.file && STAT_ID_EQ (st, context_stack->id))
408 {
409 gconf_error (&LOCUS, 0, _("Recursive inclusion"));
410 return 1;
411 }
412
413 if ((ctx = ctx_lookup (&st)))
414 {
415 gconf_error (&LOCUS, 0, _("Recursive inclusion"));
416 if (ctx->prev)
417 gconf_error (&ctx->prev->locus, 0,
418 _("`%s' already included here"), name);
419 else
420 gconf_error (&LOCUS, 0,
421 _("`%s' already included at top level"), name);
422 return 1;
423 }
424 }
425 else if (rc)
426 {
427 gconf_error (NULL, errno, _("Cannot stat `%s'"), name);
428 return 1;
429 }
430
431 if (once && source_lookup (&st))
432 return -1;
433
434 fp = fopen (name, "r");
435 if (!fp)
436 {
437 gconf_error (&LOCUS, errno, _("Cannot open `%s'"), name);
438 return 1;
439 }
440
441 /* Push current context */
442 ctx = xmalloc (sizeof (*ctx));
443 ctx->locus.file = gconf_install_text (name);
444 ctx->locus.line = 1;
445 ctx->xlines = 0;
446 ctx->namelen = strlen (ctx->locus.file);
447 ctx->id.i_node = st.st_ino;
448 ctx->id.device = st.st_dev;
449 ctx->infile = fp;
450 ctx->prev = context_stack;
451 context_stack = ctx;
452
453 if (yy_flex_debug)
454 fprintf (stderr, "Processing file `%s'\n", name);
455
456 pp_line_stmt ();
457
458 return 0;
459}
460
461static int
462pop_source ()
463{
464 struct buffer_ctx *ctx;
465
466 if (!context_stack)
467 return 1;
468
469 fclose (INFILE);
470
471 /* Restore previous context */
472 ctx = context_stack->prev;
473 free (context_stack);
474 context_stack = ctx;
475
476 if (!context_stack)
477 {
478 if (yy_flex_debug)
479 fprintf (stderr, "End of input\n");
480 return 1;
481 }
482
483 LOCUS.line++;
484
485 if (yy_flex_debug)
486 fprintf (stderr, "Resuming file `%s' at line %lu\n",
487 LOCUS.file, (unsigned long) LOCUS.line);
488
489 pp_line_stmt ();
490
491 return 0;
492}
493
494static int
495try_file (const char *name, int allow_cwd, int err_not_found, char **newp)
496{
497 static char *cwd = ".";
498 struct file_data fd;
499
500 fd.name = name;
501 fd.namelen = strlen (name);
502 fd.buf = NULL;
503 fd.buflen = 0;
504 fd.found = 0;
505
506 if (!include_path)
507 gconf_include_path_setup (NULL);
508 if (allow_cwd)
509 {
510 gl_list_node_t node = gl_list_add_last (include_path, cwd);
511 pp_list_find (include_path, &fd);
512 gl_list_remove_node (include_path, node);
513 }
514 else
515 pp_list_find (include_path, &fd);
516
517 if (!fd.found)
518 {
519 pp_list_find (std_include_path, &fd);
520
521 if (!fd.found && err_not_found)
522 {
523 gconf_error (&LOCUS, 0, _("%s: No such file or directory"), name);
524 *newp = NULL;
525 }
526 }
527 if (fd.found)
528 *newp = fd.buf;
529 return fd.found;
530}
531
532static int
533parse_include (const char *text, int once)
534{
535 struct wordsplit ws;
536 char *tmp = NULL;
537 char *p = NULL;
538 int rc = 1;
539
540 if (wordsplit (text, &ws, WRDSF_DEFFLAGS))
541 gconf_error (&LOCUS, 0, _("Cannot parse include line"));
542 else if (ws.ws_wordc != 2)
543 {
544 wordsplit_free (&ws);
545 gconf_error (&LOCUS, 0, _("invalid include statement"));
546 }
547 else
548 {
549 size_t len;
550 int allow_cwd;
551
552 p = ws.ws_wordv[1];
553 len = strlen (p);
554
555 if (p[0] == '<' && p[len - 1] == '>')
556 {
557 allow_cwd = 0;
558 p[len - 1] = 0;
559 p++;
560 }
561 else
562 allow_cwd = 1;
563
564 if (p[0] != '/' && try_file (p, allow_cwd, 1, &tmp))
565 p = tmp;
566 }
567
568 if (p)
569 rc = push_source (p, once);
570 free (tmp);
571 wordsplit_free (&ws);
572 return rc;
573}
574
575int
576gconf_preproc_init (const char *name)
577{
578 return push_source (name, 0);
579}
580
581void
582gconf_preproc_done ()
583{
584 if (incl_sources)
585 hash_free (incl_sources);
586 free (linebuf);
587 free (putback_buffer);
588}
589
590int
591gconf_preproc_run (const char *config_file, const char *extpp)
592{
593 size_t i;
594 char buffer[512];
595
596 if (gconf_preproc_init (config_file))
597 return 1;
598 if (extpp)
599 {
600 FILE *outfile;
601 char *setup_file;
602 char *cmd;
603
604 if (try_file ("pp-setup", 1, 0, &setup_file))
605 {
606 asprintf (&cmd, "%s %s -", extpp, setup_file);
607 free (setup_file);
608 }
609 else
610 cmd = xstrdup (extpp);
611 //FIXME_DEBUG_F1 (2, "Running preprocessor: `%s'", cmd);
612 outfile = popen (cmd, "w");
613 if (!outfile)
614 {
615 gconf_error (NULL, errno,
616 _("Unable to start external preprocessor `%s'"), cmd);
617 free (cmd);
618 return 1;
619 }
620
621 while ((i = gconf_preproc_fill_buffer (buffer, sizeof buffer)))
622 fwrite (buffer, 1, i, outfile);
623 pclose (outfile);
624 free (cmd);
625 }
626 else
627 {
628 while ((i = gconf_preproc_fill_buffer (buffer, sizeof buffer)))
629 fwrite (buffer, 1, i, stdout);
630 }
631 gconf_preproc_done ();
632 return 0;
633}
634
635FILE *
636gconf_preproc_extrn_start (const char *file_name, pid_t *ppid)
637{
638 int pout[2];
639 pid_t pid;
640 int i;
641 FILE *fp = NULL;
642
643 //FIXME_DEBUG_F1 (2, "Running preprocessor: `%s'", ppcmd);
644
645 pipe (pout);
646 switch (pid = fork ())
647 {
648 /* The child branch. */
649 case 0:
650 if (pout[1] != 1)
651 {
652 close (1);
653 dup2 (pout[1], 1);
654 }
655
656 /* Close unneeded descripitors */
657 for (i = getdtablesize (); i > 2; i--)
658 close (i);
659
660 if (!gconf_log_to_stderr)
661 {
662 int p[2];
663 char *buf = NULL;
664 size_t size = 0;
665 FILE *fp;
666
667 signal (SIGCHLD, SIG_DFL);
668 pipe (p);
669 switch (pid = fork ())
670 {
671 /* Grandchild */
672 case 0:
673 if (p[1] != 2)
674 {
675 close (2);
676 dup2 (p[1], 2);
677 }
678 close (p[0]);
679
680 if (gconf_preproc_run (file_name, gconf_preprocessor))
681 exit (127);
682 exit (0);
683
684 case -1:
685 /* Fork failed */
686 if (gconf_log_setup_hook)
687 gconf_log_setup_hook ();
688 gconf_error (NULL, errno, _("Cannot run `%s'"),
689 gconf_preprocessor);
690 exit (127);
691
692 default:
693 /* Sub-master */
694 close (p[1]);
695 fp = fdopen (p[0], "r");
696 if (gconf_log_setup_hook)
697 gconf_log_setup_hook ();
698 while (getline (&buf, &size, fp) > 0)
699 gconf_error (NULL, 0, "%s", buf);
700 }
701 }
702 else
703 {
704 gconf_preproc_run (file_name, gconf_preprocessor);
705 }
706 exit (0);
707
708 case -1:
709 /* Fork failed */
710 gconf_error (NULL, errno, _("Cannot run `%s'"), gconf_preprocessor);
711 break;
712
713 default:
714 close (pout[1]);
715 fp = fdopen (pout[0], "r");
716 break;
717 }
718 *ppid = pid;
719 return fp;
720}
721
722void
723gconf_preproc_extrn_shutdown (pid_t pid)
724{
725 int status;
726 waitpid (pid, &status, 0);
727}
728
diff --git a/gconf/gconf-text.c b/gconf/gconf-text.c
deleted file mode 100644
index 0545293..0000000
--- a/gconf/gconf-text.c
+++ b/dev/null
@@ -1,73 +0,0 @@
1/* gconf - General purpose configuration parser.
2 Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <gconf.h>
21#include <string.h>
22#include <hash.h>
23#include <xalloc.h>
24
25static Hash_table *text_table;
26
27/* Calculate the hash of a string. */
28static size_t
29text_hasher (void const *data, unsigned n_buckets)
30{
31 return hash_string (data, n_buckets);
32}
33
34/* Compare two strings for equality. */
35static bool
36text_compare (void const *data1, void const *data2)
37{
38 return strcmp (data1, data2) == 0;
39}
40
41static void
42text_free (void *data)
43{
44 free (data);
45}
46
47/* Lookup a text. If it does not exist, create it. */
48char *
49gconf_install_text (const char *str)
50{
51 char *text, *s;
52
53 s = xstrdup (str);
54
55 if (!((text_table
56 || (text_table = hash_initialize (0, 0,
57 text_hasher,
58 text_compare,
59 text_free)))
60 && (text = hash_insert (text_table, s))))
61 xalloc_die ();
62
63 if (s != text)
64 free (s);
65 return text;
66}
67
68void
69gconf_destroy_text ()
70{
71 if (text_table)
72 hash_free (text_table);
73}
diff --git a/gconf/gconf.h b/gconf/gconf.h
deleted file mode 100644
index f3d1bf8..0000000
--- a/gconf/gconf.h
+++ b/dev/null
@@ -1,163 +0,0 @@
1/* gconf - General purpose configuration parser.
2 Copyright (C) 2007, 2008, 2009 Sergey Poznyakoff
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include <sys/types.h>
18#include <unistd.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <stdbool.h>
22#include <gl_linked_list.h>
23
24typedef struct {
25 char *file;
26 int line;
27} gconf_locus_t;
28
29extern gconf_locus_t gconf_locus;
30
31enum gconf_data_type {
32 gconf_type_void,
33 gconf_type_string,
34 gconf_type_short,
35 gconf_type_ushort,
36 gconf_type_int,
37 gconf_type_uint,
38 gconf_type_long,
39 gconf_type_ulong,
40 gconf_type_size,
41/* gconf_type_off,*/
42 gconf_type_uintmax,
43 gconf_type_intmax,
44 gconf_type_time,
45 gconf_type_bool,
46 gconf_type_ipv4,
47 gconf_type_cidr,
48 gconf_type_host,
49 gconf_type_sockaddr,
50 gconf_type_section
51};
52
53#define GCONF_LIST 0x8000
54#define GCONF_TYPE_MASK 0x00ff
55#define GCONF_TYPE(c) ((c) & GCONF_TYPE_MASK)
56#define GCONF_IS_LIST(c) ((c) & GCONF_LIST)
57
58enum gconf_callback_command {
59 gconf_callback_section_begin,
60 gconf_callback_section_end,
61 gconf_callback_set_value
62};
63
64#define GCONF_TYPE_STRING 0
65#define GCONF_TYPE_LIST 1
66#define GCONF_TYPE_ARRAY 2
67
68typedef struct gconf_value {
69 int type;
70 union {
71 gl_list_t list;
72 const char *string;
73 struct {
74 size_t c;
75 struct gconf_value *v;
76 } arg;
77 } v;
78} gconf_value_t;
79
80typedef int (*gconf_callback_fn) (
81 enum gconf_callback_command cmd,
82 gconf_locus_t * /* locus */,
83 void * /* varptr */,
84 gconf_value_t * /* value */,
85 void * /* cb_data */
86 );
87
88struct gconf_keyword {
89 const char *ident;
90 const char *argname;
91 const char *docstring;
92 enum gconf_data_type type;
93 void *varptr;
94 size_t offset;
95 gconf_callback_fn callback;
96 void *callback_data;
97 struct gconf_keyword *kwd;
98};
99
100struct gconf_sockaddr {
101 int len;
102 struct sockaddr *sa;
103};
104
105gconf_value_t *gconf_value_dup(gconf_value_t *input);
106
107extern void gconf_print_diag(gconf_locus_t *, int, int, const char*);
108
109void gconf_warning(gconf_locus_t *locus, int errcode, const char *fmt, ...)
110 __attribute__ ((__format__ (__printf__, 3, 4)));
111void gconf_error(gconf_locus_t *locus, int errcode, const char *fmt, ...)
112 __attribute__ ((__format__ (__printf__, 3, 4)));
113void gconf_set_keywords(struct gconf_keyword *kwd);
114void gconf_gram_trace(int n);
115void gconf_lex_trace (int n);
116
117int gconf_lex_begin(const char*);
118void gconf_lex_end(void);
119int gconf_parse (const char *name);
120
121void gconf_line_begin (void);
122void gconf_line_add (const char *text, size_t len);
123char *gconf_line_finish (void);
124
125extern int gconf_string_convert (void *target, enum gconf_data_type type,
126 const char *string);
127
128extern gconf_locus_t gconf_current_locus;
129extern int gconf_error_count;
130extern int gconf_default_port;
131
132extern const char *gconf_preprocessor;
133extern bool gconf_log_to_stderr;
134extern void (*gconf_log_setup_hook) ();
135
136size_t gconf_preproc_fill_buffer (char *buf, size_t size);
137void gconf_preproc_add_include_dir (char *dir);
138int gconf_preproc_init (const char *name);
139void gconf_preproc_done (void);
140int gconf_preproc_run (const char *config_file, const char *extpp);
141
142FILE *gconf_preproc_extrn_start (const char *file, pid_t *ppid);
143void gconf_preproc_extrn_shutdown (pid_t pid);
144
145char *gconf_install_text (const char *str);
146void gconf_destroy_text (void);
147
148void gconf_include_path_setup (const char *dir, ...);
149void gconf_include_path_setup_v (char **dirs);
150
151const char *gconf_data_type_string (enum gconf_data_type type);
152void gconf_format_docstring (FILE *stream, const char *docstring,
153 unsigned level);
154void gconf_format_simple_statement (FILE *stream, struct gconf_keyword *kwp,
155 unsigned level);
156void gconf_format_block_statement (FILE *stream, struct gconf_keyword *kwp,
157 unsigned level);
158void gconf_format_statement_array (FILE *stream, struct gconf_keyword *kwp,
159 unsigned n,
160 unsigned level);
161
162
163
diff --git a/gconf/gnulib.modules b/gconf/gnulib.modules
deleted file mode 100644
index 5ba9e5f..0000000
--- a/gconf/gnulib.modules
+++ b/dev/null
@@ -1,14 +0,0 @@
1# getdtablesize ??
2c-ctype
3getline
4hash
5inttostr
6inttypes
7linked-list
8obstack
9regex
10stdbool
11strtoimax
12strtoumax
13vasprintf
14xalloc
diff --git a/gconf/wordsplit.c b/gconf/wordsplit.c
deleted file mode 100644
index a5bb13e..0000000
--- a/gconf/wordsplit.c
+++ b/dev/null
@@ -1,568 +0,0 @@
1/* wordsplit - a word splitter
2 Copyright (C) 2009 Sergey Poznyakoff
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20
21#include <ctype.h>
22#include <c-ctype.h>
23#include <errno.h>
24#include <unistd.h>
25#include <string.h>
26#include <wordsplit.h>
27
28#include <error.h>
29#include <gettext.h>
30#define _(msgid) gettext (msgid)
31#include <xalloc.h>
32
33#define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
34#define isdelim(c,delim) (strchr(delim,(c))!=NULL)
35
36#define _ARGCV_WORD_SED_EXPR 0x10000
37#define _ARGCV_WORD_MASK 0xf0000
38
39#define ALLOC_INIT 128
40#define ALLOC_INCR 128
41
42static int
43wordsplit_init (struct wordsplit *wsp, const char *input, size_t len,
44 int flags)
45{
46 wsp->ws_flags = flags;
47 if ((wsp->ws_flags & (WRDSF_NOVAR|WRDSF_NOCMD))
48 != (WRDSF_NOVAR|WRDSF_NOCMD))
49 {
50 if (wsp->ws_flags & WRDSF_SHOWERR)
51 error (0, 0,
52 _("variable expansion and command substitution "
53 "are not yet supported"));
54 errno = EINVAL;
55 return 1;
56 }
57
58 wsp->ws_input = input;
59 wsp->ws_len = len;
60
61 if (!(wsp->ws_flags & WRDSF_DOOFFS))
62 wsp->ws_offs = 0;
63
64 if (!(wsp->ws_flags & WRDSF_DELIM))
65 wsp->ws_delim = " ";
66
67 if (!(wsp->ws_flags & WRDSF_COMMENT))
68 wsp->ws_comment = NULL;
69
70 if (wsp->ws_flags & WRDSF_REUSE)
71 {
72 wsp->ws_wordn = wsp->ws_wordc + 1;
73 if (wsp->ws_flags & WRDSF_DOOFFS)
74 wsp->ws_wordn += wsp->ws_offs;
75 if (!(wsp->ws_flags & WRDSF_APPEND))
76 wsp->ws_wordc = 0;
77 }
78 else
79 {
80 wsp->ws_wordv = NULL;
81 wsp->ws_wordc = 0;
82 wsp->ws_wordn = 0;
83 }
84
85 wsp->ws_endp = 0;
86 return 0;
87}
88
89static int
90alloc_space (struct wordsplit *wsp)
91{
92 size_t offs = (wsp->ws_flags & WRDSF_DOOFFS) ? wsp->ws_offs : 0;
93 char **ptr;
94 size_t newalloc;
95
96 if (wsp->ws_wordv == NULL)
97 {
98 newalloc = offs + ALLOC_INIT;
99 ptr = calloc (newalloc, sizeof (ptr[0]));
100 }
101 else if (wsp->ws_wordn < offs + wsp->ws_wordc + 1)
102 {
103 newalloc = offs + wsp->ws_wordc + ALLOC_INCR;
104 ptr = realloc (wsp->ws_wordv, newalloc * sizeof (ptr[0]));
105 }
106 else
107 return 0;
108
109 if (ptr)
110 {
111 wsp->ws_wordn = newalloc;
112 wsp->ws_wordv = ptr;
113 }
114 else
115 {
116 if (wsp->ws_flags & WRDSF_ENOMEMABRT)
117 xalloc_die ();
118 else if (wsp->ws_flags & WRDSF_SHOWERR)
119 error (0, 0, _("memory exhausted"));
120 errno = ENOMEM;
121 return 1;
122 }
123 return 0;
124}
125
126static int
127skip_sed_expr(const char *command, size_t i, size_t len)
128{
129 int state;
130
131 do
132 {
133 int delim;
134
135 if (command[i] == ';')
136 i++;
137 if (!(command[i] == 's' && i + 3 < len && c_ispunct(command[i+1])))
138 break;
139
140 delim = command[++i];
141 state = 1;
142 for (i++; i < len; i++)
143 {
144 if (state == 3)
145 {
146 if (command[i] == delim || !c_isalnum(command[i]))
147 break;
148 }
149 else if (command[i] == '\\')
150 i++;
151 else if (command[i] == delim)
152 state++;
153 }
154 }
155 while (state == 3 && i < len && command[i] == ';');
156 return i;
157}
158
159static size_t
160skip_delim (struct wordsplit *wsp)
161{
162 size_t start = wsp->ws_endp;
163 if (wsp->ws_flags & WRDSF_SQUEEZE_DELIMS)
164 {
165 do
166 start++;
167 while (start < wsp->ws_len
168 && isdelim (wsp->ws_input[start], wsp->ws_delim));
169 start--;
170 }
171
172 if (!(wsp->ws_flags & WRDSF_RETURN_DELIMS))
173 start++;
174
175 return start;
176}
177
178#define _WRDS_WORD 1
179#define _WRDS_CONT 2
180
181static int
182scan_word (struct wordsplit *wsp, size_t *pstart, size_t *pend)
183{
184 size_t start = *pstart;
185 size_t len = wsp->ws_len;
186 const char *command = wsp->ws_input;
187 const char *delim = wsp->ws_delim;
188 const char *comment = wsp->ws_comment;
189
190 size_t i = start;
191
192 if (i >= len)
193 return WRDSE_EOF;
194
195 if (wsp->ws_flags & WRDSF_WS)
196 {
197 /* Skip initial whitespace */
198 while (i < len && isws (command[i]))
199 i++;
200 }
201
202 start = i;
203
204 wsp->ws_flags &= ~_ARGCV_WORD_MASK;
205
206 if (wsp->ws_flags & WRDSF_SED_EXPR
207 && command[i] == 's' && i + 3 < len && c_ispunct (command[i+1]))
208 {
209 wsp->ws_flags |= _ARGCV_WORD_SED_EXPR;
210 i = skip_sed_expr (command, i, len);
211 }
212 else if (!isdelim (command[i], delim))
213 {
214 while (i < len)
215 {
216 if (comment && strchr (comment, command[i]) != NULL)
217 {
218 size_t j;
219 for (j = i + 1; j < len && command[j] != '\n'; j++)
220 ;
221 *pstart = start;
222 *pend = i;
223 wsp->ws_endp = j;
224 return i > start ? _WRDS_WORD : _WRDS_CONT;
225 }
226
227 if (wsp->ws_flags & WRDSF_QUOTE)
228 {
229 if (command[i] == '\\')
230 {
231 if (++i == len)
232 break;
233 i++;
234 continue;
235 }
236
237 if (command[i] == '\'' || command[i] == '"')
238 {
239 size_t j;
240 for (j = i + 1; j < len && command[j] != command[i]; j++)
241 if (command[j] == '\\')
242 j++;
243 if (j < len && command[j] == command[i])
244 i = j + 1;
245 else
246 {
247 wsp->ws_endp = i;
248 if (wsp->ws_flags & WRDSF_SHOWERR)
249 error (0, 0,
250 _("missing closing %c (start near #%lu)"),
251 command[i], (unsigned long) i);
252 return WRDSE_QUOTE;
253 }
254 }
255 }
256
257 if (((wsp->ws_flags & WRDSF_WS) && isws (command[i]))
258 || isdelim (command[i], delim))
259 break;
260 else
261 i++;
262 }
263 }
264 else if (wsp->ws_flags & WRDSF_RETURN_DELIMS)
265 i++;
266
267 *pstart = start;
268 *pend = i;
269 wsp->ws_endp = i;
270
271 return _WRDS_WORD;
272}
273
274static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\tv\v";
275
276int
277wordsplit_unquote_char (int c)
278{
279 char *p;
280
281 for (p = quote_transtab; *p; p += 2)
282 {
283 if (*p == c)
284 return p[1];
285 }
286 return c;
287}
288
289int
290wordsplit_quote_char (int c)
291{
292 char *p;
293
294 for (p = quote_transtab + sizeof(quote_transtab) - 2;
295 p > quote_transtab; p -= 2)
296 {
297 if (*p == c)
298 return p[-1];
299 }
300 return -1;
301}
302
303#define to_num(c) \
304 (isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 ))
305
306static int
307xtonum (int *pval, const char *src, int base, int cnt)
308{
309 int i, val;
310
311 for (i = 0, val = 0; i < cnt; i++, src++)
312 {
313 int n = *(unsigned char*)src;
314 if (n > 127 || (n = to_num(n)) >= base)
315 break;
316 val = val*base + n;
317 }
318 *pval = val;
319 return i;
320}
321
322size_t
323wordsplit_quoted_length (const char *str, int quote_hex, int *quote)
324{
325 size_t len = 0;
326
327 *quote = 0;
328 for (; *str; str++)
329 {
330 if (*str == ' ')
331 {
332 len++;
333 *quote = 1;
334 }
335 else if (*str == '"')
336 {
337 len += 2;
338 *quote = 1;
339 }
340 else if (*str != '\t' && *str != '\\' && isprint (*str))
341 len++;
342 else if (quote_hex)
343 len += 3;
344 else
345 {
346 if (wordsplit_quote_char (*str) != -1)
347 len += 2;
348 else
349 len += 4;
350 }
351 }
352 return len;
353}
354
355void
356wordsplit_unquote_copy (char *dst, const char *src, size_t n)
357{
358 int i = 0;
359 int c;
360 int expect_delim = 0;
361
362 while (i < n)
363 {
364 switch (src[i])
365 {
366 case '\'':
367 case '"':
368 if (!expect_delim)
369 {
370 const char *p;
371
372 for (p = src+i+1; *p && *p != src[i]; p++)
373 if (*p == '\\')
374 p++;
375 if (*p)
376 expect_delim = src[i++];
377 else
378 *dst++ = src[i++];
379 }
380 else if (expect_delim == src[i])
381 ++i;
382 else
383 *dst++ = src[i++];
384 break;
385
386 case '\\':
387 ++i;
388 if (src[i] == 'x' || src[i] == 'X')
389 {
390 if (n - i < 2)
391 {
392 *dst++ = '\\';
393 *dst++ = src[i++];
394 }
395 else
396 {
397 int off = xtonum(&c, src + i + 1, 16, 2);
398 if (off == 0)
399 {
400 *dst++ = '\\';
401 *dst++ = src[i++];
402 }
403 else
404 {
405 *dst++ = c;
406 i += off + 1;
407 }
408 }
409 }
410 else if ((unsigned char)src[i] < 128 && isdigit (src[i]))
411 {
412 if (n - i < 1)
413 {
414 *dst++ = '\\';
415 *dst++ = src[i++];
416 }
417 else
418 {
419 int off = xtonum (&c, src+i, 8, 3);
420 if (off == 0)
421 {
422 *dst++ = '\\';
423 *dst++ = src[i++];
424 }
425 else
426 {
427 *dst++ = c;
428 i += off;
429 }
430 }
431 }
432 else
433 *dst++ = wordsplit_unquote_char (src[i++]);
434 break;
435
436 default:
437 *dst++ = src[i++];
438 }
439 }
440 *dst = 0;
441}
442
443void
444wordsplit_quote_copy (char *dst, const char *src, int quote_hex)
445{
446 for (; *src; src++)
447 {
448 if (*src == '"')
449 {
450 *dst++ = '\\';
451 *dst++ = *src;
452 }
453 else if (*src != '\t' && *src != '\\' && isprint (*src))
454 *dst++ = *src;
455 else
456 {
457 char tmp[4];
458
459 if (quote_hex)
460 {
461 snprintf (tmp, sizeof tmp, "%%%02X", *(unsigned char*)src);
462 memcpy (dst, tmp, 3);
463 dst += 3;
464 }
465 else
466 {
467 int c = wordsplit_quote_char (*src);
468 *dst++ = '\\';
469 if (c != -1)
470 *dst++ = c;
471 else
472 {
473 snprintf (tmp, sizeof tmp, "%03o", *(unsigned char*)src);
474 memcpy (dst, tmp, 3);
475 dst += 3;
476 }
477 }
478 }
479 }
480}
481
482int
483wordsplit_len (const char *command, size_t len, struct wordsplit *wsp,
484 int flags)
485{
486 int rc;
487 size_t start = 0, end = 0;
488
489 rc = wordsplit_init (wsp, command, len, flags);
490 if (rc)
491 return rc;
492
493 for (; (rc = scan_word (wsp, &start, &end)) > 0; start = skip_delim (wsp))
494 {
495 int unquote = 1;
496 size_t n;
497 char *p;
498
499 if (rc == _WRDS_CONT)
500 continue;
501
502 if (alloc_space (wsp))
503 return WRDSE_NOSPACE;
504
505 n = end - start;
506
507 if (wsp->ws_flags & WRDSF_QUOTE &&
508 !(wsp->ws_flags & _ARGCV_WORD_SED_EXPR))
509 {
510 if (start < end
511 && (command[start] == '"' || command[start] == '\'')
512 && command[end-1] == command[start])
513 {
514 unquote = command[start] == '"';
515 start++;
516 n -= 2;
517 }
518 }
519 else
520 unquote = 0;
521
522 p = malloc (n + 1);
523 if (!p)
524 {
525 if (wsp->ws_flags & WRDSF_ENOMEMABRT)
526 xalloc_die ();
527 if (wsp->ws_flags & WRDSF_SHOWERR)
528 error (0, 0, _("memory exhausted"));
529 if (!(wsp->ws_flags & WRDSF_REUSE))
530 wordsplit_free (wsp);
531 errno = ENOMEM;
532 return WRDSE_NOSPACE;
533 }
534
535 if (unquote)
536 wordsplit_unquote_copy (p, &command[start], n);
537 else
538 {
539 memcpy (p, &command[start], n);
540 p[n] = 0;
541 }
542 wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = p;
543 wsp->ws_wordc++;
544
545 ;
546 }
547 if (alloc_space (wsp))
548 return WRDSE_NOSPACE;
549 wsp->ws_wordv[wsp->ws_offs + wsp->ws_wordc] = NULL;
550 /* FIXME: if (rc) free(ws) */
551 return rc;
552}
553
554int
555wordsplit (const char *command, struct wordsplit *ws, int flags)
556{
557 return wordsplit_len (command, strlen (command), ws, flags);
558}
559
560void
561wordsplit_free (struct wordsplit *ws)
562{
563 free (ws->ws_wordv);
564 ws->ws_wordv = NULL;
565}
566
567
568
diff --git a/gconf/wordsplit.h b/gconf/wordsplit.h
deleted file mode 100644
index d4d1f0c..0000000
--- a/gconf/wordsplit.h
+++ b/dev/null
@@ -1,88 +0,0 @@
1/* wordsplit - a word splitter
2 Copyright (C) 2009 Sergey Poznyakoff
3
4 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
16
17struct wordsplit
18{
19 size_t ws_wordc;
20 char **ws_wordv;
21 size_t ws_offs;
22 size_t ws_wordn;
23 int ws_flags;
24 const char *ws_delim;
25 const char *ws_comment;
26
27 const char *ws_input;
28 size_t ws_len;
29 size_t ws_endp;
30};
31
32/* Append the words found to the array resulting from a previous
33 call. */
34#define WRDSF_APPEND 0x0001
35/* Insert we_offs initial NULLs in the array ws_wordv.
36 (These are not counted in the returned ws_wordc.) */
37#define WRDSF_DOOFFS 0x0002
38/* Don't do command substitution. Reserved for future use. */
39#define WRDSF_NOCMD 0x0004
40/* The parameter p resulted from a previous call to
41 wordsplit(), and wordsplit_free() was not called. Reuse the
42 allocated storage. */
43#define WRDSF_REUSE 0x0008
44/* Print errors */
45#define WRDSF_SHOWERR 0x0010
46/* Consider it an error if an undefined shell variable
47 is expanded. */
48#define WRDSF_UNDEF 0x0020
49
50/* Don't do variable expansion. Reserved for future use. */
51#define WRDSF_NOVAR 0x0040
52/* Abort on ENOMEM error */
53#define WRDSF_ENOMEMABRT 0x0080
54/* Treat whitespace as delimiters */
55#define WRDSF_WS 0x0100
56/* Handle quotes and escape directives */
57#define WRDSF_QUOTE 0x0200
58/* Replace each input sequence of repeated delimiters with a single
59 delimiter */
60#define WRDSF_SQUEEZE_DELIMS 0x0400
61/* Return delimiters */
62#define WRDSF_RETURN_DELIMS 0x0800
63/* Treat sed expressions as words */
64#define WRDSF_SED_EXPR 0x1000
65/* ws_delim field is initialized */
66#define WRDSF_DELIM 0x2000
67/* ws_comment field is initialized */
68#define WRDSF_COMMENT 0x4000
69
70#define WRDSF_DEFFLAGS \
71 (WRDSF_NOVAR | WRDSF_NOCMD | \
72 WRDSF_WS | WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS)
73
74#define WRDSE_EOF 0
75#define WRDSE_QUOTE 1
76#define WRDSE_NOSPACE 2
77
78int wordsplit (const char *s, struct wordsplit *p, int flags);
79void wordsplit_free (struct wordsplit *p);
80
81int wordsplit_unquote_char (int c);
82int wordsplit_quote_char (int c);
83size_t wordsplit_quoted_length (const char *str, int quote_hex, int *quote);
84void wordsplit_unquote_copy (char *dst, const char *src, size_t n);
85void wordsplit_quote_copy (char *dst, const char *src, int quote_hex);
86
87
88
diff --git a/grecs b/grecs
new file mode 160000
Subproject b6a8ef19274af628364f90a992c146c3123e67d
diff --git a/src/Makefile.am b/src/Makefile.am
index 993ce0d..c96fbcb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -58,8 +58,8 @@ SUFFIXES=.opt .c .h
58incdir=$(pkgdatadir)/$(VERSION)/include 58incdir=$(pkgdatadir)/$(VERSION)/include
59inc_DATA = $(PP_SETUP_FILE) 59inc_DATA = $(PP_SETUP_FILE)
60 60
61LDADD=../gconf/libgconf.a ../gnu/libgnu.a @SQLLIB@ @GPGMELIB@ @MAILUTILS_LIBS@ 61LDADD=../grecs/src/libgrecs.a ../gnu/libgnu.a @SQLLIB@ @GPGMELIB@ @MAILUTILS_LIBS@
62INCLUDES = -I$(top_srcdir)/gconf -I$(top_srcdir)/gnu -I../gnu @MAILUTILS_INCLUDES@ 62INCLUDES = -I$(top_srcdir)/grecs/src/ -I$(top_srcdir)/gnu -I../gnu @MAILUTILS_INCLUDES@
63AM_CPPFLAGS= \ 63AM_CPPFLAGS= \
64 -DSYSCONFDIR=\"$(sysconfdir)\"\ 64 -DSYSCONFDIR=\"$(sysconfdir)\"\
65 -DLOCALSTATEDIR=\"$(localstatedir)\"\ 65 -DLOCALSTATEDIR=\"$(localstatedir)\"\
diff --git a/src/cmdline.opt b/src/cmdline.opt
index fd87e5e..3515072 100644
--- a/src/cmdline.opt
+++ b/src/cmdline.opt
@@ -133,7 +133,7 @@ GROUP(Preprocessor control)
133OPTION(include-directory,I,DIR, 133OPTION(include-directory,I,DIR,
134 [<add include directory>]) 134 [<add include directory>])
135BEGIN 135BEGIN
136 gconf_preproc_add_include_dir (optarg); 136 grecs_preproc_add_include_dir (optarg);
137END 137END
138 138
139OPTION(define,D,SYMBOL[=VALUE], 139OPTION(define,D,SYMBOL[=VALUE],
@@ -159,13 +159,13 @@ END
159OPTION(preprocessor,,COMMAND, 159OPTION(preprocessor,,COMMAND,
160 [<use COMMAND instead of the default preprocessor>]) 160 [<use COMMAND instead of the default preprocessor>])
161BEGIN 161BEGIN
162 gconf_preprocessor = optarg; 162 grecs_preprocessor = optarg;
163END 163END
164 164
165OPTION(no-preprocessor,,, 165OPTION(no-preprocessor,,,
166 [<disable preprocessing>]) 166 [<disable preprocessing>])
167BEGIN 167BEGIN
168 gconf_preprocessor = NULL; 168 grecs_preprocessor = NULL;
169END 169END
170 170
171GROUP(Debugging) 171GROUP(Debugging)
@@ -179,13 +179,13 @@ END
179OPTION(dump-grammar-trace,,, 179OPTION(dump-grammar-trace,,,
180 [<dump configuration grammar traces>]) 180 [<dump configuration grammar traces>])
181BEGIN 181BEGIN
182 gconf_gram_trace (1); 182 grecs_gram_trace (1);
183END 183END
184 184
185OPTION(dump-lex-trace,,, 185OPTION(dump-lex-trace,,,
186 [<dump lexical analyzer traces>]) 186 [<dump lexical analyzer traces>])
187BEGIN 187BEGIN
188 gconf_lex_trace (1); 188 grecs_lex_trace (1);
189END 189END
190 190
191GROUP([<Additional help>]) 191GROUP([<Additional help>])
@@ -202,13 +202,13 @@ void
202parse_options(int argc, char *argv[]) 202parse_options(int argc, char *argv[])
203{ 203{
204 GETOPT(argc, argv) 204 GETOPT(argc, argv)
205 if (pp_cmd_stack_init && gconf_preprocessor) 205 if (pp_cmd_stack_init && grecs_preprocessor)
206 { 206 {
207 char *defs = obstack_finish (&pp_cmd_stack); 207 char *defs = obstack_finish (&pp_cmd_stack);
208 char *cmd = xmalloc (strlen (gconf_preprocessor) + strlen (defs) + 1); 208 char *cmd = xmalloc (strlen (grecs_preprocessor) + strlen (defs) + 1);
209 strcpy (cmd, gconf_preprocessor); 209 strcpy (cmd, grecs_preprocessor);
210 strcat (cmd, defs); 210 strcat (cmd, defs);
211 gconf_preprocessor = cmd; 211 grecs_preprocessor = cmd;
212 obstack_free (&pp_cmd_stack, NULL); 212 obstack_free (&pp_cmd_stack, NULL);
213 } 213 }
214} 214}
diff --git a/src/config.c b/src/config.c
index 11ac92d..60b5792 100644
--- a/src/config.c
+++ b/src/config.c
@@ -127,18 +127,18 @@ int
127string_to (const char *what, const char *str, 127string_to (const char *what, const char *str,
128 const char **args, int *vals, 128 const char **args, int *vals,
129 int *pret, 129 int *pret,
130 gconf_locus_t *locus) 130 grecs_locus_t *locus)
131{ 131{
132 ptrdiff_t x = ARGMATCH (str, args, vals); 132 ptrdiff_t x = ARGMATCH (str, args, vals);
133 133
134 if (x == (ptrdiff_t)-1) 134 if (x == (ptrdiff_t)-1)
135 { 135 {
136 gconf_error (locus, 0, _("unknown %s: %s"), what, str); 136 grecs_error (locus, 0, _("unknown %s: %s"), what, str);
137 return 1; 137 return 1;
138 } 138 }
139 else if (x == (ptrdiff_t)-2) 139 else if (x == (ptrdiff_t)-2)
140 { 140 {
141 gconf_error (locus, 0, _("ambiguous %s: %s"), what, str); 141 grecs_error (locus, 0, _("ambiguous %s: %s"), what, str);
142 return 1; 142 return 1;
143 } 143 }
144 *pret = vals[x]; 144 *pret = vals[x];
@@ -169,7 +169,7 @@ notification_event_str (enum notification_event evt)
169} 169}
170 170
171int 171int
172string_to_notification_event (gconf_locus_t *locus, const char *val, 172string_to_notification_event (grecs_locus_t *locus, const char *val,
173 enum notification_event *pret) 173 enum notification_event *pret)
174{ 174{
175 int rc, res; 175 int rc, res;
@@ -203,7 +203,7 @@ notification_target_str (enum notification_target tgt)
203} 203}
204 204
205int 205int
206string_to_notification_target (gconf_locus_t *locus, const char *val, 206string_to_notification_target (grecs_locus_t *locus, const char *val,
207 enum notification_target *pret) 207 enum notification_target *pret)
208{ 208{
209 int rc, res; 209 int rc, res;
@@ -217,35 +217,35 @@ string_to_notification_target (gconf_locus_t *locus, const char *val,
217 217
218 218
219int 219int
220assert_string_arg (gconf_locus_t *locus, 220assert_string_arg (grecs_locus_t *locus,
221 enum gconf_callback_command cmd, 221 enum grecs_callback_command cmd,
222 const gconf_value_t *value) 222 const grecs_value_t *value)
223{ 223{
224 if (cmd != gconf_callback_set_value) 224 if (cmd != grecs_callback_set_value)
225 { 225 {
226 gconf_error (locus, 0, _("Unexpected block statement")); 226 grecs_error (locus, 0, _("Unexpected block statement"));
227 return 1; 227 return 1;
228 } 228 }
229 if (!value || value->type != GCONF_TYPE_STRING) 229 if (!value || value->type != GCONF_TYPE_STRING)
230 { 230 {
231 gconf_error (locus, 0, _("expected scalar value as a tag")); 231 grecs_error (locus, 0, _("expected scalar value as a tag"));
232 return 1; 232 return 1;
233 } 233 }
234 return 0; 234 return 0;
235} 235}
236 236
237gconf_value_t * 237grecs_value_t *
238get_arg (gconf_locus_t *locus, gconf_value_t *value, unsigned n, int type) 238get_arg (grecs_locus_t *locus, grecs_value_t *value, unsigned n, int type)
239{ 239{
240 if (n >= value->v.arg.c) 240 if (n >= value->v.arg.c)
241 { 241 {
242 gconf_error (locus, 0, _("not enough arguments")); 242 grecs_error (locus, 0, _("not enough arguments"));
243 return NULL; 243 return NULL;
244 } 244 }
245 value = value->v.arg.v + n; 245 value = value->v.arg.v + n;
246 if (value->type != type) 246 if (value->type != type)
247 { 247 {
248 gconf_error (locus, 0, _("argument %d has wrong type"), n); 248 grecs_error (locus, 0, _("argument %d has wrong type"), n);
249 return NULL; 249 return NULL;
250 } 250 }
251 return value; 251 return value;
@@ -253,10 +253,10 @@ get_arg (gconf_locus_t *locus, gconf_value_t *value, unsigned n, int type)
253 253
254 254
255static int 255static int
256cb_mailer (enum gconf_callback_command cmd, 256cb_mailer (enum grecs_callback_command cmd,
257 gconf_locus_t *locus, 257 grecs_locus_t *locus,
258 void *varptr, 258 void *varptr,
259 gconf_value_t *value, 259 grecs_value_t *value,
260 void *cb_data) 260 void *cb_data)
261{ 261{
262 int rc; 262 int rc;
@@ -265,16 +265,16 @@ cb_mailer (enum gconf_callback_command cmd,
265 return 1; 265 return 1;
266 rc = mu_mailer_create (&mailer, value->v.string); 266 rc = mu_mailer_create (&mailer, value->v.string);
267 if (rc) 267 if (rc)
268 gconf_error (locus, 0, _("cannot create mailer `%s': %s"), 268 grecs_error (locus, 0, _("cannot create mailer `%s': %s"),
269 value->v.string, mu_strerror (rc)); 269 value->v.string, mu_strerror (rc));
270 return rc; 270 return rc;
271} 271}
272 272
273static int 273static int
274cb_email_address (enum gconf_callback_command cmd, 274cb_email_address (enum grecs_callback_command cmd,
275 gconf_locus_t *locus, 275 grecs_locus_t *locus,
276 void *varptr, 276 void *varptr,
277 gconf_value_t *value, 277 grecs_value_t *value,
278 void *cb_data) 278 void *cb_data)
279{ 279{
280 int rc; 280 int rc;
@@ -286,7 +286,7 @@ cb_email_address (enum gconf_callback_command cmd,
286 rc = mu_address_create (&addr, value->v.string); 286 rc = mu_address_create (&addr, value->v.string);
287 if (rc) 287 if (rc)
288 { 288 {
289 gconf_error (locus, 0, _("%s: invalid email address: %s"), 289 grecs_error (locus, 0, _("%s: invalid email address: %s"),
290 value->v.string, mu_strerror (rc)); 290 value->v.string, mu_strerror (rc));
291 return rc; 291 return rc;
292 } 292 }
@@ -299,7 +299,7 @@ cb_email_address (enum gconf_callback_command cmd,
299 299
300 while (gl_list_iterator_next (&itr, &p, NULL)) 300 while (gl_list_iterator_next (&itr, &p, NULL))
301 { 301 {
302 const gconf_value_t *vp = p; 302 const grecs_value_t *vp = p;
303 mu_address_t a; 303 mu_address_t a;
304 if (assert_string_arg (locus, cmd, vp)) 304 if (assert_string_arg (locus, cmd, vp))
305 return 1; 305 return 1;
@@ -309,7 +309,7 @@ cb_email_address (enum gconf_callback_command cmd,
309 rc = mu_address_union (&addr, a); 309 rc = mu_address_union (&addr, a);
310 else 310 else
311 { 311 {
312 gconf_error (locus, 0, _("%s: invalid email address: %s"), 312 grecs_error (locus, 0, _("%s: invalid email address: %s"),
313 vp->v.string, mu_strerror (rc)); 313 vp->v.string, mu_strerror (rc));
314 } 314 }
315 mu_address_destroy (&a); 315 mu_address_destroy (&a);
@@ -320,7 +320,7 @@ cb_email_address (enum gconf_callback_command cmd,
320 break; 320 break;
321 321
322 case GCONF_TYPE_ARRAY: 322 case GCONF_TYPE_ARRAY:
323 gconf_error (locus, 0, _("too many arguments")); 323 grecs_error (locus, 0, _("too many arguments"));
324 return 1; 324 return 1;
325 } 325 }
326 326
@@ -329,10 +329,10 @@ cb_email_address (enum gconf_callback_command cmd,
329} 329}
330 330
331static int 331static int
332cb_interval (enum gconf_callback_command cmd, 332cb_interval (enum grecs_callback_command cmd,
333 gconf_locus_t *locus, 333 grecs_locus_t *locus,
334 void *varptr, 334 void *varptr,
335 gconf_value_t *value, 335 grecs_value_t *value,
336 void *cb_data) 336 void *cb_data)
337{ 337{
338 int rc; 338 int rc;
@@ -346,7 +346,7 @@ cb_interval (enum gconf_callback_command cmd,
346 /* FIXME 2: Support ISO intervals? */ 346 /* FIXME 2: Support ISO intervals? */
347 rc = parse_time_interval (value->v.string, &interval, &endp); 347 rc = parse_time_interval (value->v.string, &interval, &endp);
348 if (rc) 348 if (rc)
349 gconf_error (locus, 0, _("unrecognized interval format (near `%s')"), 349 grecs_error (locus, 0, _("unrecognized interval format (near `%s')"),
350 endp); 350 endp);
351 else 351 else
352 *(time_t*) varptr = interval; 352 *(time_t*) varptr = interval;
@@ -354,10 +354,10 @@ cb_interval (enum gconf_callback_command cmd,
354} 354}
355 355
356static int 356static int
357cb_absolute_name (enum gconf_callback_command cmd, 357cb_absolute_name (enum grecs_callback_command cmd,
358 gconf_locus_t *locus, 358 grecs_locus_t *locus,
359 void *varptr, 359 void *varptr,
360 gconf_value_t *value, 360 grecs_value_t *value,
361 void *cb_data) 361 void *cb_data)
362{ 362{
363 char *word; 363 char *word;
@@ -368,17 +368,17 @@ cb_absolute_name (enum gconf_callback_command cmd,
368 368
369 word = safe_file_name ((char*)value->v.string); 369 word = safe_file_name ((char*)value->v.string);
370 if (!word || word[0] != '/') 370 if (!word || word[0] != '/')
371 gconf_error (locus, 0, _("must be an absolute file name")); 371 grecs_error (locus, 0, _("must be an absolute file name"));
372 else 372 else
373 *(char**) varptr = word; 373 *(char**) varptr = word;
374 return 0; 374 return 0;
375} 375}
376 376
377static int 377static int
378cb_set_umask (enum gconf_callback_command cmd, 378cb_set_umask (enum grecs_callback_command cmd,
379 gconf_locus_t *locus, 379 grecs_locus_t *locus,
380 void *varptr, 380 void *varptr,
381 gconf_value_t *value, 381 grecs_value_t *value,
382 void *cb_data) 382 void *cb_data)
383{ 383{
384 char *p; 384 char *p;
@@ -388,7 +388,7 @@ cb_set_umask (enum gconf_callback_command cmd,
388 return 1; 388 return 1;
389 m = strtoul (value->v.string, &p, 8) & 0777;