magicpoint-1.10a.tar.gz (MirPorts)
[alioth/magicpoint.git] / parse.c
1 /*
2  * Copyright (C) 1997 and 1998 WIDE Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. Neither the name of the project nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 /*
29  * $Id: parse.c,v 1.93 2003/06/14 10:22:56 nishida Exp $
30  */
31
32 #include "mgp.h"
33 #ifdef HAVE_FCNTL_H
34 # include <fcntl.h>
35 #endif
36
37 static struct ctrl *parse_text __P((char *, u_int));
38 static void read_rc __P((FILE *, char *));
39 static void read_file __P((FILE *, char *, u_int *, u_int *, int));
40 static void secondpass __P((void));
41 static void thirdpass __P((void));
42 static void debug __P((void));
43 static int define_font __P((struct ctrl *));
44 static struct ctrl *find_font __P((char *));
45
46 /*image*/
47 extern int findImage __P((char *, char *));
48
49 /* lex/yacc variables */
50 extern int n_errors;
51 extern struct ctrl *root;
52 extern char *yyfilename;
53 extern int yylineno;
54 /* Prevent warning if -Wall.  */
55 #ifdef __GNUC__
56 extern void lex_init(u_char *);
57 extern int yyparse (void);
58 #endif
59
60 static int filterval = 0;
61
62 void
63 load_file(filename)
64         char *filename;
65 {
66         FILE *fp;
67         u_int page;
68         u_int line;
69         char rc[MAXPATHLEN];
70         char *dir;
71
72         page = 1;
73         line = 0;
74
75         dir = getenv("HOME");
76         if (dir) {
77                 snprintf(rc, sizeof(rc), "%s/%s", dir, RCFILE);
78                 fp = fopen(rc, "r");
79                 if (fp) {
80                         read_rc(fp, rc);
81                         fclose(fp);
82                 }
83         }
84
85         if ((fp = fopen(filename, "r")) == NULL) {
86                 fprintf(stderr, "can't open %s\n", filename);
87                 exit(-1);
88         }
89         read_file(fp, filename, &page, &line, 1);
90         fclose(fp);
91         secondpass();
92         thirdpass();
93         if (parse_debug)
94                 debug();
95 }
96
97 void
98 cleanup_file()
99 {
100         u_int line;
101         u_int page;
102
103         for (line = 0; line < MAXLINE; line ++) {
104                 if (default_control[line]) {
105                         ctlfree(default_control[line]);
106                         default_control[line] = NULL;
107                 }
108                 if (init_control[line]) {
109                         ctlfree(init_control[line]);
110                         init_control[line] = NULL;
111                 }
112         }
113         for (page = 0; page < MAXPAGE; page ++) {
114                 for (line = 0; line < MAXLINE; line ++) {
115                         if (!page_control[page][line])
116                                 continue;
117                         ctlfree(page_control[page][line]);
118                         page_control[page][line] = NULL;
119                 }
120                 memset(&page_attribute[page], 0, sizeof(page_attribute[page]));
121         }
122         for (line = 0; line < MAXTAB + MAXSTYLE; line++) {
123                 if (!tab_control[line])
124                         continue;
125                 ctlfree(tab_control[line]);
126                 tab_control[line] = NULL;
127         }
128         for (line = 0; line < MAXFONTDEF; line++) {
129                 if (!fontdef_control[line])
130                         continue;
131                 ctlfree(fontdef_control[line]);
132                 fontdef_control[line] = NULL;
133         }
134 }
135
136 static struct ctrl *
137 parse_text(p, page)
138         char *p;
139         u_int page;
140 {
141         struct ctrl sentinel;
142         struct ctrl *cp;
143
144         assert(p);
145
146         cp = &sentinel;
147
148         cp->ct_next = ctlalloc1(CTL_TEXT);
149         if (!cp->ct_next) {
150                 ctlfree(cp);
151                 return NULL;
152         }
153         cp = cp->ct_next;
154         cp->ct_page = page;
155         cp->ctc_value = strdup(p);
156
157         return sentinel.ct_next;
158 }
159
160 /*
161  * read ~/.mgprc: there's no percentage sign
162  */
163 static void
164 read_rc(fp, filename)
165         FILE *fp;
166         char *filename;
167 {
168         char buf[BUFSIZ];
169 #if 0
170         struct ctrl *cp;
171 #endif
172         int lineno;
173
174         if (2 <= parse_debug)
175                 fprintf(stderr, "read_rc(%s):\n", filename);
176
177         lineno = 0;
178         while (fgets(buf, sizeof(buf), fp) != NULL) {
179                 lineno++;
180                 if (buf[strlen(buf) - 1] == '\n')
181                         buf[strlen(buf) - 1] = '\0';
182                 if (buf[0] == '#' || !buf[0])
183                         continue;
184
185                 yyfilename = filename;
186                 yylineno = lineno;
187
188                 lex_init(buf);
189                 if (yyparse() || n_errors) {
190                         fprintf(stderr, "%s:%d: fatal syntax error detected\n",
191                                 filename, lineno);
192                         exit(-1);
193                 }
194
195                 if (!root) {
196                         fprintf(stderr, "%s:%d: something bad happened\n",
197                                 filename, lineno);
198                         exit(-1);
199                 }
200                 if (2 <= parse_debug) {
201                         fprintf(stderr, "%s:%d: %s\n", filename, lineno, buf);
202                         debug1(root);
203                 }
204
205                 switch (root->ct_op) {
206 #if 0
207                 case CTL_DEFFONT:
208                         /* safety check */
209                         for (cp = root; cp; cp = cp->ct_next) {
210                                 if (cp->ct_op == CTL_FONT) {
211                                         fprintf(stderr,
212 "%s:%d: %%font used in %%deffont, which is disallowed\n",
213                                                 filename, lineno);
214                                         exit(-1);
215                                 }
216                         }
217
218                         if (define_font(root) < 0) {
219                                 fprintf(stderr, "%s:%d: could not define "
220                                         "font \"%s\"\n", filename, lineno,
221                                         root->ctc_value);
222                                 exit(-1);
223                         }
224                         break;
225 #endif
226 #ifdef VFLIB
227                 case CTL_VFCAP:
228                         vfcap_name = root->ctc_value;
229                         break;
230 #endif
231 #ifdef FREETYPE
232                 case CTL_TFDIR:
233                         freetypefontdir = root->ctc_value;
234                         break;
235                 case CTL_TFONT0:
236                         freetypefont0 = root->ctc_value;
237                         break;
238                 case CTL_TMFONT0:
239                         freetypemfont0 = root->ctc_value;
240                         break;
241 #endif
242                 case CTL_NOOP:
243                         /* done in grammar.y */
244                         break;
245                 default:
246                         fprintf(stderr, "%s:%d: operator disallowed:\n\t",
247                                 filename, lineno);
248                         debug0(root);
249                         exit(-1);
250                 }
251         }
252 }
253
254 static void
255 read_file(fp, filename, page, line, preamble)
256         FILE *fp;
257         char *filename;
258         u_int *page;
259         u_int *line;
260         int preamble;
261 {
262         char buf[BUFSIZ];
263         char buf2[BUFSIZ];
264         struct ctrl **ch;
265         struct ctrl *cp;
266         struct ctrl *p;
267         int line_cont;
268         char *infilename;
269         struct ctrl *filtermode;
270         int filterfd = -1;
271         char filtername[MAXPATHLEN];
272         pid_t filterpid = -1;
273         void (*filtersig)() = (void (*)())NULL;
274         int lineno;
275         static char *searchpath[] = {
276                 "",     /*mgp_fname*/
277 #ifdef MGPLIBDIR
278                 MGPLIBDIR "/",
279 #endif
280                 NULL,
281         };
282
283         if (2 <= parse_debug)
284                 fprintf(stderr, "read_file(%s):\n", filename);
285
286         filtername[0] = '\0';
287         lineno = 0;
288
289         if (!preamble)
290                 goto page;
291
292         /*
293          * default analysis in preamble
294          */
295         while (fgets(buf, sizeof(buf), fp) != NULL) {
296                 lineno++;
297                 if (buf[strlen(buf) - 1] == '\n')
298                         buf[strlen(buf) - 1] = '\0';
299
300                 if (buf[0] == '#')
301                         continue;
302                 if (buf[0] != '%') {
303                         fprintf(stderr, "%s:%d: no text allowed in preamble; "
304                                 "ignored\n", filename, lineno);
305                         continue;
306                 }
307                 if (buf[1] == '%')
308                         continue;
309
310                 yyfilename = filename;
311                 yylineno = lineno;
312                 lex_init(buf + 1);
313                 if (yyparse() || n_errors) {
314                         fprintf(stderr, "%s:%d: fatal syntax error detected\n",
315                                 filename, lineno);
316                         exit(-1);
317                 }
318                 if (!root) {
319                         fprintf(stderr, "%s:%d: something bad happened\n",
320                                 filename, lineno);
321                         exit(-1);
322                 }
323                 if (2 <= parse_debug)
324                         debug1(root);
325
326                 switch (root->ct_op) {
327                 case CTL_PAGE:
328                         goto page;
329
330                 case CTL_INCLUDE:
331                     {
332                         FILE *infp;
333
334                         infilename = root->ctc_value;
335                         searchpath[0] = mgp_fname;
336                         infp = fsearchopen(infilename, "r", searchpath);
337                         if (infp == NULL) {
338                                 fprintf(stderr, "%s:%d: can't open "
339                                         "include file \"%s\"\n",
340                                         filename, lineno, infilename);
341                                 exit(-1);
342                         }
343                         read_file(infp, infilename, page, line, 1);
344                         fclose(infp);
345                         continue;
346                     }
347
348                 case CTL_DEFAULT:
349                         ch = &default_control[root->cti_value - 1];
350                         if (*ch)
351                                 ctlappend(*ch, root->ct_next);
352                         else
353                                 *ch = root->ct_next;
354                         break;
355
356                 case CTL_TAB:
357                     {
358                         int i = root->cti_value;
359                         if (i < 0) {
360                                 fprintf(stderr, "%s:%d: "
361                                         "invalid tab index %d\n",
362                                         filename, lineno, root->cti_value);
363                                 exit(-1);
364                         }
365                         if (i >= MAXTAB) {      /*XXX*/
366                                 /* must be a string */
367                                 /* find a free entry */
368                                 for (i = MAXTAB ; i < MAXTAB + MAXSTYLE ; i++) {
369                                         if (!tab_control[i])
370                                                 continue;
371                                         if (strcmp(tab_control[i]->ctc_value,
372                                                     root->ctc_value) == 0) {
373                                                 ctlfree(tab_control[i]);
374                                                 tab_control[i] = NULL;
375                                                 break;
376                                         }
377                                 }
378
379                                 for (i = MAXTAB ; i < MAXTAB + MAXSTYLE ; i++) {
380                                         if (!tab_control[i])
381                                                 break;
382                                 }
383                                 if (i == MAXTAB + MAXSTYLE) {
384                                         fprintf(stderr, "%s:%d: "
385                                                 "too many styles\n",
386                                                 filename, lineno);
387                                         exit(-1);
388                                 }
389                         }
390                         ch = &tab_control[i];
391                         if (*ch)
392                                 ctlappend(*ch, root->ct_next);
393                         else if (i < MAXTAB)
394                                 *ch = root->ct_next;
395                         else
396                                 *ch = root; /* keep name as well */
397                     }
398                         break;
399
400                 case CTL_DEFFONT:
401                         /* safety check */
402                         for (cp = root; cp; cp = cp->ct_next) {
403                                 if (cp->ct_op == CTL_FONT) {
404                                         fprintf(stderr,
405 "%s:%d: %%font used in %%deffont, which is disallowed\n",
406                                                 filename, lineno);
407                                         exit(-1);
408                                 }
409                         }
410
411                         if (define_font(root) < 0) {
412                                 fprintf(stderr, "%s:%d: could not define "
413                                         "font \"%s\"\n", filename, lineno,
414                                         root->ctc_value);
415                                 exit(-1);
416                         }
417                         break;
418
419                 default:
420                         fprintf(stderr, "%s:%d: invalid operator\n",
421                                 filename, lineno);
422                         exit(-1);
423                 }
424         }
425
426         /*
427          * page analysis
428          */
429 page:
430         line_cont = 0;
431         filtermode = NULL;
432 command:
433         while (fgets(buf, sizeof(buf), fp) != NULL) {
434                 lineno++;
435                 if (filtermode && strncmp(buf, "%endfilter", 10) != 0) {
436                         write(filterfd, buf, strlen(buf));
437                         continue;
438                 }
439             {
440                 char *p, *q;
441
442                 p = buf + strlen(buf);
443                 if (buf < p && p[-1] == '\n') {
444                         p--;
445                         *p = '\0'; 
446                 }
447                 while (buf < p && p - buf < sizeof(buf) && p[-1] == '\\') {
448                         p--;
449                         if (fgets(buf2, sizeof(buf) - (p - buf), fp) == NULL)
450                                 break;
451                         q = buf2;
452                         /* ignore blanks */
453                         while (*q && isspace(*q))
454                                 q++;
455                         strncpy(p, q, sizeof(buf) - (p - buf));
456                         p += strlen(p);
457                         if (buf < p && p[-1] == '\n') {
458                                 p--;
459                                 *p = '\0'; 
460                         }
461                 }
462             }
463                 if (buf[0] == '#')
464                         continue;
465 #if 1 /* escape # by backslash */
466                 if (buf[0] == 0x5c && (buf[1] == 0x5c || buf[1] == 0x23))
467                         memcpy(&buf[0], &buf[1], strlen(buf));
468 #endif
469                 if (buf[0] == '%') {
470                         /* this is directive */
471                         int pb;
472                         int ct;
473                         int prevfiltermode;
474
475                         if (buf[1] == '%')
476                                 continue;
477
478                         prevfiltermode = filtermode ? 1 : 0;
479
480                         yyfilename = filename;
481                         yylineno = lineno;
482                         lex_init(buf + 1);
483                         if (yyparse() || n_errors) {
484                                 fprintf(stderr,
485                                         "%s:%d: fatal syntax error detected\n",
486                                         filename, lineno);
487                                 exit(-1);
488                         }
489                         if (!root) {
490                                 fprintf(stderr,
491                                         "%s:%d: something bad happened\n",
492                                         filename, lineno);
493                                 exit(-1);
494                         }
495                         if (2 <= parse_debug)
496                                 debug1(root);
497
498                         cp = root;
499
500                         pb = ct = 0;
501                         for (p = cp; p; p = p->ct_next) {
502                                 switch (p->ct_op) {
503                                 case CTL_PAGE:
504                                         pb++;
505                                         break;
506                                 case CTL_NODEF:
507                                         page_attribute[*page].pg_flag
508                                                 |= PGFLAG_NODEF;
509                                         break;
510                                 case CTL_CONT:
511                                         ct++;
512                                         break;
513                                 case CTL_FILTER:
514                                         filtermode = p;
515                                         break;
516                                 case CTL_ENDFILTER:
517                                         filtermode = NULL;
518                                         break;
519                                 case CTL_EMBED:
520                                         embed_file(fp, p, &lineno);
521                                         goto command;
522                                 }
523                         }
524
525                         /* filter */
526                         if (!prevfiltermode && filtermode) {
527                                 int filtertmp;
528                                 int pipefd[2];
529
530                                 if (mgp_flag & FL_NOFORK) {
531                                         int i;
532                                         if (mgp_flag & FL_VERBOSE) {
533                                             fprintf(stderr, "%s:%d: %%filter ",
534                                                 filename, lineno);
535                                             for (i = 0; i < cp->cta_argc; i++) {
536                                                 fprintf(stderr, "%c%s",
537                                                     (i == 0) ? '"' : ' ',
538                                                     cp->cta_argv[i]);
539                                                 }
540                                                 fprintf(stderr, "\": "
541                                                     "directive skipped\n");
542                                         }
543                                         filterfd = open("/dev/null", O_WRONLY);
544                                         strcpy(filtername, "/dev/null");
545                                         continue;
546                                 }
547
548                                 sprintf(filtername, "/tmp/%d.%ld.%d",
549                                         getpid(), (long)time(NULL),
550                                         filterval++);
551                                 filtertmp = open(filtername, O_CREAT|O_WRONLY,
552                                         0644);
553                                 if (filtertmp < 0) {
554                                         fprintf(stderr,
555                                             "%s:%d: cannot open file tmp file "
556                                             "for filter\n", filename, lineno);
557                                         exit(-1);
558                                 }
559                                 if (pipe(pipefd) < 0) {
560                                         fprintf(stderr,
561                                             "%s:%d: cannot open pipe for "
562                                             "filter\n", filename, lineno);
563                                         exit(-1);
564                                 }
565
566                                 filterpid = fork();
567                                 if (filterpid < 0) {
568                                         perror("fork");
569                                         exit(1);
570                                 } else if (filterpid == 0) {
571                                         close(pipefd[1]);
572                                         close(STDIN_FILENO);
573                                         dup2(pipefd[0], STDIN_FILENO);
574                                         close(pipefd[0]);
575                                         close(STDOUT_FILENO);
576                                         dup2(filtertmp, STDOUT_FILENO);
577                                         close(STDERR_FILENO);
578                                         dup2(filtertmp, STDERR_FILENO);
579                                         close(filtertmp);
580                                         execvp(filtermode->cta_argv[0],
581                                                 (char **)filtermode->cta_argv);
582                                 } else {
583                                         close(filtertmp);
584                                         close(pipefd[0]);
585                                         filterfd = pipefd[1];
586                                         filtersig = signal(SIGCHLD, SIG_DFL);
587                                 }
588                                 continue;
589                         } else if (prevfiltermode && !filtermode
590                          && filtername[0]) {
591                                 FILE *filterfp;
592                                 int estat;
593
594                                 if (mgp_flag & FL_NOFORK) {
595                                         close(filterfd);
596                                         filtername[0] = '\0';
597                                         continue;
598                                 }
599
600                                 close(filterfd);
601                                 waitpid(filterpid, &estat, 0);
602                                 signal(SIGCHLD, filtersig);
603                                 filterfp = fopen(filtername, "r");
604                                 if (filterfp == NULL) {
605                                         fprintf(stderr, "%s:%d: cant read "
606                                                 "filter output\n",
607                                                 filename, lineno);
608                                         exit(-1);
609                                 }
610                                 read_file(filterfp, filtername, page, line, 0);
611                                 fclose(filterfp);
612                                 unlink(filtername);
613                                 filtername[0] = '\0';
614                                 continue;
615                         }
616
617                         if (pb) {
618                                 /* Seen pagebreak. */
619                                 page_attribute[*page].pg_linenum = *line;
620                                 *page = *page + 1;
621                                 *line = 0;
622                                 continue;
623                         }
624                         if (ct)
625                                 line_cont = 1;
626
627                         if (cp) {
628                                 /*
629                                  * append to the currently existing
630                                  * page struct.
631                                  */
632                                 ch = &page_control[*page][*line];
633
634 #if 0
635                                 if (!line_cont &&
636                                     (/* cp->ct_op == CTL_IMAGE || */
637                                      cp->ct_op == CTL_BAR)) {
638                                         struct ctrl *cp1;
639                                         cp1 = ctlalloc1(CTL_LINESTART);
640                                         if (cp1) {
641                                                 if (!*ch)
642                                                         *ch = cp1;
643                                                 else
644                                                         ctlappend(*ch, cp1);
645                                         }
646                                 }
647 #endif
648
649                                 if (!*ch)
650                                         *ch = cp;
651                                 else
652                                         ctlappend(*ch, cp);
653
654                                 /*
655                                  * special case: %image and %bar has to be
656                                  * treated as independent item
657                                  */
658                                 if (cp->ct_op == CTL_IMAGE
659                                  || cp->ct_op == CTL_ANIM
660                                  || cp->ct_op == CTL_BAR) {
661                                         line_cont = 0;
662                                         *line = *line + 1;
663                                 }
664                         }
665                 } else {
666                         /* this is data */
667                         cp = parse_text(buf, *page);
668                         if (cp) {
669                                 ch = &page_control[*page][*line];
670                                 if (!*ch)
671                                         *ch = cp;
672                                 else
673                                         ctlappend(*ch, cp);
674                         }
675                         line_cont = 0;
676
677                         *line = *line + 1;
678                 }
679         }
680
681         /* Treat as we've seen pagebreak.  See the above comment for detail. */
682         page_attribute[*page].pg_linenum = *line;
683 #if 0
684         *page = *page + 1;
685         *line = 0;
686 #endif
687
688         maxpage = *page;
689 }
690
691 /*
692  * rather simple rewrites.
693  */
694 static void
695 secondpass()
696 {
697         u_int page;
698         u_int l, text;
699         struct ctrl **ch;
700         struct ctrl *cp;
701         struct ctrl *cp1;
702
703         /*
704          * add CTL_PAUSE to the last line of a page.
705          * we don't add one at the last page, intentionally.
706          */
707         for (page = 1; page < maxpage; page++) {
708                 l = page_attribute[page].pg_linenum;
709
710                 ch = &page_control[page][l + 1];
711                 cp = ctlalloc1(CTL_PAUSE);
712                 if (cp) {
713                         cp->cti_value = 1;      /* 1 indicates page end */
714                         if (!*ch)
715                                 *ch = cp;
716                         else
717                                 ctlappend(*ch, cp);
718                 }
719                 page_attribute[page].pg_linenum++;
720         }
721
722         /*
723          * split GAP into VGAP and HGAP.
724          */
725         for (page = 1; page <= maxpage; page++) {
726                 text = 1;
727                 for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
728                         for (cp = page_control[page][l];
729                              cp;
730                              cp = cp->ct_next) {
731                                 if (cp->ct_op == CTL_GAP) {
732                                         cp->ct_op = CTL_VGAP;
733                                         cp1 = ctlalloc1(CTL_HGAP);
734                                         cp1->cti_value = cp->cti_value;
735                                         cp1->ct_next = cp->ct_next;
736                                         cp->ct_next = cp1->ct_next;
737                                 }
738
739                                 /*
740                                  * check if this page contains only texts
741                                  */
742                                 if (cp->ct_op == CTL_BIMAGE || cp->ct_op == CTL_BGRAD ||
743                                         cp->ct_op == CTL_IMAGE  || 
744 #ifdef MNG
745                                         cp->ct_op == CTL_ANIM   || 
746 #endif /* MNG */
747                                         (cp->ct_op == CTL_PAUSE 
748                                                 && l != page_attribute[page].pg_linenum)) {
749                                                 text = 0; 
750                                         }
751                                 }
752                 }
753                 page_attribute[page].pg_text = text;
754         }
755
756
757         /* CTL_PREFIX in tab_control should be CTL_TABPREFIX. */
758         for (l = 0; l < MAXTAB + MAXSTYLE; l++) {
759                 for (cp = tab_control[l]; cp; cp = cp->ct_next) {
760                         if (cp->ct_op == CTL_PREFIX)
761                                 cp->ct_op = CTL_TABPREFIX;
762                         if (cp->ct_op == CTL_PREFIXN)
763                                 cp->ct_op = CTL_TABPREFIXN;
764                 }
765         }
766 }
767
768 /*
769  * rather complex rewrites.  ordering is VERY important.
770  */
771 static void
772 thirdpass()
773 {
774         u_int page;
775         u_int line;
776         u_int l;
777         struct ctrl **ch;
778         struct ctrl *cp;
779         struct ctrl *cp1;
780         struct ctrl *cp2;
781         struct ctrl *cpt;
782         char *p;
783         struct ctrl *carryover[MAXPAGE];
784
785     {
786         /*
787          * there are several control items that are to be carried
788          * over to the next line.  make them explicit so that there'll
789          * be no bogus control items to be used when we go back a page.
790          */
791         struct ctrl *tmpstr[10];
792         struct ctrl *tmpint[10];
793         struct ctrl *tmplong[10];
794         struct ctrl *tmpvoid[10];
795         struct ctrl *tmparea[10];
796         struct ctrl sentinel;
797         int i;
798
799         memset(carryover, 0, sizeof(carryover));
800         memset(tmpstr, 0, sizeof(tmpstr));
801         memset(tmpint, 0, sizeof(tmpint));
802         memset(tmplong, 0, sizeof(tmplong));
803         memset(tmpvoid, 0, sizeof(tmpvoid));
804         memset(tmparea, 0, sizeof(tmparea));
805
806         /* default value for page 1 */
807         tmpstr[0] = ctlalloc1(CTL_PREFIX);
808         tmpstr[0]->ctc_value = strdup("");
809 #if defined(VFLIB) && defined(VFONT)
810         tmpstr[1] = ctlalloc1(CTL_VFONT);
811         tmpstr[1]->ctc_value = strdup(VFONT);           /*XXX*/
812 #else
813         tmpstr[1] = ctlalloc1(CTL_NOOP);
814         tmpstr[1]->ctc_value = strdup("");
815 #endif
816         tmpstr[2] = ctlalloc1(CTL_XFONT2);
817         tmpstr[2]->ctc2_value1 = strdup(DEFAULT_X_FONT);
818         tmpstr[2]->ctc2_value2 = strdup("iso8859-1");
819 #ifdef FREETYPE
820         tmpstr[3] = ctlalloc1(CTL_TFONT);
821         tmpstr[3]->ctc2_value1 = strdup(freetypefont0 ? freetypefont0 :"arial.ttf");
822         tmpstr[3]->ctc2_value2 = strdup("iso8859-1");
823 #else
824         tmpstr[3] = ctlalloc1(CTL_NOOP);        /* CTL_TFONT */
825         tmpstr[3]->ctc_value = strdup("");
826 #endif
827 #ifdef FREETYPE_CHARSET16
828         tmpstr[4] = ctlalloc1(CTL_TMFONT);      /* CTL_TMFONT */
829         tmpstr[4]->ctc_value = strdup("wadalab-gothic.ttf");
830 #else
831         tmpstr[4] = ctlalloc1(CTL_NOOP);        /* CTL_TMFONT */
832         tmpstr[4]->ctc_value = strdup("");
833 #endif
834         tmpstr[5] = ctlalloc1(CTL_XFONT2);
835         tmpstr[5]->ctc2_value1 = strdup("k14");
836         tmpstr[5]->ctc2_value2 = strdup("jisx0208.1983-*");
837         tmplong[0] = ctlalloc1(CTL_FORE);
838         get_color(DEFAULT_FORE, &tmplong[0]->ctl_value);
839         tmplong[1] = ctlalloc1(CTL_BACK);
840         get_color(DEFAULT_BACK, &tmplong[1]->ctl_value);
841         tmplong[2] = ctlalloc1(CTL_CCOLOR);
842         get_color(DEFAULT_FORE, &tmplong[2]->ctl_value);
843         tmpint[0] = ctlalloc1(CTL_SIZE);
844         tmpint[0]->ctf_value = DEFAULT_CHARSIZE;
845         tmpint[1] = ctlalloc1(CTL_HGAP);
846         tmpint[1]->cti_value = DEFAULT_HGAP;
847         tmpint[2] = ctlalloc1(CTL_VGAP);
848         tmpint[2]->cti_value = DEFAULT_VGAP;
849         tmpint[3] = ctlalloc1(CTL_QUALITY);
850         tmpint[3]->cti_value = DEFAULT_BQUALITY;
851 #ifdef XFT2
852         tmpint[4] = ctlalloc1(CTL_OPAQUE);
853         tmpint[4]->cti_value = DEFAULT_OPAQUE;
854 #endif
855         tmpvoid[0] = ctlalloc1(CTL_LEFT);
856         tmparea[0] = ctlalloc1(CTL_AREA);
857         tmparea[0]->ctar_width = 100;
858         tmparea[0]->ctar_height = 100;
859         tmparea[0]->ctar_xoff = 0;
860         tmparea[0]->ctar_yoff = 0;
861
862         /* for page 1 */
863         cp = &sentinel;
864         for (i = 0; i < 10; i++) {
865                 if (!tmpstr[i])
866                         continue;
867                 cp->ct_next = ctlalloc1(tmpstr[i]->ct_op);
868                 if (ctl_words[tmpstr[i]->ct_op].ctl_vtype == T_STR2) {
869                         if (tmpstr[i]->ctc2_value1) {
870                                 cp->ct_next->ctc2_value1 =
871                                         strdup(tmpstr[i]->ctc2_value1);
872                         } else
873                                 cp->ct_next->ctc2_value1 = NULL;
874                         if (tmpstr[i]->ctc2_value2) {
875                                 cp->ct_next->ctc2_value2 =
876                                         strdup(tmpstr[i]->ctc2_value2);
877                         } else
878                                 cp->ct_next->ctc2_value2 = NULL;
879                 } else {
880                         if (tmpstr[i]->ctc_value) {
881                                 cp->ct_next->ctc_value =
882                                         strdup(tmpstr[i]->ctc_value);
883                         } else
884                                 cp->ct_next->ctc_value = NULL;
885                 }
886                 cp = cp->ct_next;
887         }
888         for (i = 0; i < 10; i++) {
889                 if (!tmplong[i])
890                         continue;
891                 cp->ct_next = ctlalloc1(tmplong[i]->ct_op);
892                 cp->ct_next->ctl_value = tmplong[i]->ctl_value;
893                 cp = cp->ct_next;
894         }
895         for (i = 0; i < 10; i++) {
896                 if (!tmpint[i])
897                         continue;
898                 cp->ct_next = ctlalloc1(tmpint[i]->ct_op);
899                 cp->ct_next->ct_val = tmpint[i]->ct_val;
900                 cp = cp->ct_next;
901         }
902         for (i = 0; i < 10; i++) {
903                 if (!tmpvoid[i])
904                         continue;
905                 cp->ct_next = ctlalloc1(tmpvoid[i]->ct_op);
906                 cp = cp->ct_next;
907         }
908         for (i = 0; i < 10; i++) {
909                 if (!tmparea[i])
910                         continue;
911                 cp->ct_next = ctlalloc1(tmparea[i]->ct_op);
912                 cp->ct_next->ctar_width = tmparea[i]->ctar_width;
913                 cp->ct_next->ctar_height = tmparea[i]->ctar_height;
914                 cp->ct_next->ctar_xoff = tmparea[i]->ctar_xoff;
915                 cp->ct_next->ctar_yoff = tmparea[i]->ctar_yoff;
916                 cp = cp->ct_next;
917         }
918         carryover[0] = sentinel.ct_next;
919
920         /*
921          * parse through the pages, remember what kind of directives are there.
922          */
923         for (page = 1; page <= maxpage; page++) {
924                 for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
925                         for (cp = page_control[page][l];
926                              cp;
927                              cp = cp->ct_next) {
928                                 switch (cp->ct_op) {
929                                 case CTL_PREFIX: tmpstr[0] = cp; break;
930                                 case CTL_VFONT: tmpstr[1] = cp; break;
931                                 case CTL_TFONT: tmpstr[3] = cp; break;
932 #ifdef FREETYPE_CHARSET16
933                                 case CTL_TMFONT: tmpstr[4] = cp; break;
934 #endif
935                                 case CTL_XFONT2:
936                                         if (strcmp(cp->ctc2_value2,
937                                                         "iso8859-1") == 0) {
938                                                 tmpstr[2] = cp;
939                                                 break;
940                                         }
941                                     {
942                                         struct ctrl **cpe;      /*empty cp*/
943                                         cpe = (struct ctrl **)NULL;
944                                         for (i = 5; i < 10; i++) {
945                                             if (!tmpstr[i]) {
946                                                 if (!cpe)
947                                                     cpe = &tmpstr[i];
948                                                 continue;
949                                             }
950                                             if (strcmp(cp->ctc2_value2,
951                                                 tmpstr[i]->ctc2_value2) == 0) {
952                                                     tmpstr[i] = cp;
953                                                     goto xfont_ok;
954                                             }
955                                         }
956                                         if (cpe)
957                                             *cpe = cp;
958                                     xfont_ok:
959                                         break;
960                                     }
961
962                                 case CTL_FORE: tmplong[0] = cp; break;
963                                 case CTL_BACK: tmplong[1] = cp; break;
964                                 case CTL_CCOLOR: tmpint[2] = cp; break;
965
966                                 case CTL_SIZE: tmpint[0] = cp; break;
967                                 case CTL_HGAP: tmpint[1] = cp; break;
968                                 case CTL_VGAP: tmpint[2] = cp; break;
969                                 case CTL_QUALITY: tmpint[3] = cp; break;
970                                 case CTL_OPAQUE: tmpint[4] = cp; break;
971
972                                 case CTL_LEFT: tmpvoid[0] = cp; break;
973                                 case CTL_RIGHT: tmpvoid[0] = cp; break;
974                                 case CTL_CENTER: tmpvoid[0] = cp; break;
975                                 case CTL_LEFTFILL: tmpvoid[0] = cp; break;
976
977                                 case CTL_AREA: tmparea[0] = cp; break;
978                                 }
979                         }
980                 }
981
982                 cp = &sentinel;
983                 for (i = 0; i < 10; i++) {
984                         if (!tmpstr[i])
985                                 continue;
986                         cp->ct_next = ctlalloc1(tmpstr[i]->ct_op);
987                         if (ctl_words[tmpstr[i]->ct_op].ctl_vtype == T_STR2) {
988                                 if (tmpstr[i]->ctc2_value1) {
989                                         cp->ct_next->ctc2_value1 =
990                                                 strdup(tmpstr[i]->ctc2_value1);
991                                 } else
992                                         cp->ct_next->ctc2_value1 = NULL;
993                                 if (tmpstr[i]->ctc2_value2) {
994                                         cp->ct_next->ctc2_value2 =
995                                                 strdup(tmpstr[i]->ctc2_value2);
996                                 } else
997                                         cp->ct_next->ctc2_value2 = NULL;
998                         } else {
999                                 if (tmpstr[i]->ctc_value) {
1000                                         cp->ct_next->ctc_value =
1001                                                 strdup(tmpstr[i]->ctc_value);
1002                                 } else
1003                                         cp->ct_next->ctc_value = NULL;
1004                         }
1005                         cp = cp->ct_next;
1006                 }
1007                 for (i = 0; i < 10; i++) {
1008                         if (!tmplong[i])
1009                                 continue;
1010                         cp->ct_next = ctlalloc1(tmplong[i]->ct_op);
1011                         cp->ct_next->ctl_value = tmplong[i]->ctl_value;
1012                         cp = cp->ct_next;
1013                 }
1014                 for (i = 0; i < 10; i++) {
1015                         if (!tmpint[i])
1016                                 continue;
1017                         cp->ct_next = ctlalloc1(tmpint[i]->ct_op);
1018                         cp->ct_next->ct_val = tmpint[i]->ct_val;
1019                         cp = cp->ct_next;
1020                 }
1021                 for (i = 0; i < 10; i++) {
1022                         if (!tmpvoid[i])
1023                                 continue;
1024                         cp->ct_next = ctlalloc1(tmpvoid[i]->ct_op);
1025                         cp = cp->ct_next;
1026                 }
1027                 for (i = 0; i < 10; i++) {
1028                         if (!tmparea[i])
1029                                 continue;
1030                         cp->ct_next = ctlalloc1(tmparea[i]->ct_op);
1031                         cp->ct_next->ctar_width = tmparea[i]->ctar_width;
1032                         cp->ct_next->ctar_height = tmparea[i]->ctar_height;
1033                         cp->ct_next->ctar_xoff = tmparea[i]->ctar_xoff;
1034                         cp->ct_next->ctar_yoff = tmparea[i]->ctar_yoff;
1035                         cp = cp->ct_next;
1036                 }
1037
1038                 carryover[page] = sentinel.ct_next;
1039         }
1040     }
1041
1042         /* add default directives to each line */
1043         for (page = 1; page <= maxpage; page++) {
1044                 if (page_attribute[page].pg_flag & PGFLAG_NODEF)
1045                         continue;
1046                 line = page_attribute[page].pg_linenum;
1047                 for (l = 0; l <= line; l++) {
1048                         ch = &page_control[page][l];
1049                         if (default_control[l]) {
1050                                 ctlinsert(ch, ctlcopy(default_control[l]));
1051                         }
1052                 }
1053         }
1054
1055         /*
1056          * add carryover directives to each page.
1057          * default directive has priority over the carryover items,
1058          * so carryover items should appear earlier than default directive.
1059          */
1060         for (page = 1; page <= maxpage; page++) {
1061                 ch = &page_control[page][0];
1062                 if (carryover[page - 1])
1063                         ctlinsert(ch, carryover[page - 1]);
1064         }
1065
1066         /*
1067          * add CTL_LINEEND and CTL_LINESTART to each lines that contain
1068          * CTL_TEXT/CTL_IMAGE/CTL_BAR/CTL_ICON.
1069          * note that we must carefully handle CTL_CONT.
1070          */
1071     {
1072         int textseen;
1073         int contseen;
1074         for (page = 1; page <= maxpage; page++) {
1075                 line = page_attribute[page].pg_linenum;
1076                 for (l = 0; l <= line; l++) {
1077                         textseen = 0;
1078                         for (cp = page_control[page][l];
1079                              cp;
1080                              cp = cp->ct_next) {
1081                                 if (cp->ct_op == CTL_TEXT
1082                                  || cp->ct_op == CTL_IMAGE
1083                                  || cp->ct_op == CTL_BAR
1084 #ifdef MNG
1085                                  || cp->ct_op == CTL_ANIM
1086 #endif /* MNG */
1087                                  || cp->ct_op == CTL_ICON) {
1088                                         textseen++;
1089                                         break;
1090                                 }
1091                         }
1092
1093                         if (!textseen)
1094                                 continue;
1095
1096                         /*
1097                          * check if the line #l includes CONT directive.
1098                          * if it has, don't add LINESTART to the line #l.
1099                          */
1100                         contseen = 0;
1101                         for (cp = page_control[page][l];
1102                              cp;
1103                              cp = cp->ct_next) {
1104                                 if (cp->ct_op == CTL_CONT) {
1105                                         contseen++;
1106                                         break;
1107                                 }
1108                         }
1109                         if (!contseen) {
1110                                 cp = ctlalloc1(CTL_LINESTART);
1111                                 if (cp) {
1112                                     for (ch = &page_control[page][l];
1113                                          ch && *ch;
1114                                          ch = &((*ch)->ct_next)) {
1115                                         if ((*ch)->ct_op == CTL_TEXT
1116                                          || (*ch)->ct_op == CTL_IMAGE
1117                                          || (*ch)->ct_op == CTL_BAR
1118 #ifdef MNG
1119                                          || (*ch)->ct_op == CTL_ANIM
1120 #endif /* MNG */
1121                                          || (*ch)->ct_op == CTL_ICON) {
1122                                             break;
1123                                         }
1124                                     }
1125                                     ctlinsert(ch,  cp);
1126                                 }
1127                         }
1128
1129                         /*
1130                          * check if the line #(l+1) includes CONT directive.
1131                          * if it has, don't add LINEEND to the line #l.
1132                          */
1133                         contseen = 0;
1134                         if (l + 1 <= line) {
1135                                 for (cp = page_control[page][l + 1];
1136                                      cp;
1137                                      cp = cp->ct_next) {
1138                                         if (cp->ct_op == CTL_CONT) {
1139                                                 contseen++;
1140                                                 break;
1141                                         }
1142                                 }
1143                         }
1144                         if (!contseen) {
1145                                 cp2 = NULL;
1146                                 for (cp1 = page_control[page][l];
1147                                      cp1;
1148                                      cp1 = cp1->ct_next) {
1149                                         if (cp1->ct_op == CTL_TEXT
1150                                          || cp1->ct_op == CTL_IMAGE
1151                                          || cp1->ct_op == CTL_BAR
1152 #ifdef MNG
1153                                          || cp1->ct_op == CTL_ANIM
1154 #endif /* MNG */
1155                                          || cp1->ct_op == CTL_ICON) {
1156                                             cp2 = cp1;
1157                                         }
1158                                 }
1159                                 /* cp2 has the last TEXT/IMAGE/whatever */
1160                                 if (cp2) {
1161                                         cp = ctlalloc1(CTL_LINEEND);
1162                                         if (cp)
1163                                                 ctlinsert(&(cp2->ct_next),  cp);
1164                                 }
1165                         }
1166                 }
1167                 if (contseen){
1168                         /* we have extra cont in the last line */
1169                         for (cp2 = page_control[page][line-1];
1170                                 cp2->ct_next; cp2 = cp2->ct_next); 
1171                         cp = ctlalloc1(CTL_LINEEND);
1172                         if (cp) ctlinsert(&(cp2->ct_next),  cp);
1173                 }
1174         }
1175     }
1176
1177         /* insert CTL_TAB */
1178         for (page = 1; page <= maxpage; page++) {
1179                 line = page_attribute[page].pg_linenum;
1180                 for (l = 0; l <= line; l++) {
1181                         int tab_depth = 0;
1182                         /*
1183                          * if we don't have CTL_LINESTART, we don't add
1184                          * directives here.
1185                          */
1186                         cp = page_control[page][l];
1187                         while (cp && cp->ct_op != CTL_LINESTART)
1188                                 cp = cp->ct_next;
1189                         if (!cp)
1190                                 continue;
1191
1192                         /* cp2: CTL_LINESTART */
1193                         cp2 = cp1 = cp;
1194                         while (cp && cp->ct_op != CTL_TEXT) {
1195                                 cp1 = cp;
1196                                 cp = cp->ct_next;
1197                         }
1198                         if (!cp)
1199                                 continue;
1200                         if (cp1->ct_next != cp)
1201                                 continue;
1202                         p = cp->ctc_value;
1203                         if (p && *p == '\t') {
1204                                 p++;
1205                                 tab_depth++;
1206                                 while (*p == '\t') {
1207                                         tab_depth++;
1208                                         p++;
1209                                 }
1210                                 if (p) {
1211                                         char *tmp;
1212
1213                                         tmp = cp->ctc_value;
1214                                         p = cp->ctc_value = strdup(p);
1215                                         free(tmp);
1216                                 }
1217                         }
1218
1219 #if 0
1220                         /* insert CTL_TAB items into CTL_LINESTART */
1221                         if (tab_control[tab_depth]) {
1222                                 ctlinsert(&cp1->ct_next,
1223                                     ctlcopy(tab_control[tab_depth]));
1224                         }
1225 #else
1226                         if (tab_control[tab_depth]) {
1227                                 ch = &page_control[page][l];
1228                                 for (cpt = tab_control[tab_depth]; cpt; cpt = cpt->ct_next){
1229                                         /* Thses ctrl items should be in CTL_LINESTART */
1230                                         if (cpt->ct_op == CTL_IMAGE || cpt->ct_op == CTL_TABPREFIX ||
1231                                                         cpt->ct_op == CTL_ICON){
1232                                                 ctlinsert(&cp1->ct_next, ctlcopy1(cpt));
1233                                                 cp1 = cp1->ct_next; 
1234                                         } else
1235                                         /* other ctrl items should be in the head of the ctrls */
1236                                                 ctlinsert(ch, ctlcopy1(cpt));
1237                                 }
1238                         }
1239 #endif
1240
1241                         /* special: style escape */
1242                         if (p && *p == '&') {
1243                                 char *p0;
1244                                 char *tmp;
1245                                 int i;
1246
1247                                 p0 = p;
1248                                 while (*p && !isspace(*p))
1249                                         p++;
1250
1251                                 tmp = cp->ctc_value;
1252                                 if (!*p)
1253                                         cp->ctc_value = strdup(p);
1254                                 else {
1255                                         *p++ = '\0';
1256                                         while (*p && isspace(*p))
1257                                                 p++;
1258                                         cp->ctc_value = strdup(p);
1259                                 }
1260
1261                                 for (i = MAXTAB; i < MAXTAB + MAXSTYLE ; i++) {
1262                                         if (tab_control[i]
1263                                          && strcmp(p0 + 1, tab_control[i]->ctc_value) == 0)
1264                                                 break;
1265                                 }
1266                                 if (i == MAXTAB + MAXSTYLE) {
1267                                         fprintf(stderr, "style %s not found\n",
1268                                                 p0 + 1);
1269                                 } else {
1270                                         ctlinsert(&cp1->ct_next,
1271                                             ctlcopy(tab_control[i]->ct_next));
1272                                 }
1273                                 free(tmp);
1274                         }
1275                 }
1276         }
1277
1278         /* find where to put PREFIX. */
1279         for (page = 1; page <= maxpage; page++) {
1280                 line = page_attribute[page].pg_linenum;
1281                 for (l = 0; l <= line; l++) {
1282                         for (cp = page_control[page][l]; cp; cp = cp->ct_next) {
1283                                 if (cp->ct_op == CTL_LINESTART)
1284                                         break;
1285                         }
1286                         if (!cp)
1287                                 continue;
1288                         cp1 = cp;       /* cp1: CTL_LINESTART */
1289
1290                         for (cp = cp1; cp->ct_next; cp = cp->ct_next) {
1291                                 if (cp->ct_next->ct_op == CTL_TEXT
1292                                  || cp->ct_next->ct_op == CTL_IMAGE
1293 #ifdef MNG
1294                                  || cp->ct_next->ct_op == CTL_ANIM
1295 #endif /* MNG */
1296                                  || cp->ct_next->ct_op == CTL_ICON) {
1297                                         break;
1298                                 }
1299                         }
1300                         if (!cp)
1301                                 continue;
1302
1303                         cp2 = ctlalloc1(CTL_PREFIXPOS);
1304                         if (!cp2)
1305                                 continue;
1306
1307                         cp2->ct_next = cp->ct_next;
1308                         cp->ct_next = cp2;
1309                 }
1310         }
1311
1312         /*
1313          * CTL_FONT must be replaced with appropriate font def defined by
1314          * CTL_DEFFONT.
1315          */
1316         for (page = 1; page <= maxpage; page++) {
1317                 for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
1318                         for (cp = page_control[page][l];
1319                              cp;
1320                              cp = cp->ct_next) {
1321                                 if (cp->ct_op == CTL_FONT) {
1322                                         cp->ct_op = CTL_NOOP;
1323                                         cp1 = find_font(cp->ctc_value);
1324                                         if (!cp1) {
1325                                                 fprintf(stderr,
1326                         "page %d line %d: font def for \"%s\" not found: ignored\n",
1327                                                         page, l, cp->ctc_value);
1328                                                 continue;
1329                                         }
1330                                         ctlinsert(&cp->ct_next,
1331                                                 ctlcopy(cp1->ct_next));
1332                                 }
1333                         }
1334                 }
1335         }
1336
1337         /*
1338          * CTL_XFONT is now obsolete, use CTL_XFONT2.
1339          */
1340         for (page = 1; page <= maxpage; page++) {
1341                 for (l = 0; l <= page_attribute[page].pg_linenum; l++) {
1342                         for (cp = page_control[page][l];
1343                              cp;
1344                              cp = cp->ct_next) {
1345                                 if (cp->ct_op == CTL_XFONT) {
1346                                         p = cp->ctc_value;
1347                                         cp->ct_op = CTL_XFONT2;
1348                                         cp->ctc2_value1 = p;
1349                                         cp->ctc2_value2 = strdup("iso8859-1");
1350                                 }
1351                         }
1352                 }
1353         }
1354 }
1355
1356 void
1357 debug0(p)
1358         struct ctrl *p;
1359 {
1360         int i;
1361
1362         fprintf(stderr, "%p: ", p);
1363         fprintf(stderr, " %s ", ctl_words[p->ct_op].ctl_string);
1364
1365         switch (ctl_words[p->ct_op].ctl_vtype) {
1366         case T_STR:
1367                 fprintf(stderr, "\"%s\"", p->ctc_value);
1368                 break;
1369         case T_STR2:
1370                 fprintf(stderr, "\"%s\" \"%s\"",
1371                         p->ctc2_value1, p->ctc2_value2);
1372                 break;
1373         case T_INT:
1374                 fprintf(stderr, "%d", p->cti_value);
1375                 break;
1376         case T_LONG:
1377                 fprintf(stderr, "#%lx", p->ctl_value);
1378                 break;
1379         case T_DOUBLE:
1380                 fprintf(stderr, "#%g", p->ctf_value);
1381                 break;
1382         case T_VOID:
1383                 break;
1384         case T_SP:
1385                 break;
1386         default:
1387                 fprintf(stderr, "(UNDEFINED TYPE)");
1388         }
1389
1390         if (ctl_words[p->ct_op].ctl_vtype != T_SP)
1391                 goto done;
1392
1393         switch (p->ct_op) {
1394         case CTL_PAUSE:
1395                 fprintf(stderr, "(%s)",
1396                         p->cti_value ? "page end" : "normal");
1397                 break;
1398         case CTL_TAB:
1399                 if (p->cti_value > MAXTAB)
1400                         fprintf(stderr, "\"%s\"", p->ctc_value);
1401                 else
1402                         fprintf(stderr, "%d", p->cti_value);
1403                 break;
1404         case CTL_SYSTEM:
1405         case CTL_XSYSTEM:
1406         case CTL_FILTER:
1407                 fprintf(stderr, "argc=%d term=%s flag=%d",
1408                         p->cta_argc,
1409                         p->cta_argv[p->cta_argc] ? "bad" : "good",
1410                         p->cta_flag);
1411                 for (i = 0; i < p->cta_argc; i++)
1412                         fprintf(stderr, "%s ", p->cta_argv[i]);
1413                 break;
1414         case CTL_BAR:
1415                 fprintf(stderr, "color=#%lx width=%d start=%d length=%d",
1416                         p->ctb_color, p->ctb_width,
1417                         p->ctb_start, p->ctb_length);
1418                 break;
1419         case CTL_BIMAGE:
1420         case CTL_IMAGE:
1421                 fprintf(stderr, "file=%s colors=%d x=%d y=%d zoom=%d",
1422                         p->ctm_fname, p->ctm_numcolor,
1423                         p->ctm_ximagesize, p->ctm_yimagesize,
1424                         p->ctm_zoomflag);
1425                 break;
1426         case CTL_BGRAD:
1427                 fprintf(stderr, "w=%d h=%d nc=%d dir=%d zoom=%d colors=%d",
1428                         p->ctd_width, p->ctd_height,
1429                         p->ctd_numcolor, p->ctd_dir,
1430                         p->ctd_zoomflag, p->ctd_g_colors);
1431                 break;
1432         case CTL_ICON:
1433                 fprintf(stderr, "type=%s color=%x siz=%d",
1434                         p->ctic_value, (int)p->ctic_color, (int) p->ctic_size);
1435                 break;
1436         case CTL_VALIGN:
1437                 fprintf(stderr, ((p->cti_value == VL_CENTER) ? "center"
1438                                  : ((p->cti_value == VL_TOP) ? "top"
1439                                     : ((p->cti_value == VL_BOTTOM) ? "bottom"
1440                                        : "???"))));
1441                 break;
1442         case CTL_AREA:
1443                 fprintf(stderr, "xoff=%d w=%d yoff=%d h=%d",
1444                         p->ctar_xoff, p->ctar_width,
1445                         p->ctar_yoff, p->ctar_height);
1446                 break;
1447         default:
1448                 fprintf(stderr, "???");
1449         }
1450
1451 done:
1452         fprintf(stderr, "\n");
1453 }
1454
1455 void
1456 debug1(p)
1457         struct ctrl *p;
1458 {
1459         while (p) {
1460                 fprintf(stderr, "\t");
1461                 debug0(p);
1462                 p = p->ct_next;
1463         }
1464 }
1465
1466 static void
1467 debug()
1468 {
1469         int page, line;
1470
1471         for (line = 0; line < MAXLINE; line ++) {
1472                 if (!default_control[line])
1473                         continue;
1474                 fprintf(stderr, "def line %d:\n", line);
1475                 debug1(default_control[line]);
1476         }
1477         for (page = 0; page < MAXPAGE; page ++) {
1478                 for (line = 0; line < MAXLINE; line ++) {
1479                         if (!page_control[page][line])
1480                                 continue;
1481                         fprintf(stderr, "page %d line %d:\n", page, line);
1482                         debug1(page_control[page][line]);
1483                 }
1484         }
1485 }
1486
1487 int
1488 chkfile(p)
1489         char *p;
1490 {
1491         char buf[BUFSIZ];
1492
1493         buf[0] = '\0';
1494         if (findImage(p, buf) >= 0) {
1495                 if (parse_debug)
1496                         fprintf(stderr, "File %s found\n", p);
1497                 return 0;
1498         }
1499         fprintf(stderr, "File %s can not found\n", p);
1500         parse_error++;
1501         return -1;
1502 }
1503
1504 /*------------------------------------------------------------*/
1505
1506 struct ctrl *
1507 ctllastitem(this)
1508         struct ctrl *this;
1509 {
1510         struct ctrl *p;
1511
1512         assert(this);
1513         p = this;
1514         while (p && p->ct_next)
1515                 p = p->ct_next;
1516
1517         return p;
1518 }
1519
1520 void
1521 ctlappend(to, this)
1522         struct ctrl *to;
1523         struct ctrl *this;
1524 {
1525         struct ctrl *p;
1526
1527         assert(to);
1528         assert(this);
1529         p = ctllastitem(to);
1530         p->ct_next = this;
1531 }
1532
1533 void
1534 ctlinsert(here, this)
1535         struct ctrl **here;
1536         struct ctrl *this;
1537 {
1538         struct ctrl *p;
1539         struct ctrl *q;
1540
1541         assert(here); assert(this);
1542         p = *here;
1543         *here = this;
1544         q = ctllastitem(this);
1545         q->ct_next = p;
1546 }
1547
1548 struct ctrl *
1549 ctlalloc1(op)
1550         u_int op;
1551 {
1552         struct ctrl *p;
1553
1554         p = (struct ctrl *)malloc(sizeof(struct ctrl));
1555         if (!p) {
1556                 perror("malloc");
1557                 exit(-1);
1558         }
1559         memset(p, 0, sizeof(struct ctrl));
1560         p->ct_op = op;
1561         p->ct_next = NULL;      /*just to make sure*/
1562         return p;
1563 }
1564
1565 void
1566 ctlfree(this)
1567         struct ctrl *this;
1568 {
1569         struct ctrl *p;
1570         struct ctrl *q;
1571
1572         assert(this);
1573         p = this;
1574         do {
1575                 q = p->ct_next;
1576                 free(p);
1577                 p = q;
1578         } while (p);
1579 }
1580
1581 struct ctrl *
1582 ctlcopy(this)
1583         struct ctrl *this;
1584 {
1585         struct ctrl *dst0;
1586         struct ctrl *dst;
1587         struct ctrl *src;
1588
1589         src = this;
1590         if (!src)
1591                 return NULL;
1592         dst = dst0 = ctlalloc1(0);
1593         memcpy(dst, src, sizeof(struct ctrl));
1594         src = src->ct_next;
1595         while (src) {
1596                 dst->ct_next = ctlalloc1(0);
1597                 dst = dst->ct_next;
1598                 memcpy(dst, src, sizeof(struct ctrl));
1599                 src = src->ct_next;
1600         }
1601
1602         return dst0;
1603 }
1604
1605 struct ctrl *
1606 ctlcopy1(src)
1607         struct ctrl *src;
1608 {
1609         struct ctrl *dst;
1610         if (!src)
1611                 return NULL;
1612         dst = ctlalloc1(0);
1613         memcpy(dst, src, sizeof(struct ctrl));
1614         dst->ct_next = NULL;
1615         return dst;
1616 }
1617
1618 int
1619 ctlcmp(a, b)
1620         struct ctrl *a;
1621         struct ctrl *b;
1622 {
1623         int i;
1624
1625         assert(a);
1626         assert(b);
1627
1628         if (a->ct_op != b->ct_op)
1629                 return 1;
1630         if (a->ct_flag != b->ct_flag)
1631                 return 1;
1632
1633         switch (ctl_words[a->ct_op].ctl_vtype) {
1634         case T_STR:
1635                 return strcmp(a->ctc_value, b->ctc_value);
1636         case T_STR2:
1637                 if (strcmp(a->ctc2_value1, b->ctc2_value1) == 0
1638                  && strcmp(a->ctc2_value2, b->ctc2_value2) == 0) {
1639                         return 0;
1640                 } else
1641                         return 1;
1642         case T_INT:
1643                 return (a->cti_value == b->cti_value) ? 0 : 1;
1644         case T_LONG:
1645                 return (a->ctl_value == b->ctl_value) ? 0 : 1;
1646         case T_DOUBLE:
1647                 return (a->ctf_value == b->ctf_value) ? 0 : 1;
1648         case T_VOID:
1649                 return 0;
1650         case T_SP:
1651                 break;
1652         default:
1653                 fprintf(stderr, "UNDEFINED TYPE in ctlcmp()\n");
1654                 return 1;
1655         }
1656
1657         switch (a->ct_op) {
1658         case CTL_TAB:
1659         case CTL_PAUSE:
1660                 return (a->cti_value == b->cti_value) ? 0 : 1;
1661         case CTL_SYSTEM:
1662         case CTL_XSYSTEM:
1663         case CTL_FILTER:
1664                 return 1;
1665         case CTL_IMAGE:
1666         case CTL_BIMAGE:
1667                 if (a->ctm_numcolor == b->ctm_numcolor
1668                  && a->ctm_ximagesize == b->ctm_ximagesize
1669                  && a->ctm_yimagesize == b->ctm_yimagesize
1670                  && a->ctm_zoomflag == b->ctm_zoomflag)
1671                         return strcmp(a->ctm_fname, b->ctm_fname);
1672                 else
1673                         return 1;
1674         case CTL_BGRAD:
1675                 if (a->ctd_g_colors == b->ctd_g_colors
1676                  && a->ctd_numcolor == b->ctd_numcolor
1677                  && a->ctd_dir == b->ctd_dir
1678                  && a->ctd_width == b->ctd_width
1679                  && a->ctd_height == b->ctd_height
1680                  && a->ctd_zoomflag == b->ctd_zoomflag) {
1681                         for (i = 0; i < a->ctd_g_colors; i++) {
1682                                 if (memcmp(a->ctd_colors[0], b->ctd_colors[0],
1683                                                 sizeof(struct g_color)) != 0)
1684                                         return 1;
1685                         }
1686                         return 0;
1687                 } else
1688                         return 1;
1689         case CTL_BAR:
1690                 if (a->ctb_color == b->ctb_color
1691                  && a->ctb_width == b->ctb_width
1692                  && a->ctb_start == b->ctb_start
1693                  && a->ctb_length == b->ctb_length)
1694                         return 0;
1695                 else
1696                         return 1;
1697         case CTL_ICON:
1698                 if (strcmp(a->ctic_value, b->ctic_value) == 0
1699                  && a->ctic_color == b->ctic_color
1700                  && a->ctic_size == b->ctic_size)
1701                         return 0;
1702                 else
1703                         return 1;
1704         default:
1705                 assert(0);
1706         }
1707 }
1708
1709 FILE *
1710 fsearchopen(fname, mode, path)
1711         char *fname;
1712         char *mode;
1713         char **path;
1714 {
1715         FILE *fp;
1716         char buf[MAXPATHLEN];
1717         char *p;
1718         int i;
1719
1720         i = -1;
1721         fp = NULL;
1722         while (1) {
1723                 p = (i == -1) ? "" : path[i];
1724                 if (!p)
1725                         break;
1726                 strcpy(buf, p);
1727                 if ((p = strrchr(buf, '/'))) {
1728                         p[1] = '\0';
1729                 }
1730                 strcat(buf, fname);
1731                 fp = fopen(buf, mode);
1732                 if (fp)
1733                         break;
1734                 i++;
1735         }
1736         return fp;
1737 }
1738
1739 static int
1740 define_font(cp)
1741         struct ctrl *cp;
1742 {
1743         int i;
1744
1745         /* find duplicated def */
1746         for (i = 0; i < MAXFONTDEF; i++) {
1747                 if (!fontdef_control[i])
1748                         continue;
1749                 if (strcmp(fontdef_control[i]->ctc_value,
1750                                 cp->ctc_value) == 0) {
1751                         ctlfree(fontdef_control[i]);
1752                         fontdef_control[i] = NULL;
1753                         goto defineit;
1754                 }
1755         }
1756
1757         /* find empty def */
1758         for (i = 0; i < MAXFONTDEF; i++) {
1759                 if (!fontdef_control[i])
1760                         break;
1761         }
1762         if (i == MAXFONTDEF) {
1763                 return -1;
1764         }
1765
1766 defineit:
1767         /* define it */
1768         fontdef_control[i] = cp;
1769         return 0;
1770 }
1771
1772 static struct ctrl *
1773 find_font(font)
1774         char *font;
1775 {
1776         int i;
1777
1778         /* find duplicated def */
1779         for (i = 0; i < MAXFONTDEF; i++) {
1780                 if (!fontdef_control[i])
1781                         continue;
1782                 if (strcmp(fontdef_control[i]->ctc_value, font) == 0)
1783                         return fontdef_control[i];
1784         }
1785         return NULL;
1786 }