-rw-r--r-- | gconf/gconf-gram.y | 891 |
1 files changed, 0 insertions, 891 deletions
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 | |||
42 | typedef union | ||
43 | { | ||
44 | struct sockaddr s; | ||
45 | struct sockaddr_in s_in; | ||
46 | struct sockaddr_un s_un; | ||
47 | } sockaddr_union_t; | ||
48 | |||
49 | static struct gconf_keyword config_keywords; | ||
50 | static struct gconf_keyword *cursect; | ||
51 | static gl_list_t sections; | ||
52 | int gconf_error_count; | ||
53 | |||
54 | int gconf_default_port = 0; | ||
55 | |||
56 | static void *target_ptr(struct gconf_keyword *kwp); | ||
57 | static void stmt_begin(struct gconf_keyword *kwp, gconf_value_t tag); | ||
58 | static void stmt_end(struct gconf_keyword *kwp); | ||
59 | static struct gconf_keyword *find_keyword(const char *ident); | ||
60 | |||
61 | static void process_ident(struct gconf_keyword *kwp, gconf_value_t *value); | ||
62 | static 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 | |||
81 | input : stmtlist | ||
82 | ; | ||
83 | |||
84 | stmtlist: stmt | ||
85 | | stmtlist stmt | ||
86 | ; | ||
87 | |||
88 | stmt : simple | ||
89 | | block | ||
90 | ; | ||
91 | |||
92 | simple : ident vallist ';' | ||
93 | { | ||
94 | process_ident($1, &$2); | ||
95 | } | ||
96 | ; | ||
97 | |||
98 | block : ident tag { stmt_begin($<kw>1, $<value>2); } '{' stmtlist '}' opt_sc | ||
99 | { | ||
100 | stmt_end($1); | ||
101 | } | ||
102 | ; | ||
103 | |||
104 | ident : IDENT | ||
105 | { | ||
106 | $$ = find_keyword($1); | ||
107 | if (!$$) | ||
108 | gconf_error(&gconf_current_locus, 0, _("Unknown keyword")); | ||
109 | } | ||
110 | ; | ||
111 | |||
112 | tag : /* empty */ | ||
113 | { | ||
114 | $$.type = GCONF_TYPE_STRING; | ||
115 | $$.v.string = NULL; | ||
116 | } | ||
117 | | value | ||
118 | ; | ||
119 | |||
120 | vallist : 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 | |||
142 | vlist : 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 | |||
153 | value : 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 | |||
170 | string : STRING | ||
171 | | IDENT | ||
172 | | slist | ||
173 | ; | ||
174 | |||
175 | slist : 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 | |||
189 | slist0 : 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 | |||
201 | list : '(' ')' | ||
202 | { | ||
203 | $$ = NULL; | ||
204 | } | ||
205 | | '(' values ')' | ||
206 | { | ||
207 | $$ = $2; | ||
208 | } | ||
209 | | '(' values ',' ')' | ||
210 | { | ||
211 | $$ = $2; | ||
212 | } | ||
213 | ; | ||
214 | |||
215 | values : 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 | |||
227 | opt_sc : /* empty */ | ||
228 | | ';' | ||
229 | ; | ||
230 | |||
231 | %% | ||
232 | |||
233 | int | ||
234 | yyerror(char *s) | ||
235 | { | ||
236 | gconf_error (&gconf_current_locus, 0, "%s", s); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static void | ||
241 | listel_dispose(const void *el) | ||
242 | { | ||
243 | free((void*)el); | ||
244 | } | ||
245 | |||
246 | static gl_list_t | ||
247 | simple_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 | |||
257 | void | ||
258 | gconf_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 | |||
270 | void | ||
271 | gconf_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 | |||
284 | void | ||
285 | gconf_set_keywords (struct gconf_keyword *kwd) | ||
286 | { | ||
287 | config_keywords.kwd = kwd; | ||
288 | } | ||
289 | |||
290 | int | ||
291 | gconf_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 | |||
309 | void | ||
310 | gconf_gram_trace (int n) | ||
311 | { | ||
312 | yydebug = n; | ||
313 | } | ||
314 | |||
315 | |||
316 | |||
317 | static void * | ||
318 | target_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 | |||
331 | static int | ||
332 | fake_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 | |||
341 | static 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 | |||
353 | static void | ||
354 | stmt_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 | |||
377 | static void | ||
378 | stmt_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 | |||
402 | static struct gconf_keyword * | ||
403 | find_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 | |||
420 | static int | ||
421 | string_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 | |||
445 | static int | ||
446 | string_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 | |||
470 | static int | ||
471 | string_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 | |||
493 | static int | ||
494 | string_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 | |||
508 | static int | ||
509 | string_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 | |||
597 | int | ||
598 | gconf_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 | |||
715 | struct gconf_prop | ||
716 | { | ||
717 | size_t size; | ||
718 | gl_listelement_equals_fn eqfn; | ||
719 | }; | ||
720 | |||
721 | static bool | ||
722 | string_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 | |||
737 | DECL_NUMEQ(short) | ||
738 | DECL_NUMEQ(int) | ||
739 | DECL_NUMEQ(long) | ||
740 | DECL_NUMEQ(size_t) | ||
741 | DECL_NUMEQ(uintmax_t) | ||
742 | DECL_NUMEQ(intmax_t) | ||
743 | DECL_NUMEQ(time_t) | ||
744 | __DECL_NUMEQ(in_addr, struct in_addr) | ||
745 | __DECL_NUMEQ(gconf_sockaddr, struct gconf_sockaddr) | ||
746 | |||
747 | struct 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 | |||
772 | static void | ||
773 | process_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 | |||