]> git.lyx.org Git - lyx.git/blob - development/Win32/packaging/dtl/dv2dt.c
* Enable man2ps to work without hard-coding the locations of groff or dpost.
[lyx.git] / development / Win32 / packaging / dtl / dv2dt.c
1 /* dv2dt - convert DVI file to human-readable "DTL" format.
2    - (ANSI C) version 0.6.0 - 17:54 GMT +11  Wed 8 March 1995
3    - author:  Geoffrey Tobin    ecsgrt@luxor.latrobe.edu.au
4    - patch:  Michal Tomczak-Jaegermann   ntomczak@vm.ucs.ualberta.ca
5    - Reference:  "The DVI Driver Standard, Level 0",
6                  by  The TUG DVI Driver Standards Committee.
7                  Appendix A, "Device-Independent File Format".
8 */
9
10 /* unix version; read from stdin, write to stdout, by default. */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 #include "dtl.h"
18
19 #define PRINT_BCOM   if (group) fprintf (dtl, "%s", BCOM)
20 #define PRINT_ECOM   if (group) fprintf (dtl, "%s", ECOM)
21
22 /*
23   operation's:
24      opcode,
25      name,
26      number of args,
27      string of arguments.
28 */
29 struct op_info_st {int code; char * name; int nargs; char * args; };
30
31 typedef  struct op_info_st  op_info;
32
33 /*
34   table's:
35      name,
36      first opcode,
37      last opcode,
38      pointer to opcode info.
39 */
40 struct op_table_st {char * name; int first; int last; op_info * list; };
41
42 typedef  struct op_table_st  op_table;
43
44 /* Table for opcodes 128 to 170 inclusive. */
45
46 op_info  op_info_128_170 [] =
47 {
48   {128, "s1", 1, "1"},
49   {129, "s2", 1, "2"},
50   {130, "s3", 1, "3"},
51   {131, "s4", 1, "-4"},
52   {132, "sr", 2, "-4 -4"},
53   {133, "p1", 1, "1"},
54   {134, "p2", 1, "2"},
55   {135, "p3", 1, "3"},
56   {136, "p4", 1, "-4"},
57   {137, "pr", 2, "-4 -4"},
58   {138, "nop", 0, ""},
59   {139, "bop", 11, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
60   {140, "eop", 0, ""},
61   {141, "[", 0, ""},
62   {142, "]", 0, ""},
63   {143, "r1", 1, "-1"},
64   {144, "r2", 1, "-2"},
65   {145, "r3", 1, "-3"},
66   {146, "r4", 1, "-4"},
67   {147, "w0", 0, ""},
68   {148, "w1", 1, "-1"},
69   {149, "w2", 1, "-2"},
70   {150, "w3", 1, "-3"},
71   {151, "w4", 1, "-4"},
72   {152, "x0", 0, ""},
73   {153, "x1", 1, "-1"},
74   {154, "x2", 1, "-2"},
75   {155, "x3", 1, "-3"},
76   {156, "x4", 1, "-4"},
77   {157, "d1", 1, "-1"},
78   {158, "d2", 1, "-2"},
79   {159, "d3", 1, "-3"},
80   {160, "d4", 1, "-4"},
81   {161, "y0", 0, ""},
82   {162, "y1", 1, "-1"},
83   {163, "y2", 1, "-2"},
84   {164, "y3", 1, "-3"},
85   {165, "y4", 1, "-4"},
86   {166, "z0", 0, ""},
87   {167, "z1", 1, "-1"},
88   {168, "z2", 1, "-2"},
89   {169, "z3", 1, "-3"},
90   {170, "z4", 1, "-4"}
91 };  /* op_info  op_info_128_170 [] */
92
93 op_table  op_128_170  =  {"op_128_170", 128, 170, op_info_128_170};
94
95 /* Table for font with 1 to 4 bytes (opcodes 235 to 238) inclusive. */
96
97 op_info  fnt_n [] =
98 {
99   {235, "f1", 1, "1"},
100   {236, "f2", 1, "2"},
101   {237, "f3", 1, "3"},
102   {238, "f4", 1, "-4"}
103 };  /* op_info  fnt_n [] */
104
105 op_table  fnt  =  {"f", 235, 238, fnt_n};
106
107
108 /* function prototypes */
109
110 int open_dvi ARGS((char * dvi_file, FILE ** dvi));
111 int open_dtl ARGS((char * dtl_file, FILE ** dtl));
112 int dv2dt ARGS((FILE * dvi, FILE * dtl));
113
114 COUNT wunsigned ARGS((int n,  FILE * dvi,  FILE * dtl));
115 COUNT wsigned   ARGS((int n,  FILE * dvi,  FILE * dtl));
116 S4 rsigned   ARGS((int n,  FILE * dvi));
117 U4 runsigned ARGS((int n,  FILE * dvi));
118
119 COUNT wtable ARGS((op_table table, int opcode, FILE * dvi, FILE * dtl));
120
121 COUNT setseq ARGS((int opcode, FILE * dvi, FILE * dtl));
122 Void setpchar ARGS((int charcode, FILE * dtl));
123 Void xferstring ARGS((int k, FILE * dvi, FILE * dtl));
124
125 COUNT special ARGS((FILE * dvi,  FILE * dtl,  int n));
126 COUNT fontdef ARGS((FILE * dvi,  FILE * dtl,  int n));
127 COUNT preamble  ARGS((FILE * dvi,  FILE * dtl));
128 COUNT postamble ARGS((FILE * dvi,  FILE * dtl));
129 COUNT postpost  ARGS((FILE * dvi,  FILE * dtl));
130
131
132 String program;  /* name of dv2dt program */
133
134 int
135 main
136 #ifdef STDC
137   (int argc,  char * argv[])
138 #else
139   (argc, argv)
140   int argc;
141   char * argv[];
142 #endif
143 {
144   FILE * dvi = stdin;
145   FILE * dtl = stdout;
146
147   /* Watch out:  C's standard library's string functions are dicey */
148   strncpy (program, argv[0], MAXSTRLEN);
149
150   if (argc > 1)
151     open_dvi (argv[1], &dvi);
152
153   if (argc > 2)
154     open_dtl (argv[2], &dtl);
155
156   dv2dt (dvi, dtl);
157
158   return 0;  /* OK */
159 }
160 /* end main */
161
162 int
163 open_dvi
164 #ifdef STDC
165   (char * dvi_file, FILE ** pdvi)
166 #else
167   (dvi_file, pdvi)
168   char * dvi_file;
169   FILE ** pdvi;
170 #endif
171 /* I:  dvi_file;  I:  pdvi;  O:  *pdvi. */
172 {
173   if (pdvi == NULL)
174   {
175     fprintf (stderr, "%s:  address of dvi variable is NULL.\n", program);
176     exit (1);
177   }
178
179   *pdvi = fopen (dvi_file, "rb");
180
181   if (*pdvi == NULL)
182   {
183     fprintf (stderr, "%s:  Cannot open \"%s\" for binary reading.\n",
184       program, dvi_file);
185     exit (1);
186   }
187
188   return 1;  /* OK */
189 }
190 /* open_dvi */
191
192 int
193 open_dtl
194 #ifdef STDC
195   (char * dtl_file, FILE ** pdtl)
196 #else
197   (dtl_file, pdtl)
198   char * dtl_file;
199   FILE ** pdtl;
200 #endif
201 /* I:  dtl_file;  I:  pdtl;  O:  *pdtl. */
202 {
203   if (pdtl == NULL)
204   {
205     fprintf (stderr, "%s:  address of dtl variable is NULL.\n", program);
206     exit (1);
207   }
208
209   *pdtl = fopen (dtl_file, "w");
210
211   if (*pdtl == NULL)
212   {
213     fprintf (stderr, "%s:  Cannot open \"%s\" for text writing.\n",
214       program, dtl_file);
215     exit (1);
216   }
217
218   return 1;  /* OK */
219 }
220 /* open_dtl */
221
222 int
223 dv2dt
224 #ifdef STDC
225   (FILE * dvi, FILE * dtl)
226 #else
227   (dvi, dtl)
228   FILE * dvi;
229   FILE * dtl;
230 #endif
231 {
232   int opcode;
233   COUNT count;  /* intended to count bytes to DVI file; as yet unused. */
234
235   PRINT_BCOM;
236   fprintf (dtl, "variety ");
237 /*  fprintf (dtl, BMES); */
238   fprintf (dtl, VARIETY);
239 /*  fprintf (dtl, EMES); */
240   PRINT_ECOM;
241   fprintf (dtl, "\n");
242
243   /* start counting DVI bytes */
244   count = 0;
245   while ((opcode = fgetc (dvi)) != EOF)
246   {
247     PRINT_BCOM;  /* start of command and parameters */
248     if (opcode < 0 || opcode > 255)
249     {
250       count += 1;
251       fprintf (stderr, "%s:  Non-byte from \"fgetc()\"!\n", program);
252       exit (1);
253     }
254     else if (opcode <= 127)
255     {
256       /* setchar commands */
257       /* count += 1; */
258       /* fprintf (dtl, "%s%d", SETCHAR, opcode); */
259       count +=
260       setseq (opcode, dvi, dtl);
261     }
262     else if (opcode >= 128 && opcode <= 170)
263     {
264       count +=
265       wtable (op_128_170, opcode, dvi, dtl);
266     }
267     else if (opcode >= 171 && opcode <= 234)
268     {
269       count += 1;
270       fprintf (dtl, "%s%d", FONTNUM, opcode - 171);
271     }
272     else if (opcode >= 235 && opcode <= 238)
273     {
274       count +=
275       wtable (fnt, opcode, dvi, dtl);
276     }
277     else if (opcode >= 239 && opcode <= 242)
278     {
279       count +=
280       special (dvi, dtl, opcode - 238);
281     }
282     else if (opcode >= 243 && opcode <= 246)
283     {
284       count +=
285       fontdef (dvi, dtl, opcode - 242);
286     }
287     else if (opcode == 247)
288     {
289       count +=
290       preamble (dvi, dtl);
291     }
292     else if (opcode == 248)
293     {
294       count +=
295       postamble (dvi, dtl);
296     }
297     else if (opcode == 249)
298     {
299       count +=
300       postpost (dvi, dtl);
301     }
302     else if (opcode >= 250 && opcode <= 255)
303     {
304       count += 1;
305       fprintf (dtl, "opcode%d", opcode);
306     }
307     else
308     {
309       count += 1;
310       fprintf (stderr, "%s:  unknown byte.\n", program);
311       exit (1);
312     }
313     PRINT_ECOM;  /* end of command and parameters */
314     fprintf (dtl, "\n");
315     if (fflush (dtl) == EOF)
316     {
317       fprintf (stderr, "%s:  fflush on dtl file gave write error!\n", program);
318       exit (1);
319     }
320   } /* end while */
321
322   return 1;  /* OK */
323 }
324 /* dv2dt */
325
326
327 COUNT
328 wunsigned
329 #ifdef STDC
330   (int n, FILE * dvi, FILE * dtl)
331 #else
332   (n, dvi, dtl)
333   int n;
334   FILE * dvi;
335   FILE * dtl;
336 #endif
337 {
338   U4 unum;
339
340   fprintf (dtl, " ");
341   unum = runsigned (n, dvi);
342   fprintf (dtl, UF4, unum);
343   return n;
344 }
345 /* end wunsigned */
346
347 COUNT
348 wsigned
349 #ifdef STDC
350   (int n, FILE * dvi, FILE * dtl)
351 #else
352   (n, dvi, dtl)
353   int n;
354   FILE * dvi;
355   FILE * dtl;
356 #endif
357 {
358   S4 snum;
359
360   fprintf (dtl, " ");
361   snum = rsigned (n, dvi);
362   fprintf (dtl, SF4, snum);
363   return n;
364 }
365 /* end wsigned */
366
367 U4
368 runsigned
369 #ifdef STDC
370   (int n,  FILE * dvi)
371 #else
372   (n, dvi)
373   int n;
374   FILE * dvi;
375 #endif
376 /* read 1 <= n <= 4 bytes for an unsigned integer from dvi file */
377 /* DVI format uses Big-endian storage of numbers. */
378 {
379   U4 integer;
380   int ibyte = 0;
381   int i;
382
383   if (n < 1 || n > 4)
384   {
385     fprintf (stderr,
386       "%s:  runsigned() asked for %d bytes.  Must be 1 to 4.\n", program, n);
387     exit (1);
388   }
389
390   /* Following calculation works iff storage is big-endian. */
391   integer = 0;
392   for (i = 0; i < n; i++)
393   {
394     integer *= 256;
395     ibyte = fgetc (dvi);
396     integer += ibyte;
397   }
398
399   return integer;
400 }
401 /* end runsigned */
402
403 S4
404 rsigned
405 #ifdef STDC
406   (int n,  FILE * dvi)
407 #else
408   (n, dvi)
409   int n;
410   FILE * dvi;
411 #endif
412 /* read 1 <= n <= 4 bytes for a signed integer from dvi file */
413 /* DVI format uses Big-endian storage of numbers. */
414 {
415   S4 integer;
416   int ibyte = 0;
417   int i;
418
419   if (n < 1 || n > 4)
420   {
421     fprintf (stderr,
422       "%s:  rsigned() asked for %d bytes.  Must be 1 to 4.\n", program, n);
423     exit (1);
424   }
425
426   /* Following calculation works iff storage is big-endian. */
427   integer = 0;
428   for (i = 0; i < n; i++)
429   {
430     integer *= 256;
431     ibyte = fgetc (dvi);
432     /* Big-endian implies sign byte is first byte. */
433     if (i == 0 && ibyte >= 128)
434     {
435       ibyte -= 256;
436     }
437     integer += ibyte;
438   }
439
440   return integer;
441 }
442 /* end rsigned */
443
444 COUNT
445 wtable
446 #ifdef STDC
447   (op_table table, int opcode, FILE * dvi, FILE * dtl)
448 #else
449   (table, opcode, dvi, dtl)
450   op_table table;
451   int opcode;
452   FILE * dvi;
453   FILE * dtl;
454 #endif
455 /* write command with given opcode in given table */
456 /* return number of DVI bytes in this command */
457 {
458   op_info op;  /* pointer into table of operations and arguments */
459   COUNT bcount = 0;  /* number of bytes in arguments of this opcode */
460   String args;  /* arguments string */
461   int i;  /* count of arguments read from args */
462   int pos;  /* position in args */
463
464   /* Defensive programming. */
465   if (opcode < table.first || opcode > table.last)
466   {
467     fprintf (stderr,
468       "%s: opcode %d is outside table %s [ %d to %d ] !\n",
469       program, opcode, table.name, table.first, table.last);
470     exit (1);
471   }
472
473   op = table.list [opcode - table.first];
474
475   /* Further defensive programming. */
476   if (op.code != opcode)
477   {
478     fprintf (stderr, "%s: internal table %s wrong!\n", program, table.name);
479     exit (1);
480   }
481
482   bcount = 1;
483   fprintf (dtl, "%s", op.name);
484
485   /* NB:  sscanf does an ungetc, */
486   /*      so args must be writable. */
487
488   strncpy (args, op.args, MAXSTRLEN);
489
490   pos = 0;
491   for (i = 0; i < op.nargs; i++)
492   {
493     int argtype;  /* sign and number of bytes in current argument */
494     int nconv;  /* number of successful conversions from args */
495     int nread;  /* number of bytes read from args */
496
497     nconv = sscanf (args + pos, "%d%n", &argtype, &nread);
498
499     /* internal consistency checks */
500     if (nconv != 1 || nread <= 0)
501     {
502       fprintf (stderr,
503         "%s: internal read of table %s failed!\n", program, table.name);
504       exit (1);
505     }
506
507     pos += nread;
508
509     bcount += ( argtype < 0 ?
510                wsigned  (-argtype, dvi, dtl) :
511                wunsigned (argtype, dvi, dtl)  ) ;
512   } /* end for */
513
514   return bcount;
515
516 }
517 /* wtable */
518
519 COUNT
520 setseq
521 #ifdef STDC
522   (int opcode, FILE * dvi, FILE * dtl)
523 #else
524   (opcode, dvi, dtl)
525   int opcode;
526   FILE * dvi;
527   FILE * dtl;
528 #endif
529 /* write a sequence of setchar commands */
530 /* return count of DVI bytes interpreted into DTL */
531 {
532   int charcode = opcode;  /* fortuitous */
533   int ccount = 0;
534
535   if (!isprint (charcode))
536   {
537     ccount = 1;
538     fprintf (dtl, "%s%02X", SETCHAR, opcode);
539   }
540   else
541   {
542     /* start of sequence of font characters */
543     fprintf (dtl, BSEQ);
544
545     /* first character */
546     ccount = 1;
547     setpchar (charcode, dtl);
548
549     /* subsequent characters */
550     while ((opcode = fgetc (dvi)) != EOF)
551     {
552       if (opcode < 0 || opcode > 127)
553       {
554         break;  /* not a setchar command, so sequence has ended */
555       }
556       charcode = opcode;  /* fortuitous */
557       if (!isprint (charcode))  /* not printable ascii */
558       {
559         break;  /* end of font character sequence, as for other commands */
560       }
561       else  /* printable ASCII */
562       {
563         ccount += 1;
564         setpchar (charcode, dtl);
565       }
566     }  /* end for loop */
567
568     /* prepare to reread opcode of next DVI command */
569     if (ungetc (opcode, dvi) == EOF)
570     {
571       fprintf (stderr, "setseq:  cannot push back a byte\n");
572       exit (1);
573     }
574
575     /* end of sequence of font characters */
576     fprintf (dtl, ESEQ);
577   }
578   return ccount;
579 }
580 /* setseq */
581
582 Void
583 setpchar
584 #ifdef STDC
585   (int charcode, FILE * dtl)
586 #else
587   (charcode, dtl)
588   int charcode;
589   FILE * dtl;
590 #endif
591 /* set printable character */
592 {
593   switch (charcode)
594   {
595     case ESC_CHAR:
596       fprintf (dtl, "%c", ESC_CHAR);
597       fprintf (dtl, "%c", ESC_CHAR);
598       break;
599     case QUOTE_CHAR:
600       fprintf (dtl, "%c", ESC_CHAR);
601       fprintf (dtl, "%c", QUOTE_CHAR);
602       break;
603     case BSEQ_CHAR:
604       fprintf (dtl, "%c", ESC_CHAR);
605       fprintf (dtl, "%c", BSEQ_CHAR);
606       break;
607     case ESEQ_CHAR:
608       fprintf (dtl, "%c", ESC_CHAR);
609       fprintf (dtl, "%c", ESEQ_CHAR);
610       break;
611     default:
612       fprintf (dtl, "%c", charcode);
613       break;
614   }
615 }
616 /* setpchar */
617
618 Void
619 xferstring
620 #ifdef STDC
621   (int k, FILE * dvi, FILE * dtl)
622 #else
623   (k, dvi, dtl)
624   int k;
625   FILE * dvi;
626   FILE * dtl;
627 #endif
628 /* copy string of k characters from dvi file to dtl file */
629 {
630   int i;
631   int ch;
632
633   fprintf (dtl, " ");
634   fprintf (dtl, "'");
635   for (i=0; i < k; i++)
636   {
637     ch = fgetc (dvi);
638     if (ch == ESC_CHAR || ch == EMES_CHAR)
639     {
640       fprintf (dtl, "%c", ESC_CHAR);
641     }
642     fprintf (dtl, "%c", ch);
643   }
644   fprintf (dtl, "'");
645 }
646 /* xferstring */
647
648 COUNT
649 special
650 #ifdef STDC
651   (FILE * dvi,  FILE * dtl,  int n)
652 #else
653   (dvi, dtl, n)
654   FILE * dvi;
655   FILE * dtl;
656   int n;
657 #endif
658 /* read special 1 .. 4 from dvi and write in dtl */
659 /* return number of DVI bytes interpreted into DTL */
660 {
661   U4  k;
662
663   if (n < 1 || n > 4)
664   {
665     fprintf (stderr, "%s:  special %d, range is 1 to 4.\n", program, n);
666     exit (1);
667   }
668
669   fprintf (dtl, "%s%d", SPECIAL, n);
670
671   /* k[n] = length of special string */
672   fprintf (dtl, " ");
673   k = runsigned (n, dvi);
674   fprintf (dtl, UF4, k);
675
676   /* x[k] = special string */
677   xferstring (k, dvi, dtl);
678
679   return (1 + n + k);
680 }
681 /* end special */
682
683 COUNT
684 fontdef
685 #ifdef STDC
686   (FILE * dvi,  FILE * dtl,  int n)
687 #else
688   (dvi,  dtl,  n)
689   FILE * dvi;
690   FILE * dtl;
691   int n;
692 #endif
693 /* read fontdef 1 .. 4 from dvi and write in dtl */
694 /* return number of DVI bytes interpreted into DTL */
695 {
696   U4 ku, c, s, d, a, l;
697   S4 ks;
698
699   if (n < 1 || n > 4)
700   {
701     fprintf (stderr, "%s:  font def %d, range is 1 to 4.\n", program, n);
702     exit (1);
703   }
704
705   fprintf (dtl, "%s%d", FONTDEF, n);
706
707   /* k[n] = font number */
708   fprintf (dtl, " ");
709   if (n == 4)
710   {
711     ks = rsigned (n, dvi);
712     fprintf (dtl, SF4, ks);
713   }
714   else
715   {
716     ku = runsigned (n, dvi);
717     fprintf (dtl, UF4, ku);
718   }
719
720   /* c[4] = checksum */
721   fprintf (dtl, " ");
722   c = runsigned (4, dvi);
723 #ifdef HEX_CHECKSUM
724   fprintf (dtl, XF4, c);
725 #else /* NOT HEX_CHECKSUM */
726   /* write in octal, to allow quick comparison with tftopl's output */
727   fprintf (dtl, OF4, c);
728 #endif
729
730   /* s[4] = scale factor */
731   fprintf (dtl, " ");
732   s = runsigned (4, dvi);
733   fprintf (dtl, UF4, s);
734
735   /* d[4] = design size */
736   fprintf (dtl, " ");
737   d = runsigned (4, dvi);
738   fprintf (dtl, UF4, d);
739
740   /* a[1] = length of area (directory) name */
741   a = runsigned (1, dvi);
742   fprintf (dtl, " ");
743   fprintf (dtl, UF4, a);
744
745   /* l[1] = length of font name */
746   l = runsigned (1, dvi);
747   fprintf (dtl, " ");
748   fprintf (dtl, UF4, l);
749
750   /* n[a+l] = font pathname string => area (directory) + font */
751   xferstring (a, dvi, dtl);
752   xferstring (l, dvi, dtl);
753
754   return (1 + n + 4 + 4 + 4 + 1 + 1 + a + l);
755 }
756 /* end fontdef */
757
758 COUNT
759 preamble
760 #ifdef STDC
761   (FILE * dvi,  FILE * dtl)
762 #else
763   (dvi,  dtl)
764   FILE * dvi;
765   FILE * dtl;
766 #endif
767 /* read preamble from dvi and write in dtl */
768 /* return number of DVI bytes interpreted into DTL */
769 {
770   U4 id, num, den, mag, k;
771
772   fprintf (dtl, "pre");
773
774   /* i[1] = DVI format identification */
775   fprintf (dtl, " ");
776   id = runsigned (1, dvi);
777   fprintf (dtl, UF4, id);
778
779   /* num[4] = numerator of DVI unit */
780   fprintf (dtl, " ");
781   num = runsigned (4, dvi);
782   fprintf (dtl, UF4, num);
783
784   /* den[4] = denominator of DVI unit */
785   fprintf (dtl, " ");
786   den = runsigned (4, dvi);
787   fprintf (dtl, UF4, den);
788
789   /* mag[4] = 1000 x magnification */
790   fprintf (dtl, " ");
791   mag = runsigned (4, dvi);
792   fprintf (dtl, UF4, mag);
793
794   /* k[1] = length of comment */
795   fprintf (dtl, " ");
796   k = runsigned (1, dvi);
797   fprintf (dtl, UF4, k);
798
799   /* x[k] = comment string */
800   xferstring (k, dvi, dtl);
801
802   return (1 + 1 + 4 + 4 + 4 + 1 + k);
803 }
804 /* end preamble */
805
806 COUNT
807 postamble
808 #ifdef STDC
809   (FILE * dvi,  FILE * dtl)
810 #else
811   (dvi,  dtl)
812   FILE * dvi;
813   FILE * dtl;
814 #endif
815 /* read postamble from dvi and write in dtl */
816 /* return number of bytes */
817 {
818   U4 p, num, den, mag, l, u, s, t;
819
820   fprintf (dtl, "post");
821
822   /* p[4] = pointer to final bop */
823   fprintf (dtl, " ");
824   p = runsigned (4, dvi);
825   fprintf (dtl, UF4, p);
826
827   /* num[4] = numerator of DVI unit */
828   fprintf (dtl, " ");
829   num = runsigned (4, dvi);
830   fprintf (dtl, UF4, num);
831
832   /* den[4] = denominator of DVI unit */
833   fprintf (dtl, " ");
834   den = runsigned (4, dvi);
835   fprintf (dtl, UF4, den);
836
837   /* mag[4] = 1000 x magnification */
838   fprintf (dtl, " ");
839   mag = runsigned (4, dvi);
840   fprintf (dtl, UF4, mag);
841
842   /* l[4] = height + depth of tallest page */
843   fprintf (dtl, " ");
844   l = runsigned (4, dvi);
845   fprintf (dtl, UF4, l);
846
847   /* u[4] = width of widest page */
848   fprintf (dtl, " ");
849   u = runsigned (4, dvi);
850   fprintf (dtl, UF4, u);
851
852   /* s[2] = maximum stack depth */
853   fprintf (dtl, " ");
854   s = runsigned (2, dvi);
855   fprintf (dtl, UF4, s);
856
857   /* t[2] = total number of pages (bop commands) */
858   fprintf (dtl, " ");
859   t = runsigned (2, dvi);
860   fprintf (dtl, UF4, t);
861
862 /*  return (29);  */
863   return (1 + 4 + 4 + 4 + 4 + 4 + 4 + 2 + 2);
864 }
865 /* end postamble */
866
867 COUNT
868 postpost
869 #ifdef STDC
870   (FILE * dvi,  FILE * dtl)
871 #else
872   (dvi,  dtl)
873   FILE * dvi;
874   FILE * dtl;
875 #endif
876 /* read post_post from dvi and write in dtl */
877 /* return number of bytes */
878 {
879   U4 q, id;
880   int b223;  /* hope this is 8-bit clean */
881   int n223;  /* number of "223" bytes in final padding */
882
883   fprintf (dtl, "post_post");
884
885   /* q[4] = pointer to post command */
886   fprintf (dtl, " ");
887   q = runsigned (4, dvi);
888   fprintf (dtl, UF4, q);
889
890   /* i[1] = DVI identification byte */
891   fprintf (dtl, " ");
892   id = runsigned (1, dvi);
893   fprintf (dtl, UF4, id);
894
895   /* final padding by "223" bytes */
896   /* hope this way of obtaining b223 is 8-bit clean */
897   for (n223 = 0; (b223 = fgetc (dvi)) == 223; n223++)
898   {
899     fprintf (dtl, " ");
900     fprintf (dtl, "%d", 223);
901   }
902   if (n223 < 4)
903   {
904     fprintf (stderr,
905       "%s:  bad post_post:  fewer than four \"223\" bytes.\n", program);
906     exit (1);
907   }
908   if (b223 != EOF)
909   {
910     fprintf (stderr,
911       "%s:  bad post_post:  doesn't end with a \"223\".\n", program);
912     exit (1);
913   }
914
915   return (1 + 4 + 1 + n223);
916 }
917 /* end postpost */
918
919 /* end of "dv2dt.c" */