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