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

Diff of /cvsgraph/readconf.c

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

revision 1.2, Wed Jan 9 00:28:36 2002 UTC revision 1.26, Wed May 21 13:33:35 2008 UTC
# Line 2  Line 2 
2   * CvsGraph graphical representation generator of brances and revisions   * CvsGraph graphical representation generator of brances and revisions
3   * of a file in cvs/rcs.   * of a file in cvs/rcs.
4   *   *
5   * Copyright (C) 2001  B. Stultiens   * Copyright (C) 2001,2002  B. Stultiens
6   *   *
7   * This program is free software; you can redistribute it and/or modify   * 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   * it under the terms of the GNU General Public License as published by
# Line 42  Line 42 
42    
43  typedef struct  typedef struct
44  {  {
45          char    *keyword;          const char      *keyword;
46          int     type;          int             type;
47          union {          union {
48                  void    *v;     /* join of other values */                  void    *v;     /* join of other values */
49                  int     *i;                  int     *i;
# Line 51  Line 51 
51                  char    **s;                  char    **s;
52                  color_t *c;                  color_t *c;
53                  double  *d;                  double  *d;
54                  int     val;    /* FIXME: Oops, sizeof(int) must be sizeof(void *) */                  stringlist_t *sl;
55                    condstring_t *cs;
56                    colorlist_t *cl;
57                    int     val;
58          } confref;          } confref;
59  } keyword_t;  } keyword_t;
60    
# Line 67  Line 70 
70  static int nstacked_opts;  static int nstacked_opts;
71  static char **stacked_opts;  static char **stacked_opts;
72    
 enum {  
         TYPE_dummy = 256,  
         TYPE_KEYWORD,  
         TYPE_NUMBER,  
         TYPE_VALUE,  
         TYPE_BOOLEAN,  
         TYPE_COLOR,  
         TYPE_FONT,  
         TYPE_STRING,  
         TYPE_DOUBLE  
 };  
   
73  static keyword_t keywords[] = {  static keyword_t keywords[] = {
74          { "branch_bgcolor",     TYPE_COLOR,     { &conf.branch_bgcolor } },          { "branch_bgcolor",     TYPE_COLOR,     { &conf.branch_bgcolor } },
75          { "branch_bspace",      TYPE_NUMBER,    { &conf.branch_bspace } },          { "branch_bspace",      TYPE_NUMBER,    { &conf.branch_bspace } },
# Line 96  Line 87 
87          { "branch_connect",     TYPE_NUMBER,    { &conf.branch_connect } },          { "branch_connect",     TYPE_NUMBER,    { &conf.branch_connect } },
88          { "branch_margin",      TYPE_NUMBER,    { &conf.branch_margin } },          { "branch_margin",      TYPE_NUMBER,    { &conf.branch_margin } },
89          { "branch_dupbox",      TYPE_BOOLEAN,   { &conf.branch_dupbox } },          { "branch_dupbox",      TYPE_BOOLEAN,   { &conf.branch_dupbox } },
90            { "branch_fold",        TYPE_BOOLEAN,   { &conf.branch_fold } },
91            { "branch_foldall",     TYPE_BOOLEAN,   { &conf.branch_foldall } },
92            { "branch_resort",      TYPE_BOOLEAN,   { &conf.branch_resort } },
93            { "branch_subtree",     TYPE_STRING,    { &conf.branch_subtree } },
94          { "upside_down",        TYPE_BOOLEAN,   { &conf.upside_down } },          { "upside_down",        TYPE_BOOLEAN,   { &conf.upside_down } },
95            { "left_right",         TYPE_BOOLEAN,   { &conf.left_right } },
96          { "auto_stretch",       TYPE_BOOLEAN,   { &conf.auto_stretch } },          { "auto_stretch",       TYPE_BOOLEAN,   { &conf.auto_stretch } },
97          { "color_bg",           TYPE_COLOR,     { &conf.color_bg } },          { "color_bg",           TYPE_COLOR,     { &conf.color_bg } },
98          { "transparent_bg",     TYPE_BOOLEAN,   { &conf.transparent_bg } },          { "transparent_bg",     TYPE_BOOLEAN,   { &conf.transparent_bg } },
# Line 108  Line 104 
104          { "strip_first_rev",    TYPE_BOOLEAN,   { &conf.strip_first_rev } },          { "strip_first_rev",    TYPE_BOOLEAN,   { &conf.strip_first_rev } },
105          { "anti_alias",         TYPE_BOOLEAN,   { &conf.anti_alias } },          { "anti_alias",         TYPE_BOOLEAN,   { &conf.anti_alias } },
106          { "use_ttf",            TYPE_BOOLEAN,   { &conf.use_ttf } },          { "use_ttf",            TYPE_BOOLEAN,   { &conf.use_ttf } },
107            { "parse_logs",         TYPE_BOOLEAN,   { &conf.parse_logs } },
108            { "html_level",         TYPE_NUMBER,    { &conf.html_level } },
109            { "thick_lines",        TYPE_NUMBER,    { &conf.thick_lines } },
110            { "msg_color",          TYPE_COLOR,     { &conf.msg_color } },
111            { "msg_font",           TYPE_FONT,      { &conf.msg_font.gdfont } },
112            { "msg_ttfont",         TYPE_STRING,    { &conf.msg_font.ttfont } },
113            { "msg_ttsize",         TYPE_DOUBLE,    { &conf.msg_font.ttsize } },
114            { "rev_hidenumber",     TYPE_BOOLEAN,   { &conf.rev_hidenumber } },
115          { "rev_color",          TYPE_COLOR,     { &conf.rev_color } },          { "rev_color",          TYPE_COLOR,     { &conf.rev_color } },
116          { "rev_bgcolor",        TYPE_COLOR,     { &conf.rev_bgcolor } },          { "rev_bgcolor",        TYPE_COLOR,     { &conf.rev_bgcolor } },
117          { "rev_font",           TYPE_FONT,      { &conf.rev_font.gdfont } },          { "rev_font",           TYPE_FONT,      { &conf.rev_font.gdfont } },
# Line 120  Line 124 
124          { "rev_rspace",         TYPE_NUMBER,    { &conf.rev_rspace } },          { "rev_rspace",         TYPE_NUMBER,    { &conf.rev_rspace } },
125          { "rev_tspace",         TYPE_NUMBER,    { &conf.rev_tspace } },          { "rev_tspace",         TYPE_NUMBER,    { &conf.rev_tspace } },
126          { "rev_bspace",         TYPE_NUMBER,    { &conf.rev_bspace } },          { "rev_bspace",         TYPE_NUMBER,    { &conf.rev_bspace } },
127          { "rev_text",           TYPE_STRING,    { &conf.rev_text } },          { "rev_text",           TYPE_CSTRING,   { &conf.rev_text } },
128            { "rev_idtext",         TYPE_CSTRING,   { &conf.rev_idtext } },
129          { "rev_text_color",     TYPE_COLOR,     { &conf.rev_text_color } },          { "rev_text_color",     TYPE_COLOR,     { &conf.rev_text_color } },
130          { "rev_text_font",      TYPE_FONT,      { &conf.rev_text_font.gdfont } },          { "rev_text_font",      TYPE_FONT,      { &conf.rev_text_font.gdfont } },
131          { "rev_text_ttfont",    TYPE_STRING,    { &conf.rev_text_font.ttfont } },          { "rev_text_ttfont",    TYPE_STRING,    { &conf.rev_text_font.ttfont } },
132          { "rev_text_ttsize",    TYPE_DOUBLE,    { &conf.rev_text_font.ttsize } },          { "rev_text_ttsize",    TYPE_DOUBLE,    { &conf.rev_text_font.ttsize } },
133            { "rev_maxtags",        TYPE_NUMBER,    { &conf.rev_maxtags } },
134            { "merge_color",        TYPE_COLORLIST, { &conf.merge_color } },
135            { "merge_from",         TYPE_STRINGLIST,        { &conf.merge_from } },
136            { "merge_to",           TYPE_STRINGLIST,        { &conf.merge_to } },
137            { "merge_findall",      TYPE_BOOLEAN,   { &conf.merge_findall } },
138            { "merge_front",        TYPE_BOOLEAN,   { &conf.merge_front } },
139            { "merge_nocase",       TYPE_BOOLEAN,   { &conf.merge_nocase } },
140            { "merge_arrows",       TYPE_BOOLEAN,   { &conf.merge_arrows } },
141            { "merge_cvsnt",        TYPE_BOOLEAN,   { &conf.merge_cvsnt } },
142            { "merge_cvsnt_color",  TYPE_COLOR,     { &conf.merge_cvsnt_color } },
143            { "merge_on_tag",       TYPE_BOOLEAN,   { &conf.merge_on_tag } },
144            { "arrow_width",        TYPE_NUMBER,    { &conf.arrow_width } },
145            { "arrow_length",       TYPE_NUMBER,    { &conf.arrow_length } },
146          { "tag_color",          TYPE_COLOR,     { &conf.tag_color } },          { "tag_color",          TYPE_COLOR,     { &conf.tag_color } },
147          { "tag_font",           TYPE_FONT,      { &conf.tag_font.gdfont } },          { "tag_font",           TYPE_FONT,      { &conf.tag_font.gdfont } },
148          { "tag_ttfont",         TYPE_STRING,    { &conf.tag_font.ttfont } },          { "tag_ttfont",         TYPE_STRING,    { &conf.tag_font.ttfont } },
149          { "tag_ttsize",         TYPE_DOUBLE,    { &conf.tag_font.ttsize } },          { "tag_ttsize",         TYPE_DOUBLE,    { &conf.tag_font.ttsize } },
150            { "tag_ignore",         TYPE_STRING,    { &conf.tag_ignore } },
151            { "tag_ignore_merge",   TYPE_BOOLEAN,   { &conf.tag_ignore_merge } },
152            { "tag_nocase",         TYPE_BOOLEAN,   { &conf.tag_nocase } },
153            { "tag_negate",         TYPE_BOOLEAN,   { &conf.tag_negate } },
154          { "title",              TYPE_STRING,    { &conf.title } },          { "title",              TYPE_STRING,    { &conf.title } },
155          { "title_x",            TYPE_NUMBER,    { &conf.title_x } },          { "title_x",            TYPE_NUMBER,    { &conf.title_x } },
156          { "title_y",            TYPE_NUMBER,    { &conf.title_y } },          { "title_y",            TYPE_NUMBER,    { &conf.title_y } },
# Line 143  Line 165 
165          { "margin_right",       TYPE_NUMBER,    { &conf.margin_right } },          { "margin_right",       TYPE_NUMBER,    { &conf.margin_right } },
166          { "image_type",         TYPE_NUMBER,    { &conf.image_type } },          { "image_type",         TYPE_NUMBER,    { &conf.image_type } },
167          { "image_quality",      TYPE_NUMBER,    { &conf.image_quality } },          { "image_quality",      TYPE_NUMBER,    { &conf.image_quality } },
168            { "image_compress",     TYPE_NUMBER,    { &conf.image_compress } },
169            { "image_interlace",    TYPE_BOOLEAN,   { &conf.image_interlace } },
170          { "map_name",           TYPE_STRING,    { &conf.map_name } },          { "map_name",           TYPE_STRING,    { &conf.map_name } },
171          { "map_branch_href",    TYPE_STRING,    { &conf.map_branch_href } },          { "map_branch_href",    TYPE_STRING,    { &conf.map_branch_href } },
172          { "map_branch_alt",     TYPE_STRING,    { &conf.map_branch_alt } },          { "map_branch_alt",     TYPE_STRING,    { &conf.map_branch_alt } },
# Line 150  Line 174 
174          { "map_rev_alt",        TYPE_STRING,    { &conf.map_rev_alt } },          { "map_rev_alt",        TYPE_STRING,    { &conf.map_rev_alt } },
175          { "map_diff_href",      TYPE_STRING,    { &conf.map_diff_href } },          { "map_diff_href",      TYPE_STRING,    { &conf.map_diff_href } },
176          { "map_diff_alt",       TYPE_STRING,    { &conf.map_diff_alt } },          { "map_diff_alt",       TYPE_STRING,    { &conf.map_diff_alt } },
177          { "jpeg",               TYPE_VALUE,     { (void *)IMAGE_JPEG } },          { "map_merge_href",     TYPE_STRING,    { &conf.map_merge_href } },
178          { "png",                TYPE_VALUE,     { (void *)IMAGE_PNG } },          { "map_merge_alt",      TYPE_STRING,    { &conf.map_merge_alt } },
179          { "gif",                TYPE_VALUE,     { (void *)IMAGE_GIF } },          { "jpeg",               TYPE_VALUE,     { val: IMAGE_JPEG } },
180          { "true",               TYPE_VALUE,     { (void *)1 } },          { "png",                TYPE_VALUE,     { val: IMAGE_PNG } },
181          { "false",              TYPE_VALUE,     { (void *)0 } },          { "gif",                TYPE_VALUE,     { val: IMAGE_GIF } },
182          { "left",               TYPE_VALUE,     { (void *)0 } },          { "true",               TYPE_VALUE,     { val: 1 } },
183          { "center",             TYPE_VALUE,     { (void *)1 } },          { "false",              TYPE_VALUE,     { val: 0 } },
184          { "right",              TYPE_VALUE,     { (void *)2 } },          { "not",                TYPE_VALUE,     { val: -1 } },
185          { "tiny",               TYPE_VALUE,     { (void *)0 } },          { "left",               TYPE_VALUE,     { val: 0 } },
186          { "small",              TYPE_VALUE,     { (void *)1 } },          { "center",             TYPE_VALUE,     { val: 1 } },
187          { "medium",             TYPE_VALUE,     { (void *)2 } },          { "right",              TYPE_VALUE,     { val: 2 } },
188          { "large",              TYPE_VALUE,     { (void *)3 } },          { "tiny",               TYPE_VALUE,     { val: 0 } },
189          { "giant",              TYPE_VALUE,     { (void *)4 } },          { "small",              TYPE_VALUE,     { val: 1 } },
190            { "medium",             TYPE_VALUE,     { val: 2 } },
191            { "large",              TYPE_VALUE,     { val: 3 } },
192            { "giant",              TYPE_VALUE,     { val: 4 } },
193            { "HTML3",              TYPE_VALUE,     { val: 1 } },
194            { "HTML4",              TYPE_VALUE,     { val: 2 } },
195            { "XHTML",              TYPE_VALUE,     { val: 3 } },
196  };  };
197    
198  #define NKEYWORDS       (sizeof(keywords) / sizeof(keywords[0]))  #define NKEYWORDS       (sizeof(keywords) / sizeof(keywords[0]))
# Line 252  Line 282 
282          fprintf(DEBUGSTREAM, "%s\n", s);          fprintf(DEBUGSTREAM, "%s\n", s);
283  }  }
284    
285    static char *debug_op[] = { "=~", "=*", "!~", "!*", "==", "!_", ">=", ">", "<=", "<" };
286    
287    static void debug_pcolornode(node_t *n)
288    {
289            if(!n)
290                    return;
291            if(n->op == TYPE_STRING)
292                    fprintf(DEBUGSTREAM, "%s ", n->value.str);
293            else if(n->op == TYPE_COLOR)
294                    fprintf(DEBUGSTREAM, "#%02x%02x%02x ", n->value.clr.r, n->value.clr.g, n->value.clr.b);
295            else
296            {
297                    char *key;
298                    fprintf(DEBUGSTREAM, "[ ");
299                    switch(n->key)
300                    {
301                    case KEY_STATE:         key = "state"; break;
302                    case KEY_AUTHOR:        key = "author"; break;
303                    case KEY_TAG:           key = "tag"; break;
304                    case KEY_DATE:          key = "date"; break;
305                    case KEY_REV:           key = "rev"; break;
306                    case KEY_UNKNOWN:       key = "unknown"; break;
307                    default:                key = "<undefined>"; break;
308                    }
309                    fprintf(DEBUGSTREAM, "%s ", key);
310                    if(n->op > OP_FIRST && n->op < OP_LAST)
311                            fprintf(DEBUGSTREAM, "%s ", debug_op[n->op - OP_FIRST - 1]);
312                    else
313                            fprintf(DEBUGSTREAM, "op(-?-) ");
314                    fprintf(DEBUGSTREAM, "%s ", n->content);
315                    debug_pcolornode(n->tcase);
316                    debug_pcolornode(n->fcase);
317                    fprintf(DEBUGSTREAM, "]");
318            }
319    }
320    
321  static void debug_pcolor(const char *n, color_t *c)  static void debug_pcolor(const char *n, color_t *c)
322  {  {
323          debug_pname(n);          debug_pname(n);
324          fprintf(DEBUGSTREAM, "#%02x%02x%02x\n", c->r, c->g, c->b);          if(c->node)
325            {
326                    debug_pcolornode(c->node);
327                    fprintf(DEBUGSTREAM, "\n");
328            }
329            else
330                    fprintf(DEBUGSTREAM, "#%02x%02x%02x\n", c->r, c->g, c->b);
331    }
332    
333    static void debug_pcolorlist(const char *n, colorlist_t *cl)
334    {
335            int i;
336            char buf[128];
337            for(i = 0; i < cl->n; i++)
338            {
339                    sprintf(buf, "%s{%d}", n, i);
340                    debug_pcolor(buf, &cl->clrs[i]);
341            }
342    }
343    
344    static void debug_pstringlist(const char *n, stringlist_t *sl)
345    {
346            int i;
347            char buf[128];
348            for(i = 0; i < sl->n; i++)
349            {
350                    sprintf(buf, "%s{%d}", n, i);
351                    debug_pstring(buf, sl->strs[i]);
352            }
353  }  }
354    
355  void dump_config(void)  void dump_config(void)
# Line 267  Line 361 
361          debug_pcolor("color_bg", &conf.color_bg);          debug_pcolor("color_bg", &conf.color_bg);
362          debug_pbool("box_shadow", conf.box_shadow);          debug_pbool("box_shadow", conf.box_shadow);
363          debug_pbool("upside_down", conf.upside_down);          debug_pbool("upside_down", conf.upside_down);
364            debug_pbool("left_right", conf.left_right);
365          debug_pbool("strip_untagged", conf.strip_untagged);          debug_pbool("strip_untagged", conf.strip_untagged);
366          debug_pbool("strip_first_rev", conf.strip_first_rev);          debug_pbool("strip_first_rev", conf.strip_first_rev);
367          debug_pbool("auto_kern", conf.auto_kern);          debug_pbool("auto_stretch", conf.auto_stretch);
368            debug_pbool("anti_alias", conf.anti_alias);
369            debug_pbool("use_ttf", conf.use_ttf);
370            debug_pint("thick_lines", conf.thick_lines);
371            debug_pint("html_level", conf.html_level);
372            debug_pbool("parse_logs", conf.parse_logs);
373            debug_pbool("transparent_bg", conf.transparent_bg);
374    
375            debug_pint("arrow_length", conf.arrow_length);
376            debug_pint("arrow_width", conf.arrow_width);
377    
378            debug_pbool("merge_arrows", conf.merge_arrows);
379            debug_pcolor("merge_cvsnt_color", &conf.merge_cvsnt_color);
380            debug_pbool("merge_cvsnt", conf.merge_cvsnt);
381            debug_pbool("merge_findall", conf.merge_findall);
382            debug_pcolorlist("merge_color", &conf.merge_color);
383            debug_pstringlist("merge_from", &conf.merge_from);
384            debug_pstringlist("merge_to", &conf.merge_to);
385            debug_pbool("merge_front", conf.merge_front);
386            debug_pbool("merge_nocase", conf.merge_nocase);
387            debug_pbool("merge_on_tag", conf.merge_on_tag);
388    
389            debug_pcolor("msg_color", &conf.msg_color);
390            debug_pfont("msg_font", conf.msg_font.gdfont);
391            debug_pstring("msg_ttfont", conf.msg_font.ttfont);
392            debug_pdouble("msg_ttsize", conf.msg_font.ttsize);
393    
394          debug_pfont("tag_font", conf.tag_font.gdfont);          debug_pfont("tag_font", conf.tag_font.gdfont);
395          debug_pstring("tag_ttfont", conf.tag_font.ttfont);          debug_pstring("tag_ttfont", conf.tag_font.ttfont);
396          debug_psouble("tag_ttsize", conf.tag_font.ttsize);          debug_pdouble("tag_ttsize", conf.tag_font.ttsize);
397          debug_pcolor("tag_color", &conf.tag_color);          debug_pcolor("tag_color", &conf.tag_color);
398            debug_pbool("tag_ignore_merge", conf.tag_ignore_merge);
399            debug_pstring("tag_ignore", conf.tag_ignore);
400            debug_pbool("tag_negate", conf.tag_negate);
401            debug_pbool("tag_nocase", conf.tag_nocase);
402    
403          debug_pfont("rev_font", conf.rev_font.gdfont);          debug_pfont("rev_font", conf.rev_font.gdfont);
404          debug_pstring("rev_ttfont", conf.rev_font.ttfont);          debug_pstring("rev_ttfont", conf.rev_font.ttfont);
# Line 284  Line 408 
408          debug_pint("rev_separator", conf.rev_separator);          debug_pint("rev_separator", conf.rev_separator);
409          debug_pint("rev_minline", conf.rev_minline);          debug_pint("rev_minline", conf.rev_minline);
410          debug_pint("rev_maxline", conf.rev_maxline);          debug_pint("rev_maxline", conf.rev_maxline);
411            debug_pint("rev_maxtags", conf.rev_maxtags);
412          debug_pint("rev_lspace", conf.rev_lspace);          debug_pint("rev_lspace", conf.rev_lspace);
413          debug_pint("rev_rspace", conf.rev_rspace);          debug_pint("rev_rspace", conf.rev_rspace);
414          debug_pint("rev_tspace", conf.rev_tspace);          debug_pint("rev_tspace", conf.rev_tspace);
415          debug_pint("rev_bspace", conf.rev_bspace);          debug_pint("rev_bspace", conf.rev_bspace);
416          debug_pstring("rev_text", conf.rev_text);          debug_pcstring("rev_text", conf.rev_text);
417          debug_pcolor("rev_text_color", &conf.rev_text_color);          debug_pcolor("rev_text_color", &conf.rev_text_color);
418          debug_pfont("rev_text_font", conf.rev_text_font.gdfont);          debug_pfont("rev_text_font", conf.rev_text_font.gdfont);
419          debug_pstring("rev_text_ttfont", conf.rev_text_font.ttfont);          debug_pstring("rev_text_ttfont", conf.rev_text_font.ttfont);
420          debug_pdouble("rev_text_ttsize", conf.rev_text_font.ttsize);          debug_pdouble("rev_text_ttsize", conf.rev_text_font.ttsize);
421            debug_pbool("rev_hidenumber", conf.rev_hidenumber);
422    
423          debug_pfont("branch_font", conf.branch_font.gdfont);          debug_pfont("branch_font", conf.branch_font.gdfont);
424          debug_pstring("branch_ttfont", conf.branch_font.ttfont);          debug_pstring("branch_ttfont", conf.branch_font.ttfont);
# Line 310  Line 436 
436          debug_pint("branch_connect", conf.branch_connect);          debug_pint("branch_connect", conf.branch_connect);
437          debug_pint("branch_margin", conf.branch_margin);          debug_pint("branch_margin", conf.branch_margin);
438          debug_pint("branch_dupbox", conf.branch_dupbox);          debug_pint("branch_dupbox", conf.branch_dupbox);
439            debug_pbool("branch_fold", conf.branch_fold);
440            debug_pbool("branch_foldall", conf.branch_foldall);
441            debug_pbool("branch_resort", conf.branch_resort);
442            debug_pstring("branch_subtree", conf.branch_subtree);
443    
444          debug_pstring("title", conf.title);          debug_pstring("title", conf.title);
445          debug_pint("title_x", conf.title_x);          debug_pint("title_x", conf.title_x);
# Line 327  Line 457 
457    
458          debug_pint("image_type", conf.image_type);          debug_pint("image_type", conf.image_type);
459          debug_pint("image_quality", conf.image_quality);          debug_pint("image_quality", conf.image_quality);
460            debug_pint("image_compress", conf.image_compress);
461            debug_pbool("image_interlace", conf.image_interlace);
462    
463          debug_pstring("map_name", conf.map_name);          debug_pstring("map_name", conf.map_name);
464          debug_pstring("map_branch_href", conf.map_branch_href);          debug_pstring("map_branch_href", conf.map_branch_href);
# Line 335  Line 467 
467          debug_pstring("map_rev_alt", conf.map_rev_alt);          debug_pstring("map_rev_alt", conf.map_rev_alt);
468          debug_pstring("map_diff_href", conf.map_diff_href);          debug_pstring("map_diff_href", conf.map_diff_href);
469          debug_pstring("map_diff_alt", conf.map_diff_alt);          debug_pstring("map_diff_alt", conf.map_diff_alt);
470            debug_pstring("map_merge_href", conf.map_merge_href);
471            debug_pstring("map_merge_alt", conf.map_merge_alt);
472    
473          debug_pstring("expand[0]", conf.expand[0]);          debug_pstring("expand[0]", conf.expand[0]);
474          debug_pstring("expand[1]", conf.expand[1]);          debug_pstring("expand[1]", conf.expand[1]);
# Line 470  Line 604 
604    
605                  switch(ch)                  switch(ch)
606                  {                  {
                 case EOF:  
607                  case '=':                  case '=':
608                            ch = get_input();
609                            switch(ch)
610                            {
611                            case '~': return OP_CONTAINED;
612                            case '*': return OP_CONTAINEDI;
613                            case '=': return OP_EQ;
614                            default:
615                                    unget_input(ch);
616                                    return '=';
617                            }
618                            break;
619    
620                    case '!':
621                            ch = get_input();
622                            switch(ch)
623                            {
624                            case '~': return OP_NCONTAINED;
625                            case '*': return OP_NCONTAINEDI;
626                            case '=': return OP_NE;
627                            default:
628                                    stack_msg(MSG_ERR, "config: %d: Invalid operator", line_number);
629                                    unget_input(ch);
630                                    return '!';
631                            }
632                            break;
633    
634                    case '>':
635                            ch = get_input();
636                            if(ch == '=')
637                                    return OP_GE;
638                            unget_input(ch);
639                            return OP_GT;
640    
641                    case '<':
642                            ch = get_input();
643                            if(ch == '=')
644                                    return OP_LE;
645                            unget_input(ch);
646                            return OP_LT;
647    
648                    case EOF:
649                  case ';':                  case ';':
650                    case '[':
651                    case ']':
652                          return ch;                          return ch;
653    
654                  case '#':       /* Comment */                  case '#':       /* Comment */
# Line 508  Line 684 
684                                                  c[0] = get_input();                                                  c[0] = get_input();
685                                                  c[1] = get_input();                                                  c[1] = get_input();
686                                                  c[2] = '\0';                                                  c[2] = '\0';
687                                                  if(!isxdigit(c[0]) || !isxdigit(c[1]))                                                  if(!isxdigit((int)(unsigned char)c[0]) || !isxdigit((int)(unsigned char)c[1]))
688                                                          yyerror("Invalid hex escape");                                                          stack_msg(MSG_ERR, "config: %d: Invalid hex escape", line_number);
689                                                  add_str((int)strtol(c, NULL, 16));                                                  add_str((int)strtol(c, NULL, 16));
690                                                  break;                                                  break;
691                                          case '0':                                          case '0':
# Line 528  Line 704 
704                                                  add_str((int)strtol(c, NULL, 8));                                                  add_str((int)strtol(c, NULL, 8));
705                                                  break;                                                  break;
706                                          case EOF:                                          case EOF:
707                                                    yyerror("Unexpected EOF in escape");                                                  yyerror("Unexpected EOF in escape");
708                                                    break;                                                  break;
709                                          }                                          }
710                                          break;                                          break;
711                                  case '"':                                  case '"':
# Line 559  Line 735 
735                                  while(1)                                  while(1)
736                                  {                                  {
737                                          ch = get_input();                                          ch = get_input();
738                                          if(isalpha(ch) || ch == '_')                                          if(isalnum(ch) || ch == '_')
739                                                  add_str(ch);                                                  add_str(ch);
740                                          else                                          else
741                                          {                                          {
# Line 570  Line 746 
746                                  skw.keyword = get_str();                                  skw.keyword = get_str();
747                                  kw = bsearch(&skw, keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);                                  kw = bsearch(&skw, keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);
748                                  if(!kw)                                  if(!kw)
749                                          yyerror("Unknown keyword '%s'", skw.keyword);                                  {
750                                  xfree(skw.keyword);                                          stack_msg(MSG_ERR, "config: %d: Unknown keyword '%s'", line_number, skw.keyword);
751                                            yylval.kw = NULL;
752                                            return TYPE_KEYWORD;
753                                    }
754                                    xfree((void *)skw.keyword);
755                                  if(kw->type == TYPE_VALUE)                                  if(kw->type == TYPE_VALUE)
756                                  {                                  {
757                                          yylval.i = kw->confref.val;                                          yylval.i = (int)kw->confref.val;
758                                          return TYPE_NUMBER;                                          return TYPE_NUMBER;
759                                  }                                  }
760                                  yylval.kw = kw;                                  yylval.kw = kw;
# Line 606  Line 786 
786                                  {                                  {
787                                          yylval.d = strtod(s, &eptr);                                          yylval.d = strtod(s, &eptr);
788                                          if(*eptr)                                          if(*eptr)
789                                                  yyerror("Invalid floating point number");                                                  stack_msg(MSG_ERR, "config: %d: Invalid floating point number", line_number);
790                                  }                                  }
791                                  else                                  else
792                                  {                                  {
793                                          yylval.i = strtol(s, &eptr, 0);                                          yylval.i = strtol(s, &eptr, 0);
794                                          if(*eptr)                                          if(*eptr)
795                                                  yyerror("Invalid number");                                                  stack_msg(MSG_ERR, "config: %d: Invalid number", line_number);
796                                  }                                  }
797                                  xfree(s);                                  xfree(s);
798                                  return type;                                  return type;
# Line 627  Line 807 
807  static void set_color(color_t *c, char *s)  static void set_color(color_t *c, char *s)
808  {  {
809          char *cptr;          char *cptr;
810            c->node = NULL;
811          if(*s != '#' || strlen(s) != 7)          if(*s != '#' || strlen(s) != 7)
812          {          {
813  colorerror:  colorerror:
814                  yyerror("Invalid color value");                  stack_msg(MSG_ERR, "config: %d: Invalid color value '%s'", line_number, s);
815                    return;
816          }          }
817          c->b = strtol(s+5, &cptr, 16);          c->b = strtol(s+5, &cptr, 16);
818          if(*cptr)          if(*cptr)
# Line 671  Line 853 
853   *              ;   *              ;
854   *   *
855   *      line    : <keyword> '=' <value> ';'   *      line    : <keyword> '=' <value> ';'
856     *              | <keyword> '=' expr ';'
857   *              | ';'   *              | ';'
858     *
859     *      expr    : '[' <kw> <op> <value> expr expr ']'
860     *              | <value>
861   *              ;   *              ;
862   **************************************************************************   **************************************************************************
863   */   */
864    static int skip_to_semicolon(int state)
865    {
866            int token;
867            while(1)
868            {
869                    token = config_lex();
870                    if(token == ';')
871                            return 0;
872                    else if(token == EOF)
873                            return state;
874            }
875    }
876    
877    static node_t *new_node(char *val)
878    {
879            node_t *n = xmalloc(sizeof(*n));
880            if(!strcmp(val, "state"))
881                    n->key = KEY_STATE;
882            else if(!strcmp(val, "author"))
883                    n->key = KEY_AUTHOR;
884            else if(!strcmp(val, "tag"))
885                    n->key = KEY_TAG;
886            else if(!strcmp(val, "date"))
887                    n->key = KEY_DATE;
888            else if(!strcmp(val, "rev"))
889                    n->key = KEY_REV;
890            else
891            {
892                    n->key = KEY_UNKNOWN;
893                    stack_msg(MSG_ERR, "config: %d: Unknown key '%s'", line_number, val);
894            }
895            return n;
896    }
897    
898    typedef struct __statestack_t
899    {
900            int     state;
901            node_t  *node;
902    } statestack_t;
903    
904    static int nstatestack = 0;
905    static int nastatestack;
906    static statestack_t *statestack = NULL;
907    
908    static void push_state(node_t *node, int state)
909    {
910            if(!statestack)
911            {
912                    statestack = xmalloc(4 * sizeof(*statestack));
913                    nastatestack = 4;
914                    nstatestack = 0;
915            }
916            else if(nstatestack >= nastatestack)
917            {
918                    nastatestack *= 2;
919                    statestack = xrealloc(statestack, nastatestack * sizeof(*statestack));
920            }
921            statestack[nstatestack].node = node;
922            statestack[nstatestack].state = state;
923            nstatestack++;
924    }
925    
926    static int pop_state(node_t **node, int *state)
927    {
928            if(nstatestack <= 0)
929            {
930                    *state = 3;
931                    return 0;
932            }
933            assert(*node != NULL);
934            if(statestack[nstatestack-1].state == 8)
935                    statestack[nstatestack-1].node->tcase = *node;
936            else if(statestack[nstatestack-1].state == 9)
937                    statestack[nstatestack-1].node->fcase = *node;
938            *state = statestack[nstatestack-1].state;
939            *node = statestack[nstatestack-1].node;
940            return nstatestack--;
941    }
942    
943    /* YYYY.MM.DD.hh.mm.ss */
944    /* 0123456789012345678 */
945    /*           111111111 */
946    static char *fixup_date(const char *str)
947    {
948            int i;
949            int y=1970, m=1, d=1, h=0, mi=0, s=0;
950            int l = strlen(str);
951            char date[6*16]; /* Should be wildly enough to hold 19 chars from 6 numbers with all possible errors */
952            if(l < 4 || l > 19)
953            {
954    date_err:
955                    stack_msg(MSG_ERR, "config: %d: Invalid date string '%s'", line_number, str);
956                    return "1970.01.01.00.00.00";
957            }
958            for(i = 0; i < l; i++)
959            {
960                    if(!strchr("0123456789.", str[i]))
961                            goto date_err;
962            }
963            i = sscanf(str, "%d.%d.%d.%d.%d.%d", &y, &m, &d, &h, &mi, &s);
964            if(i == EOF || i < 0 || i > 6)
965                    goto date_err;
966            if(i >= 1 && (y < 1970 || y > 2037))
967                    goto date_err;
968            if(i >= 2 && (m < 1 || m > 12))
969                    goto date_err;
970            if(i >= 3 && (d < 1 || d > 31))
971                    goto date_err;
972            if(i >= 4 && (h < 0 || h > 23))
973                    goto date_err;
974            if(i >= 5 && (mi < 0 || mi > 59))
975                    goto date_err;
976            if(i >= 6 && (s < 0 || s > 59))
977                    goto date_err;
978            sprintf(date, "%04d.%02d.%02d.%02d.%02d.%02d", y, m, d, h, mi, s);
979            return strdup(date);
980    }
981    
982  static void config_parse(void)  static void config_parse(void)
983  {  {
984          int state = 0;          int state = 0;
985          int token;          int token;
986          int t;          int t;
987          keyword_t *kw = NULL;          keyword_t *kw = NULL;
988            node_t *node = NULL;
989    
990          while(1)          while(1)
991          {          {
# Line 688  Line 993 
993                  if(token == EOF)                  if(token == EOF)
994                  {                  {
995                          if(state)                          if(state)
996                                  yyerror("Unexpected EOF");                                  stack_msg(MSG_ERR, "config: %d: Unexpected EOF", line_number);
997                          break;                          break;
998                  }                  }
999    
# Line 701  Line 1006 
1006                                  state = 1;                                  state = 1;
1007                          }                          }
1008                          else if(token != ';')                          else if(token != ';')
1009                                  yyerror("Keyword expected");                                  stack_msg(MSG_ERR, "config: %d: Keyword expected", line_number);
1010                          break;                          break;
1011                  case 1:                  case 1:
1012                          if(token != '=')                          if(token != '=')
1013                                  yyerror("'=' expected");                          {
1014                          state = 2;                                  stack_msg(MSG_ERR, "config: %d: '=' expected", line_number);
1015                                    state = skip_to_semicolon(state);
1016                                    break;
1017                            }
1018                            else
1019                                    state = 2;
1020                          break;                          break;
1021                  case 2:                  case 2:
1022                            if(!kw)
1023                            {
1024                                    /* Error recovery of failed keyword */
1025                                    state = 3;
1026                                    break;
1027                            }
1028                            if(token == '[')
1029                            {
1030                                    if(kw->type != TYPE_COLOR && kw->type != TYPE_CSTRING)
1031                                    {
1032                                            stack_msg(MSG_ERR, "config: %d: Conditional expression not allowed for keyword", line_number);
1033                                            state = skip_to_semicolon(state);
1034                                            break;
1035                                    }
1036                                    state = 4;
1037                                    break;
1038                            }
1039                          if(kw->type == TYPE_FONT || kw->type == TYPE_BOOLEAN)                          if(kw->type == TYPE_FONT || kw->type == TYPE_BOOLEAN)
1040                                  t = TYPE_NUMBER;                                  t = TYPE_NUMBER;
1041                          else if(kw->type == TYPE_COLOR)                          else if(kw->type == TYPE_COLOR || kw->type == TYPE_COLORLIST || kw->type == TYPE_STRINGLIST || kw->type == TYPE_CSTRING)
1042                                  t = TYPE_STRING;                                  t = TYPE_STRING;
1043                          else                          else
1044                                  t = kw->type;                                  t = kw->type;
# Line 728  Line 1055 
1055                                  char *e;                                  char *e;
1056                                  switch(kw->type)                                  switch(kw->type)
1057                                  {                                  {
1058                                  case TYPE_STRING:       e = "String"; break;                                  case TYPE_STRING:       e = "String"; yylval.str = xstrdup("error recovery"); break;
1059                                  case TYPE_NUMBER:       e = "Number"; break;                                  case TYPE_STRINGLIST:   e = "StringL"; yylval.str = xstrdup("error recovery"); break;
1060                                  case TYPE_COLOR:        e = "Color"; break;                                  case TYPE_CSTRING:      e = "CString"; yylval.str = xstrdup("error recovery"); break;
1061                                  case TYPE_FONT:         e = "Font"; break;                                  case TYPE_NUMBER:       e = "Number"; yylval.i = 0; break;
1062                                  case TYPE_BOOLEAN:      e = "Boolean"; break;                                  case TYPE_COLOR:        e = "Color"; yylval.str = xstrdup("#123456"); break;
1063                                  case TYPE_DOUBLE:       e = "Double"; break;                                  case TYPE_COLORLIST:    e = "ColorL"; yylval.str = xstrdup("#123456"); break;
1064                                  default:                e = "Internal error: Unknown type"; break;                                  case TYPE_FONT:         e = "Font"; yylval.i = 0; break;
1065                                    case TYPE_BOOLEAN:      e = "Boolean"; yylval.i = 0; break;
1066                                    case TYPE_DOUBLE:       e = "Double"; yylval.d = 0.0; break;
1067                                    default:                e = "Internal error: Unknown type"; yylval.i = 0; break;
1068                                  }                                  }
1069                                  yyerror("%s expected", e);                                  stack_msg(MSG_ERR, "config: %d: %s expected", line_number, e);
1070                          }                          }
1071  #ifdef DEBUG  #ifdef DEBUG
1072                          printf("processing: '%s'\n", kw->keyword);                          printf("processing: '%s'\n", kw->keyword);
# Line 746  Line 1076 
1076                                  case TYPE_STRING:                                  case TYPE_STRING:
1077                                          *kw->confref.s = yylval.str;                                          *kw->confref.s = yylval.str;
1078                                          break;                                          break;
1079                                    case TYPE_STRINGLIST:
1080                                            kw->confref.sl->strs = xrealloc(kw->confref.sl->strs, sizeof(*kw->confref.sl->strs) * (kw->confref.sl->n + 1));
1081                                            kw->confref.sl->strs[kw->confref.sl->n] = yylval.str;
1082                                            kw->confref.sl->n++;
1083                                            break;
1084                                    case TYPE_CSTRING:
1085                                            kw->confref.cs->str = yylval.str;
1086                                            break;
1087                                  case TYPE_NUMBER:                                  case TYPE_NUMBER:
1088                                          *kw->confref.i = yylval.i;                                          *kw->confref.i = yylval.i;
1089                                          break;                                          break;
1090                                  case TYPE_BOOLEAN:                                  case TYPE_BOOLEAN:
1091                                          *kw->confref.i = yylval.i != 0;                                          if(yylval.i == -1)
1092                                                    *kw->confref.i = !*kw->confref.i;
1093                                            else
1094                                                    *kw->confref.i = yylval.i != 0;
1095                                          break;                                          break;
1096                                  case TYPE_COLOR:                                  case TYPE_COLOR:
1097                                          set_color(kw->confref.c, yylval.str);                                          set_color(kw->confref.c, yylval.str);
1098                                          break;                                          break;
1099                                    case TYPE_COLORLIST:
1100                                            kw->confref.cl->clrs = xrealloc(kw->confref.cl->clrs, sizeof(*kw->confref.cl->clrs) * (kw->confref.cl->n + 1));
1101                                            set_color(&kw->confref.cl->clrs[kw->confref.cl->n], yylval.str);
1102                                            kw->confref.cl->n++;
1103                                            break;
1104                                  case TYPE_FONT:                                  case TYPE_FONT:
1105                                          kw->confref.f->gdfont = get_font(yylval.i);                                          kw->confref.f->gdfont = get_font(yylval.i);
1106                                          break;                                          break;
# Line 765  Line 1111 
1111                                          yyerror("Internal error: Unknown type passed %d", kw->type);                                          yyerror("Internal error: Unknown type passed %d", kw->type);
1112                                          break;                                          break;
1113                          }                          }
1114                            kw = NULL;
1115                          state = 3;                          state = 3;
1116                          break;                          break;
1117                  case 3:                  case 3:
1118                          if(token != ';')                          if(token != ';')
1119                                  yyerror("';' expected");                                  stack_msg(MSG_ERR, "config: %d: ';' expected", line_number);
1120                          state = 0;                          state = 0;
1121                          break;                          break;
1122                    case 4:
1123                            if(token != TYPE_STRING)
1124                            {
1125                                    stack_msg(MSG_ERR, "config: %d: String expected (condition key)", line_number);
1126                                    state = skip_to_semicolon(state);
1127                                    break;
1128                            }
1129                            node = new_node(yylval.str);
1130                            state = 5;
1131                            break;
1132                    case 5:
1133                            if(token <= OP_FIRST || token >= OP_LAST)
1134                            {
1135                                    stack_msg(MSG_ERR, "config: %d: Operator expected", line_number);
1136                                    state = skip_to_semicolon(state);
1137                                    break;
1138                            }
1139                            node->op = token;
1140                            state = 6;
1141                            break;
1142                    case 6:
1143                            if(token != TYPE_STRING)
1144                            {
1145                                    stack_msg(MSG_ERR, "config: %d: String expected (condition)", line_number);
1146                                    state = skip_to_semicolon(state);
1147                                    break;
1148                            }
1149                            if(node->key == KEY_DATE)
1150                                    node->content = fixup_date(yylval.str);
1151                            else
1152                                    node->content = yylval.str;
1153                            state = 7;
1154                            break;
1155                    case 7:
1156                            if(token == '[')
1157                            {
1158                                    push_state(node, 8);
1159                                    node = NULL;
1160                                    state = 4;
1161                                    break;
1162                            }
1163                            if(token != TYPE_STRING)
1164                            {
1165                                    stack_msg(MSG_ERR, "config: %d: String or '[' expected (true case)", line_number);
1166                                    state = skip_to_semicolon(state);
1167                                    break;
1168                            }
1169                            node->tcase = xmalloc(sizeof(*node->tcase));
1170                            if(kw->type == TYPE_COLOR || kw->type == TYPE_COLORLIST)
1171                            {
1172                                    node->tcase->key = TYPE_COLOR;
1173                                    set_color(&node->tcase->value.clr, yylval.str);
1174                            }
1175                            else
1176                            {
1177                                    node->tcase->key = TYPE_STRING;
1178                                    node->tcase->value.str = yylval.str;
1179                            }
1180                            state = 8;
1181                            break;
1182                    case 8:
1183                            if(token == '[')
1184                            {
1185                                    push_state(node, 9);
1186                                    node = NULL;
1187                                    state = 4;
1188                                    break;
1189                            }
1190                            if(token != TYPE_STRING)
1191                            {
1192                                    stack_msg(MSG_ERR, "config: %d: String or '[' expected (false case)", line_number);
1193                                    state = skip_to_semicolon(state);
1194                                    break;
1195                            }
1196                            node->fcase = xmalloc(sizeof(*node->fcase));
1197                            if(kw->type == TYPE_COLOR || kw->type == TYPE_COLORLIST)
1198                            {
1199                                    node->fcase->key = TYPE_COLOR;
1200                                    set_color(&node->fcase->value.clr, yylval.str);
1201                            }
1202                            else
1203                            {
1204                                    node->fcase->key = TYPE_STRING;
1205                                    node->fcase->value.str = yylval.str;
1206                            }
1207                            state = 9;
1208                            break;
1209                    case 9:
1210                            if(token != ']')
1211                            {
1212                                    stack_msg(MSG_ERR, "config: %d: ']' expected", line_number);
1213                                    state = skip_to_semicolon(state);
1214                                    break;
1215                            }
1216                            if(!pop_state(&node, &state))
1217                            {
1218                                    if(kw->type == TYPE_COLOR)
1219                                            kw->confref.c->node = node;
1220                                    else if(kw->type == TYPE_CSTRING)
1221                                            kw->confref.cs->node = node;
1222                                    else
1223                                            stack_msg(MSG_ERR, "config: %d: Color or conditional string keyword expected", line_number);
1224                                    node = NULL;
1225                                    kw = NULL;
1226                            }
1227                            break;
1228                  default:                  default:
1229                          yyerror("Internal error: invalid state %d", state);                          yyerror("Internal error: invalid state %d", state);
1230                          break;                          break;
# Line 843  Line 1296 
1296                  }                  }
1297                  input_file = NULL;                  input_file = NULL;
1298          }          }
1299    
1300            if(conf.merge_from.n != conf.merge_to.n)
1301            {
1302                    int x = conf.merge_from.n < conf.merge_to.n ? conf.merge_from.n : conf.merge_to.n;
1303                    stack_msg(MSG_ERR, "config: merge_from(n=%d) does not match merge_to(n=%d)", conf.merge_from.n, conf.merge_to.n);
1304                    conf.merge_from.n = x;
1305                    conf.merge_to.n = x;
1306            }
1307            if(conf.merge_color.n < conf.merge_from.n)
1308            {
1309                    /* Silently extend missing merge_color statements with black */
1310                    int x;
1311                    char c[] = "#000000";
1312                    for(x = conf.merge_color.n; x < conf.merge_from.n; x++)
1313                    {
1314                            conf.merge_color.clrs = xrealloc(conf.merge_color.clrs, sizeof(*conf.merge_color.clrs) * (conf.merge_color.n + 1));
1315                            set_color(&conf.merge_color.clrs[conf.merge_color.n], c);
1316                            conf.merge_color.n++;
1317                    }
1318            }
1319    
1320  #ifdef DEBUG  #ifdef DEBUG
1321          dump_config();          dump_config();
1322  #endif  #endif
1323  }  }
1324    
1325    /*
1326     **************************************************************************
1327     * Color reference by name for late-binding color allocation
1328     **************************************************************************
1329     */
1330    color_t *get_colorref(const char *confcolor, int idx)
1331    {
1332            keyword_t skw;
1333            keyword_t *kw;
1334    
1335            if(!confcolor)
1336                    return NULL;
1337    
1338            skw.keyword = confcolor;
1339            kw = bsearch(&skw, keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);
1340            if(!kw || (kw->type != TYPE_COLOR && kw->type != TYPE_COLORLIST))
1341                    return NULL;
1342            if(kw->type == TYPE_COLORLIST)
1343            {
1344                    if(idx >= kw->confref.cl->n)
1345                            return NULL;
1346                    return &kw->confref.cl->clrs[idx];
1347            }
1348            return kw->confref.c;
1349    }

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.26

  ViewVC Help
Powered by ViewVC 1.1.0 with CvsGraph 1.7.0