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

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.24.4.1

  ViewVC Help
Powered by ViewVC 1.1.0 with CvsGraph 1.7.0