1 /* Copyright (c) 1987, 1989, 2012 University of Maryland Department of
2 Computer Science.
3
4 Permission is hereby granted, free of charge, to any person obtaining
5 a copy of this software and associated documentation files (the
6 "Software"), to deal in the Software without restriction, including
7 without limitation, the rights to use, copy, modify, merge, publish,
8 distribute, sublicense, and/or sell copies of the Software, and to
9 permit persons to whom the Software is furnished to do so, subject to
10 the following conditions: The above copyright notice, this permission
11 notice and the disclaimer statement shall be included in all copies
12 or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 /*
24 * DVI page rearrangement program
25 *
26 * Reads DVI version 2 files and rearranges pages into signatures,
27 * writing a new DVI file.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #ifdef KPATHSEA
35 #include <kpathsea/config.h>
36 #include <kpathsea/c-fopen.h>
37 #include <kpathsea/getopt.h>
38 #else
39 #define FOPEN_RBIN_MODE "rb"
40 #define FOPEN_WBIN_MODE "wb"
41 #define SET_BINARY(x) (void)0
42 extern char *optarg;
43 extern int optind;
44 #endif
45
46 #include "types.h"
47 #include "dviclass.h"
48 #include "dvicodes.h"
49 #include "error.h"
50 #include "fio.h"
51 #include "gripes.h"
52 #include "search.h"
53 #include <stdio.h>
54 #include <ctype.h>
55 #include "seek.h"
56
57 #define white(x) ((x) == ' ' || (x) == '\t' || (x) == ',')
58
59 #define MAXDVIPAGES 1000 /* max (absolute) pages in DVI file */
60
61 char *ProgName;
62
63 /* Globals */
64 char serrbuf[BUFSIZ]; /* buffer for stderr */
65
66 /*
67 * We will try to keep output lines shorter than MAXCOL characters.
68 */
69 #define MAXCOL 75
70
71 /*
72 * We use the following structure to keep track of fonts we have seen.
73 * The final DVI file lists only the fonts it uses.
74 */
75 struct fontinfo {
76 i32 fi_newindex; /* font number in output file */
77 int fi_reallyused; /* true => used on a page we copied */
78 i32 fi_checksum; /* the checksum */
79 i32 fi_mag; /* the magnification */
80 i32 fi_designsize; /* the design size */
81 short fi_n1; /* the name header length */
82 short fi_n2; /* the name body length */
83 char *fi_name; /* the name itself */
84 };
85
86 int Signature; /* #pages per signature (multiple of 4) */
87
88 int SFlag; /* true => -s, silent operation */
89
90 struct search *FontFinder; /* maps from input indicies to fontinfo */
91 i32 NextOutputFontIndex; /* generates output indicies */
92 i32 CurrentFontIndex; /* current (old) index in input */
93 i32 OutputFontIndex; /* current (new) index in ouput */
94
95 const char *DVIFileName; /* name of input DVI file */
96 FILE *inf; /* the input file itself */
97 FILE *outf; /* the output DVI file */
98
99 long StartOfPage[MAXDVIPAGES]; /* The file positions of the
100 input pages */
101
102 long StartOfLastPage; /* The file position just before we
103 started the last page */
104 long CurrentPosition; /* The current position of the file */
105
106 int UseThisPage; /* true => current page is selected */
107
108 i32 InputPageNumber; /* current absolute page in old DVI file */
109 int NumberOfOutputPages; /* number of pages in new DVI file */
110
111 i32 Numerator; /* numerator from DVI file */
112 i32 Denominator; /* denominator from DVI file */
113 i32 DVIMag; /* magnification from DVI file */
114
115 i32 Count[10]; /* the 10 \count variables */
116
117 /* save some string space: we use this a lot */
118 char writeerr[] = "error writing DVI file";
119
120 #ifndef KPATHSEA
121 char *malloc(), *realloc();
122 #endif
123 /*
124 * You may get lint warnings about sprintf's return value.
125 * Older versions of 4BSD have `char *sprintf()'. ANSI and
126 * SysV use `int sprintf()'; so ignore the warnings.
127 */
128
129 /*
130 * Lint gets somewhat confused over putc.
131 */
132 #ifdef lint
133 #undef putc
134 #ifdef ultrix /* grr */
135 #define putc(c, f) fputc((char)(c), f)
136 #else
137 #define putc(c, f) fputc((int)(c), f)
138 #endif
139 #endif
140
141 static void WriteFont(struct fontinfo *fi);
142 static void PutFontSelector(i32 index);
143 static void ScanDVIFile(void);
144 static void HandleDVIFile(void);
145 static int HandlePage(void);
146 static void PutEmptyPage(void);
147
148 /*
149 * Print a message to stderr, with an optional leading space, and handling
150 * long line wraps.
151 */
152 static void
message(int space,const char * str,int len)153 message(int space, const char *str, int len)
154 {
155 static int beenhere;
156 static int col;
157
158 if (!beenhere)
159 space = 0, beenhere++;
160 if (len == 0)
161 len = strlen(str);
162 col += len;
163 if (space) {
164 if (col >= MAXCOL)
165 (void) putc('\n', stderr), col = len;
166 else
167 (void) putc(' ', stderr), col++;
168 }
169 while (--len >= 0)
170 (void) putc(*str++, stderr);
171 (void) fflush(stderr);
172 }
173
174 /*
175 * Start a page (process a DVI_BOP).
176 */
177 static void
BeginPage(void)178 BeginPage(void)
179 {
180 register i32 *i;
181
182 OutputFontIndex = -1; /* new page requires respecifying font */
183 for (i = Count; i < &Count[10]; i++)
184 fGetLong(inf, *i);
185 (void) GetLong(inf); /* previous page pointer */
186
187 if (!UseThisPage)
188 return;
189
190 putbyte(outf, DVI_BOP);
191 for (i = Count; i < &Count[10]; i++)
192 PutLong(outf, *i);
193 PutLong(outf, StartOfLastPage);
194 if (ferror(outf))
195 error(1, -1, writeerr);
196
197 StartOfLastPage = CurrentPosition;
198 CurrentPosition += 45; /* we just wrote this much */
199
200 if (!SFlag) { /* write nice page usage messages */
201 register int z = 0;
202 register int mlen = 0;
203 char msg[80];
204
205 (void) sprintf(msg, "[%ld", (long)Count[0]);
206 mlen = strlen(msg);
207 for (i = &Count[1]; i < &Count[10]; i++) {
208 if (*i == 0) {
209 z++;
210 continue;
211 }
212 while (--z >= 0)
213 msg[mlen++] = '.', msg[mlen++] = '0';
214 z = 0;
215 (void) sprintf(msg + mlen, ".%ld", (long)*i);
216 mlen += strlen(msg + mlen);
217 }
218 message(1, msg, mlen);
219 }
220 }
221
222 /*
223 * End a page (process a DVI_EOP).
224 */
225 static void
EndPage(void)226 EndPage(void)
227 {
228
229 if (!UseThisPage)
230 return;
231 if (!SFlag)
232 message(0, "]", 1);
233 putbyte(outf, DVI_EOP);
234 if (ferror(outf))
235 error(1, -1, writeerr);
236 CurrentPosition++;
237 NumberOfOutputPages++;
238 }
239
240 /*
241 * For each of the fonts used in the new DVI file, write out a definition.
242 */
243 /* ARGSUSED */
244 static void
PostAmbleFontEnumerator(char * addr,i32 key)245 PostAmbleFontEnumerator(char *addr, i32 key)
246 {
247
248 if (((struct fontinfo *)addr)->fi_reallyused)
249 WriteFont((struct fontinfo *)addr);
250 }
251
252 static void
HandlePostAmble(void)253 HandlePostAmble(void)
254 {
255 register i32 c;
256
257 (void) GetLong(inf); /* previous page pointer */
258 if (GetLong(inf) != Numerator)
259 GripeMismatchedValue("numerator");
260 if (GetLong(inf) != Denominator)
261 GripeMismatchedValue("denominator");
262 if (GetLong(inf) != DVIMag)
263 GripeMismatchedValue("\\magnification");
264
265 putbyte(outf, DVI_POST);
266 PutLong(outf, StartOfLastPage);
267 PutLong(outf, Numerator);
268 PutLong(outf, Denominator);
269 PutLong(outf, DVIMag);
270 c = GetLong(inf);
271 PutLong(outf, c); /* tallest page height */
272 c = GetLong(inf);
273 PutLong(outf, c); /* widest page width */
274 c = GetWord(inf);
275 PutWord(outf, c); /* DVI stack size */
276 PutWord(outf, NumberOfOutputPages);
277 StartOfLastPage = CurrentPosition; /* point at post */
278 CurrentPosition += 29; /* count all those `put's */
279 #ifdef notdef
280 (void) GetWord(inf); /* skip original number of pages */
281 #endif
282
283 /*
284 * just ignore all the incoming font definitions; we are done with
285 * input file
286 */
287
288 /*
289 * run through the FontFinder table and dump definitions for the
290 * fonts we have used.
291 */
292 SEnumerate(FontFinder, PostAmbleFontEnumerator);
293
294 putbyte(outf, DVI_POSTPOST);
295 PutLong(outf, StartOfLastPage); /* actually start of postamble */
296 putbyte(outf, DVI_VERSION);
297 putbyte(outf, DVI_FILLER);
298 putbyte(outf, DVI_FILLER);
299 putbyte(outf, DVI_FILLER);
300 putbyte(outf, DVI_FILLER);
301 CurrentPosition += 10;
302 while (CurrentPosition & 3) {
303 putbyte(outf, DVI_FILLER);
304 CurrentPosition++;
305 }
306 if (ferror(outf))
307 error(1, -1, writeerr);
308 }
309
310 /*
311 * Write a font definition to the output file
312 */
313 static void
WriteFont(struct fontinfo * fi)314 WriteFont(struct fontinfo *fi)
315 {
316 register int l;
317 register char *s;
318
319 if (fi->fi_newindex < 256) {
320 putbyte(outf, DVI_FNTDEF1);
321 putbyte(outf, fi->fi_newindex);
322 CurrentPosition += 2;
323 } else if (fi->fi_newindex < 65536) {
324 putbyte(outf, DVI_FNTDEF2);
325 PutWord(outf, fi->fi_newindex);
326 CurrentPosition += 3;
327 } else if (fi->fi_newindex < 16777216) {
328 putbyte(outf, DVI_FNTDEF3);
329 Put3Byte(outf, fi->fi_newindex);
330 CurrentPosition += 4;
331 } else {
332 putbyte(outf, DVI_FNTDEF4);
333 PutLong(outf, fi->fi_newindex);
334 CurrentPosition += 5;
335 }
336 PutLong(outf, fi->fi_checksum);
337 PutLong(outf, fi->fi_mag);
338 PutLong(outf, fi->fi_designsize);
339 putbyte(outf, fi->fi_n1);
340 putbyte(outf, fi->fi_n2);
341 l = fi->fi_n1 + fi->fi_n2;
342 CurrentPosition += 14 + l;
343 s = fi->fi_name;
344 while (--l >= 0)
345 putbyte(outf, *s++);
346 }
347
348 /*
349 * Handle the preamble. Someday we should update the comment field.
350 */
351 static void
HandlePreAmble(void)352 HandlePreAmble(void)
353 {
354 register int n, c;
355
356 c = getc(inf);
357 if (c == EOF)
358 GripeUnexpectedDVIEOF();
359 if (c != DVI_PRE)
360 GripeMissingOp("PRE");
361 if (getc(inf) != DVI_VERSION)
362 error(1, 0, "%s is not a DVI version %d file",
363 DVIFileName, DVI_VERSION);
364 Numerator = GetLong(inf);
365 Denominator = GetLong(inf);
366 DVIMag = GetLong(inf);
367 putbyte(outf, DVI_PRE);
368 putbyte(outf, DVI_VERSION);
369 PutLong(outf, Numerator);
370 PutLong(outf, Denominator);
371 PutLong(outf, DVIMag);
372
373 n = UnSign8(GetByte(inf));
374 CurrentPosition = 15 + n; /* well, almost */
375 putbyte(outf, n);
376 while (--n >= 0) {
377 c = GetByte(inf);
378 putbyte(outf, c);
379 }
380 }
381
382 int
main(int argc,char ** argv)383 main(int argc, char **argv)
384 {
385 register int c;
386 register char *s;
387 char *outname = NULL;
388
389 Signature = 0;
390
391 ProgName = *argv;
392 setbuf(stderr, serrbuf);
393
394 while ((c = getopt(argc, argv, "i:o:s:q")) != EOF) {
395 switch (c) {
396
397 case 'q': /* silent */
398 SFlag++;
399 break;
400
401 case 'i':
402 if (DVIFileName != NULL)
403 goto usage;
404 DVIFileName = optarg;
405 break;
406
407 case 'o':
408 if (outname != NULL)
409 goto usage;
410 outname = optarg;
411 break;
412
413 case 's':
414 if (Signature != 0)
415 goto usage;
416 Signature = atoi(optarg);
417 if (Signature <= 0)
418 error(1, -1, "-s parameter must be > 0");
419 if (Signature % 4 != 0)
420 error(1, -1,
421 "-s parameter must be a multiple of 4");
422 break;
423
424 case '?':
425 usage:
426 (void) fprintf(stderr, "\
427 Usage: %s [-s signature] [-q] [-i infile] [-o outfile] [infile [outfile]]\n",
428 ProgName);
429 (void) fflush(stderr);
430 exit(1);
431 }
432 }
433
434 while (optind < argc) {
435 s = argv[optind++];
436 c = *s;
437 if (DVIFileName == NULL)
438 DVIFileName = s;
439 else if (outname == NULL)
440 outname = s;
441 else
442 goto usage;
443 }
444 if (DVIFileName == NULL) {
445 DVIFileName = "`stdin'";
446 inf = stdin;
447 if (!isatty(fileno(inf)))
448 SET_BINARY(fileno(inf));
449 } else if ((inf = fopen(DVIFileName, FOPEN_RBIN_MODE)) == 0)
450 error(1, -1, "cannot read %s", DVIFileName);
451 if (outname == NULL) {
452 outf = stdout;
453 if (!isatty(fileno(outf)))
454 SET_BINARY(fileno(outf));
455 }
456 else if ((outf = fopen(outname, FOPEN_WBIN_MODE)) == 0)
457 error(1, -1, "cannot write %s", outname);
458
459 if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
460 error(1, 0, "cannot create font finder (out of memory?)");
461
462 /* copy inf to TEMP file if not seekable */
463 if ((inf = SeekFile(inf)) == NULL) {
464 error(1, 0, "can't seek file");
465 }
466 InputPageNumber = 0;
467 StartOfLastPage = -1;
468 HandlePreAmble();
469 ScanDVIFile();
470 HandleDVIFile();
471 HandlePostAmble();
472 if (!SFlag)
473 (void) fprintf(stderr, "\nWrote %d page%s, %ld bytes\n",
474 NumberOfOutputPages, NumberOfOutputPages == 1 ? "" : "s",
475 (long)CurrentPosition);
476 return 0;
477 }
478
479 /*
480 * Handle a font definition.
481 */
482 static void
HandleFontDef(i32 index)483 HandleFontDef(i32 index)
484 {
485 register struct fontinfo *fi;
486 register int i;
487 register char *s;
488 int def = S_CREATE | S_EXCL;
489
490 if (!UseThisPage) {
491 if ((fi = (struct fontinfo *)SSearch(FontFinder, index, &def)) == 0) {
492 if (def & S_COLL)
493 error(1, 0, "font %ld already defined", (long)index);
494 else
495 error(1, 0, "cannot stash font %ld (out of memory?)",
496 (long)index);
497 }
498 fi->fi_reallyused = 0;
499 fi->fi_checksum = GetLong(inf);
500 fi->fi_mag = GetLong(inf);
501 fi->fi_designsize = GetLong(inf);
502 fi->fi_n1 = UnSign8(GetByte(inf));
503 fi->fi_n2 = UnSign8(GetByte(inf));
504 i = fi->fi_n1 + fi->fi_n2;
505 if ((s = malloc((unsigned)i)) == 0)
506 GripeOutOfMemory(i, "font name");
507 fi->fi_name = s;
508 while (--i >= 0)
509 *s++ = GetByte(inf);
510 } else {
511 (void) GetLong(inf);
512 (void) GetLong(inf);
513 (void) GetLong(inf);
514 i = UnSign8(GetByte(inf));
515 i += UnSign8(GetByte(inf));
516 while (--i >= 0)
517 (void) GetByte(inf);
518 }
519 }
520
521 /*
522 * Handle a \special.
523 */
524 static void
HandleSpecial(int c,int l,i32 p)525 HandleSpecial(int c, int l, i32 p)
526 {
527 register int i;
528
529 if (UseThisPage) {
530 putbyte(outf, c);
531 switch (l) {
532
533 case DPL_UNS1:
534 putbyte(outf, p);
535 CurrentPosition += 2;
536 break;
537
538 case DPL_UNS2:
539 PutWord(outf, p);
540 CurrentPosition += 3;
541 break;
542
543 case DPL_UNS3:
544 Put3Byte(outf, p);
545 CurrentPosition += 4;
546 break;
547
548 case DPL_SGN4:
549 PutLong(outf, p);
550 CurrentPosition += 5;
551 break;
552
553 default:
554 panic("HandleSpecial l=%d", l);
555 /* NOTREACHED */
556 }
557 CurrentPosition += p;
558 while (--p >= 0) {
559 i = getc(inf);
560 putbyte(outf, i);
561 }
562 if (feof(inf))
563 GripeUnexpectedDVIEOF();
564 if (ferror(outf))
565 error(1, -1, writeerr);
566 } else
567 while (--p >= 0)
568 (void) getc(inf);
569 }
570
571 static void
ReallyUseFont(void)572 ReallyUseFont(void)
573 {
574 register struct fontinfo *fi;
575 int look = S_LOOKUP;
576
577 fi = (struct fontinfo *)SSearch(FontFinder, CurrentFontIndex, &look);
578 if (fi == NULL)
579 error(1, 0, "DVI file requested font %ld without defining it",
580 (long)CurrentFontIndex);
581 if (fi->fi_reallyused == 0) {
582 fi->fi_reallyused++;
583 fi->fi_newindex = NextOutputFontIndex++;
584 WriteFont(fi);
585 }
586 if (fi->fi_newindex != OutputFontIndex) {
587 PutFontSelector(fi->fi_newindex);
588 OutputFontIndex = fi->fi_newindex;
589 }
590 }
591
592 /*
593 * Write a font selection command to the output file
594 */
595 static void
PutFontSelector(i32 index)596 PutFontSelector(i32 index)
597 {
598
599 if (index < 64) {
600 putbyte(outf, index + DVI_FNTNUM0);
601 CurrentPosition++;
602 } else if (index < 256) {
603 putbyte(outf, DVI_FNT1);
604 putbyte(outf, index);
605 CurrentPosition += 2;
606 } else if (index < 65536) {
607 putbyte(outf, DVI_FNT2);
608 PutWord(outf, index);
609 CurrentPosition += 3;
610 } else if (index < 16777216) {
611 putbyte(outf, DVI_FNT3);
612 Put3Byte(outf, index);
613 CurrentPosition += 4;
614 } else {
615 putbyte(outf, DVI_FNT4);
616 PutLong(outf, index);
617 CurrentPosition += 5;
618 }
619 }
620
621 /*
622 * The following table describes the length (in bytes) of each of the DVI
623 * commands that we can simply copy, starting with DVI_SET1 (128).
624 */
625 char oplen[128] = {
626 0, 0, 0, 0, /* DVI_SET1 .. DVI_SET4 */
627 9, /* DVI_SETRULE */
628 0, 0, 0, 0, /* DVI_PUT1 .. DVI_PUT4 */
629 9, /* DVI_PUTRULE */
630 1, /* DVI_NOP */
631 0, /* DVI_BOP */
632 0, /* DVI_EOP */
633 1, /* DVI_PUSH */
634 1, /* DVI_POP */
635 2, 3, 4, 5, /* DVI_RIGHT1 .. DVI_RIGHT4 */
636 1, /* DVI_W0 */
637 2, 3, 4, 5, /* DVI_W1 .. DVI_W4 */
638 1, /* DVI_X0 */
639 2, 3, 4, 5, /* DVI_X1 .. DVI_X4 */
640 2, 3, 4, 5, /* DVI_DOWN1 .. DVI_DOWN4 */
641 1, /* DVI_Y0 */
642 2, 3, 4, 5, /* DVI_Y1 .. DVI_Y4 */
643 1, /* DVI_Z0 */
644 2, 3, 4, 5, /* DVI_Z1 .. DVI_Z4 */
645 0, /* DVI_FNTNUM0 (171) */
646 0, 0, 0, 0, 0, 0, 0, 0, /* 172 .. 179 */
647 0, 0, 0, 0, 0, 0, 0, 0, /* 180 .. 187 */
648 0, 0, 0, 0, 0, 0, 0, 0, /* 188 .. 195 */
649 0, 0, 0, 0, 0, 0, 0, 0, /* 196 .. 203 */
650 0, 0, 0, 0, 0, 0, 0, 0, /* 204 .. 211 */
651 0, 0, 0, 0, 0, 0, 0, 0, /* 212 .. 219 */
652 0, 0, 0, 0, 0, 0, 0, 0, /* 220 .. 227 */
653 0, 0, 0, 0, 0, 0, 0, /* 228 .. 234 */
654 0, 0, 0, 0, /* DVI_FNT1 .. DVI_FNT4 */
655 0, 0, 0, 0, /* DVI_XXX1 .. DVI_XXX4 */
656 0, 0, 0, 0, /* DVI_FNTDEF1 .. DVI_FNTDEF4 */
657 0, /* DVI_PRE */
658 0, /* DVI_POST */
659 0, /* DVI_POSTPOST */
660 0, 0, 0, 0, 0, 0, /* 250 .. 255 */
661 };
662
663 /*
664 * Here we scan the input DVI file and record pointers to the pages.
665 */
666 static void
ScanDVIFile(void)667 ScanDVIFile(void)
668 {
669 UseThisPage = 0;
670
671 StartOfPage[InputPageNumber] = ftell(inf);
672 while (HandlePage()) { /* scan DVI file */
673 StartOfPage[++InputPageNumber] = ftell(inf);
674 }
675 }
676
677 /*
678 * Here we read the input DVI file and write relevant pages to the
679 * output DVI file. We also keep track of font changes, handle font
680 * definitions, and perform some other housekeeping.
681 */
682 static void
HandleDVIFile(void)683 HandleDVIFile(void)
684 {
685 int CurrentPage, ActualPage, MaxPage;
686
687 UseThisPage = 1;
688
689 MaxPage = InputPageNumber + (4-InputPageNumber%4)%4;
690
691 if (!Signature)
692 Signature = MaxPage;
693 for (CurrentPage = 0; CurrentPage < MaxPage; CurrentPage++) {
694 ActualPage = CurrentPage - CurrentPage%Signature;
695 switch (CurrentPage%4) {
696 case 0:
697 case 3:
698 ActualPage += Signature-1-(CurrentPage%Signature)/2;
699 break;
700 case 1:
701 case 2:
702 ActualPage += (CurrentPage%Signature)/2;
703 break;
704 }
705 if (ActualPage < InputPageNumber) {
706 if (fseek(inf, StartOfPage[ActualPage], 0) == -1)
707 error(1, -1,
708 "can't seek page %d", ActualPage+1);
709 HandlePage();
710 } else
711 PutEmptyPage();
712 }
713 if (fseek(inf, StartOfPage[InputPageNumber]+1, 0) == -1)
714 error(1, -1, "can't seek last page");
715 }
716
717 static int
HandlePage(void)718 HandlePage(void)
719 {
720 register int c, l;
721 register i32 p = 0; /* avoid uninitialized warning */
722 register int CurrentFontOK = 0;
723 int doingpage = 0;
724
725 /* Only way out is via "return" statement */
726 for (;;) {
727 c = getc(inf); /* getc() returns unsigned values */
728 if (DVI_IsChar(c)) {
729 /*
730 * Copy chars, note font usage, but ignore if
731 * page is not interesting.
732 */
733 if (!UseThisPage)
734 continue;
735 if (!CurrentFontOK) {
736 ReallyUseFont();
737 CurrentFontOK++;
738 }
739 putbyte(outf, c);
740 CurrentPosition++;
741 continue;
742 }
743 if (DVI_IsFont(c)) { /* note font change */
744 CurrentFontIndex = c - DVI_FNTNUM0;
745 CurrentFontOK = 0;
746 continue;
747 }
748 if (c == EOF)
749 GripeUnexpectedDVIEOF();
750 if ((l = (oplen - 128)[c]) != 0) { /* simple copy */
751 if (!UseThisPage) {
752 while (--l > 0)
753 (void) getc(inf);
754 continue;
755 }
756 CurrentPosition += l;
757 putbyte(outf, c);
758 while (--l > 0) {
759 c = getc(inf);
760 putbyte(outf, c);
761 }
762 if (ferror(outf))
763 error(1, -1, writeerr);
764 continue;
765 }
766 if ((l = DVI_OpLen(c)) != 0) {
767 /*
768 * Handle other generics.
769 * N.B.: there should only be unsigned parameters
770 * here (save SGN4), for commands with negative
771 * parameters have been taken care of above.
772 */
773 switch (l) {
774
775 case DPL_UNS1:
776 p = getc(inf);
777 break;
778
779 case DPL_UNS2:
780 fGetWord(inf, p);
781 break;
782
783 case DPL_UNS3:
784 fGet3Byte(inf, p);
785 break;
786
787 case DPL_SGN4:
788 fGetLong(inf, p);
789 break;
790
791 default:
792 panic("HandleDVIFile l=%d", l);
793 }
794
795 /*
796 * Now that we have the parameter, perform the
797 * command.
798 */
799 switch (DVI_DT(c)) {
800
801 case DT_SET:
802 case DT_PUT:
803 if (!UseThisPage)
804 continue;
805 if (!CurrentFontOK) {
806 ReallyUseFont();
807 CurrentFontOK++;
808 }
809 putbyte(outf, c);
810 switch (l) {
811
812 case DPL_UNS1:
813 putbyte(outf, p);
814 CurrentPosition += 2;
815 continue;
816
817 case DPL_UNS2:
818 PutWord(outf, p);
819 CurrentPosition += 3;
820 continue;
821
822 case DPL_UNS3:
823 Put3Byte(outf, p);
824 CurrentPosition += 4;
825 continue;
826
827 case DPL_SGN4:
828 PutLong(outf, p);
829 CurrentPosition += 5;
830 continue;
831 }
832
833 case DT_FNT:
834 CurrentFontIndex = p;
835 CurrentFontOK = 0;
836 continue;
837
838 case DT_XXX:
839 HandleSpecial(c, l, p);
840 continue;
841
842 case DT_FNTDEF:
843 HandleFontDef(p);
844 continue;
845
846 default:
847 panic("HandleDVIFile DVI_DT(%d)=%d",
848 c, DVI_DT(c));
849 }
850 continue;
851 }
852
853 switch (c) { /* handle the few remaining cases */
854
855 case DVI_BOP:
856 if (doingpage)
857 GripeUnexpectedOp("BOP (during page)");
858 BeginPage();
859 doingpage = 1;
860 break;
861
862 case DVI_EOP:
863 if (!doingpage)
864 GripeUnexpectedOp("EOP (outside page)");
865 EndPage();
866 doingpage = 0;
867 return(1);
868
869 case DVI_PRE:
870 GripeUnexpectedOp("PRE");
871 /* NOTREACHED */
872
873 case DVI_POST:
874 if (doingpage)
875 GripeUnexpectedOp("POST (inside page)");
876 return(0);
877
878 case DVI_POSTPOST:
879 GripeUnexpectedOp("POSTPOST");
880 /* NOTREACHED */
881
882 default:
883 GripeUndefinedOp(c);
884 /* NOTREACHED */
885 }
886 }
887 }
888
889 /* write an empty page to fill out space */
890 static void
PutEmptyPage(void)891 PutEmptyPage(void)
892 {
893 int i;
894
895 putbyte(outf, DVI_BOP);
896 PutLong(outf, -1L);
897 for (i = 1; i < 10; i++) /* set all sub counts to 0 */
898 PutLong(outf, 0L);
899 PutLong(outf, StartOfLastPage);
900 putbyte(outf, DVI_EOP);
901 if (!SFlag) { /* write nice page usage messages */
902 const char *msg = "[*]";
903 message(1, msg, strlen(msg));
904 }
905 if (ferror(outf))
906 error(1, -1, writeerr);
907
908 StartOfLastPage = CurrentPosition;
909 CurrentPosition += 46; /* we just wrote this much */
910 NumberOfOutputPages++;
911 }
912