1 /*****************************************************************************/
2 /* */
3 /* disdvi --- disassembles TeX dvi files. */
4 /* */
5 /* */
6 /* 2.26 23oct2010 TexLivel support pTex and XeTex */
7 /* 2.25 23jan2003 M.J.E. Mol fixed bug in copying font name (name[i]) */
8 /* 2.24 27may96 M.J.E. Mol A few typecasts added */
9 /* 2.23 23jul95 M.J.E. Mol Cleanups from duz@roxi.ez.fht-mannheim.de */
10 /* 2.22 13dec90 M.J.E. Mol Fixed bug in num(). Cleaned up code. */
11 /* 2.21 03may90 M.J.E. Mol Created usage(). */
12 /* 2.2 02may90 M.J.E. Mol Included port to VAX/VMS VAXC by */
13 /* Robert Schneider. */
14 /* 2.1 19jan90 M.J.E. Mol Maintain a list of fonts and */
15 /* show fontnames in font changes. */
16 /* Show character code when printing ligatures */
17 /* 2.0 23jan89 M.J.E. Mol (c) 1989 */
18 /* marcel@mesa.nl */
19 /* */
20 /*****************************************************************************/
21
22 /*
23 * dvi2tty
24 * Copyright (C) 2003 Marcel J.E. Mol <marcel@mesa.nl>
25 *
26 * This program is free software; you can redistribute it and/or
27 * modify it under the terms of the GNU General Public License
28 * as published by the Free Software Foundation; either version 2
29 * of the License, or (at your option) any later version.
30 *
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 *
40 */
41
42 const char *disdvi = "@(#) disdvi.c 2.26 20101027 M.J.E. Mol (c) 1989-2010, marcel@mesa.nl";
43
44 /*
45 * Include files
46 */
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #if defined(MSDOS) || defined(WIN32)
51 # include <fcntl.h>
52 #else
53 # if !defined(THINK_C) /* Macintosh */
54 # include <unistd.h>
55 # endif
56 #endif
57 #include <ctype.h>
58 #include <string.h>
59 #include "commands.h"
60 #if defined(THINK_C)
61 # include "macintosh.h"
62 #endif
63
64 #if defined(KPATHSEA)
65 # define NO_DEBUG 1
66 # include <kpathsea/config.h>
67 # include <kpathsea/lib.h>
68 #endif
69
70
71 /*
72 * Constant definitions
73 */
74
75 #define LASTCHAR 127 /* max dvi character, above are commands */
76
77 #define get1() num(1)
78 #define get2() num(2)
79 #define get3() num(3)
80 #define get4() num(4)
81 #define sget1() snum(1)
82 #define sget2() snum(2)
83 #define sget3() snum(3)
84 #define sget4() snum(4)
85
86
87
88 /*
89 * Type definitions
90 */
91
92 typedef struct _font {
93 long num;
94 struct _font * next;
95 char * name;
96 } font;
97
98
99
100 /*
101 * Variable declarations
102 */
103
104 font * fonts = NULL;
105 FILE * dvifp;
106 char * dvi_name;
107 long pc = 0;
108
109 char * progname;
110
111 int is_ptex = 0;
112 int is_xetex = 0;
113 const char * dvi_ext = ".dvi";
114
115 /*
116 * Function declarations
117 */
118
119 #if defined(VMS)
120 main (int argc, char ** argv);
121 #endif
122 void bop (void);
123 void preamble (void);
124 void postamble (void);
125 void postpostamble (void);
126 void fontdef (int x);
127 const char * fontname (unsigned long fntnum);
128 void special (int x);
129 void printnonprint (int ch);
130 unsigned long num (int size);
131 long snum (int size);
132 void usage (void);
133 void picfile (int opcode);
134 void natfontdef (int opcode);
135 void glyphs (int opcode);
136 void dvidir (int opcode);
137 void invalid (int opcode);
138
139
140
141
142 /*
143 * MAIN --
144 */
145
146 #if defined(VMS)
main(int argc,char ** argv)147 main(int argc, char **argv)
148 #else
149 int main(int argc, char **argv)
150 #endif
151 {
152 register int opcode; /* dvi opcode */
153 register int i;
154 unsigned long fontnum;
155
156 #if defined(THINK_C)
157 argc = process_disdvi_command_line(&argv);
158 #endif
159
160 progname = *argv++;
161
162 if ((argc > 1) && (*argv[0] == '-')) {
163 if (!strcmp(*argv, "-h")) {
164 usage();
165 exit(0);
166 }
167 if (!strcmp(*argv, "-p"))
168 is_ptex = 1;
169 else if (!strcmp(*argv, "-x")) {
170 is_xetex = 1;
171 dvi_ext = ".xdv";
172 } else {
173 fprintf(stderr, "Invalid option `%s'\n", *argv);
174 usage();
175 exit(3);
176 }
177 argv++;
178 argc--;
179 }
180
181 if (argc > 2) {
182 fprintf(stderr, "To many arguments\n");
183 usage();
184 exit(1);
185 }
186
187 if (argc == 2) {
188 if ((i = strlen(*argv)) == 0) {
189 fprintf(stderr, "Illegal empty filename\n");
190 usage();
191 exit(2);
192 }
193 if ((i >= 5) && (!strcmp(*argv+i-4, dvi_ext)))
194 dvi_name = *argv;
195 else {
196 dvi_name = malloc((i+5) * sizeof(char));
197 strcpy(dvi_name, *argv);
198 strcat(dvi_name, dvi_ext);
199 }
200 if ((dvifp = fopen(dvi_name, "r")) == NULL) {
201 perror(dvi_name);
202 exit(3);
203 }
204 }
205 else
206 dvifp = stdin;
207
208 #if defined(MSDOS) || defined(WIN32)
209 setmode(fileno(dvifp), O_BINARY);
210 #endif
211
212 while ((opcode = (int) get1()) != EOF) { /* process until end of file */
213 printf("%06ld: ", pc - 1);
214 if ((opcode <= LASTCHAR) && isprint(opcode)) {
215 printf("Char: ");
216 while ((opcode <= LASTCHAR) && isprint(opcode)) {
217 putchar(opcode);
218 opcode = (int) get1();
219 }
220 putchar('\n');
221 printf("%06ld: ", pc - 1);
222 }
223
224 if (opcode <= LASTCHAR)
225 printnonprint(opcode); /* it must be a non-printable */
226 else if ((opcode >= FONT_00) && (opcode <= FONT_63))
227 printf("FONT_%02d /* %s */\n", opcode - FONT_00,
228 fontname((unsigned long) opcode - FONT_00));
229 else
230 switch (opcode) {
231 case SET1 :
232 case SET2 :
233 case SET3 :
234 case SET4 : printf("SET%d: %ld\n", opcode - SET1 + 1,
235 num(opcode - SET1 + 1));
236 break;
237 case SET_RULE : printf("SET_RULE: height: %ld\n", sget4());
238 printf("%06ld: ", pc);
239 printf(" length: %ld\n", sget4());
240 break;
241 case PUT1 :
242 case PUT2 :
243 case PUT3 :
244 case PUT4 : printf("PUT%d: %ld\n", opcode - PUT1 + 1,
245 num(opcode - PUT1 + 1));
246 break;
247 case PUT_RULE : printf("PUT_RULE: height: %ld\n", sget4());
248 printf("%06ld: ", pc);
249 printf(" length: %ld\n", sget4());
250 break;
251 case NOP : printf("NOP\n"); break;
252 case BOP : bop(); break;
253 case EOP : printf("EOP\n"); break;
254 case PUSH : printf("PUSH\n"); break;
255 case POP : printf("POP\n"); break;
256 case RIGHT1 :
257 case RIGHT2 :
258 case RIGHT3 :
259 case RIGHT4 : printf("RIGHT%d: %ld\n", opcode - RIGHT1 + 1,
260 snum(opcode - RIGHT1 + 1));
261 break;
262 case W0 : printf("W0\n"); break;
263 case W1 :
264 case W2 :
265 case W3 :
266 case W4 : printf("W%d: %ld\n", opcode - W0,
267 snum(opcode - W0));
268 break;
269 case X0 : printf("X0\n"); break;
270 case X1 :
271 case X2 :
272 case X3 :
273 case X4 : printf("X%d: %ld\n", opcode - X0,
274 snum(opcode - X0));
275 break;
276 case DOWN1 :
277 case DOWN2 :
278 case DOWN3 :
279 case DOWN4 : printf("DOWN%d: %ld\n", opcode - DOWN1 + 1,
280 snum(opcode - DOWN1 + 1));
281 break;
282 case Y0 : printf("Y0\n"); break;
283 case Y1 :
284 case Y2 :
285 case Y3 :
286 case Y4 : printf("Y%d: %ld\n", opcode - Y0,
287 snum(opcode - Y0));
288 break;
289 case Z0 : printf("Z0\n"); break;
290 case Z1 :
291 case Z2 :
292 case Z3 :
293 case Z4 : printf("Z%d: %ld\n", opcode - Z0,
294 snum(opcode - Z0));
295 break;
296 case FNT1 :
297 case FNT2 :
298 case FNT3 :
299 case FNT4 : fontnum = num(opcode -FNT1 + 1);
300 printf("FNT%d: %ld /* %s */\n",
301 opcode - FNT1 + 1, fontnum,
302 fontname(fontnum));
303 break;
304 case XXX1 :
305 case XXX2 :
306 case XXX3 :
307 case XXX4 : special(opcode - XXX1 + 1); break;
308 case FNT_DEF1 :
309 case FNT_DEF2 :
310 case FNT_DEF3 :
311 case FNT_DEF4 : fontdef(opcode - FNT_DEF1 + 1); break;
312 case PRE : preamble(); break;
313 case POST : postamble(); break;
314 case POST_POST: postpostamble(); break;
315 case PIC_FILE : picfile(opcode); break;
316 case NAT_FNT : natfontdef(opcode); break;
317 case SET_GL_AR:
318 case SET_GL_ST: glyphs(opcode); break;
319 case DVI_DIR : dvidir(opcode); break;
320 default : invalid(opcode);
321 }
322 }
323
324 exit(0);
325
326 } /* main */
327
328
329
330 /*
331 * BOP -- Process beginning of page.
332 */
333
bop(void)334 void bop(void)
335 {
336 int i;
337
338 printf("BOP page number : %ld", sget4());
339 for (i=9; i > 0; i--) {
340 if (i % 3 == 0)
341 printf("\n%06ld: ", pc);
342 printf(" %6ld", sget4());
343 }
344 printf("\n%06ld: ", pc);
345 printf(" prev page offset : %06ld\n", sget4());
346
347 return;
348
349 } /* bop */
350
351
352
353 /*
354 * POSTAMBLE -- Process post amble.
355 */
356
postamble(void)357 void postamble(void)
358 {
359
360 printf("POST last page offset : %06ld\n", sget4());
361 printf("%06ld: ", pc);
362 printf(" numerator : %ld\n", get4());
363 printf("%06ld: ", pc);
364 printf(" denominator : %ld\n", get4());
365 printf("%06ld: ", pc);
366 printf(" magnification : %ld\n", get4());
367 printf("%06ld: ", pc);
368 printf(" max page height : %ld\n", get4());
369 printf("%06ld: ", pc);
370 printf(" max page width : %ld\n", get4());
371 printf("%06ld: ", pc);
372 printf(" stack size needed: %d\n", (int) get2());
373 printf("%06ld: ", pc);
374 printf(" number of pages : %d\n", (int) get2());
375
376 return;
377
378 } /* postamble */
379
380
381
382 /*
383 * PREAMBLE -- Process pre amble.
384 */
385
preamble(void)386 void preamble(void)
387 {
388 register int i;
389
390 printf("PRE version : %d\n", (int) get1());
391 printf("%06ld: ", pc);
392 printf(" numerator : %ld\n", get4());
393 printf("%06ld: ", pc);
394 printf(" denominator : %ld\n", get4());
395 printf("%06ld: ", pc);
396 printf(" magnification : %ld\n", get4());
397 printf("%06ld: ", pc);
398 i = (int) get1();
399 printf(" job name (%3d) :", i);
400 while (i-- > 0)
401 putchar((int) get1());
402 putchar('\n');
403
404 return;
405
406 } /* preamble */
407
408
409
410 /*
411 * POSTPOSTAMBLE -- Process post post amble.
412 */
413
postpostamble(void)414 void postpostamble(void)
415 {
416 register int i;
417
418 printf("POSTPOST postamble offset : %06ld\n", get4());
419 printf("%06ld: ", pc);
420 printf(" version : %d\n", (int) get1());
421 while ((i = (int) get1()) == TRAILER) {
422 printf("%06ld: ", pc - 1);
423 printf("TRAILER\n");
424 }
425 while (i != EOF) {
426 printf("%06ld: ", pc - 1);
427 printf("BAD DVI FILE END: 0x%02X\n", i);
428 i = (int) get1();
429 }
430
431 return;
432
433 } /* postpostamble */
434
435
436
437 /*
438 * SPECIAL -- Process special opcode.
439 */
440
special(int x)441 void special(int x)
442 {
443 register long len;
444
445 len = num(x);
446 printf("XXX%d: %ld bytes\n", x, len);
447 printf("%06ld: ", pc);
448 for (; len>0; len--) /* a bit dangerous ... */
449 putchar((int) get1()); /* can be non-printables */
450 putchar('\n');
451
452 return;
453
454 } /* special */
455
456
457
458 /*
459 * FONTDEF -- Process a font definition.
460 */
461
fontdef(int x)462 void fontdef(int x)
463 {
464 register int i;
465 char * name;
466 font * fnt;
467 int namelen;
468 unsigned long fntnum;
469 int new = 0;
470
471 fntnum = num(x);
472 printf("FNT_DEF%d: %ld\n", x, fntnum);
473 printf("%06ld: ", pc); /* avoid side-effect on pc in get4() */
474 printf(" checksum : %ld\n", get4());
475 printf("%06ld: ", pc);
476 printf(" scale : %ld\n", get4());
477 printf("%06ld: ", pc);
478 printf(" design : %ld\n", get4());
479 printf("%06ld: ", pc);
480 printf(" name : ");
481 namelen = (int) get1() + (int) get1();
482 fnt = fonts;
483 while (fnt != NULL && fnt->num != fntnum)
484 fnt = fnt->next;
485 if (fnt == NULL) {
486 if ((fnt = (font *) malloc(sizeof(font))) == NULL) {
487 perror("fontdef");
488 exit(1);
489 }
490 fnt->num = fntnum;
491 new = 1;
492 }
493 else
494 free(fnt->name); /* free old name */
495 if ((name = (char *) malloc((namelen+1) * sizeof(char))) == NULL) {
496 perror("fontdef");
497 exit(1);
498 }
499
500 for (i = 0; i < namelen; i++)
501 name[i] = get1();
502 name[i] = '\0';
503 fnt->name = name;
504 if (new) {
505 fnt->next = fonts;
506 fonts = fnt;
507 }
508
509 printf("%s\n", name);
510
511 return;
512
513 } /* fontdef */
514
515
516
517 /*
518 * FONTNAME -- Return font name.
519 */
520
fontname(unsigned long fntnum)521 const char * fontname(unsigned long fntnum)
522 {
523 font * fnt;
524
525 fnt = fonts;
526 while (fnt != NULL && fnt->num != fntnum)
527 fnt = fnt->next;
528 if (fnt != NULL)
529 return fnt->name;
530
531 return "unknown fontname";
532
533 } /* fontname */
534
535
536
537 /*
538 * PRINTNONPRINT -- Translate non-printable characters.
539 */
540
printnonprint(int ch)541 void printnonprint(int ch)
542 {
543
544 printf("Char: ");
545 switch (ch) {
546 case 11 : printf("ff /* ligature (non-printing) 0x%02X */",
547 ch);
548 break;
549 case 12 : printf("fi /* ligature (non-printing) 0x%02X */",
550 ch);
551 break;
552 case 13 : printf("fl /* ligature (non-printing) 0x%02X */",
553 ch);
554 break;
555 case 14 : printf("ffi /* ligature (non-printing) 0x%02X */",
556 ch);
557 break;
558 case 15 : printf("ffl /* ligature (non-printing) 0x%02X */",
559 ch);
560 break;
561 case 16 : printf("i /* (non-printing) 0x%02X */", ch);
562 break;
563 case 17 : printf("j /* (non-printing) 0x%02X */", ch);
564 break;
565 case 25 : printf("ss /* german (non-printing) 0x%02X */", ch);
566 break;
567 case 26 : printf("ae /* scandinavian (non-printing) 0x%02X */",
568 ch);
569 break;
570 case 27 : printf("oe /* scandinavian (non-printing) 0x%02X */",
571 ch);
572 break;
573 case 28 : printf("o /* scandinavian (non-printing) 0x%02X */",
574 ch);
575 break;
576 case 29 : printf("AE /* scandinavian (non-printing) 0x%02X */",
577 ch);
578 break;
579 case 30 : printf("OE /* scandinavian (non-printing) 0x%02X */",
580 ch);
581 break;
582 case 31 : printf("O /* scandinavian (non-printing) 0x%02X */",
583 ch);
584 break;
585 default : printf("0x%02X", ch); break;
586 }
587 putchar('\n');
588
589 return;
590
591 } /* printnonprint */
592
593
594
595 /*
596 * NUM --
597 */
598
num(int size)599 unsigned long num(int size)
600 {
601 register int i;
602 register unsigned long x = 0;
603
604 pc += size;
605 for (i = size; i > 0; i--)
606 x = (x << 8) + (unsigned) getc(dvifp);
607
608 return x;
609
610 } /* num */
611
612
613
614 /*
615 * SNUM --
616 */
617
snum(int size)618 long snum(int size)
619 {
620 register int i;
621 register long x;
622
623 pc += size;
624 x = getc(dvifp);
625 if (x & 0x80)
626 x -= 0x100;
627 for (i = size - 1; i > 0; i--)
628 x = (x << 8) + (unsigned) getc(dvifp);
629
630 return x;
631
632 } /* snum */
633
634
635
636 /*
637 * USAGE --
638 */
639
usage(void)640 void usage(void)
641 {
642
643 fprintf(stderr, "\n%s\n\n", disdvi);
644 fprintf(stderr, " disassembles (p)TeX dvi and XeTeX xdv files\n");
645 fprintf(stderr, "Usage: %s [-h | [-p] [dvi_file[.dvi]]\n", progname);
646 fprintf(stderr, " | -x [xdv_file[.xdv]]]\n");
647 fprintf(stderr, "\n If you like this code and want to support is feel free\n to donate at Paypal marcel@mesa.nl. Thanks.\n\n");
648
649
650 return;
651
652 } /* usage */
653
654
655
picfile(int opcode)656 void picfile(int opcode)
657 {
658 int i;
659
660 if (!is_xetex) {
661 invalid(opcode);
662 return;
663 }
664
665 printf("PIC_FILE flags : %ld\n", get1());
666 printf("%06ld: trans :", pc);
667 for (i=0; i<6; i++)
668 printf(" %ld", sget4());
669 printf("\n%06ld: ", pc);
670 printf(" page : %ld\n", get2());
671 printf("%06ld: ", pc);
672 i = (int) get1();
673 printf(" path name (%3d) :", i);
674 while (i-- > 0)
675 putchar((int) get1());
676 putchar('\n');
677 } /* picfile */
678
679
680
natfontdef(int opcode)681 void natfontdef(int opcode)
682 {
683 register int i;
684 char * name;
685 font * fnt;
686 int flags, namelen, famlen, stylen;
687 long fntnum;
688 int new = 0;
689
690 if (!is_xetex) {
691 invalid(opcode);
692 return;
693 }
694
695 fntnum = num(4);
696 printf("NAT_FNT: %ld\n", fntnum);
697 printf("%06ld: ", pc);
698 printf(" scale : %ld\n", get4());
699 printf("%06ld: ", pc);
700 flags = get2();
701 printf(" flags : %d\n", flags);
702 printf("%06ld: ", pc);
703 printf(" name : ");
704 namelen = (int) get1();
705 famlen = (int) get1();
706 stylen = (int) get1();
707 fnt = fonts;
708 while (fnt != NULL && fnt->num != fntnum)
709 fnt = fnt->next;
710 if (fnt == NULL) {
711 if ((fnt = (font *) malloc(sizeof(font))) == NULL) {
712 perror("fontdef");
713 exit(1);
714 }
715 fnt->num = fntnum;
716 new = 1;
717 }
718 else
719 free(fnt->name); /* free old name */
720 if ((name = (char *) malloc((namelen+1) * sizeof(char))) == NULL) {
721 perror("fontdef");
722 exit(1);
723 }
724
725 for (i = 0; i < namelen; i++)
726 name[i] = get1();
727 name[namelen] = '\0';
728 fnt->name = name;
729 if (new) {
730 fnt->next = fonts;
731 fonts = fnt;
732 }
733
734 printf("%s\n", name);
735
736 if (famlen) {
737 printf(" family : ");
738 while (famlen-- > 0)
739 putchar((int) get1());
740 putchar('\n');
741 }
742
743 if (stylen) {
744 printf(" style : ");
745 while (stylen-- > 0)
746 putchar((int) get1());
747 putchar('\n');
748 }
749 } /* fontdef */
750
751
752
glyphs(int opcode)753 void glyphs(int opcode)
754 {
755 long width;
756 int x, n, i, j;
757 long * xy;
758
759 if (!is_xetex) {
760 invalid(opcode);
761 return;
762 }
763
764 x = SET_GL_ST - opcode + 1;
765 width = sget4();
766 n = get2();
767 printf("GLYPH_%s width : %ld\n", x == 2 ? "ARR" : "STR", width);
768 if ((xy = (long *) malloc(n * x * sizeof(long))) == NULL) {
769 perror("glyphs");
770 exit(1);
771 }
772 for (j=0; j < n * x; j++)
773 xy[j] = sget4();
774 for (i=0, j=0; i < n; i++) {
775 printf(" x: %ld", xy[j++]);
776 if (x == 2)
777 printf(" y: %ld", xy[j++]);
778 printf(" g: %ld\n", get2());
779 }
780 } /* glyphs */
781
782
783
dvidir(int opcode)784 void dvidir(int opcode)
785 {
786 if (!is_ptex) {
787 invalid(opcode);
788 return;
789 }
790
791 printf("DVI_DIR: %ld\n", get1());
792 } /* dvidir */
793
794
795
invalid(int opcode)796 void invalid(int opcode)
797 {
798 printf("INVALID %d\n", opcode);
799 } /* invalid */
800