/[CvsGraph]/cvsgraph/readconf.c
ViewVC logotype

Annotate of /cvsgraph/readconf.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (hide annotations)
Thu Jul 18 15:26:34 2002 UTC (15 years, 3 months ago) by bertho
Branch: MAIN
Changes since 1.4: +2 -0 lines
File MIME type: text/plain
First changes for left_right drawing of the tree.
Still missing proper branch_dupbox, upside_down and imagemap support.
1 bertho 1.1 /*
2     * CvsGraph graphical representation generator of brances and revisions
3     * of a file in cvs/rcs.
4     *
5 bertho 1.3 * Copyright (C) 2001,2002 B. Stultiens
6 bertho 1.1 *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     /*#define DEBUG 1*/
23    
24     #include <stdio.h>
25     #include <stdlib.h>
26     #include <string.h>
27     #include <ctype.h>
28     #include <assert.h>
29    
30     #include <gd.h>
31     #include <gdfontt.h>
32     #include <gdfonts.h>
33     #include <gdfontmb.h>
34     #include <gdfontl.h>
35     #include <gdfontg.h>
36    
37     #include "utils.h"
38     #include "cvsgraph.h"
39     #include "readconf.h"
40    
41     int line_number;
42    
43     typedef struct
44     {
45     char *keyword;
46     int type;
47     union {
48     void *v; /* join of other values */
49     int *i;
50     font_t *f;
51     char **s;
52     color_t *c;
53 bertho 1.2 double *d;
54 bertho 1.1 int val; /* FIXME: Oops, sizeof(int) must be sizeof(void *) */
55     } confref;
56     } keyword_t;
57    
58     typedef union {
59     keyword_t *kw;
60     int i;
61 bertho 1.2 double d;
62 bertho 1.1 char *str;
63     } YYSTYPE;
64    
65     static YYSTYPE yylval;
66    
67     static int nstacked_opts;
68     static char **stacked_opts;
69    
70     enum {
71     TYPE_dummy = 256,
72     TYPE_KEYWORD,
73     TYPE_NUMBER,
74     TYPE_VALUE,
75     TYPE_BOOLEAN,
76     TYPE_COLOR,
77     TYPE_FONT,
78 bertho 1.2 TYPE_STRING,
79     TYPE_DOUBLE
80 bertho 1.1 };
81    
82     static keyword_t keywords[] = {
83     { "branch_bgcolor", TYPE_COLOR, { &conf.branch_bgcolor } },
84     { "branch_bspace", TYPE_NUMBER, { &conf.branch_bspace } },
85     { "branch_color", TYPE_COLOR, { &conf.branch_color } },
86 bertho 1.2 { "branch_font", TYPE_FONT, { &conf.branch_font.gdfont } },
87     { "branch_ttfont", TYPE_STRING, { &conf.branch_font.ttfont } },
88     { "branch_ttsize", TYPE_DOUBLE, { &conf.branch_font.ttsize } },
89     { "branch_tag_color", TYPE_COLOR, { &conf.branch_tag_color } },
90     { "branch_tag_font", TYPE_FONT, { &conf.branch_tag_font.gdfont } },
91     { "branch_tag_ttfont", TYPE_STRING, { &conf.branch_tag_font.ttfont } },
92     { "branch_tag_ttsize", TYPE_DOUBLE, { &conf.branch_tag_font.ttsize } },
93 bertho 1.1 { "branch_lspace", TYPE_NUMBER, { &conf.branch_lspace } },
94     { "branch_rspace", TYPE_NUMBER, { &conf.branch_rspace } },
95     { "branch_tspace", TYPE_NUMBER, { &conf.branch_tspace } },
96     { "branch_connect", TYPE_NUMBER, { &conf.branch_connect } },
97     { "branch_margin", TYPE_NUMBER, { &conf.branch_margin } },
98     { "branch_dupbox", TYPE_BOOLEAN, { &conf.branch_dupbox } },
99     { "upside_down", TYPE_BOOLEAN, { &conf.upside_down } },
100 bertho 1.5 { "left_right", TYPE_BOOLEAN, { &conf.left_right } },
101 bertho 1.2 { "auto_stretch", TYPE_BOOLEAN, { &conf.auto_stretch } },
102 bertho 1.1 { "color_bg", TYPE_COLOR, { &conf.color_bg } },
103 bertho 1.2 { "transparent_bg", TYPE_BOOLEAN, { &conf.transparent_bg } },
104 bertho 1.1 { "cvsmodule", TYPE_STRING, { &conf.cvsmodule } },
105     { "cvsroot", TYPE_STRING, { &conf.cvsroot } },
106     { "date_format", TYPE_STRING, { &conf.date_format } },
107     { "box_shadow", TYPE_BOOLEAN, { &conf.box_shadow } },
108     { "strip_untagged", TYPE_BOOLEAN, { &conf.strip_untagged } },
109     { "strip_first_rev", TYPE_BOOLEAN, { &conf.strip_first_rev } },
110 bertho 1.2 { "anti_alias", TYPE_BOOLEAN, { &conf.anti_alias } },
111     { "use_ttf", TYPE_BOOLEAN, { &conf.use_ttf } },
112 bertho 1.4 { "parse_logs", TYPE_BOOLEAN, { &conf.parse_logs } },
113 bertho 1.3 { "thick_lines", TYPE_NUMBER, { &conf.thick_lines } },
114 bertho 1.1 { "rev_color", TYPE_COLOR, { &conf.rev_color } },
115     { "rev_bgcolor", TYPE_COLOR, { &conf.rev_bgcolor } },
116 bertho 1.2 { "rev_font", TYPE_FONT, { &conf.rev_font.gdfont } },
117     { "rev_ttfont", TYPE_STRING, { &conf.rev_font.ttfont } },
118     { "rev_ttsize", TYPE_DOUBLE, { &conf.rev_font.ttsize } },
119 bertho 1.1 { "rev_separator", TYPE_NUMBER, { &conf.rev_separator } },
120     { "rev_minline", TYPE_NUMBER, { &conf.rev_minline } },
121     { "rev_maxline", TYPE_NUMBER, { &conf.rev_maxline } },
122     { "rev_lspace", TYPE_NUMBER, { &conf.rev_lspace } },
123     { "rev_rspace", TYPE_NUMBER, { &conf.rev_rspace } },
124     { "rev_tspace", TYPE_NUMBER, { &conf.rev_tspace } },
125     { "rev_bspace", TYPE_NUMBER, { &conf.rev_bspace } },
126     { "rev_text", TYPE_STRING, { &conf.rev_text } },
127     { "rev_text_color", TYPE_COLOR, { &conf.rev_text_color } },
128 bertho 1.2 { "rev_text_font", TYPE_FONT, { &conf.rev_text_font.gdfont } },
129     { "rev_text_ttfont", TYPE_STRING, { &conf.rev_text_font.ttfont } },
130     { "rev_text_ttsize", TYPE_DOUBLE, { &conf.rev_text_font.ttsize } },
131 bertho 1.1 { "tag_color", TYPE_COLOR, { &conf.tag_color } },
132 bertho 1.2 { "tag_font", TYPE_FONT, { &conf.tag_font.gdfont } },
133     { "tag_ttfont", TYPE_STRING, { &conf.tag_font.ttfont } },
134     { "tag_ttsize", TYPE_DOUBLE, { &conf.tag_font.ttsize } },
135 bertho 1.1 { "title", TYPE_STRING, { &conf.title } },
136     { "title_x", TYPE_NUMBER, { &conf.title_x } },
137     { "title_y", TYPE_NUMBER, { &conf.title_y } },
138 bertho 1.2 { "title_font", TYPE_FONT, { &conf.title_font.gdfont } },
139     { "title_ttfont", TYPE_STRING, { &conf.title_font.ttfont } },
140     { "title_ttsize", TYPE_DOUBLE, { &conf.title_font.ttsize } },
141 bertho 1.1 { "title_align", TYPE_NUMBER, { &conf.title_align } },
142     { "title_color", TYPE_COLOR, { &conf.title_color } },
143     { "margin_top", TYPE_NUMBER, { &conf.margin_top } },
144     { "margin_bottom", TYPE_NUMBER, { &conf.margin_bottom } },
145     { "margin_left", TYPE_NUMBER, { &conf.margin_left } },
146     { "margin_right", TYPE_NUMBER, { &conf.margin_right } },
147     { "image_type", TYPE_NUMBER, { &conf.image_type } },
148     { "image_quality", TYPE_NUMBER, { &conf.image_quality } },
149     { "map_name", TYPE_STRING, { &conf.map_name } },
150     { "map_branch_href", TYPE_STRING, { &conf.map_branch_href } },
151     { "map_branch_alt", TYPE_STRING, { &conf.map_branch_alt } },
152     { "map_rev_href", TYPE_STRING, { &conf.map_rev_href } },
153     { "map_rev_alt", TYPE_STRING, { &conf.map_rev_alt } },
154     { "map_diff_href", TYPE_STRING, { &conf.map_diff_href } },
155     { "map_diff_alt", TYPE_STRING, { &conf.map_diff_alt } },
156     { "jpeg", TYPE_VALUE, { (void *)IMAGE_JPEG } },
157     { "png", TYPE_VALUE, { (void *)IMAGE_PNG } },
158     { "gif", TYPE_VALUE, { (void *)IMAGE_GIF } },
159     { "true", TYPE_VALUE, { (void *)1 } },
160     { "false", TYPE_VALUE, { (void *)0 } },
161 bertho 1.3 { "not", TYPE_VALUE, { (void *)-1 } },
162 bertho 1.1 { "left", TYPE_VALUE, { (void *)0 } },
163     { "center", TYPE_VALUE, { (void *)1 } },
164     { "right", TYPE_VALUE, { (void *)2 } },
165     { "tiny", TYPE_VALUE, { (void *)0 } },
166     { "small", TYPE_VALUE, { (void *)1 } },
167     { "medium", TYPE_VALUE, { (void *)2 } },
168     { "large", TYPE_VALUE, { (void *)3 } },
169     { "giant", TYPE_VALUE, { (void *)4 } },
170     };
171    
172     #define NKEYWORDS (sizeof(keywords) / sizeof(keywords[0]))
173    
174     static int cmp_kw(const void *k1, const void *k2)
175     {
176     return strcmp(((keyword_t *)k1)->keyword, ((keyword_t *)k2)->keyword);
177     }
178    
179     /*
180     **************************************************************************
181     * Debug routines
182     **************************************************************************
183     */
184     #ifdef DEBUG
185     #define DEBUGSTREAM stdout
186     static void debug_pname(const char *n)
187     {
188     fprintf(DEBUGSTREAM, "%-16s: ", n);
189     }
190    
191     static void debug_pstring(const char *n, const char *a)
192     {
193     debug_pname(n);
194     if(!a)
195     fprintf(DEBUGSTREAM, "<not-set>\n");
196     else
197     {
198     fputc('\'', DEBUGSTREAM);
199     for(; *a; a++)
200     {
201     if(isprint(*a))
202     fputc(*a, DEBUGSTREAM);
203     else
204     {
205     fputc('\\', DEBUGSTREAM);
206     switch(*a)
207     {
208     case '\a': fputc('a', DEBUGSTREAM); break;
209     case '\b': fputc('b', DEBUGSTREAM); break;
210     case '\f': fputc('f', DEBUGSTREAM); break;
211     case '\n': fputc('n', DEBUGSTREAM); break;
212     case '\r': fputc('r', DEBUGSTREAM); break;
213     case '\t': fputc('t', DEBUGSTREAM); break;
214     case '\v': fputc('v', DEBUGSTREAM); break;
215     default:
216     fprintf(DEBUGSTREAM, "x%02x", (unsigned char)*a);
217     }
218     }
219     }
220     fprintf(DEBUGSTREAM, "'\n");
221     }
222     }
223    
224     static void debug_pbool(const char *n, int b)
225     {
226     debug_pname(n);
227     fprintf(DEBUGSTREAM, "%s\n", b ? "true" : "false");
228     }
229    
230     static void debug_pint(const char *n, int i)
231     {
232     debug_pname(n);
233     fprintf(DEBUGSTREAM, "%i\n", i);
234     }
235    
236 bertho 1.2 static void debug_pdouble(const char *n, double d)
237     {
238     debug_pname(n);
239     fprintf(DEBUGSTREAM, "%g\n", d);
240     }
241    
242     static void debug_pfont(const char *n, gdFontPtr f)
243 bertho 1.1 {
244     const char *s = "<Unknown font>";
245     debug_pname(n);
246     if(f == gdFontTiny)
247     s = "gdFontTiny";
248     else if(f == gdFontSmall)
249     s = "gdFontSmall";
250     else if(f == gdFontMediumBold)
251     s = "gdFontMediumBold";
252     else if(f == gdFontLarge)
253     s = "gdFontLarge";
254     else if(f == gdFontGiant)
255     s = "gdFontGiant";
256     fprintf(DEBUGSTREAM, "%s\n", s);
257     }
258    
259     static void debug_pcolor(const char *n, color_t *c)
260     {
261     debug_pname(n);
262     fprintf(DEBUGSTREAM, "#%02x%02x%02x\n", c->r, c->g, c->b);
263     }
264    
265     void dump_config(void)
266     {
267     debug_pstring("cvsroot", conf.cvsroot);
268     debug_pstring("cvsmodule", conf.cvsmodule);
269     debug_pstring("date_format", conf.date_format);
270    
271     debug_pcolor("color_bg", &conf.color_bg);
272     debug_pbool("box_shadow", conf.box_shadow);
273     debug_pbool("upside_down", conf.upside_down);
274 bertho 1.5 debug_pbool("left_right", conf.left_right);
275 bertho 1.1 debug_pbool("strip_untagged", conf.strip_untagged);
276     debug_pbool("strip_first_rev", conf.strip_first_rev);
277 bertho 1.3 debug_pbool("auto_stretch", conf.auto_stretch);
278     debug_pbool("anti_alias", conf.anti_alias);
279     debug_pbool("use_ttf", conf.use_ttf);
280     debug_pint("thick_lines", conf.thick_lines);
281 bertho 1.1
282 bertho 1.2 debug_pfont("tag_font", conf.tag_font.gdfont);
283     debug_pstring("tag_ttfont", conf.tag_font.ttfont);
284     debug_psouble("tag_ttsize", conf.tag_font.ttsize);
285 bertho 1.1 debug_pcolor("tag_color", &conf.tag_color);
286    
287 bertho 1.2 debug_pfont("rev_font", conf.rev_font.gdfont);
288     debug_pstring("rev_ttfont", conf.rev_font.ttfont);
289     debug_pdouble("rev_ttsize", conf.rev_font.ttsize);
290 bertho 1.1 debug_pcolor("rev_color", &conf.rev_color);
291     debug_pcolor("rev_bgcolor", &conf.rev_bgcolor);
292     debug_pint("rev_separator", conf.rev_separator);
293     debug_pint("rev_minline", conf.rev_minline);
294     debug_pint("rev_maxline", conf.rev_maxline);
295     debug_pint("rev_lspace", conf.rev_lspace);
296     debug_pint("rev_rspace", conf.rev_rspace);
297     debug_pint("rev_tspace", conf.rev_tspace);
298     debug_pint("rev_bspace", conf.rev_bspace);
299     debug_pstring("rev_text", conf.rev_text);
300     debug_pcolor("rev_text_color", &conf.rev_text_color);
301 bertho 1.2 debug_pfont("rev_text_font", conf.rev_text_font.gdfont);
302     debug_pstring("rev_text_ttfont", conf.rev_text_font.ttfont);
303     debug_pdouble("rev_text_ttsize", conf.rev_text_font.ttsize);
304    
305     debug_pfont("branch_font", conf.branch_font.gdfont);
306     debug_pstring("branch_ttfont", conf.branch_font.ttfont);
307     debug_pdouble("branch_ttsize", conf.branch_font.ttsize);
308 bertho 1.1 debug_pcolor("branch_color", &conf.branch_color);
309 bertho 1.2 debug_pfont("branch_tag_font", conf.branch_tag_font.gdfont);
310     debug_pstring("branch_tag_ttfont", conf.branch_tag_font.ttfont);
311     debug_pdouble("branch_tag_ttsize", conf.branch_tag_font.ttsize);
312     debug_pcolor("branch_tag_color", &conf.branch_tag_color);
313 bertho 1.1 debug_pcolor("branch_bgcolor", &conf.branch_bgcolor);
314     debug_pint("branch_lspace", conf.branch_lspace);
315     debug_pint("branch_rspace", conf.branch_rspace);
316     debug_pint("branch_tspace", conf.branch_tspace);
317     debug_pint("branch_bspace", conf.branch_bspace);
318     debug_pint("branch_connect", conf.branch_connect);
319     debug_pint("branch_margin", conf.branch_margin);
320     debug_pint("branch_dupbox", conf.branch_dupbox);
321    
322     debug_pstring("title", conf.title);
323     debug_pint("title_x", conf.title_x);
324     debug_pint("title_y", conf.title_y);
325 bertho 1.2 debug_pfont("title_font", conf.title_font.gdfont);
326     debug_pstring("title_ttfont", conf.title_font.ttfont);
327     debug_pdouble("title_ttsize", conf.title_font.ttsize);
328 bertho 1.1 debug_pint("title_align", conf.title_align);
329     debug_pcolor("title_color", &conf.title_color);
330    
331     debug_pint("margin_top", conf.margin_top);
332     debug_pint("margin_bottom", conf.margin_bottom);
333     debug_pint("margin_left", conf.margin_left);
334     debug_pint("margin_right", conf.margin_right);
335    
336     debug_pint("image_type", conf.image_type);
337     debug_pint("image_quality", conf.image_quality);
338    
339     debug_pstring("map_name", conf.map_name);
340     debug_pstring("map_branch_href", conf.map_branch_href);
341     debug_pstring("map_branch_alt", conf.map_branch_alt);
342     debug_pstring("map_rev_href", conf.map_rev_href);
343     debug_pstring("map_rev_alt", conf.map_rev_alt);
344     debug_pstring("map_diff_href", conf.map_diff_href);
345     debug_pstring("map_diff_alt", conf.map_diff_alt);
346    
347     debug_pstring("expand[0]", conf.expand[0]);
348     debug_pstring("expand[1]", conf.expand[1]);
349     debug_pstring("expand[2]", conf.expand[2]);
350     debug_pstring("expand[3]", conf.expand[3]);
351     debug_pstring("expand[4]", conf.expand[4]);
352     debug_pstring("expand[5]", conf.expand[5]);
353     debug_pstring("expand[6]", conf.expand[6]);
354     debug_pstring("expand[7]", conf.expand[7]);
355     debug_pstring("expand[8]", conf.expand[8]);
356     debug_pstring("expand[9]", conf.expand[9]);
357     }
358     #endif
359    
360     /*
361     **************************************************************************
362     * String collection routines
363     **************************************************************************
364     */
365     #define STRALLOCSIZE 128
366     static char *str;
367     static int nstr;
368     static int nastr;
369    
370     static void reset_str(void)
371     {
372     nstr = 0;
373     }
374    
375     static void add_str(int c)
376     {
377     if(nstr + 1 + 1 > nastr)
378     {
379     str = xrealloc(str, nastr+STRALLOCSIZE);
380     nastr += STRALLOCSIZE;
381     }
382     str[nstr++] = c;
383     }
384    
385     static char *get_str(void)
386     {
387     if(!str)
388     return xstrdup("");
389    
390     str[nstr] = '\0';
391     return xstrdup(str);
392     }
393    
394     /*
395     **************************************************************************
396     * Input routines
397     **************************************************************************
398     */
399     static char *buf = NULL;
400     static int bufsize = 0;
401     static int bufalloc = 0;
402     static int bufpos = 0;
403     static int bufunput = -1;
404     static FILE *buffp;
405    
406     static void set_input(FILE *fp, char *s)
407     {
408     assert((fp == NULL && s != NULL) || (fp != NULL && s == NULL));
409     buffp = fp;
410     bufsize = bufpos = 0;
411     if(s)
412     {
413     if(!buf)
414     {
415     bufalloc = 8192;
416     buf = xmalloc(bufalloc * sizeof(*buf));
417     }
418     bufsize = strlen(s);
419     assert(bufsize < bufalloc);
420     strcpy(buf, s);
421     }
422     }
423    
424     static int get_input(void)
425     {
426     if(bufunput != -1)
427     {
428     int c = bufunput;
429     bufunput = -1;
430     return c;
431     }
432    
433     if(bufpos < bufsize)
434     {
435     assert(buf != NULL);
436     retry_input:
437     return (int)((unsigned char)buf[bufpos++]);
438     }
439    
440     if(!buf)
441     {
442     bufalloc = 8192;
443     buf = xmalloc(bufalloc * sizeof(*buf));
444     bufsize = bufpos = 0;
445     }
446     if(buffp)
447     {
448     bufsize = fread(buf, 1, bufalloc, buffp);
449     bufpos = 0;
450     if(!bufsize)
451     return EOF;
452     goto retry_input;
453     }
454     return EOF;
455     }
456    
457     static void unget_input(int c)
458     {
459     bufunput = c;
460     }
461    
462     /*
463     **************************************************************************
464     * Lexical scanner
465     **************************************************************************
466     */
467     static int config_lex(void)
468     {
469     int ch;
470     while(1)
471     {
472     ch = get_input();
473     if(ch == '\n')
474     line_number++;
475    
476     if(isspace(ch))
477     continue;
478    
479     switch(ch)
480     {
481     case EOF:
482     case '=':
483     case ';':
484     return ch;
485    
486     case '#': /* Comment */
487     while((ch = get_input()) != '\n' && ch != EOF)
488     ;
489     if(ch != EOF)
490     unget_input(ch);
491     break;
492    
493     case '"':
494     reset_str();
495     while(1)
496     {
497     char c[4];
498     ch = get_input();
499     switch(ch)
500     {
501     case '\\': /* Start an escape sequence */
502     switch(ch = get_input())
503     {
504     default: /* This includes '\\', '"' and embedded newlines */
505     add_str(ch);
506     break;
507     case 'a': add_str('\a'); break;
508     case 'b': add_str('\b'); break;
509     case 'f': add_str('\f'); break;
510     case 'n': add_str('\n'); break;
511     case 'r': add_str('\r'); break;
512     case 't': add_str('\t'); break;
513     case 'v': add_str('\v'); break;
514     case 'x':
515     case 'X': /* Hex escape */
516     c[0] = get_input();
517     c[1] = get_input();
518     c[2] = '\0';
519     if(!isxdigit(c[0]) || !isxdigit(c[1]))
520     yyerror("Invalid hex escape");
521     add_str((int)strtol(c, NULL, 16));
522     break;
523     case '0':
524     case '1':
525     case '2': /* Octal escape */
526     c[0] = ch;
527     c[1] = c[2] = c[3] = '\0';
528     if((ch = get_input()) >= '0' && ch <= '7')
529     c[1] = ch;
530     else
531     unget_input(ch);
532     if((ch = get_input()) >= '0' && ch <= '7')
533     c[2] = ch;
534     else
535     unget_input(ch);
536     add_str((int)strtol(c, NULL, 8));
537     break;
538     case EOF:
539     yyerror("Unexpected EOF in escape");
540     break;
541     }
542     break;
543     case '"':
544     yylval.str = get_str();
545     return TYPE_STRING;
546     case '\n':
547     yyerror("Newline in string");
548     break;
549     case EOF:
550     yyerror("Unexpected EOF in string");
551     break;
552     default:
553     add_str(ch);
554     break;
555     }
556     }
557     break;
558    
559     default:
560     if(isalpha(ch) || ch == '_')
561     {
562     keyword_t skw;
563     keyword_t *kw;
564     /* Collect keyword */
565     reset_str();
566     add_str(ch);
567     while(1)
568     {
569     ch = get_input();
570     if(isalpha(ch) || ch == '_')
571     add_str(ch);
572     else
573     {
574     unget_input(ch);
575     break;
576     }
577     }
578     skw.keyword = get_str();
579     kw = bsearch(&skw, keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);
580     if(!kw)
581     yyerror("Unknown keyword '%s'", skw.keyword);
582     xfree(skw.keyword);
583     if(kw->type == TYPE_VALUE)
584     {
585     yylval.i = kw->confref.val;
586     return TYPE_NUMBER;
587     }
588     yylval.kw = kw;
589     return TYPE_KEYWORD;
590     }
591     else if(isdigit(ch) || ch == '+' || ch == '-')
592     {
593     char *s;
594     char *eptr;
595 bertho 1.2 int type = TYPE_NUMBER;
596 bertho 1.1 /* Collect number */
597     reset_str();
598     add_str(ch);
599     while(1)
600     {
601     ch = get_input();
602 bertho 1.2 if(isxdigit(ch) || ch == 'x' || ch == 'X' || ch == '.') /* Not exact, but close enough */
603 bertho 1.1 add_str(ch);
604     else
605     {
606     unget_input(ch);
607     break;
608     }
609 bertho 1.2 if(ch == '.')
610     type = TYPE_DOUBLE;
611 bertho 1.1 }
612     s = get_str();
613 bertho 1.2 if(type == TYPE_DOUBLE)
614     {
615     yylval.d = strtod(s, &eptr);
616     if(*eptr)
617     yyerror("Invalid floating point number");
618     }
619     else
620     {
621     yylval.i = strtol(s, &eptr, 0);
622     if(*eptr)
623     yyerror("Invalid number");
624     }
625 bertho 1.1 xfree(s);
626 bertho 1.2 return type;
627 bertho 1.1 }
628     else
629     yyerror("Unmatched text '%c' (0x%02x)", isprint(ch) ? ch : ' ', ch);
630     break;
631     }
632     }
633     }
634    
635     static void set_color(color_t *c, char *s)
636     {
637     char *cptr;
638     if(*s != '#' || strlen(s) != 7)
639     {
640     colorerror:
641     yyerror("Invalid color value");
642     }
643     c->b = strtol(s+5, &cptr, 16);
644     if(*cptr)
645     goto colorerror;
646     s[5] = '\0';
647     c->g = strtol(s+3, &cptr, 16);
648     if(*cptr)
649     goto colorerror;
650     s[3] = '\0';
651     c->r = strtol(s+1, &cptr, 16);
652     if(*cptr)
653     goto colorerror;
654     }
655    
656     static gdFontPtr get_font(int id)
657     {
658     switch(id)
659     {
660     case 0: return gdFontTiny;
661     case 1: return gdFontSmall;
662     default:
663     case 2: return gdFontMediumBold;
664     case 3: return gdFontLarge;
665     case 4: return gdFontGiant;
666     }
667     }
668    
669     /*
670     **************************************************************************
671     * The config parser
672     * Grammar:
673     * file : <Empty>
674     * | lines
675     * ;
676     *
677     * lines : line
678     * | lines line
679     * ;
680     *
681     * line : <keyword> '=' <value> ';'
682     * | ';'
683     * ;
684     **************************************************************************
685     */
686     static void config_parse(void)
687     {
688     int state = 0;
689     int token;
690     int t;
691     keyword_t *kw = NULL;
692    
693     while(1)
694     {
695     token = config_lex();
696     if(token == EOF)
697     {
698     if(state)
699     yyerror("Unexpected EOF");
700     break;
701     }
702    
703     switch(state)
704     {
705     case 0:
706     if(token == TYPE_KEYWORD)
707     {
708     kw = yylval.kw;
709     state = 1;
710     }
711     else if(token != ';')
712     yyerror("Keyword expected");
713     break;
714     case 1:
715     if(token != '=')
716     yyerror("'=' expected");
717     state = 2;
718     break;
719     case 2:
720     if(kw->type == TYPE_FONT || kw->type == TYPE_BOOLEAN)
721     t = TYPE_NUMBER;
722     else if(kw->type == TYPE_COLOR)
723     t = TYPE_STRING;
724     else
725     t = kw->type;
726 bertho 1.2
727     if(token == TYPE_NUMBER && kw->type == TYPE_DOUBLE)
728     {
729     /* Auto promote numbers to doubles if required */
730     yylval.d = (double)yylval.i;
731     token = TYPE_DOUBLE;
732     }
733    
734 bertho 1.1 if(token != t)
735     {
736     char *e;
737     switch(kw->type)
738     {
739     case TYPE_STRING: e = "String"; break;
740     case TYPE_NUMBER: e = "Number"; break;
741     case TYPE_COLOR: e = "Color"; break;
742     case TYPE_FONT: e = "Font"; break;
743     case TYPE_BOOLEAN: e = "Boolean"; break;
744 bertho 1.2 case TYPE_DOUBLE: e = "Double"; break;
745 bertho 1.1 default: e = "Internal error: Unknown type"; break;
746     }
747     yyerror("%s expected", e);
748     }
749     #ifdef DEBUG
750     printf("processing: '%s'\n", kw->keyword);
751     #endif
752     switch(kw->type)
753     {
754     case TYPE_STRING:
755     *kw->confref.s = yylval.str;
756     break;
757     case TYPE_NUMBER:
758     *kw->confref.i = yylval.i;
759     break;
760     case TYPE_BOOLEAN:
761 bertho 1.3 if(yylval.i == -1)
762     *kw->confref.i = !*kw->confref.i;
763     else
764     *kw->confref.i = yylval.i != 0;
765 bertho 1.1 break;
766     case TYPE_COLOR:
767     set_color(kw->confref.c, yylval.str);
768     break;
769     case TYPE_FONT:
770 bertho 1.2 kw->confref.f->gdfont = get_font(yylval.i);
771     break;
772     case TYPE_DOUBLE:
773     *kw->confref.d = yylval.d;
774 bertho 1.1 break;
775     default:
776     yyerror("Internal error: Unknown type passed %d", kw->type);
777     break;
778     }
779     state = 3;
780     break;
781     case 3:
782     if(token != ';')
783     yyerror("';' expected");
784     state = 0;
785     break;
786     default:
787     yyerror("Internal error: invalid state %d", state);
788     break;
789     }
790     }
791     }
792    
793     /*
794     **************************************************************************
795     * Configuration
796     **************************************************************************
797     */
798     void stack_option(const char *opt)
799     {
800     stacked_opts = xrealloc(stacked_opts, sizeof(*stacked_opts) * (nstacked_opts + 1));
801     stacked_opts[nstacked_opts] = xmalloc(strlen(opt) + 2);
802     strcpy(stacked_opts[nstacked_opts], opt);
803     strcat(stacked_opts[nstacked_opts], ";");
804     nstacked_opts++;
805     #ifdef DEBUG
806     printf("stacking option: '%s'\n", stacked_opts[nstacked_opts-1]);
807     #endif
808     }
809    
810     void read_config(const char *path)
811     {
812     FILE *fp;
813    
814     /* Make sure we have them sorted for bsearch */
815     qsort(keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);
816    
817     if(path)
818     {
819     if((fp = fopen(path, "r")) != NULL)
820     input_file = path;
821     }
822     else
823     {
824     if((fp = fopen("./" CONFFILENAME, "r")) == NULL)
825     {
826     if((fp = fopen(ETCDIR "/" CONFFILENAME, "r")) != NULL)
827     input_file = ETCDIR "/" CONFFILENAME;
828     }
829     else
830     input_file = "./" CONFFILENAME;
831     }
832    
833     if(fp)
834     {
835     line_number = 1;
836     set_input(fp, NULL);
837     config_parse();
838     fclose(fp);
839     input_file = NULL;
840     }
841    
842     if(nstacked_opts)
843     {
844     int i;
845     for(i = 0; i < nstacked_opts; i++)
846     {
847     line_number = 0;
848     set_input(NULL, stacked_opts[i]);
849     input_file = stacked_opts[i];
850     #ifdef DEBUG
851     printf("parsing stacked option: '%s'\n", stacked_opts[i]);
852     #endif
853     config_parse();
854     }
855     input_file = NULL;
856     }
857     #ifdef DEBUG
858     dump_config();
859     #endif
860     }
861    

  ViewVC Help
Powered by ViewVC 1.1.0 with CvsGraph 1.7.0