890e75b7b60fd4d7682585ddc45bbe13fd64161d
[alioth/magicpoint.git] / grammar.y
1 %{
2 /*
3  * Copyright (C) 1997 and 1998 WIDE Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 /*
30  * partly derived from lbl libpcap source code, which has the following
31  * copyright notice:
32  */
33 /*
34  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
35  *      The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that: (1) source code distributions
39  * retain the above copyright notice and this paragraph in its entirety, (2)
40  * distributions including binary code include the above copyright notice and
41  * this paragraph in its entirety in the documentation or other materials
42  * provided with the distribution, and (3) all advertising materials mentioning
43  * features or use of this software display the following acknowledgement:
44  * ``This product includes software developed by the University of California,
45  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
46  * the University nor the names of its contributors may be used to endorse
47  * or promote products derived from this software without specific prior
48  * written permission.
49  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
50  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
51  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
52  *
53  */
54
55 #include "mgp.h"
56 #include <stdarg.h>
57
58 int yylex(void);
59
60 int n_errors = 0;
61 struct ctrl *root;
62 char *yyfilename;
63 int yylineno;
64
65 void
66 yyerror(char *msg, ...)
67 {
68         va_list ap;
69         va_start(ap, msg);
70         ++n_errors;
71         fprintf(stderr, "%s:%d: error: ", yyfilename, yylineno);
72         vfprintf(stderr, msg, ap);
73         fprintf(stderr, "\n");
74         va_end(ap);
75 }
76
77 static void
78 yywarn(char *msg, ...)
79 {
80         va_list ap;
81         va_start(ap, msg);
82         fprintf(stderr, "%s:%d: warning: ", yyfilename, yylineno);
83         vfprintf(stderr, msg, ap);
84         fprintf(stderr, "\n");
85         va_end(ap);
86 }
87
88 static struct ctrl *
89 gen_void(op)
90         int op;
91 {
92         struct ctrl *ct;
93
94         if (!(ct = ctlalloc1(op))) {
95                 yyerror("cannot allocate void node");
96                 return ct;
97         }
98         return ct;
99 }
100
101 static struct ctrl *
102 gen_double_int(op, v)
103         int op;
104         int v;
105 {
106         struct ctrl *ct;
107
108         if (!(ct = ctlalloc1(op))) {
109                 yyerror("cannot allocate double node");
110                 return ct;
111         }
112         ct->ctf_value = (double)v;
113         return ct;
114 }
115
116 static struct ctrl *
117 gen_double(op, v)
118         int op;
119         double v;
120 {
121         struct ctrl *ct;
122
123         if (!(ct = ctlalloc1(op))) {
124                 yyerror("cannot allocate double node");
125                 return ct;
126         }
127         ct->ctf_value = v;
128         return ct;
129 }
130
131 static struct ctrl *
132 gen_int(op, v)
133         int op;
134         int v;
135 {
136         struct ctrl *ct;
137
138         if (!(ct = ctlalloc1(op))) {
139                 yyerror("cannot allocate integer node");
140                 return ct;
141         }
142         ct->cti_value = v;
143         return ct;
144 }
145
146 static struct ctrl *
147 gen_int2(op, v1, v2)
148         int op;
149         int v1;
150         int v2;
151 {
152         struct ctrl *ct;
153
154         if (!(ct = ctlalloc1(op))) {
155                 yyerror("cannot allocate integer2 node");
156                 return ct;
157         }
158         ct->cti2_value1 = v1;
159         ct->cti2_value2 = v2;
160         return ct;
161 }
162
163 static struct ctrl *
164 gen_int3(op, v1, v2, v3)
165         int op;
166         int v1;
167         int v2;
168         int v3;
169 {
170         struct ctrl *ct;
171
172         if (!(ct = ctlalloc1(op))) {
173                 yyerror("cannot allocate integer3 node");
174                 return ct;
175         }
176         ct->cti3_value1 = v1;
177         ct->cti3_value2 = v2;
178         ct->cti3_value3 = v3;
179         return ct;
180 }
181
182 static struct ctrl *
183 gen_str(op, str)
184         int op;
185         char *str;
186 {
187         struct ctrl *ct;
188
189         if (!(ct = ctlalloc1(op))) {
190                 yyerror("cannot allocate str1 node");
191                 return ct;
192         }
193         ct->ctc_value = strdup(str);
194         return ct;
195 }
196
197 static struct ctrl *
198 gen_str2(op, str1, str2)
199         int op;
200         char *str1;
201         char *str2;
202 {
203         struct ctrl *ct;
204
205         if (!(ct = ctlalloc1(op))) {
206                 yyerror("cannot allocate str2 node");
207                 return ct;
208         }
209         ct->ctc2_value1 = strdup(str1);
210         ct->ctc2_value2 = strdup(str2);
211         return ct;
212 }
213
214 static struct ctrl *
215 gen_color(op, color)
216         int op;
217         char *color;
218 {
219         struct ctrl *ct;
220
221         if (!(ct = ctlalloc1(op))) {
222                 yyerror("cannot allocate color node");
223                 return ct;
224         }
225         if (get_color(color, &ct->ctl_value) < 0)
226                 yyerror("cannot allocate color \"%s\"", color);
227         return ct;
228 }
229
230 static struct ctrl *
231 gen_bgrad(w, h, colors, dir, zoomflg, extra)
232         int w;
233         int h;
234         int colors;
235         int dir;
236         int zoomflg;
237         struct ctrl *extra;
238 {
239         struct ctrl *ct;
240         struct ctrl *p;
241         int siz;
242
243         if (!(ct = ctlalloc1(CTL_BGRAD))) {
244                 yyerror("cannot allocate node (op=BGRAD)");
245                 return ct;
246         }
247         ct->ctd_width = w;
248         ct->ctd_height = h;
249         ct->ctd_numcolor = colors;
250         ct->ctd_dir = dir;
251         ct->ctd_zoomflag = zoomflg;
252
253         /* process color list. */
254         siz = ct->ctd_g_colors = 0;
255         for (p = extra; p; p = p->ct_next)
256                 siz++;
257         if (siz <= 2) {
258                 ct->ct_val.ctrl_grad.colors =
259                         malloc(3 * sizeof(struct gcolor *));
260         } else {
261                 ct->ct_val.ctrl_grad.colors =
262                         malloc((siz + 1) * sizeof(struct gcolor *));
263         }
264         if (!ct->ct_val.ctrl_grad.colors) {
265                 yyerror("cannot allocate color table");
266                 return ct;
267         }
268
269         ct->ctd_g_colors = 2;
270         ct->ct_val.ctrl_grad.colors[0] = name2gcolor(DEFAULT_GRADSTART);
271         ct->ct_val.ctrl_grad.colors[1] = name2gcolor(DEFAULT_GRADEND);
272         switch (siz) {
273         case 0:
274                 break;
275         case 1:
276                 ct->ct_val.ctrl_grad.colors[0] = name2gcolor(extra->ctc_value);
277                 break;
278         default:
279                 ct->ctd_g_colors = siz;
280                 siz = 0;
281                 for (p = extra; p; p = p->ct_next) {
282                         ct->ct_val.ctrl_grad.colors[siz] =
283                                 name2gcolor(p->ctc_value);
284                         siz++;
285                 }
286         }
287
288         /* normalize */
289         if (ct->ctd_dir < 0) {  /*circle*/
290                 ct->ctd_mode = 1;
291                 ct->ctd_dir = abs(ct->ctd_dir);
292         } else                  /*linear*/
293                 ct->ctd_mode = 0;
294         while (ct->ctd_dir < 0)
295                 ct->ctd_dir += 360;
296         ct->ctd_dir %= 360;
297         if (ct->ctd_width <= 0)
298                 ct->ctd_width = 100;
299         if (ct->ctd_height <= 0)
300                 ct->ctd_height = 100;
301
302         if (extra)
303                 ctlfree(extra);
304
305         return ct;
306 }
307
308 static struct ctrl *
309 gen_newimage(arg)
310         struct ctrl *arg;
311 {
312         struct ctrl *p;
313         struct ctrl *ct;
314
315         if (!(ct = ctlalloc1(CTL_IMAGE))) {
316                 yyerror("cannot allocate node (op=IMAGE)");
317                 return ct;
318         }
319
320         /* default setting */
321         ct->ctm_ximagesize = 100;
322         ct->ctm_yimagesize = 100;
323         ct->ctm_zoomflag = Z_NORMAL | (Z_NORMAL << Z_YSHIFT);
324         ct->ctm_raise = 0;
325         ct->ctm_rotate = 0;
326         ct->ctm_zoomonclk = 0;
327
328         for (p = arg; p; p = p->ct_next) {
329                 if (p->ctc_value[0] != '-')
330                         break;
331
332                 if (strcmp(p->ctc_value, "-colors") == 0 && p->ct_next) {
333                         p = p->ct_next;
334                         ct->ctm_numcolor = atoi(p->ctc_value);
335                 } else if (strcmp(p->ctc_value, "-xysize") == 0
336                         && p->ct_next && p->ct_next->ct_next) {
337                         p = p->ct_next;
338                         ct->ctm_ximagesize = atoi(p->ctc_value);
339                         p = p->ct_next;
340                         ct->ctm_yimagesize = atoi(p->ctc_value);
341                         ct->ctm_zoomflag = Z_ABSOLUTE | (Z_ABSOLUTE << Z_YSHIFT);
342                 } else if (strcmp(p->ctc_value, "-zoom") == 0 && p->ct_next) {
343                         p = p->ct_next;
344                         ct->ctm_ximagesize = atoi(p->ctc_value);
345                         ct->ctm_yimagesize = atoi(p->ctc_value);
346                         ct->ctm_zoomflag = Z_NORMAL | (Z_NORMAL << Z_YSHIFT);
347                 } else if (strcmp(p->ctc_value, "-xyzoom") == 0
348                         && p->ct_next && p->ct_next->ct_next) {
349                         p = p->ct_next;
350                         ct->ctm_ximagesize = atoi(p->ctc_value);
351                         p = p->ct_next;
352                         ct->ctm_yimagesize = atoi(p->ctc_value);
353                         ct->ctm_zoomflag = Z_NORMAL | (Z_NORMAL << Z_YSHIFT);
354                 } else if (strcmp(p->ctc_value, "-scrzoom") == 0 && p->ct_next) {
355                         p = p->ct_next;
356                         ct->ctm_ximagesize = atoi(p->ctc_value);
357                         ct->ctm_yimagesize = atoi(p->ctc_value);
358                         ct->ctm_zoomflag = Z_SCREEN | (Z_SCREEN << Z_YSHIFT);
359                 } else if (strcmp(p->ctc_value, "-xscrzoom") == 0 && p->ct_next) {
360                         p = p->ct_next;
361                         ct->ctm_ximagesize = atoi(p->ctc_value);
362                         ct->ctm_yimagesize = 100;
363                         ct->ctm_zoomflag = Z_SCREEN | (Z_OBEY << Z_YSHIFT);
364                 } else if (strcmp(p->ctc_value, "-yscrzoom") == 0 && p->ct_next) {
365                         p = p->ct_next;
366                         ct->ctm_ximagesize = 100;
367                         ct->ctm_yimagesize = atoi(p->ctc_value);
368                         ct->ctm_zoomflag = Z_OBEY | (Z_SCREEN << Z_YSHIFT);
369                 } else if (strcmp(p->ctc_value, "-xyscrzoom") == 0
370                         && p->ct_next && p->ct_next->ct_next) {
371                         p = p->ct_next;
372                         ct->ctm_ximagesize = atoi(p->ctc_value);
373                         p = p->ct_next;
374                         ct->ctm_yimagesize = atoi(p->ctc_value);
375                         ct->ctm_zoomflag = Z_SCREEN | (Z_SCREEN << Z_YSHIFT);
376                 } else if (strcmp(p->ctc_value, "-raise") == 0 && p->ct_next) {
377                         p = p->ct_next;
378                         ct->ctm_raise = atoi(p->ctc_value);
379                 } else if (strcmp(p->ctc_value, "-rotate") == 0 && p->ct_next) {
380                         p = p->ct_next;
381                         ct->ctm_rotate = atoi(p->ctc_value);
382                 } else if (strcmp(p->ctc_value, "-zoomonclk") == 0 && p->ct_next) {
383                         p = p->ct_next;
384                         ct->ctm_zoomonclk = atoi(p->ctc_value);
385                 } else {
386                         yyerror("invalid argument %s specified for newimage",
387                                 p->ctc_value);
388                         return ct;
389                 }
390         }
391
392         if (!p) {
393                 yyerror("no filename specified to newimage");
394                 return ct;
395         }
396
397         if (p->ct_next) {
398                 yyerror("multiple filename specified to newimage");
399                 return ct;
400         }
401
402         ct->ctm_fname = p->ctc_value;
403         chkfile(ct->ctm_fname);
404         return ct;
405 }
406
407 static struct ctrl *
408 gen_image(op, fname, colors, xsiz, ysiz, zoomflg)
409         int op;
410         char *fname;
411         int colors;
412         int xsiz;
413         int ysiz;
414         int zoomflg;
415 {
416         struct ctrl *ct;
417
418         if (!(ct = ctlalloc1(op))) {
419                 yyerror("cannot allocate node (op=IMAGE)");
420                 return ct;
421         }
422         ct->ctm_fname = fname;
423         ct->ctm_numcolor = colors;
424         ct->ctm_ximagesize = xsiz;
425         ct->ctm_yimagesize = ysiz;
426         switch (zoomflg) {
427         case 0:
428                 ct->ctm_zoomflag = 0;
429                 if (ct->ctm_ximagesize == 0) {
430                         ct->ctm_ximagesize = 100;
431                         ct->ctm_zoomflag |= Z_NORMAL;
432                 } else
433                         ct->ctm_zoomflag |= Z_SCREEN;
434                 if (ct->ctm_yimagesize == 0) {
435                         ct->ctm_yimagesize = 100;
436                         ct->ctm_zoomflag |= (Z_NORMAL << Z_YSHIFT);
437                 } else
438                         ct->ctm_zoomflag |= (Z_SCREEN << Z_YSHIFT);
439                 break;
440         case 1:
441                 ct->ctm_zoomflag = Z_NORMAL | (Z_NORMAL << Z_YSHIFT);
442                 break;
443         case 2:
444                 ct->ctm_zoomflag = Z_SCREEN0 | (Z_SCREEN0 << Z_YSHIFT);
445                 break;
446         }
447         chkfile(ct->ctm_fname);
448         return ct;
449 }
450
451 static struct ctrl *
452 gen_bar(color, thick, start, len)
453         char *color;
454         int thick;
455         int start;
456         int len;
457 {
458         struct ctrl *ct;
459
460         if (!(ct = ctlalloc1(CTL_BAR))) {
461                 yyerror("cannot allocate node (op=BAR)");
462                 return ct;
463         }
464         if (get_color(color, &ct->ctb_color) < 0)
465                 yyerror("cannot allocate color %s", color);
466         ct->ctb_width = thick;
467         ct->ctb_start = start;
468         ct->ctb_length = len;
469
470         /* normalize */
471         if (ct->ctb_width < 0)
472                 ct->ctb_width = 0;
473         else if (1000 < ct->ctb_width)
474                 ct->ctb_width = 1000;
475         if (ct->ctb_start < 0)
476                 ct->ctb_start = 0;
477         else if (100 < ct->ctb_start)
478                 ct->ctb_start = 100;
479         if (100 < ct->ctb_start + ct->ctb_length)
480                 ct->ctb_length = 100 - ct->ctb_start;
481
482         return ct;
483 }
484
485 static struct ctrl *
486 gen_icon(n, color, siz)
487         char *n;
488         char *color;
489         int siz;
490 {
491         struct ctrl *ct;
492
493         if (!(ct = ctlalloc1(CTL_ICON))) {
494                 yyerror("cannot allocate node (op=ICON)");
495                 return ct;
496         }
497         ct->ctic_value = n;
498         if (get_color(color, &ct->ctic_color) < 0)
499                 yyerror("cannot allocate color %s", color);
500         ct->ctic_size = siz;
501         return ct;
502 }
503
504 static struct ctrl *
505 gen_pcache(flag, mode, effect, value)
506         int     flag;
507         int     mode;
508         int     effect;
509         int     value;
510 {
511         struct ctrl *ct;
512
513         if (!(ct = ctlalloc1(CTL_PCACHE))) {
514                 yyerror("cannot allocate node (op=PCACHE)");
515                 return ct;
516         }
517         ct->ctch_flag = flag;
518         ct->ctch_mode = mode;
519         ct->ctch_effect = effect;
520         ct->ctch_value = value;
521
522         return ct;
523 }
524
525 static struct ctrl *
526 gen_valign(align)
527         char *align;
528 {
529         struct ctrl *ct;
530
531         if (!(ct = ctlalloc1(CTL_VALIGN))) {
532                 yyerror("cannot allocate node (op=VALIGN)");
533                 return ct;
534         }
535         if (!strcmp(align, "center"))
536                 ct->cti_value = VL_CENTER;
537         else {
538                 if (!strcmp(align, "top"))
539                         ct->cti_value = VL_TOP;
540                 else {
541                         if (!strcmp(align, "bottom"))
542                                 ct->cti_value = VL_BOTTOM;
543                         else {
544                                 yyerror("%valign center|top|bottom");
545                                 ctlfree(ct);
546                                 return NULL;
547                         }
548                 }
549         }
550         return ct;
551 }
552
553 static struct ctrl *
554 gen_area(width, height, xoff, yoff)
555         int width;
556         int height;
557         int xoff;
558         int yoff;
559 {
560         struct ctrl *ct;
561
562         if (!(ct = ctlalloc1(CTL_AREA))) {
563                 yyerror("cannot allocate node (op=AREA)");
564                 return ct;
565         }
566         if (width < 0 || width > 100)
567                 width = 100;
568         if (height < 0 || height > 100)
569                 height = 100;
570         if (xoff < 0)
571                 xoff = (100 - width) / 2;
572         else if (width + xoff > 100)
573                 xoff = 100 - width;
574         if (yoff < 0)
575                 yoff = (100 - height) / 2;
576 #ifdef notdef   /* mgp doesn't check overflow in y axis, anyway. */
577         else if (height + yoff > 100)
578                 yoff = 100 - height;
579 #endif
580         ct->ctar_width = width;
581         ct->ctar_height = height;
582         ct->ctar_xoff = xoff;
583         ct->ctar_yoff = yoff;
584         return ct;
585 }
586
587 static struct ctrl *
588 gen_argsfromstr(op, str, flag)
589         int op;
590         char *str;
591         int flag;
592 {
593         struct ctrl *ct;
594         int siz;
595         char **h;
596
597         if (!(ct = ctlalloc1(op))) {
598                 yyerror("cannot allocate args node");
599                 return ct;
600         }
601
602         ct->cta_argc = 0;
603         ct->cta_argv = malloc((siz = 16) * sizeof(char *));     /*initial siz*/
604         ct->cta_flag = flag;
605         if (!ct->cta_argv) {
606                 yyerror("cannot allocate args table");
607                 return ct;
608         }
609         for (h = (char **)ct->cta_argv;
610              (*h = strsep((char **)&str, " "));
611              /*none*/) {
612                 if (**h != '\0') {
613                         h++;
614                         ct->cta_argc++;
615                         if (siz < ct->cta_argc + 2) {
616                                 siz *= 2;
617                                 ct->cta_argv = realloc(ct->cta_argv,
618                                         siz * sizeof(char *));
619                                 if (!ct->cta_argv) {
620                                         yyerror("cannot allocate args table");
621                                         return ct;
622                                 }
623                         }
624                 }
625         }
626         ct->cta_argv[ct->cta_argc] = NULL;
627
628         return ct;
629 }
630
631 static void
632 check_xfont(seed, registry)
633         char *seed;
634         char *registry;
635 {
636         int hyphen;
637         char *p;
638
639         hyphen = 0;
640         for (p = seed; *p; p++) {
641                 if (*p == '-')
642                         hyphen++;
643         }
644         switch (hyphen) {
645         case 0:
646         case 1:
647         case 2:
648         case XLFD_HYPHEN:
649                 break;
650         default:
651                 yyerror("invalid XFONT seed <%s>", seed);
652                 break;
653         }
654
655         hyphen = 0;
656         for (p = registry; *p; p++) {
657                 if (*p == '-')
658                         hyphen++;
659         }
660         switch (hyphen) {
661         case 0:
662         case 1:
663                 break;
664         default:
665                 yyerror("invalid XFONT registry <%s>", registry);
666                 break;
667         }
668 }
669
670 %}
671
672 %union {
673         int i;
674         double d;
675         char *s;
676         struct ctrl *ct;
677 }
678
679 %token COMMA NUM DOUBLE ID STR WINSIZ
680 %token KW_NOOP KW_DEFAULT KW_TAB KW_SIZE KW_FORE KW_BACK KW_LEFT KW_CENTER
681 %token KW_RIGHT KW_SHRINK KW_LCUTIN KW_RCUTIN KW_CONT KW_NODEF KW_XFONT
682 %token KW_IMAGE KW_BIMAGE KW_PAGE KW_HGAP KW_VGAP KW_GAP KW_PAUSE
683 %token KW_PREFIX KW_AGAIN KW_CCOLOR KW_BAR KW_INCLUDE KW_BGRAD KW_TEXT
684 %token KW_LINESTART KW_LINEEND KW_MARK KW_SYSTEM KW_FILTER KW_ENDFILTER
685 %token KW_QUALITY KW_ICON KW_LEFTFILL KW_XSYSTEM KW_TSYSTEM
686 %token KW_DEFFONT KW_FONT KW_NEWIMAGE KW_PSFONT
687 %token KW_CHARSET KW_PCACHE KW_VALIGN KW_AREA
688 %token KW_OPAQUE KW_SUP KW_SUB KW_SETSUP KW_TITLE
689
690 %type <ct> toplevel
691 %type <ct> line defaultline tabline shellline deffontline
692 %type <ct> cmd defaultcmd tabcmd  deffontcmd
693 %type <ct> nid args arg
694 %type <i> NUM
695 %type <d> DOUBLE
696 %type <s> ID STR WINSIZ STRorID
697
698 %%
699 toplevel: line                  { root = $$; }
700         | defaultline           { root = $$; }
701         | tabline               { root = $$; }
702         | shellline             { root = $$; }
703         | deffontline           { root = $$; }
704         ;
705 line:     cmd                   { $$ = $1; }
706         | cmd COMMA line        { $$ = $1; $$->ct_next = $3; }
707         ;
708 defaultline: defaultcmd line    { $$ = $1; $$->ct_next = $2; }
709         ;
710 tabline: tabcmd line            { $$ = $1; $$->ct_next = $2; }
711         ;
712 deffontline: deffontcmd line    { $$ = $1; $$->ct_next = $2; }
713         ;
714 STRorID:  STR
715         | ID                    { yywarn("\"%s\" should be quoted", $1); }
716         ;
717 shellline:
718           KW_SYSTEM STR NUM     { $$ = gen_argsfromstr(CTL_SYSTEM, $2, $3); }
719         | KW_SYSTEM STR         { $$ = gen_argsfromstr(CTL_SYSTEM, $2, 0); }
720         | KW_XSYSTEM STR NUM    { $$ = gen_argsfromstr(CTL_XSYSTEM, $2, $3); }
721         | KW_XSYSTEM STR        { $$ = gen_argsfromstr(CTL_XSYSTEM, $2, 0); }
722         | KW_TSYSTEM STR NUM    { $$ = gen_argsfromstr(CTL_TSYSTEM, $2, $3); }
723         | KW_TSYSTEM STR        { $$ = gen_argsfromstr(CTL_TSYSTEM, $2, 0); }
724         | KW_FILTER STR         { $$ = gen_argsfromstr(CTL_FILTER, $2, 0); }
725         | KW_ENDFILTER          { $$ = gen_void(CTL_ENDFILTER); }
726         ;
727 nid:      STRorID       { $$ = gen_str(CTL_NOOP, $1); }
728         | STRorID nid   { $$ = gen_str(CTL_NOOP, $1); $$->ct_next = $2; }
729         ;
730 args:     arg           { $$ = $1; }
731         | arg args      { $$ = $1; $$->ct_next = $2; }
732         ;
733 arg:      STR           { $$ = gen_str(CTL_NOOP, $1); }
734         | ID            { $$ = gen_str(CTL_NOOP, $1); }
735         | NUM           { char buf[30];
736                           snprintf(buf, sizeof(buf), "%d", $1);
737                           $$ = gen_str(CTL_NOOP, buf);
738                         }
739         ;
740 cmd:      KW_NOOP       { $$ = gen_void(CTL_NOOP); }
741         | KW_LEFT       { $$ = gen_void(CTL_LEFT); }
742         | KW_LEFTFILL   { $$ = gen_void(CTL_LEFTFILL); }
743         | KW_RIGHT      { $$ = gen_void(CTL_RIGHT); }
744         | KW_CENTER     { $$ = gen_void(CTL_CENTER); }
745         | KW_SHRINK     { $$ = gen_void(CTL_SHRINK); }
746         | KW_LCUTIN     { $$ = gen_void(CTL_LCUTIN); }
747         | KW_RCUTIN     { $$ = gen_void(CTL_RCUTIN); }
748         | KW_CONT       { $$ = gen_void(CTL_CONT); }
749         | KW_NODEF      { $$ = gen_void(CTL_NODEF); }
750         | KW_PAUSE      { $$ = gen_int(CTL_PAUSE, 0); }
751         | KW_AGAIN      { $$ = gen_void(CTL_AGAIN); }
752         | KW_MARK       { $$ = gen_void(CTL_MARK); }
753         | KW_PAGE       { $$ = gen_void(CTL_PAGE); }
754         | KW_SETSUP NUM NUM NUM { $$ = gen_int3(CTL_SETSUP, $2, $3, $4); }
755         | KW_SUP        { $$ = gen_void(CTL_SUP); }
756         | KW_SUB        { $$ = gen_void(CTL_SUB); }
757         | KW_SIZE NUM   { $$ = gen_double_int(CTL_SIZE, $2); }
758         | KW_SIZE DOUBLE        { $$ = gen_double(CTL_SIZE, $2); }
759         | KW_HGAP NUM   { $$ = gen_int(CTL_HGAP, $2); }
760         | KW_VGAP NUM   { $$ = gen_int(CTL_VGAP, $2); }
761         | KW_GAP NUM    { $$ = gen_int(CTL_GAP, $2); }
762         | KW_QUALITY NUM
763                         { if (!quality_flag)
764                                 $$ = gen_int(CTL_QUALITY, $2);
765                           else
766                                 $$ = ctlalloc1(CTL_NOOP);
767                         }
768         | KW_FORE STRorID       { $$ = gen_color(CTL_FORE, $2); }
769         | KW_BACK STRorID       { $$ = gen_color(CTL_BACK, $2); }
770         | KW_CCOLOR STRorID     { $$ = gen_color(CTL_CCOLOR, $2); }
771         | KW_BGRAD NUM NUM NUM NUM NUM nid
772                         { $$ = gen_bgrad($2, $3, $4, $5, $6, $7); }
773         | KW_BGRAD NUM NUM NUM NUM NUM
774                         { $$ = gen_bgrad($2, $3, $4, $5, $6,
775                                 (struct ctrl *)NULL);
776                         }
777         | KW_BGRAD NUM NUM NUM NUM
778                         { $$ = gen_bgrad($2, $3, $4, $5, 1,
779                                 (struct ctrl *)NULL);
780                         }
781         | KW_BGRAD NUM NUM NUM
782                         { $$ = gen_bgrad($2, $3, $4, 0, 1,
783                                 (struct ctrl *)NULL);
784                         }
785         | KW_BGRAD NUM NUM
786                         { $$ = gen_bgrad($2, $3, DEFAULT_GRADCOLORS, 0, 1,
787                                         (struct ctrl *)NULL);
788                         }
789         | KW_BGRAD NUM  { $$ = gen_bgrad($2, 100, DEFAULT_GRADCOLORS, 0, 1,
790                                         (struct ctrl *)NULL);
791                         }
792         | KW_BGRAD      { $$ = gen_bgrad(100, 100, DEFAULT_GRADCOLORS, 0, 1,
793                                         (struct ctrl *)NULL);
794                         }
795         | KW_XFONT STRorID
796                         { char *p;
797                           if (strncmp($2, "medium", 6) == 0
798                            || strncmp($2, "bold", 4) == 0) {
799                                 /* for backward compatibility */
800                                 p = malloc(strlen($2) + 1 + 6);
801                                 sprintf(p, "times-%s", $2);
802                           } else
803                                 p = $2;
804                           check_xfont(p, "iso8859-1"); /* lexical check */
805                           $$ = gen_str2(CTL_XFONT2, p, "iso8859-1");
806                         }
807         | KW_XFONT STRorID STRorID
808                         { check_xfont($2, $3);  /* lexical check */
809                           $$ = gen_str2(CTL_XFONT2, $2, $3);
810                         }
811         | KW_BIMAGE STRorID     { $$ = gen_image(CTL_BIMAGE, $2, 0, 0, 0, 0); }
812         | KW_BIMAGE STRorID WINSIZ
813                         { int x, y;
814                           x = atoi($3); y = atoi(strchr($3, 'x') + 1);
815                           $$ = gen_image(CTL_BIMAGE, $2, 0, x, y, 2);
816                         }
817         | KW_PSFONT STRorID     {
818                                         $$ = gen_str2(CTL_PSFONT, $2, "iso8859-1");
819                                 }
820         | KW_INCLUDE STRorID    { $$ = gen_str(CTL_INCLUDE, $2); }
821         | KW_PREFIX ID  { char *p;
822                           $$ = gen_str(CTL_PREFIX, $2);
823                           for (p = $$->ctc_value; *p; p++) {
824                                 if (*p == '_') *p = ' ';
825                           }
826                         }
827         | KW_PREFIX STR { $$ = gen_str(CTL_PREFIX, $2); }
828         | KW_PREFIX NUM { $$ = gen_double_int(CTL_PREFIXN, $2); }
829         | KW_PREFIX DOUBLE      { $$ = gen_double(CTL_PREFIXN, $2); }
830         | KW_NEWIMAGE args
831                         { $$ = gen_newimage($2); }
832         | KW_IMAGE STRorID WINSIZ
833                         { int x, y;
834                           x = atoi($3); y = atoi(strchr($3, 'x') + 1);
835                           $$ = gen_image(CTL_IMAGE, $2, 0, x, y, 2);
836                         }
837         | KW_IMAGE STRorID NUM WINSIZ
838                         { int x, y;
839                           x = atoi($4); y = atoi(strchr($4, 'x') + 1);
840                           $$ = gen_image(CTL_IMAGE, $2, $3, x, y, 2);
841                         }
842         | KW_IMAGE STRorID NUM NUM NUM NUM
843                         { $$ = gen_image(CTL_IMAGE, $2, $3, $4, $5, $6 ? 1 : 0); }
844         | KW_IMAGE STRorID NUM NUM NUM
845                         { $$ = gen_image(CTL_IMAGE, $2, $3, $4, $5, 0); }
846         | KW_IMAGE STRorID NUM NUM
847                         { $$ = gen_image(CTL_IMAGE, $2, $3, $4, 0, 0); }
848         | KW_IMAGE STRorID NUM
849                         { $$ = gen_image(CTL_IMAGE, $2, $3, 0, 0, 0); }
850         | KW_IMAGE STRorID      { $$ = gen_image(CTL_IMAGE, $2, 0, 0, 0, 0); }
851         | KW_BAR STRorID NUM NUM NUM
852                         { $$ = gen_bar($2, $3, $4, $5); }
853         | KW_BAR STRorID NUM NUM
854                         { $$ = gen_bar($2, $3, $4, 100); }
855         | KW_BAR STRorID NUM    { $$ = gen_bar($2, $3, 0, 100); }
856         | KW_BAR STRorID        { $$ = gen_bar($2, 10, 0, 100); }
857         | KW_BAR        { $$ = gen_bar("black", 10, 0, 100); }
858         | KW_ICON STR STRorID NUM
859                         { $$ = gen_icon($2, $3, $4); }
860         | KW_ICON ID STRorID NUM
861                         { $$ = gen_icon($2, $3, $4); }
862         | KW_FONT STR   { $$ = gen_str(CTL_FONT, $2); }
863         | KW_TITLE STR  { $$ = gen_str(CTL_TITLE, $2); }
864         | KW_TEXT STR   { $$ = gen_str(CTL_TEXT, $2); } /*easter egg*/
865         | KW_CHARSET STR        { $$ = gen_str(CTL_CHARSET, $2); }
866         | KW_AREA NUM NUM { $$ = gen_area($2, $3, -1, -1); }
867         | KW_AREA NUM NUM NUM NUM { $$ = gen_area($2, $3, $4, $5); }
868         | KW_PCACHE NUM NUM NUM NUM
869                         { $$ = gen_pcache($2, $3, $4, $5); }
870         | KW_PCACHE NUM
871                         { $$ = gen_pcache($2, 0, 0, 0); }
872         | KW_VALIGN STRorID     {
873                         $$ = gen_valign($2);
874         }
875         | KW_OPAQUE NUM { $$ = gen_int(CTL_OPAQUE, $2); }
876         ;
877 tabcmd:   KW_TAB NUM    { $$ = gen_int(CTL_TAB, $2); }
878         | KW_TAB ID     { $$ = gen_str(CTL_TAB, $2); }
879         ;
880 defaultcmd: KW_DEFAULT NUM
881                         { $$ = gen_int(CTL_DEFAULT, $2); }
882         ;
883 deffontcmd: KW_DEFFONT STR
884                         { $$ = gen_str(CTL_DEFFONT, $2); }
885         ;
886 %%