1 /* dv2dt - convert DVI file to human-readable "DTL" format.
3 This file is public domain.
4 Originally written 1995, Geoffrey Tobin.
5 The author has expressed the hope that any modification will retain enough content to remain useful. He would also appreciate being acknowledged as the original author in the documentation.
6 This declaration added 2008/11/14 by Clea F. Rees with the permission of Geoffrey Tobin.
8 - (ANSI C) version 0.6.0 - 17:54 GMT +11 Wed 8 March 1995
9 - author: Geoffrey Tobin ecsgrt@luxor.latrobe.edu.au
10 - patch: Michal Tomczak-Jaegermann ntomczak@vm.ucs.ualberta.ca
11 - Reference: "The DVI Driver Standard, Level 0",
12 by The TUG DVI Driver Standards Committee.
13 Appendix A, "Device-Independent File Format".
16 /* unix version; read from stdin, write to stdout, by default. */
25 #define PRINT_BCOM if (group) fprintf (dtl, "%s", BCOM)
26 #define PRINT_ECOM if (group) fprintf (dtl, "%s", ECOM)
35 struct op_info_st {int code; char * name; int nargs; char * args; };
37 typedef struct op_info_st op_info;
44 pointer to opcode info.
46 struct op_table_st {char * name; int first; int last; op_info * list; };
48 typedef struct op_table_st op_table;
50 /* Table for opcodes 128 to 170 inclusive. */
52 op_info op_info_128_170 [] =
58 {132, "sr", 2, "-4 -4"},
63 {137, "pr", 2, "-4 -4"},
65 {139, "bop", 11, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
97 }; /* op_info op_info_128_170 [] */
99 op_table op_128_170 = {"op_128_170", 128, 170, op_info_128_170};
101 /* Table for font with 1 to 4 bytes (opcodes 235 to 238) inclusive. */
109 }; /* op_info fnt_n [] */
111 op_table fnt = {"f", 235, 238, fnt_n};
114 /* function prototypes */
116 int open_dvi ARGS((char * dvi_file, FILE ** dvi));
117 int open_dtl ARGS((char * dtl_file, FILE ** dtl));
118 int dv2dt ARGS((FILE * dvi, FILE * dtl));
120 COUNT wunsigned ARGS((int n, FILE * dvi, FILE * dtl));
121 COUNT wsigned ARGS((int n, FILE * dvi, FILE * dtl));
122 S4 rsigned ARGS((int n, FILE * dvi));
123 U4 runsigned ARGS((int n, FILE * dvi));
125 COUNT wtable ARGS((op_table table, int opcode, FILE * dvi, FILE * dtl));
127 COUNT setseq ARGS((int opcode, FILE * dvi, FILE * dtl));
128 Void setpchar ARGS((int charcode, FILE * dtl));
129 Void xferstring ARGS((int k, FILE * dvi, FILE * dtl));
131 COUNT special ARGS((FILE * dvi, FILE * dtl, int n));
132 COUNT fontdef ARGS((FILE * dvi, FILE * dtl, int n));
133 COUNT preamble ARGS((FILE * dvi, FILE * dtl));
134 COUNT postamble ARGS((FILE * dvi, FILE * dtl));
135 COUNT postpost ARGS((FILE * dvi, FILE * dtl));
138 String program; /* name of dv2dt program */
143 (int argc, char * argv[])
153 /* Watch out: C's standard library's string functions are dicey */
154 strncpy (program, argv[0], MAXSTRLEN);
157 open_dvi (argv[1], &dvi);
160 open_dtl (argv[2], &dtl);
171 (char * dvi_file, FILE ** pdvi)
177 /* I: dvi_file; I: pdvi; O: *pdvi. */
181 fprintf (stderr, "%s: address of dvi variable is NULL.\n", program);
185 *pdvi = fopen (dvi_file, "rb");
189 fprintf (stderr, "%s: Cannot open \"%s\" for binary reading.\n",
201 (char * dtl_file, FILE ** pdtl)
207 /* I: dtl_file; I: pdtl; O: *pdtl. */
211 fprintf (stderr, "%s: address of dtl variable is NULL.\n", program);
215 *pdtl = fopen (dtl_file, "w");
219 fprintf (stderr, "%s: Cannot open \"%s\" for text writing.\n",
231 (FILE * dvi, FILE * dtl)
239 COUNT count; /* intended to count bytes to DVI file; as yet unused. */
242 fprintf (dtl, "variety ");
243 /* fprintf (dtl, BMES); */
244 fprintf (dtl, VARIETY);
245 /* fprintf (dtl, EMES); */
249 /* start counting DVI bytes */
251 while ((opcode = fgetc (dvi)) != EOF)
253 PRINT_BCOM; /* start of command and parameters */
254 if (opcode < 0 || opcode > 255)
257 fprintf (stderr, "%s: Non-byte from \"fgetc()\"!\n", program);
260 else if (opcode <= 127)
262 /* setchar commands */
264 /* fprintf (dtl, "%s%d", SETCHAR, opcode); */
266 setseq (opcode, dvi, dtl);
268 else if (opcode >= 128 && opcode <= 170)
271 wtable (op_128_170, opcode, dvi, dtl);
273 else if (opcode >= 171 && opcode <= 234)
276 fprintf (dtl, "%s%d", FONTNUM, opcode - 171);
278 else if (opcode >= 235 && opcode <= 238)
281 wtable (fnt, opcode, dvi, dtl);
283 else if (opcode >= 239 && opcode <= 242)
286 special (dvi, dtl, opcode - 238);
288 else if (opcode >= 243 && opcode <= 246)
291 fontdef (dvi, dtl, opcode - 242);
293 else if (opcode == 247)
298 else if (opcode == 248)
301 postamble (dvi, dtl);
303 else if (opcode == 249)
308 else if (opcode >= 250 && opcode <= 255)
311 fprintf (dtl, "opcode%d", opcode);
316 fprintf (stderr, "%s: unknown byte.\n", program);
319 PRINT_ECOM; /* end of command and parameters */
321 if (fflush (dtl) == EOF)
323 fprintf (stderr, "%s: fflush on dtl file gave write error!\n", program);
336 (int n, FILE * dvi, FILE * dtl)
347 unum = runsigned (n, dvi);
348 fprintf (dtl, UF4, unum);
356 (int n, FILE * dvi, FILE * dtl)
367 snum = rsigned (n, dvi);
368 fprintf (dtl, SF4, snum);
382 /* read 1 <= n <= 4 bytes for an unsigned integer from dvi file */
383 /* DVI format uses Big-endian storage of numbers. */
392 "%s: runsigned() asked for %d bytes. Must be 1 to 4.\n", program, n);
396 /* Following calculation works iff storage is big-endian. */
398 for (i = 0; i < n; i++)
418 /* read 1 <= n <= 4 bytes for a signed integer from dvi file */
419 /* DVI format uses Big-endian storage of numbers. */
428 "%s: rsigned() asked for %d bytes. Must be 1 to 4.\n", program, n);
432 /* Following calculation works iff storage is big-endian. */
434 for (i = 0; i < n; i++)
438 /* Big-endian implies sign byte is first byte. */
439 if (i == 0 && ibyte >= 128)
453 (op_table table, int opcode, FILE * dvi, FILE * dtl)
455 (table, opcode, dvi, dtl)
461 /* write command with given opcode in given table */
462 /* return number of DVI bytes in this command */
464 op_info op; /* pointer into table of operations and arguments */
465 COUNT bcount = 0; /* number of bytes in arguments of this opcode */
466 String args; /* arguments string */
467 int i; /* count of arguments read from args */
468 int pos; /* position in args */
470 /* Defensive programming. */
471 if (opcode < table.first || opcode > table.last)
474 "%s: opcode %d is outside table %s [ %d to %d ] !\n",
475 program, opcode, table.name, table.first, table.last);
479 op = table.list [opcode - table.first];
481 /* Further defensive programming. */
482 if (op.code != opcode)
484 fprintf (stderr, "%s: internal table %s wrong!\n", program, table.name);
489 fprintf (dtl, "%s", op.name);
491 /* NB: sscanf does an ungetc, */
492 /* so args must be writable. */
494 strncpy (args, op.args, MAXSTRLEN);
497 for (i = 0; i < op.nargs; i++)
499 int argtype; /* sign and number of bytes in current argument */
500 int nconv; /* number of successful conversions from args */
501 int nread; /* number of bytes read from args */
503 nconv = sscanf (args + pos, "%d%n", &argtype, &nread);
505 /* internal consistency checks */
506 if (nconv != 1 || nread <= 0)
509 "%s: internal read of table %s failed!\n", program, table.name);
515 bcount += ( argtype < 0 ?
516 wsigned (-argtype, dvi, dtl) :
517 wunsigned (argtype, dvi, dtl) ) ;
528 (int opcode, FILE * dvi, FILE * dtl)
535 /* write a sequence of setchar commands */
536 /* return count of DVI bytes interpreted into DTL */
538 int charcode = opcode; /* fortuitous */
541 if (!isprint (charcode))
544 fprintf (dtl, "%s%02X", SETCHAR, opcode);
548 /* start of sequence of font characters */
551 /* first character */
553 setpchar (charcode, dtl);
555 /* subsequent characters */
556 while ((opcode = fgetc (dvi)) != EOF)
558 if (opcode < 0 || opcode > 127)
560 break; /* not a setchar command, so sequence has ended */
562 charcode = opcode; /* fortuitous */
563 if (!isprint (charcode)) /* not printable ascii */
565 break; /* end of font character sequence, as for other commands */
567 else /* printable ASCII */
570 setpchar (charcode, dtl);
574 /* prepare to reread opcode of next DVI command */
575 if (ungetc (opcode, dvi) == EOF)
577 fprintf (stderr, "setseq: cannot push back a byte\n");
581 /* end of sequence of font characters */
591 (int charcode, FILE * dtl)
597 /* set printable character */
602 fprintf (dtl, "%c", ESC_CHAR);
603 fprintf (dtl, "%c", ESC_CHAR);
606 fprintf (dtl, "%c", ESC_CHAR);
607 fprintf (dtl, "%c", QUOTE_CHAR);
610 fprintf (dtl, "%c", ESC_CHAR);
611 fprintf (dtl, "%c", BSEQ_CHAR);
614 fprintf (dtl, "%c", ESC_CHAR);
615 fprintf (dtl, "%c", ESEQ_CHAR);
618 fprintf (dtl, "%c", charcode);
627 (int k, FILE * dvi, FILE * dtl)
634 /* copy string of k characters from dvi file to dtl file */
641 for (i=0; i < k; i++)
644 if (ch == ESC_CHAR || ch == EMES_CHAR)
646 fprintf (dtl, "%c", ESC_CHAR);
648 fprintf (dtl, "%c", ch);
657 (FILE * dvi, FILE * dtl, int n)
664 /* read special 1 .. 4 from dvi and write in dtl */
665 /* return number of DVI bytes interpreted into DTL */
671 fprintf (stderr, "%s: special %d, range is 1 to 4.\n", program, n);
675 fprintf (dtl, "%s%d", SPECIAL, n);
677 /* k[n] = length of special string */
679 k = runsigned (n, dvi);
680 fprintf (dtl, UF4, k);
682 /* x[k] = special string */
683 xferstring (k, dvi, dtl);
692 (FILE * dvi, FILE * dtl, int n)
699 /* read fontdef 1 .. 4 from dvi and write in dtl */
700 /* return number of DVI bytes interpreted into DTL */
702 U4 ku, c, s, d, a, l;
707 fprintf (stderr, "%s: font def %d, range is 1 to 4.\n", program, n);
711 fprintf (dtl, "%s%d", FONTDEF, n);
713 /* k[n] = font number */
717 ks = rsigned (n, dvi);
718 fprintf (dtl, SF4, ks);
722 ku = runsigned (n, dvi);
723 fprintf (dtl, UF4, ku);
726 /* c[4] = checksum */
728 c = runsigned (4, dvi);
730 fprintf (dtl, XF4, c);
731 #else /* NOT HEX_CHECKSUM */
732 /* write in octal, to allow quick comparison with tftopl's output */
733 fprintf (dtl, OF4, c);
736 /* s[4] = scale factor */
738 s = runsigned (4, dvi);
739 fprintf (dtl, UF4, s);
741 /* d[4] = design size */
743 d = runsigned (4, dvi);
744 fprintf (dtl, UF4, d);
746 /* a[1] = length of area (directory) name */
747 a = runsigned (1, dvi);
749 fprintf (dtl, UF4, a);
751 /* l[1] = length of font name */
752 l = runsigned (1, dvi);
754 fprintf (dtl, UF4, l);
756 /* n[a+l] = font pathname string => area (directory) + font */
757 xferstring (a, dvi, dtl);
758 xferstring (l, dvi, dtl);
760 return (1 + n + 4 + 4 + 4 + 1 + 1 + a + l);
767 (FILE * dvi, FILE * dtl)
773 /* read preamble from dvi and write in dtl */
774 /* return number of DVI bytes interpreted into DTL */
776 U4 id, num, den, mag, k;
778 fprintf (dtl, "pre");
780 /* i[1] = DVI format identification */
782 id = runsigned (1, dvi);
783 fprintf (dtl, UF4, id);
785 /* num[4] = numerator of DVI unit */
787 num = runsigned (4, dvi);
788 fprintf (dtl, UF4, num);
790 /* den[4] = denominator of DVI unit */
792 den = runsigned (4, dvi);
793 fprintf (dtl, UF4, den);
795 /* mag[4] = 1000 x magnification */
797 mag = runsigned (4, dvi);
798 fprintf (dtl, UF4, mag);
800 /* k[1] = length of comment */
802 k = runsigned (1, dvi);
803 fprintf (dtl, UF4, k);
805 /* x[k] = comment string */
806 xferstring (k, dvi, dtl);
808 return (1 + 1 + 4 + 4 + 4 + 1 + k);
815 (FILE * dvi, FILE * dtl)
821 /* read postamble from dvi and write in dtl */
822 /* return number of bytes */
824 U4 p, num, den, mag, l, u, s, t;
826 fprintf (dtl, "post");
828 /* p[4] = pointer to final bop */
830 p = runsigned (4, dvi);
831 fprintf (dtl, UF4, p);
833 /* num[4] = numerator of DVI unit */
835 num = runsigned (4, dvi);
836 fprintf (dtl, UF4, num);
838 /* den[4] = denominator of DVI unit */
840 den = runsigned (4, dvi);
841 fprintf (dtl, UF4, den);
843 /* mag[4] = 1000 x magnification */
845 mag = runsigned (4, dvi);
846 fprintf (dtl, UF4, mag);
848 /* l[4] = height + depth of tallest page */
850 l = runsigned (4, dvi);
851 fprintf (dtl, UF4, l);
853 /* u[4] = width of widest page */
855 u = runsigned (4, dvi);
856 fprintf (dtl, UF4, u);
858 /* s[2] = maximum stack depth */
860 s = runsigned (2, dvi);
861 fprintf (dtl, UF4, s);
863 /* t[2] = total number of pages (bop commands) */
865 t = runsigned (2, dvi);
866 fprintf (dtl, UF4, t);
869 return (1 + 4 + 4 + 4 + 4 + 4 + 4 + 2 + 2);
876 (FILE * dvi, FILE * dtl)
882 /* read post_post from dvi and write in dtl */
883 /* return number of bytes */
886 int b223; /* hope this is 8-bit clean */
887 int n223; /* number of "223" bytes in final padding */
889 fprintf (dtl, "post_post");
891 /* q[4] = pointer to post command */
893 q = runsigned (4, dvi);
894 fprintf (dtl, UF4, q);
896 /* i[1] = DVI identification byte */
898 id = runsigned (1, dvi);
899 fprintf (dtl, UF4, id);
901 /* final padding by "223" bytes */
902 /* hope this way of obtaining b223 is 8-bit clean */
903 for (n223 = 0; (b223 = fgetc (dvi)) == 223; n223++)
906 fprintf (dtl, "%d", 223);
911 "%s: bad post_post: fewer than four \"223\" bytes.\n", program);
917 "%s: bad post_post: doesn't end with a \"223\".\n", program);
921 return (1 + 4 + 1 + n223);
925 /* end of "dv2dt.c" */