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".
10 /* unix version; read from stdin, write to stdout, by default. */
19 #define PRINT_BCOM if (group) fprintf (dtl, "%s", BCOM)
20 #define PRINT_ECOM if (group) fprintf (dtl, "%s", ECOM)
29 struct op_info_st {int code; char * name; int nargs; char * args; };
31 typedef struct op_info_st op_info;
38 pointer to opcode info.
40 struct op_table_st {char * name; int first; int last; op_info * list; };
42 typedef struct op_table_st op_table;
44 /* Table for opcodes 128 to 170 inclusive. */
46 op_info op_info_128_170 [] =
52 {132, "sr", 2, "-4 -4"},
57 {137, "pr", 2, "-4 -4"},
59 {139, "bop", 11, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
91 }; /* op_info op_info_128_170 [] */
93 op_table op_128_170 = {"op_128_170", 128, 170, op_info_128_170};
95 /* Table for font with 1 to 4 bytes (opcodes 235 to 238) inclusive. */
103 }; /* op_info fnt_n [] */
105 op_table fnt = {"f", 235, 238, fnt_n};
108 /* function prototypes */
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));
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));
119 COUNT wtable ARGS((op_table table, int opcode, FILE * dvi, FILE * dtl));
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));
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));
132 String program; /* name of dv2dt program */
137 (int argc, char * argv[])
147 /* Watch out: C's standard library's string functions are dicey */
148 strncpy (program, argv[0], MAXSTRLEN);
151 open_dvi (argv[1], &dvi);
154 open_dtl (argv[2], &dtl);
165 (char * dvi_file, FILE ** pdvi)
171 /* I: dvi_file; I: pdvi; O: *pdvi. */
175 fprintf (stderr, "%s: address of dvi variable is NULL.\n", program);
179 *pdvi = fopen (dvi_file, "rb");
183 fprintf (stderr, "%s: Cannot open \"%s\" for binary reading.\n",
195 (char * dtl_file, FILE ** pdtl)
201 /* I: dtl_file; I: pdtl; O: *pdtl. */
205 fprintf (stderr, "%s: address of dtl variable is NULL.\n", program);
209 *pdtl = fopen (dtl_file, "w");
213 fprintf (stderr, "%s: Cannot open \"%s\" for text writing.\n",
225 (FILE * dvi, FILE * dtl)
233 COUNT count; /* intended to count bytes to DVI file; as yet unused. */
236 fprintf (dtl, "variety ");
237 /* fprintf (dtl, BMES); */
238 fprintf (dtl, VARIETY);
239 /* fprintf (dtl, EMES); */
243 /* start counting DVI bytes */
245 while ((opcode = fgetc (dvi)) != EOF)
247 PRINT_BCOM; /* start of command and parameters */
248 if (opcode < 0 || opcode > 255)
251 fprintf (stderr, "%s: Non-byte from \"fgetc()\"!\n", program);
254 else if (opcode <= 127)
256 /* setchar commands */
258 /* fprintf (dtl, "%s%d", SETCHAR, opcode); */
260 setseq (opcode, dvi, dtl);
262 else if (opcode >= 128 && opcode <= 170)
265 wtable (op_128_170, opcode, dvi, dtl);
267 else if (opcode >= 171 && opcode <= 234)
270 fprintf (dtl, "%s%d", FONTNUM, opcode - 171);
272 else if (opcode >= 235 && opcode <= 238)
275 wtable (fnt, opcode, dvi, dtl);
277 else if (opcode >= 239 && opcode <= 242)
280 special (dvi, dtl, opcode - 238);
282 else if (opcode >= 243 && opcode <= 246)
285 fontdef (dvi, dtl, opcode - 242);
287 else if (opcode == 247)
292 else if (opcode == 248)
295 postamble (dvi, dtl);
297 else if (opcode == 249)
302 else if (opcode >= 250 && opcode <= 255)
305 fprintf (dtl, "opcode%d", opcode);
310 fprintf (stderr, "%s: unknown byte.\n", program);
313 PRINT_ECOM; /* end of command and parameters */
315 if (fflush (dtl) == EOF)
317 fprintf (stderr, "%s: fflush on dtl file gave write error!\n", program);
330 (int n, FILE * dvi, FILE * dtl)
341 unum = runsigned (n, dvi);
342 fprintf (dtl, UF4, unum);
350 (int n, FILE * dvi, FILE * dtl)
361 snum = rsigned (n, dvi);
362 fprintf (dtl, SF4, snum);
376 /* read 1 <= n <= 4 bytes for an unsigned integer from dvi file */
377 /* DVI format uses Big-endian storage of numbers. */
386 "%s: runsigned() asked for %d bytes. Must be 1 to 4.\n", program, n);
390 /* Following calculation works iff storage is big-endian. */
392 for (i = 0; i < n; i++)
412 /* read 1 <= n <= 4 bytes for a signed integer from dvi file */
413 /* DVI format uses Big-endian storage of numbers. */
422 "%s: rsigned() asked for %d bytes. Must be 1 to 4.\n", program, n);
426 /* Following calculation works iff storage is big-endian. */
428 for (i = 0; i < n; i++)
432 /* Big-endian implies sign byte is first byte. */
433 if (i == 0 && ibyte >= 128)
447 (op_table table, int opcode, FILE * dvi, FILE * dtl)
449 (table, opcode, dvi, dtl)
455 /* write command with given opcode in given table */
456 /* return number of DVI bytes in this command */
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 */
464 /* Defensive programming. */
465 if (opcode < table.first || opcode > table.last)
468 "%s: opcode %d is outside table %s [ %d to %d ] !\n",
469 program, opcode, table.name, table.first, table.last);
473 op = table.list [opcode - table.first];
475 /* Further defensive programming. */
476 if (op.code != opcode)
478 fprintf (stderr, "%s: internal table %s wrong!\n", program, table.name);
483 fprintf (dtl, "%s", op.name);
485 /* NB: sscanf does an ungetc, */
486 /* so args must be writable. */
488 strncpy (args, op.args, MAXSTRLEN);
491 for (i = 0; i < op.nargs; i++)
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 */
497 nconv = sscanf (args + pos, "%d%n", &argtype, &nread);
499 /* internal consistency checks */
500 if (nconv != 1 || nread <= 0)
503 "%s: internal read of table %s failed!\n", program, table.name);
509 bcount += ( argtype < 0 ?
510 wsigned (-argtype, dvi, dtl) :
511 wunsigned (argtype, dvi, dtl) ) ;
522 (int opcode, FILE * dvi, FILE * dtl)
529 /* write a sequence of setchar commands */
530 /* return count of DVI bytes interpreted into DTL */
532 int charcode = opcode; /* fortuitous */
535 if (!isprint (charcode))
538 fprintf (dtl, "%s%02X", SETCHAR, opcode);
542 /* start of sequence of font characters */
545 /* first character */
547 setpchar (charcode, dtl);
549 /* subsequent characters */
550 while ((opcode = fgetc (dvi)) != EOF)
552 if (opcode < 0 || opcode > 127)
554 break; /* not a setchar command, so sequence has ended */
556 charcode = opcode; /* fortuitous */
557 if (!isprint (charcode)) /* not printable ascii */
559 break; /* end of font character sequence, as for other commands */
561 else /* printable ASCII */
564 setpchar (charcode, dtl);
568 /* prepare to reread opcode of next DVI command */
569 if (ungetc (opcode, dvi) == EOF)
571 fprintf (stderr, "setseq: cannot push back a byte\n");
575 /* end of sequence of font characters */
585 (int charcode, FILE * dtl)
591 /* set printable character */
596 fprintf (dtl, "%c", ESC_CHAR);
597 fprintf (dtl, "%c", ESC_CHAR);
600 fprintf (dtl, "%c", ESC_CHAR);
601 fprintf (dtl, "%c", QUOTE_CHAR);
604 fprintf (dtl, "%c", ESC_CHAR);
605 fprintf (dtl, "%c", BSEQ_CHAR);
608 fprintf (dtl, "%c", ESC_CHAR);
609 fprintf (dtl, "%c", ESEQ_CHAR);
612 fprintf (dtl, "%c", charcode);
621 (int k, FILE * dvi, FILE * dtl)
628 /* copy string of k characters from dvi file to dtl file */
635 for (i=0; i < k; i++)
638 if (ch == ESC_CHAR || ch == EMES_CHAR)
640 fprintf (dtl, "%c", ESC_CHAR);
642 fprintf (dtl, "%c", ch);
651 (FILE * dvi, FILE * dtl, int n)
658 /* read special 1 .. 4 from dvi and write in dtl */
659 /* return number of DVI bytes interpreted into DTL */
665 fprintf (stderr, "%s: special %d, range is 1 to 4.\n", program, n);
669 fprintf (dtl, "%s%d", SPECIAL, n);
671 /* k[n] = length of special string */
673 k = runsigned (n, dvi);
674 fprintf (dtl, UF4, k);
676 /* x[k] = special string */
677 xferstring (k, dvi, dtl);
686 (FILE * dvi, FILE * dtl, int n)
693 /* read fontdef 1 .. 4 from dvi and write in dtl */
694 /* return number of DVI bytes interpreted into DTL */
696 U4 ku, c, s, d, a, l;
701 fprintf (stderr, "%s: font def %d, range is 1 to 4.\n", program, n);
705 fprintf (dtl, "%s%d", FONTDEF, n);
707 /* k[n] = font number */
711 ks = rsigned (n, dvi);
712 fprintf (dtl, SF4, ks);
716 ku = runsigned (n, dvi);
717 fprintf (dtl, UF4, ku);
720 /* c[4] = checksum */
722 c = runsigned (4, dvi);
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);
730 /* s[4] = scale factor */
732 s = runsigned (4, dvi);
733 fprintf (dtl, UF4, s);
735 /* d[4] = design size */
737 d = runsigned (4, dvi);
738 fprintf (dtl, UF4, d);
740 /* a[1] = length of area (directory) name */
741 a = runsigned (1, dvi);
743 fprintf (dtl, UF4, a);
745 /* l[1] = length of font name */
746 l = runsigned (1, dvi);
748 fprintf (dtl, UF4, l);
750 /* n[a+l] = font pathname string => area (directory) + font */
751 xferstring (a, dvi, dtl);
752 xferstring (l, dvi, dtl);
754 return (1 + n + 4 + 4 + 4 + 1 + 1 + a + l);
761 (FILE * dvi, FILE * dtl)
767 /* read preamble from dvi and write in dtl */
768 /* return number of DVI bytes interpreted into DTL */
770 U4 id, num, den, mag, k;
772 fprintf (dtl, "pre");
774 /* i[1] = DVI format identification */
776 id = runsigned (1, dvi);
777 fprintf (dtl, UF4, id);
779 /* num[4] = numerator of DVI unit */
781 num = runsigned (4, dvi);
782 fprintf (dtl, UF4, num);
784 /* den[4] = denominator of DVI unit */
786 den = runsigned (4, dvi);
787 fprintf (dtl, UF4, den);
789 /* mag[4] = 1000 x magnification */
791 mag = runsigned (4, dvi);
792 fprintf (dtl, UF4, mag);
794 /* k[1] = length of comment */
796 k = runsigned (1, dvi);
797 fprintf (dtl, UF4, k);
799 /* x[k] = comment string */
800 xferstring (k, dvi, dtl);
802 return (1 + 1 + 4 + 4 + 4 + 1 + k);
809 (FILE * dvi, FILE * dtl)
815 /* read postamble from dvi and write in dtl */
816 /* return number of bytes */
818 U4 p, num, den, mag, l, u, s, t;
820 fprintf (dtl, "post");
822 /* p[4] = pointer to final bop */
824 p = runsigned (4, dvi);
825 fprintf (dtl, UF4, p);
827 /* num[4] = numerator of DVI unit */
829 num = runsigned (4, dvi);
830 fprintf (dtl, UF4, num);
832 /* den[4] = denominator of DVI unit */
834 den = runsigned (4, dvi);
835 fprintf (dtl, UF4, den);
837 /* mag[4] = 1000 x magnification */
839 mag = runsigned (4, dvi);
840 fprintf (dtl, UF4, mag);
842 /* l[4] = height + depth of tallest page */
844 l = runsigned (4, dvi);
845 fprintf (dtl, UF4, l);
847 /* u[4] = width of widest page */
849 u = runsigned (4, dvi);
850 fprintf (dtl, UF4, u);
852 /* s[2] = maximum stack depth */
854 s = runsigned (2, dvi);
855 fprintf (dtl, UF4, s);
857 /* t[2] = total number of pages (bop commands) */
859 t = runsigned (2, dvi);
860 fprintf (dtl, UF4, t);
863 return (1 + 4 + 4 + 4 + 4 + 4 + 4 + 2 + 2);
870 (FILE * dvi, FILE * dtl)
876 /* read post_post from dvi and write in dtl */
877 /* return number of bytes */
880 int b223; /* hope this is 8-bit clean */
881 int n223; /* number of "223" bytes in final padding */
883 fprintf (dtl, "post_post");
885 /* q[4] = pointer to post command */
887 q = runsigned (4, dvi);
888 fprintf (dtl, UF4, q);
890 /* i[1] = DVI identification byte */
892 id = runsigned (1, dvi);
893 fprintf (dtl, UF4, id);
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++)
900 fprintf (dtl, "%d", 223);
905 "%s: bad post_post: fewer than four \"223\" bytes.\n", program);
911 "%s: bad post_post: doesn't end with a \"223\".\n", program);
915 return (1 + 4 + 1 + n223);
919 /* end of "dv2dt.c" */