/[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.25, Wed May 21 01:41:18 2008 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                    INTTYPE 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            { "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 155  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 162  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            { "map_merge_href",     TYPE_STRING,    { &conf.map_merge_href } },
178            { "map_merge_alt",      TYPE_STRING,    { &conf.map_merge_alt } },
179          { "jpeg",               TYPE_VALUE,     { (void *)IMAGE_JPEG } },          { "jpeg",               TYPE_VALUE,     { (void *)IMAGE_JPEG } },
180          { "png",                TYPE_VALUE,     { (void *)IMAGE_PNG } },          { "png",                TYPE_VALUE,     { (void *)IMAGE_PNG } },
181          { "gif",                TYPE_VALUE,     { (void *)IMAGE_GIF } },          { "gif",                TYPE_VALUE,     { (void *)IMAGE_GIF } },
# Line 268  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 290  Line 368 
368          debug_pbool("anti_alias", conf.anti_alias);          debug_pbool("anti_alias", conf.anti_alias);
369          debug_pbool("use_ttf", conf.use_ttf);          debug_pbool("use_ttf", conf.use_ttf);
370          debug_pint("thick_lines", conf.thick_lines);          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    
388            debug_pcolor("msg_color", &conf.msg_color);
389            debug_pfont("msg_font", conf.msg_font.gdfont);
390            debug_pstring("msg_ttfont", conf.msg_font.ttfont);
391            debug_pdouble("msg_ttsize", conf.msg_font.ttsize);
392    
393          debug_pfont("tag_font", conf.tag_font.gdfont);          debug_pfont("tag_font", conf.tag_font.gdfont);
394          debug_pstring("tag_ttfont", conf.tag_font.ttfont);          debug_pstring("tag_ttfont", conf.tag_font.ttfont);
395          debug_psouble("tag_ttsize", conf.tag_font.ttsize);          debug_pdouble("tag_ttsize", conf.tag_font.ttsize);
396          debug_pcolor("tag_color", &conf.tag_color);          debug_pcolor("tag_color", &conf.tag_color);
397            debug_pbool("tag_ignore_merge", conf.tag_ignore_merge);
398            debug_pstring("tag_ignore", conf.tag_ignore);
399            debug_pbool("tag_negate", conf.tag_negate);
400            debug_pbool("tag_nocase", conf.tag_nocase);
401    
402          debug_pfont("rev_font", conf.rev_font.gdfont);          debug_pfont("rev_font", conf.rev_font.gdfont);
403          debug_pstring("rev_ttfont", conf.rev_font.ttfont);          debug_pstring("rev_ttfont", conf.rev_font.ttfont);
# Line 304  Line 407 
407          debug_pint("rev_separator", conf.rev_separator);          debug_pint("rev_separator", conf.rev_separator);
408          debug_pint("rev_minline", conf.rev_minline);          debug_pint("rev_minline", conf.rev_minline);
409          debug_pint("rev_maxline", conf.rev_maxline);          debug_pint("rev_maxline", conf.rev_maxline);
410            debug_pint("rev_maxtags", conf.rev_maxtags);
411          debug_pint("rev_lspace", conf.rev_lspace);          debug_pint("rev_lspace", conf.rev_lspace);
412          debug_pint("rev_rspace", conf.rev_rspace);          debug_pint("rev_rspace", conf.rev_rspace);
413          debug_pint("rev_tspace", conf.rev_tspace);          debug_pint("rev_tspace", conf.rev_tspace);
414          debug_pint("rev_bspace", conf.rev_bspace);          debug_pint("rev_bspace", conf.rev_bspace);
415          debug_pstring("rev_text", conf.rev_text);          debug_pcstring("rev_text", conf.rev_text);
416          debug_pcolor("rev_text_color", &conf.rev_text_color);          debug_pcolor("rev_text_color", &conf.rev_text_color);
417          debug_pfont("rev_text_font", conf.rev_text_font.gdfont);          debug_pfont("rev_text_font", conf.rev_text_font.gdfont);
418          debug_pstring("rev_text_ttfont", conf.rev_text_font.ttfont);          debug_pstring("rev_text_ttfont", conf.rev_text_font.ttfont);
419          debug_pdouble("rev_text_ttsize", conf.rev_text_font.ttsize);          debug_pdouble("rev_text_ttsize", conf.rev_text_font.ttsize);
420            debug_pbool("rev_hidenumber", conf.rev_hidenumber);
421    
422          debug_pfont("branch_font", conf.branch_font.gdfont);          debug_pfont("branch_font", conf.branch_font.gdfont);
423          debug_pstring("branch_ttfont", conf.branch_font.ttfont);          debug_pstring("branch_ttfont", conf.branch_font.ttfont);
# Line 330  Line 435 
435          debug_pint("branch_connect", conf.branch_connect);          debug_pint("branch_connect", conf.branch_connect);
436          debug_pint("branch_margin", conf.branch_margin);          debug_pint("branch_margin", conf.branch_margin);
437          debug_pint("branch_dupbox", conf.branch_dupbox);          debug_pint("branch_dupbox", conf.branch_dupbox);
438            debug_pbool("branch_fold", conf.branch_fold);
439            debug_pbool("branch_foldall", conf.branch_foldall);
440            debug_pbool("branch_resort", conf.branch_resort);
441            debug_pstring("branch_subtree", conf.branch_subtree);
442    
443          debug_pstring("title", conf.title);          debug_pstring("title", conf.title);
444          debug_pint("title_x", conf.title_x);          debug_pint("title_x", conf.title_x);
# Line 347  Line 456 
456    
457          debug_pint("image_type", conf.image_type);          debug_pint("image_type", conf.image_type);
458          debug_pint("image_quality", conf.image_quality);          debug_pint("image_quality", conf.image_quality);
459            debug_pint("image_compress", conf.image_compress);
460            debug_pbool("image_interlace", conf.image_interlace);
461    
462          debug_pstring("map_name", conf.map_name);          debug_pstring("map_name", conf.map_name);
463          debug_pstring("map_branch_href", conf.map_branch_href);          debug_pstring("map_branch_href", conf.map_branch_href);
# Line 355  Line 466 
466          debug_pstring("map_rev_alt", conf.map_rev_alt);          debug_pstring("map_rev_alt", conf.map_rev_alt);
467          debug_pstring("map_diff_href", conf.map_diff_href);          debug_pstring("map_diff_href", conf.map_diff_href);
468          debug_pstring("map_diff_alt", conf.map_diff_alt);          debug_pstring("map_diff_alt", conf.map_diff_alt);
469            debug_pstring("map_merge_href", conf.map_merge_href);
470            debug_pstring("map_merge_alt", conf.map_merge_alt);
471    
472          debug_pstring("expand[0]", conf.expand[0]);          debug_pstring("expand[0]", conf.expand[0]);
473          debug_pstring("expand[1]", conf.expand[1]);          debug_pstring("expand[1]", conf.expand[1]);
# Line 490  Line 603 
603    
604                  switch(ch)                  switch(ch)
605                  {                  {
                 case EOF:  
606                  case '=':                  case '=':
607                            ch = get_input();
608                            switch(ch)
609                            {
610                            case '~': return OP_CONTAINED;
611                            case '*': return OP_CONTAINEDI;
612                            case '=': return OP_EQ;
613                            default:
614                                    unget_input(ch);
615                                    return '=';
616                            }
617                            break;
618    
619                    case '!':
620                            ch = get_input();
621                            switch(ch)
622                            {
623                            case '~': return OP_NCONTAINED;
624                            case '*': return OP_NCONTAINEDI;
625                            case '=': return OP_NE;
626                            default:
627                                    stack_msg(MSG_ERR, "config: %d: Invalid operator", line_number);
628                                    unget_input(ch);
629                                    return '!';
630                            }
631                            break;
632    
633                    case '>':
634                            ch = get_input();
635                            if(ch == '=')
636                                    return OP_GE;
637                            unget_input(ch);
638                            return OP_GT;
639    
640                    case '<':
641                            ch = get_input();
642                            if(ch == '=')
643                                    return OP_LE;
644                            unget_input(ch);
645                            return OP_LT;
646    
647                    case EOF:
648                  case ';':                  case ';':
649                    case '[':
650                    case ']':
651                          return ch;                          return ch;
652    
653                  case '#':       /* Comment */                  case '#':       /* Comment */
# Line 529  Line 684 
684                                                  c[1] = get_input();                                                  c[1] = get_input();
685                                                  c[2] = '\0';                                                  c[2] = '\0';
686                                                  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]))
687                                                          yyerror("Invalid hex escape");                                                          stack_msg(MSG_ERR, "config: %d: Invalid hex escape", line_number);
688                                                  add_str((int)strtol(c, NULL, 16));                                                  add_str((int)strtol(c, NULL, 16));
689                                                  break;                                                  break;
690                                          case '0':                                          case '0':
# Line 548  Line 703 
703                                                  add_str((int)strtol(c, NULL, 8));                                                  add_str((int)strtol(c, NULL, 8));
704                                                  break;                                                  break;
705                                          case EOF:                                          case EOF:
706                                                    yyerror("Unexpected EOF in escape");                                                  yyerror("Unexpected EOF in escape");
707                                                    break;                                                  break;
708                                          }                                          }
709                                          break;                                          break;
710                                  case '"':                                  case '"':
# Line 590  Line 745 
745                                  skw.keyword = get_str();                                  skw.keyword = get_str();
746                                  kw = bsearch(&skw, keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);                                  kw = bsearch(&skw, keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);
747                                  if(!kw)                                  if(!kw)
748                                          yyerror("Unknown keyword '%s'", skw.keyword);                                  {
749                                  xfree(skw.keyword);                                          stack_msg(MSG_ERR, "config: %d: Unknown keyword '%s'", line_number, skw.keyword);
750                                            yylval.kw = NULL;
751                                            return TYPE_KEYWORD;
752                                    }
753                                    xfree((void *)skw.keyword);
754                                  if(kw->type == TYPE_VALUE)                                  if(kw->type == TYPE_VALUE)
755                                  {                                  {
756                                          yylval.i = kw->confref.val;                                          yylval.i = (int)kw->confref.val;
757                                          return TYPE_NUMBER;                                          return TYPE_NUMBER;
758                                  }                                  }
759                                  yylval.kw = kw;                                  yylval.kw = kw;
# Line 626  Line 785 
785                                  {                                  {
786                                          yylval.d = strtod(s, &eptr);                                          yylval.d = strtod(s, &eptr);
787                                          if(*eptr)                                          if(*eptr)
788                                                  yyerror("Invalid floating point number");                                                  stack_msg(MSG_ERR, "config: %d: Invalid floating point number", line_number);
789                                  }                                  }
790                                  else                                  else
791                                  {                                  {
792                                          yylval.i = strtol(s, &eptr, 0);                                          yylval.i = strtol(s, &eptr, 0);
793                                          if(*eptr)                                          if(*eptr)
794                                                  yyerror("Invalid number");                                                  stack_msg(MSG_ERR, "config: %d: Invalid number", line_number);
795                                  }                                  }
796                                  xfree(s);                                  xfree(s);
797                                  return type;                                  return type;
# Line 647  Line 806 
806  static void set_color(color_t *c, char *s)  static void set_color(color_t *c, char *s)
807  {  {
808          char *cptr;          char *cptr;
809            c->node = NULL;
810          if(*s != '#' || strlen(s) != 7)          if(*s != '#' || strlen(s) != 7)
811          {          {
812  colorerror:  colorerror:
813                  yyerror("Invalid color value");                  stack_msg(MSG_ERR, "config: %d: Invalid color value '%s'", line_number, s);
814                    return;
815          }          }
816          c->b = strtol(s+5, &cptr, 16);          c->b = strtol(s+5, &cptr, 16);
817          if(*cptr)          if(*cptr)
# Line 691  Line 852 
852   *              ;   *              ;
853   *   *
854   *      line    : <keyword> '=' <value> ';'   *      line    : <keyword> '=' <value> ';'
855     *              | <keyword> '=' expr ';'
856   *              | ';'   *              | ';'
857     *
858     *      expr    : '[' <kw> <op> <value> expr expr ']'
859     *              | <value>
860   *              ;   *              ;
861   **************************************************************************   **************************************************************************
862   */   */
863    static int skip_to_semicolon(int state)
864    {
865            int token;
866            while(1)
867            {
868                    token = config_lex();
869                    if(token == ';')
870                            return 0;
871                    else if(token == EOF)
872                            return state;
873            }
874    }
875    
876    static node_t *new_node(char *val)
877    {
878            node_t *n = xmalloc(sizeof(*n));
879            if(!strcmp(val, "state"))
880                    n->key = KEY_STATE;
881            else if(!strcmp(val, "author"))
882                    n->key = KEY_AUTHOR;
883            else if(!strcmp(val, "tag"))
884                    n->key = KEY_TAG;
885            else if(!strcmp(val, "date"))
886                    n->key = KEY_DATE;
887            else if(!strcmp(val, "rev"))
888                    n->key = KEY_REV;
889            else
890            {
891                    n->key = KEY_UNKNOWN;
892                    stack_msg(MSG_ERR, "config: %d: Unknown key '%s'", line_number, val);
893            }
894            return n;
895    }
896    
897    typedef struct __statestack_t
898    {
899            int     state;
900            node_t  *node;
901    } statestack_t;
902    
903    static int nstatestack = 0;
904    static int nastatestack;
905    static statestack_t *statestack = NULL;
906    
907    static void push_state(node_t *node, int state)
908    {
909            if(!statestack)
910            {
911                    statestack = xmalloc(4 * sizeof(*statestack));
912                    nastatestack = 4;
913                    nstatestack = 0;
914            }
915            else if(nstatestack >= nastatestack)
916            {
917                    nastatestack *= 2;
918                    statestack = xrealloc(statestack, nastatestack * sizeof(*statestack));
919            }
920            statestack[nstatestack].node = node;
921            statestack[nstatestack].state = state;
922            nstatestack++;
923    }
924    
925    static int pop_state(node_t **node, int *state)
926    {
927            if(nstatestack <= 0)
928            {
929                    *state = 3;
930                    return 0;
931            }
932            assert(*node != NULL);
933            if(statestack[nstatestack-1].state == 8)
934                    statestack[nstatestack-1].node->tcase = *node;
935            else if(statestack[nstatestack-1].state == 9)
936                    statestack[nstatestack-1].node->fcase = *node;
937            *state = statestack[nstatestack-1].state;
938            *node = statestack[nstatestack-1].node;
939            return nstatestack--;
940    }
941    
942    /* YYYY.MM.DD.hh.mm.ss */
943    /* 0123456789012345678 */
944    /*           111111111 */
945    static char *fixup_date(const char *str)
946    {
947            int i;
948            int y=1970, m=1, d=1, h=0, mi=0, s=0;
949            int l = strlen(str);
950            char date[6*16]; /* Should be wildly enough to hold 19 chars from 6 numbers with all possible errors */
951            if(l < 4 || l > 19)
952            {
953    date_err:
954                    stack_msg(MSG_ERR, "config: %d: Invalid date string '%s'", line_number, str);
955                    return "1970.01.01.00.00.00";
956            }
957            for(i = 0; i < l; i++)
958            {
959                    if(!strchr("0123456789.", str[i]))
960                            goto date_err;
961            }
962            i = sscanf(str, "%d.%d.%d.%d.%d.%d", &y, &m, &d, &h, &mi, &s);
963            if(i == EOF || i < 0 || i > 6)
964                    goto date_err;
965            if(i >= 1 && (y < 1970 || y > 2037))
966                    goto date_err;
967            if(i >= 2 && (m < 1 || m > 12))
968                    goto date_err;
969            if(i >= 3 && (d < 1 || d > 31))
970                    goto date_err;
971            if(i >= 4 && (h < 0 || h > 23))
972                    goto date_err;
973            if(i >= 5 && (mi < 0 || mi > 59))
974                    goto date_err;
975            if(i >= 6 && (s < 0 || s > 59))
976                    goto date_err;
977            sprintf(date, "%04d.%02d.%02d.%02d.%02d.%02d", y, m, d, h, mi, s);
978            return strdup(date);
979    }
980    
981  static void config_parse(void)  static void config_parse(void)
982  {  {
983          int state = 0;          int state = 0;
984          int token;          int token;
985          int t;          int t;
986          keyword_t *kw = NULL;          keyword_t *kw = NULL;
987            node_t *node = NULL;
988    
989          while(1)          while(1)
990          {          {
# Line 708  Line 992 
992                  if(token == EOF)                  if(token == EOF)
993                  {                  {
994                          if(state)                          if(state)
995                                  yyerror("Unexpected EOF");                                  stack_msg(MSG_ERR, "config: %d: Unexpected EOF", line_number);
996                          break;                          break;
997                  }                  }
998    
# Line 721  Line 1005 
1005                                  state = 1;                                  state = 1;
1006                          }                          }
1007                          else if(token != ';')                          else if(token != ';')
1008                                  yyerror("Keyword expected");                                  stack_msg(MSG_ERR, "config: %d: Keyword expected", line_number);
1009                          break;                          break;
1010                  case 1:                  case 1:
1011                          if(token != '=')                          if(token != '=')
1012                                  yyerror("'=' expected");                          {
1013                          state = 2;                                  stack_msg(MSG_ERR, "config: %d: '=' expected", line_number);
1014                                    state = skip_to_semicolon(state);
1015                                    break;
1016                            }
1017                            else
1018                                    state = 2;
1019                          break;                          break;
1020                  case 2:                  case 2:
1021                            if(!kw)
1022                            {
1023                                    /* Error recovery of failed keyword */
1024                                    state = 3;
1025                                    break;
1026                            }
1027                            if(token == '[')
1028                            {
1029                                    if(kw->type != TYPE_COLOR && kw->type != TYPE_CSTRING)
1030                                    {
1031                                            stack_msg(MSG_ERR, "config: %d: Conditional expression not allowed for keyword", line_number);
1032                                            state = skip_to_semicolon(state);
1033                                            break;
1034                                    }
1035                                    state = 4;
1036                                    break;
1037                            }
1038                          if(kw->type == TYPE_FONT || kw->type == TYPE_BOOLEAN)                          if(kw->type == TYPE_FONT || kw->type == TYPE_BOOLEAN)
1039                                  t = TYPE_NUMBER;                                  t = TYPE_NUMBER;
1040                          else if(kw->type == TYPE_COLOR)                          else if(kw->type == TYPE_COLOR || kw->type == TYPE_COLORLIST || kw->type == TYPE_STRINGLIST || kw->type == TYPE_CSTRING)
1041                                  t = TYPE_STRING;                                  t = TYPE_STRING;
1042                          else                          else
1043                                  t = kw->type;                                  t = kw->type;
# Line 748  Line 1054 
1054                                  char *e;                                  char *e;
1055                                  switch(kw->type)                                  switch(kw->type)
1056                                  {                                  {
1057                                  case TYPE_STRING:       e = "String"; break;                                  case TYPE_STRING:       e = "String"; yylval.str = xstrdup("error recovery"); break;
1058                                  case TYPE_NUMBER:       e = "Number"; break;                                  case TYPE_STRINGLIST:   e = "StringL"; yylval.str = xstrdup("error recovery"); break;
1059                                  case TYPE_COLOR:        e = "Color"; break;                                  case TYPE_CSTRING:      e = "CString"; yylval.str = xstrdup("error recovery"); break;
1060                                  case TYPE_FONT:         e = "Font"; break;                                  case TYPE_NUMBER:       e = "Number"; yylval.i = 0; break;
1061                                  case TYPE_BOOLEAN:      e = "Boolean"; break;                                  case TYPE_COLOR:        e = "Color"; yylval.str = xstrdup("#123456"); break;
1062                                  case TYPE_DOUBLE:       e = "Double"; break;                                  case TYPE_COLORLIST:    e = "ColorL"; yylval.str = xstrdup("#123456"); break;
1063                                  default:                e = "Internal error: Unknown type"; break;                                  case TYPE_FONT:         e = "Font"; yylval.i = 0; break;
1064                                    case TYPE_BOOLEAN:      e = "Boolean"; yylval.i = 0; break;
1065                                    case TYPE_DOUBLE:       e = "Double"; yylval.d = 0.0; break;
1066                                    default:                e = "Internal error: Unknown type"; yylval.i = 0; break;
1067                                  }                                  }
1068                                  yyerror("%s expected", e);                                  stack_msg(MSG_ERR, "config: %d: %s expected", line_number, e);
1069                          }                          }
1070  #ifdef DEBUG  #ifdef DEBUG
1071                          printf("processing: '%s'\n", kw->keyword);                          printf("processing: '%s'\n", kw->keyword);
# Line 766  Line 1075 
1075                                  case TYPE_STRING:                                  case TYPE_STRING:
1076                                          *kw->confref.s = yylval.str;                                          *kw->confref.s = yylval.str;
1077                                          break;                                          break;
1078                                    case TYPE_STRINGLIST:
1079                                            kw->confref.sl->strs = xrealloc(kw->confref.sl->strs, sizeof(*kw->confref.sl->strs) * (kw->confref.sl->n + 1));
1080                                            kw->confref.sl->strs[kw->confref.sl->n] = yylval.str;
1081                                            kw->confref.sl->n++;
1082                                            break;
1083                                    case TYPE_CSTRING:
1084                                            kw->confref.cs->str = yylval.str;
1085                                            break;
1086                                  case TYPE_NUMBER:                                  case TYPE_NUMBER:
1087                                          *kw->confref.i = yylval.i;                                          *kw->confref.i = yylval.i;
1088                                          break;                                          break;
# Line 778  Line 1095 
1095                                  case TYPE_COLOR:                                  case TYPE_COLOR:
1096                                          set_color(kw->confref.c, yylval.str);                                          set_color(kw->confref.c, yylval.str);
1097                                          break;                                          break;
1098                                    case TYPE_COLORLIST:
1099                                            kw->confref.cl->clrs = xrealloc(kw->confref.cl->clrs, sizeof(*kw->confref.cl->clrs) * (kw->confref.cl->n + 1));
1100                                            set_color(&kw->confref.cl->clrs[kw->confref.cl->n], yylval.str);
1101                                            kw->confref.cl->n++;
1102                                            break;
1103                                  case TYPE_FONT:                                  case TYPE_FONT:
1104                                          kw->confref.f->gdfont = get_font(yylval.i);                                          kw->confref.f->gdfont = get_font(yylval.i);
1105                                          break;                                          break;
# Line 788  Line 1110 
1110                                          yyerror("Internal error: Unknown type passed %d", kw->type);                                          yyerror("Internal error: Unknown type passed %d", kw->type);
1111                                          break;                                          break;
1112                          }                          }
1113                            kw = NULL;
1114                          state = 3;                          state = 3;
1115                          break;                          break;
1116                  case 3:                  case 3:
1117                          if(token != ';')                          if(token != ';')
1118                                  yyerror("';' expected");                                  stack_msg(MSG_ERR, "config: %d: ';' expected", line_number);
1119                          state = 0;                          state = 0;
1120                          break;                          break;
1121                    case 4:
1122                            if(token != TYPE_STRING)
1123                            {
1124                                    stack_msg(MSG_ERR, "config: %d: String expected (condition key)", line_number);
1125                                    state = skip_to_semicolon(state);
1126                                    break;
1127                            }
1128                            node = new_node(yylval.str);
1129                            state = 5;
1130                            break;
1131                    case 5:
1132                            if(token <= OP_FIRST || token >= OP_LAST)
1133                            {
1134                                    stack_msg(MSG_ERR, "config: %d: Operator expected", line_number);
1135                                    state = skip_to_semicolon(state);
1136                                    break;
1137                            }
1138                            node->op = token;
1139                            state = 6;
1140                            break;
1141                    case 6:
1142                            if(token != TYPE_STRING)
1143                            {
1144                                    stack_msg(MSG_ERR, "config: %d: String expected (condition)", line_number);
1145                                    state = skip_to_semicolon(state);
1146                                    break;
1147                            }
1148                            if(node->key == KEY_DATE)
1149                                    node->content = fixup_date(yylval.str);
1150                            else
1151                                    node->content = yylval.str;
1152                            state = 7;
1153                            break;
1154                    case 7:
1155                            if(token == '[')
1156                            {
1157                                    push_state(node, 8);
1158                                    node = NULL;
1159                                    state = 4;
1160                                    break;
1161                            }
1162                            if(token != TYPE_STRING)
1163                            {
1164                                    stack_msg(MSG_ERR, "config: %d: String or '[' expected (true case)", line_number);
1165                                    state = skip_to_semicolon(state);
1166                                    break;
1167                            }
1168                            node->tcase = xmalloc(sizeof(*node->tcase));
1169                            if(kw->type == TYPE_COLOR || kw->type == TYPE_COLORLIST)
1170                            {
1171                                    node->tcase->key = TYPE_COLOR;
1172                                    set_color(&node->tcase->value.clr, yylval.str);
1173                            }
1174                            else
1175                            {
1176                                    node->tcase->key = TYPE_STRING;
1177                                    node->tcase->value.str = yylval.str;
1178                            }
1179                            state = 8;
1180                            break;
1181                    case 8:
1182                            if(token == '[')
1183                            {
1184                                    push_state(node, 9);
1185                                    node = NULL;
1186                                    state = 4;
1187                                    break;
1188                            }
1189                            if(token != TYPE_STRING)
1190                            {
1191                                    stack_msg(MSG_ERR, "config: %d: String or '[' expected (false case)", line_number);
1192                                    state = skip_to_semicolon(state);
1193                                    break;
1194                            }
1195                            node->fcase = xmalloc(sizeof(*node->fcase));
1196                            if(kw->type == TYPE_COLOR || kw->type == TYPE_COLORLIST)
1197                            {
1198                                    node->fcase->key = TYPE_COLOR;
1199                                    set_color(&node->fcase->value.clr, yylval.str);
1200                            }
1201                            else
1202                            {
1203                                    node->fcase->key = TYPE_STRING;
1204                                    node->fcase->value.str = yylval.str;
1205                            }
1206                            state = 9;
1207                            break;
1208                    case 9:
1209                            if(token != ']')
1210                            {
1211                                    stack_msg(MSG_ERR, "config: %d: ']' expected", line_number);
1212                                    state = skip_to_semicolon(state);
1213                                    break;
1214                            }
1215                            if(!pop_state(&node, &state))
1216                            {
1217                                    if(kw->type == TYPE_COLOR)
1218                                            kw->confref.c->node = node;
1219                                    else if(kw->type == TYPE_CSTRING)
1220                                            kw->confref.cs->node = node;
1221                                    else
1222                                            stack_msg(MSG_ERR, "config: %d: Color or conditional string keyword expected", line_number);
1223                                    node = NULL;
1224                                    kw = NULL;
1225                            }
1226                            break;
1227                  default:                  default:
1228                          yyerror("Internal error: invalid state %d", state);                          yyerror("Internal error: invalid state %d", state);
1229                          break;                          break;
# Line 866  Line 1295 
1295                  }                  }
1296                  input_file = NULL;                  input_file = NULL;
1297          }          }
1298    
1299            if(conf.merge_from.n != conf.merge_to.n)
1300            {
1301                    int x = conf.merge_from.n < conf.merge_to.n ? conf.merge_from.n : conf.merge_to.n;
1302                    stack_msg(MSG_ERR, "config: merge_from(n=%d) does not match merge_to(n=%d)", conf.merge_from.n, conf.merge_to.n);
1303                    conf.merge_from.n = x;
1304                    conf.merge_to.n = x;
1305            }
1306            if(conf.merge_color.n < conf.merge_from.n)
1307            {
1308                    /* Silently extend missing merge_color statements with black */
1309                    int x;
1310                    char c[] = "#000000";
1311                    for(x = conf.merge_color.n; x < conf.merge_from.n; x++)
1312                    {
1313                            conf.merge_color.clrs = xrealloc(conf.merge_color.clrs, sizeof(*conf.merge_color.clrs) * (conf.merge_color.n + 1));
1314                            set_color(&conf.merge_color.clrs[conf.merge_color.n], c);
1315                            conf.merge_color.n++;
1316                    }
1317            }
1318    
1319  #ifdef DEBUG  #ifdef DEBUG
1320          dump_config();          dump_config();
1321  #endif  #endif
1322  }  }
1323    
1324    /*
1325     **************************************************************************
1326     * Color reference by name for late-binding color allocation
1327     **************************************************************************
1328     */
1329    color_t *get_colorref(const char *confcolor, int idx)
1330    {
1331            keyword_t skw;
1332            keyword_t *kw;
1333    
1334            if(!confcolor)
1335                    return NULL;
1336    
1337            skw.keyword = confcolor;
1338            kw = bsearch(&skw, keywords, NKEYWORDS, sizeof(keywords[0]), cmp_kw);
1339            if(!kw || (kw->type != TYPE_COLOR && kw->type != TYPE_COLORLIST))
1340                    return NULL;
1341            if(kw->type == TYPE_COLORLIST)
1342            {
1343                    if(idx >= kw->confref.cl->n)
1344                            return NULL;
1345                    return &kw->confref.cl->clrs[idx];
1346            }
1347            return kw->confref.c;
1348    }

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

  ViewVC Help
Powered by ViewVC 1.1.0 with CvsGraph 1.7.0