aboutsummaryrefslogtreecommitdiff
path: root/gconf
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-04-20 15:05:56 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-04-20 16:24:02 +0300
commit3a6373d888021388473bd96c000a8fdab8aedaa5 (patch)
treeacff526d947280ced0912c49af1308031e672158 /gconf
parentdf8c51d2db6f5d16b97ae2f2b62bd625e5a96833 (diff)
downloadwydawca-3a6373d888021388473bd96c000a8fdab8aedaa5.tar.gz
wydawca-3a6373d888021388473bd96c000a8fdab8aedaa5.tar.bz2
Switch to the Grecs submodule.
* gconf: Remove * Makefile.am (ACLOCAL_AMFLAGS): Add -I grecs/am. (SUBDIRS): Replace gconf with grecs (make-ChangeLog): Remove spurious rule. * bootstrap.conf: Init submodules. * configure.ac: Call GRECS_SETUP (AC_CONFIG_FILES): Add grecs/Makefile, grecs/src/Makefile. * src/wydawca.h: Include grecs.h * src/Makefile.am (LDADD,INCLUDES): Refer to grecs. * tests/Makefile.am: Likewise. * src/cmdline.opt, src/config.c, src/diskio.c, src/tcpwrap.c, src/wydawca.c: Use grecs. * README-hacking: Update
Diffstat (limited to 'gconf')
-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
11 files changed, 0 insertions, 3222 deletions
diff --git a/gconf/.gitignore b/gconf/.gitignore
deleted file mode 100644
index 42c88b2..0000000
--- a/gconf/.gitignore
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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

Return to:

Send suggestions and report system problems to the System administrator.