home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / dvi2tty-2 / disdvi.c < prev    next >
C/C++ Source or Header  |  1989-02-03  |  15KB  |  452 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /*   disdvi  ---  disassembles TeX dvi files.                                */
  4. /*                                                                           */
  5. /*****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include "commands.h"
  10. #if defined(MSDOS)
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <fcntl.h>
  14. #endif
  15.  
  16. #define LASTCHAR        127    /* max dvi character, above are commands    */
  17.  
  18. #define get1()           num(1)
  19. #define get2()           num(2)
  20. #define get3()           num(3)
  21. #define get4()           num(4)
  22. #define sget1()         snum(1)
  23. #define sget2()         snum(2)
  24. #define sget3()         snum(3)
  25. #define sget4()         snum(4)
  26.  
  27.  
  28. FILE * dvifp;
  29. char * dvi_name;
  30. long   pc = 0;
  31.  
  32. char *          malloc          ();
  33.  
  34. void            main            ();
  35. void            bop             ();
  36. void            preamble        ();
  37. void            postamble       ();
  38. void            postpostamble   ();
  39. void            fontdef         ();
  40. void            special         ();
  41. void            printnonprint   ();
  42. unsigned long   num             ();
  43. long            snum            ();
  44.  
  45.  
  46.  
  47.  
  48. /*---------------------------------------------------------------------------*/
  49.  
  50. void main(argc, argv)
  51. int argc;
  52. char **argv;
  53. {
  54.     register int opcode;                /* dvi opcode                        */
  55.     register int i;
  56.  
  57.     if (argc > 2) {
  58.         fprintf(stderr, "To many arguments\n");
  59.         fprintf(stderr, "Usage: %s [dvi-file]\n", *argv);
  60.         exit(1);
  61.     }
  62.  
  63.     if (argc == 2) {
  64.         if ((i = strlen(argv[1])) == 0) {
  65.             fprintf(stderr, "Illegal empty filename\n");
  66.             fprintf(stderr, "Usage: %s [dvi-file]\n", *argv);
  67.             exit(2);
  68.         }
  69.         if ((i >= 5) && (argv[1][i-4] == '.') && (argv[1][i-3] == 'd') &&
  70.               (argv[1][i-2] = 'v') && (argv[1][i-1] = 'i'))
  71.             dvi_name = argv[1];
  72.         else {
  73.             dvi_name = malloc((i+4) * sizeof(char));
  74.             strcpy(dvi_name, argv[1]);
  75.             strcat(dvi_name, ".dvi");
  76.         }
  77.         if ((dvifp = fopen(dvi_name, "r")) == NULL) {
  78.             perror(dvi_name);
  79.             exit(3);
  80.         }
  81.     }
  82.     else
  83.         dvifp = stdin;
  84.  
  85. #if defined(MSDOS)
  86.     setmode(fileno(dvifp), O_BINARY);
  87. #endif
  88.  
  89.     while ((opcode = (int) get1()) != EOF) {    /* process until end of file */
  90.         printf("%06ld: ", pc - 1);
  91.         if ((opcode <= LASTCHAR) && isprint(opcode)) {
  92.             printf("Char:     ");
  93.             while ((opcode <= LASTCHAR) && isprint(opcode)) {
  94.                 putchar(opcode);
  95.                 opcode = (int) get1();
  96.             }
  97.             putchar('\n');
  98.             printf("%06ld: ", pc - 1);
  99.         }
  100.  
  101.         if (opcode <= LASTCHAR) 
  102.             printnonprint(opcode);              /* it must be a non-printable */
  103.         else if ((opcode >= FONT_00) && (opcode <= FONT_63))
  104.             printf("FONT_%d\n", opcode - FONT_00);
  105.         else
  106.             switch (opcode) {
  107.                 case SET1     :
  108.                 case SET2     : 
  109.                 case SET3     :
  110.                 case SET4     : printf("SET%d:    %ld\n", opcode - SET1 + 1,
  111.                                                        num(opcode - SET1 + 1));
  112.                                 break;
  113.                 case SET_RULE : printf("SET_RULE: %ld, %ld\n", sget4(),
  114.                                                                 sget4());
  115.                                 break;
  116.                 case PUT1     :
  117.                 case PUT2     :
  118.                 case PUT3     :
  119.                 case PUT4     : printf("PUT%d:     %ld\n", opcode - PUT1 + 1,
  120.                                                        num(opcode - PUT1 + 1));
  121.                                 break;
  122.                 case PUT_RULE : printf("PUT_RULE: %ld, %ld\n", sget4(),
  123.                                                                 sget4());
  124.                                 break;
  125.                 case NOP      : printf("NOP\n");  break;
  126.                 case BOP      : bop();            break;
  127.                 case EOP      : printf("EOP\n");  break;
  128.                 case PUSH     : printf("PUSH\n"); break;
  129.                 case POP      : printf("POP\n");  break;
  130.                 case RIGHT1   :
  131.                 case RIGHT2   : 
  132.                 case RIGHT3   : 
  133.                 case RIGHT4   : printf("RIGHT%d:   %ld\n", opcode - RIGHT1 + 1,
  134.                                                      snum(opcode - RIGHT1 + 1));
  135.                                 break;
  136.                 case W0       : printf("W0\n");   break;
  137.                 case W1       : 
  138.                 case W2       :
  139.                 case W3       :
  140.                 case W4       : printf("W%d:       %ld\n", opcode - W0,
  141.                                                       snum(opcode - W0));
  142.                                 break;
  143.                 case X0       : printf("X0\n");   break;
  144.                 case X1       :
  145.                 case X2       :
  146.                 case X3       :
  147.                 case X4       : printf("X%d:       %ld\n", opcode - X0,
  148.                                                       snum(opcode - X0));
  149.                                 break;
  150.                 case DOWN1    : 
  151.                 case DOWN2    : 
  152.                 case DOWN3    :
  153.                 case DOWN4    : printf("DOWN%d:    %ld\n", opcode - DOWN1 + 1,
  154.                                                       snum(opcode - DOWN1 + 1));
  155.                                 break;
  156.                 case Y0       : printf("Y0\n");   break;
  157.                 case Y1       :
  158.                 case Y2       :
  159.                 case Y3       :
  160.                 case Y4       : printf("Y%d:       %ld\n", opcode - Y0,
  161.                                                       snum(opcode - Y0));
  162.                                 break;
  163.                 case Z0       : printf("Z0\n");   break;
  164.                 case Z1       :
  165.                 case Z2       :
  166.                 case Z3       : 
  167.                 case Z4       : printf("Z%d:       %ld\n", opcode - Z0,
  168.                                                       snum(opcode - Z0));
  169.                                 break;
  170.                 case FNT1     :
  171.                 case FNT2     :
  172.                 case FNT3     :
  173.                 case FNT4     : printf("FNT%d:     %ld\n", opcode - FNT1 + 1,
  174.                                                        num(opcode - FNT1 + 1));
  175.                                 break;
  176.                 case XXX1     : 
  177.                 case XXX2     : 
  178.                 case XXX3     :
  179.                 case XXX4     : special(opcode - XXX1 + 1);     break;
  180.                 case FNT_DEF1 :
  181.                 case FNT_DEF2 :
  182.                 case FNT_DEF3 :
  183.                 case FNT_DEF4 : fontdef(opcode - FNT_DEF1 + 1); break;
  184.                 case PRE      : preamble();                     break;
  185.                 case POST     : postamble();                    break;
  186.                 case POST_POST: postpostamble();                break;
  187.             }
  188.     }
  189.  
  190. } /* main */
  191.  
  192.  
  193. /*----------------------------------------------------------------------------*/
  194.  
  195.  
  196. void bop()
  197. {
  198.     int i;
  199.  
  200.     printf("BOP       page number      : %ld\n", sget4());
  201.     for (i=0; i < 3; i++) {
  202.         printf("%06ld: ", pc - 1);
  203.         printf("          %6ld  %6ld  %6ld\n", sget4(), sget4(), sget4()); 
  204.     }
  205.     printf("%06ld: ", pc - 1);
  206.     printf("          prev page offset : %06ld\n", sget4()); 
  207.  
  208. } /* bop */
  209.  
  210.  
  211. /*---------------------------------------------------------------------------*/
  212.  
  213. void postamble() 
  214. {
  215.  
  216.     printf("POST      last page offset : %06ld\n", sget4());
  217.     printf("%06ld: ", pc - 1);
  218.     printf("          numerator        : %ld\n", get4());
  219.     printf("%06ld: ", pc - 1);
  220.     printf("          denominator      : %ld\n", get4());
  221.     printf("%06ld: ", pc - 1);
  222.     printf("          magnification    : %ld\n", get4());
  223.     printf("%06ld: ", pc - 1);
  224.     printf("          max page height  : %ld\n", get4());
  225.     printf("%06ld: ", pc - 1);
  226.     printf("          max page width   : %ld\n", get4());
  227.     printf("%06ld: ", pc - 1);
  228.     printf("          stack size needed: %d\n", (int) get2());
  229.     printf("%06ld: ", pc - 1);
  230.     printf("          number of pages  : %d\n", (int) get2());
  231.  
  232. } /* postamble */
  233.  
  234. void preamble()
  235. {
  236.     register int i;
  237.  
  238.     printf("PRE       version          : %d\n", (int) get1());
  239.     printf("%06ld: ", pc - 1);
  240.     printf("          numerator        : %ld\n", get4());
  241.     printf("%06ld: ", pc - 1);
  242.     printf("          denominator      : %ld\n", get4());
  243.     printf("%06ld: ", pc - 1);
  244.     printf("          magnification    : %ld\n", get4());
  245.     printf("%06ld: ", pc - 1);
  246.     i = (int) get1();
  247.     printf("          job name (%03d)   :", i);
  248.     while (i-- > 0)
  249.         putchar((int) get1());
  250.     putchar('\n');
  251.  
  252. } /* preamble */
  253.  
  254.  
  255. void postpostamble()
  256. {
  257.     register int i;
  258.  
  259.     printf("POSTPOST  postamble offset : %06ld\n", get4());
  260.     printf("%06ld: ", pc - 1);
  261.     printf("          version          : %d\n", (int) get1());
  262.     while ((i = (int) get1()) == TRAILER) {
  263.         printf("%06d: ", pc - 1);
  264.         printf("TRAILER\n");
  265.     }
  266.     while (i != EOF) {
  267.         printf("%06ld: ", pc - 1);
  268.         printf("BAD DVI FILE END: 0x%02X\n", i);
  269.         i = (int) get1();
  270.     }
  271.  
  272. } /* postpostamble */
  273.  
  274.  
  275.  
  276. void special(x)
  277. register int x;
  278. {
  279.     register long len;
  280.     register long i;
  281.  
  282.     len = num(x);
  283.     printf("XXX%d:     %ld bytes\n", x, len);
  284.     printf("%06ld: ", pc - 1);
  285.     for (i = 0; i < len; i++)
  286.         putchar((int) get1());
  287.     putchar('\n');
  288.  
  289. } /* special */
  290.  
  291.  
  292.  
  293. void fontdef(x)
  294. register int x;
  295. {
  296.     register int i;
  297.  
  298.     printf("FNT_DEF%d: %ld\n", x, num(x));
  299.     printf("%06ld: ", pc - 1);
  300.     printf("          checksum         : %ld\n", get4());
  301.     printf("%06ld: ", pc - 1);
  302.     printf("          scale            : %ld\n", get4());
  303.     printf("%06ld: ", pc - 1);
  304.     printf("          design           : %ld\n", get4());
  305.     printf("%06ld: ", pc - 1);
  306.     printf("          name             : ");
  307.     for (i = (int) get1() + (int) get1(); i > 0; i--)
  308.         putchar((int) get1());
  309.     putchar('\n');
  310.  
  311. } /* fontdef */
  312.  
  313.  
  314.  
  315. void printnonprint(ch)
  316. register int ch;
  317. {
  318.  
  319.     printf("Char:     ");
  320.     switch (ch) {
  321.         case 11  :  printf("ff         /* ligature (non-printing) */"); break;
  322.         case 12  :  printf("fi         /* ligature (non-printing) */"); break;
  323.         case 13  :  printf("fl         /* ligature (non-printing) */"); break;
  324.         case 14  :  printf("ffi        /* ligature (non-printing) */"); break;
  325.         case 15  :  printf("ffl        /* ligature (non-printing) */"); break;
  326.         case 16  :  printf("i          /* (non-printing) */");          break;
  327.         case 17  :  printf("j          /* (non-printing) */");          break;
  328.         case 25  :  printf("ss         /* german (non-printing) */");   break;
  329.         case 26  :  printf("ae         /* scadinavian (non-printing) */");
  330.                     break;
  331.         case 27  :  printf("oe         /* scadinavian (non-printing) */");
  332.                     break;
  333.         case 28  :  printf("o          /* scadinavian (non-printing) */");
  334.                     break;
  335.         case 29  :  printf("AE         /* scadinavian (non-printing) */");
  336.                     break;
  337.         case 30  :  printf("OE         /* scadinavian (non-printing) */");
  338.                     break;
  339.         case 31  :  printf("O          /* scadinavian (non-printing) */");
  340.                     break;
  341.         default  :  printf("0x%2X", ch); break;
  342.     }
  343.     putchar('\n');
  344.  
  345. }
  346.  
  347.  
  348.  
  349. unsigned long num(size)
  350. register int size;
  351. {
  352.     register int i;
  353.     register long x = 0;
  354.  
  355.     pc += size;
  356.     for (i = 0; i < size; i++)
  357.         x = (x << 8) + (unsigned) getc(dvifp);
  358.     return x;
  359.  
  360. } /* num */
  361.  
  362.  
  363.  
  364. long snum(size)
  365. register int size;
  366. {
  367.     register int i;
  368.     register long x = 0;
  369.  
  370.     pc += size;
  371.     x = getc(dvifp);
  372.     if (x & 0x80)
  373.         x -= 0x100;
  374.     for (i = 1; i < size; i++)
  375.         x = (x << 8) + (unsigned) getc(dvifp);
  376.     return x;
  377.  
  378. } /* snum */
  379.  
  380.  
  381.  
  382. /*
  383.  
  384.  
  385. ================================================================================
  386. ==                          DVI file format                                   ==
  387. ================================================================================
  388. no_ops          >= 0 bytes     (NOP, nops before the preamble)
  389. preamble_marker    1 ubyte     (PRE)
  390. version_id         1 ubyte     (should be version 2)
  391. numerator          4 ubytes    (numerater must equal the one in postamble)
  392. denominator        4 ubytes    (denominator must equal the one in postamble)
  393. magnification      4 ubytes    (magnification must equal the one in postamble)
  394. id_len             1 ubyte     (lenght of identification string)
  395. id_string     id_len ubytes    (identification string)
  396.  
  397. no_ops          >= 0 bytes     (NOP, nops before a page)
  398. begin_of_page      1 ubyte     (BOP)
  399. page_nr            4 sbytes    (page number)
  400. do_be_do          36 bytes     (filler ????)
  401. prev_page_offset   4 sbytes    (offset in file where previous page starts, -1 for none)
  402. ... PAGE DATA ...
  403. end_of_page        1 ubyte     (EOP)
  404.  
  405. no_ops ???      >= 0 bytes     (NOPS, I think they are allowed here...)
  406. postamble_marker   1 ubyte     (POST)
  407. last_page_offset   4 sbytes    (offset in file where last page starts)
  408. numerator          4 ubytes    (numerater must equal the one in preamble)
  409. denominator        4 ubytes    (denominator must equal the one in preamble)
  410. magnification      4 ubytes    (magnification must equal the one in preamble)
  411. max_page_height    4 ubytes    (maximum page height)
  412. max_page_width     4 ubytes    (maximum page width)
  413. max_stack          2 ubytes    (maximum stack depth needed)
  414. total_pages        2 ubytes    (number of pages in file)
  415. ... FONT DEFINITIONS ...
  416.  
  417. postamble_offset   4 sbytes    (offset in file where postamble starts)
  418. version_id         1 ubyte     (should be version 2)
  419. trailer         >= 4 ubytes    (TRAILER)
  420. <EOF>
  421.  
  422.  
  423. FONT DEFINITIONS:
  424.    do {
  425.       switch (c = getc(dvi_fp) {
  426.           case FNTDEF1  :
  427.           case FNTDEF2  :
  428.           case FNTDEF3  :
  429.           case FNTDEF4  :  define_font(c);
  430.           case POSTPOST : break;
  431.           default       : error;
  432.       }
  433.    } while (c != POSTPOST);
  434.  
  435. ===== A font def looks like:
  436.  
  437. 1,2,3 or 4 ubytes TeXfontnumber for FNTDEF1 .. FNTDEF4
  438. 4 ubytes checksum
  439. 4 ubytes scale
  440. 4 ubytes design size
  441. 1 byte deflen1
  442. 1 byte deflen2
  443. deflen1 + deflen2 bytes fontname.
  444.  
  445. ===== A special looks like:
  446.  
  447. 1,2,3 or 4 ubytes telling length of special command for XXX1 .. XXX4
  448. all bytes in the special command are used as defined in the dvi driver.
  449.  
  450.  
  451. */
  452.