home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / DVIDVI / DVIDVI.OLD < prev    next >
Text File  |  1992-01-20  |  19KB  |  692 lines

  1. /*
  2.  *   This program converts dvi files to dvi files; it can be used
  3.  *   to:
  4.  *      reverse the pages            -
  5.  *      select even                  2:1
  6.  *      or odd                       2:0
  7.  *      print both on same page      2:0,1(5.5in,0in)
  8.  *      do folded brochures          4:-3,0(5.5in,0in)
  9.  *                                   4:1,-2(5.5in,0in)
  10.  *      etc.
  11.  */
  12. #ifndef VMS
  13. #include <stdio.h>
  14. #else /* VMS */
  15. #include "sys$library:stdio.h"       /* AKT: added sys$library: */
  16. #endif /* VMS */
  17. #define MAXPPERP (32)
  18. /*
  19.  *   Some globals to keep everyone happy.
  20.  */
  21. long **pagepos ;     /* an array holding the positions of each page. */
  22. long numpages ;      /* the total number of pages in the dvi file. */
  23. long TeXfonts[256] ; /* information about each font */
  24. char fontseen[256] ; /* have we defined this font yet? */
  25. int modulo ;         /* our mod value */
  26. struct pagespec {
  27.    int pageno, reversed ;
  28.    long hoffset, voffset ; /* in scaled points */
  29. } pages[MAXPPERP] ;  /* the organization of the pages on output */
  30. int pagesperpage ;   /* how many pages crammed onto each page? */
  31. FILE *infile ;       /* input dvi file (cannot be a stream) */
  32. char *temp[255] ;    /* a temporary place to put things */
  33. unsigned char *dvibuf ; /* our entire dvi file */
  34. long inlength ;      /* the length of the input dvi file */
  35. long postloc ;       /* location of the postamble */
  36. long mag ;           /* magnification factor */
  37. long pagecount ;     /* number of actual pages */
  38. long landscape ;     /* if landscape special, here it is! */
  39. int rem0special ;    /* should we remove the first first-page special? */
  40. long prevpp = -1 ;   /* previous page pointer on output */
  41. long outputpages ;   /* number of pages output */
  42. long dviloc ;        /* our position in the output file */
  43. long pagefake ;      /* number of pages, rounded up to multiple of modulo */
  44. /*
  45.  *   Some def's to make things friendlier.
  46.  */
  47. #define fontdeflen(p) (16L+dvibuf[(p)+14]+dvibuf[(p)+15])
  48. /*
  49.  *   Forward declarations.
  50.  */
  51. char *malloc() ;
  52. /*
  53.  *   This array holds values that indicate the length of a command, if
  54.  *   we aren't concerned with that command (which is most of them) or
  55.  *   zero, if it is a special case.  This makes running through the
  56.  *   dvi file a lot easier (and probably faster) than any form of
  57.  *   dispatch table, especially since we really don't care what the
  58.  *   pages are made of.
  59.  */
  60. short comlen[256] = {
  61.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0-15 */
  62.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 16-31 */
  63.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 32-47 */
  64.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 48-63 */
  65.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 */
  66.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80-95 */
  67.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 */
  68.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 112-127 */
  69.    2, 3, 4, 5, 9, 2, 3, 4, 5, 9, 1, 0, 0, 1, 1, 2, /* 128-143 */
  70.    3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 2, 3, 4, /* 144-159 */
  71.    5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, /* 160-175 */
  72.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176-191 */
  73.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192-207 */
  74.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208-223 */
  75.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 0, /* 224-239 */
  76.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* 240-255 */
  77. /*
  78.  *   Print a usage error messsage, and quit.
  79.  */
  80. usage() {
  81.    fprintf(stderr,
  82.        "This is dvidvi 0.5, Copyright (C) 1988, Radical Eye Software\n") ;
  83.    fprintf(stderr, "Usage:  dvidvi modulo:pagespecs input[.dvi] [output]\n") ;
  84. #ifndef VMS
  85.    exit(1) ;
  86. #else /* VMS */
  87.    exit(0x10000002) ;
  88.    /* AKT: was exit(1) */
  89. #endif /* VMS */
  90. }
  91. /*
  92.  *   Print an error message, and exit if it is fatal.
  93.  */
  94. error(s)
  95. char *s ;
  96. {
  97.    fprintf(stderr, "%s\n", s) ;    /* AKT: was dvidvi: %s */
  98.    if (*s == '!')
  99. #ifndef VMS
  100.       exit(1) ;
  101. #else /* VMS */
  102.       exit(0x10000002) ;
  103.       /* AKT: was exit(1) */
  104. #endif /* VMS */
  105. }
  106. /*
  107.  *   This function calculates approximately (whole + num/den) * sf.
  108.  *   No need for real extreme accuracy; one ten thousandth of an
  109.  *   inch should be sufficient.
  110.  *
  111.  *   No `sf' parameter means to use an old one; inches are assumed
  112.  *   originally.
  113.  *
  114.  *   Assumptions:
  115.  *
  116.  *      0 <= num < den <= 10000
  117.  *      0 <= whole
  118.  */
  119. long defaultscale = 4736286 ;
  120. long scale(whole, num, den, sf)
  121. long whole, num, den, sf ;
  122. {
  123.    long v ;
  124.  
  125.    if (sf)
  126.       defaultscale = sf ;
  127.    else
  128.       sf = defaultscale ;
  129.    v = whole * sf + num * (sf / den) ;
  130.    if (v / sf != whole || v < 0 || v > 0x40000000L)
  131.       error("! arithmetic overflow in parameter") ;
  132.    sf = sf % den ;
  133.    v += (sf * num * 2 + den) / (2 * den) ;
  134.    return(v) ;
  135. }
  136. /*
  137.  *   Multiplies *p by 1000 and divides it by mag.  Avoiding overflow.
  138.  *
  139.  *   1 <= mag <= 1000000 ;
  140.  *   0 <= *p <= 2^30
  141.  *
  142.  *   (Could blow up if a parameter * mag / 1000 > 2^30 sp.)
  143.  */
  144. scalemag(p)
  145. long *p ;
  146. {
  147.    int negative ;
  148.  
  149.    negative = 0 ;
  150.    if (*p < 0) {
  151.       negative = 1 ;
  152.       *p = - *p ;
  153.    }
  154.    *p = 1000 * (*p / mag) + (2000 * (*p % mag) + mag) / (2 * mag) ;
  155.    if (negative)
  156.       *p = - *p ;
  157. }
  158. /*
  159.  *   Convert a sequence of digits into a long; return -1 if no digits.
  160.  *   Advance the passed pointer as well.
  161.  */
  162. long myatol(s)
  163. char **s ;
  164. {
  165.    register char *p ;
  166.    register long result ;
  167.  
  168.    result = 0 ;
  169.    p = *s ;
  170.    while ('0' <= *p && *p <= '9') {
  171.       if (result > 100000000)
  172.          error("! arithmetic overflow in parameter") ;
  173.       result = 10 * result + *p++ - '0' ;
  174.    }
  175.    if (p == *s)
  176.       usage() ;
  177.    else {
  178.       *s = p ;
  179.       return(result) ;
  180.    }
  181. }
  182. /*
  183.  *   Get a dimension, allowing all the various extensions, and
  184.  *   defaults.
  185.  */
  186. long myatodim(s)
  187. char **s ;
  188. {
  189.    register long w, num, den ;
  190.    register char *p ;
  191.    int negative = 0 ;
  192.  
  193.    p = *s ;
  194.    if (**s == '-') {
  195.       (*s)++ ;
  196.       negative = 1 ;
  197.    }
  198.    w = myatol(s) ;
  199.    if (w < 0)
  200.       usage() ;
  201.    p = *s ;
  202.    num = 0 ;
  203.    den = 1 ;
  204.    if (*p == '.') {
  205.       p++ ;
  206.       while ('0' <= *p && *p <= '9') {
  207.          if (den < 1000) {
  208.             den *= 10 ;
  209.             num = num * 10 + *p - '0' ;
  210.          }
  211.          p++ ;
  212.       }
  213.    }
  214. /*
  215.  *   Allowed units are `in', `cm', `mm', `pt', `sp', `cc', `dd', and `pc';
  216.  *   must be in lower case.
  217.  */
  218.    if (*p == 'c' && p[1] == 'm') {
  219. /*  centimeters need to be multiplied by 72.27 * 2^16 / 2.54, or 1 864 680 */
  220.       w = scale(w, num, den, 1864680L) ;
  221.    } else if (*p == 'p' && p[1] == 't') {
  222. /*  real points need to be multiplied by 2^16 */
  223.       w = scale(w, num, den, 65536L) ;
  224.    } else if (*p == 'p' && p[1] == 'c') {
  225. /*  picas need to be multiplied by 65536 * 12, or 786 432 */
  226.       w = scale(w, num, den, 786432L) ;
  227.    } else if (*p == 'm' && p[1] == 'm') {
  228. /*  millimeters need to be multiplied by 72.27 * 2^16 / 25.4, or 186 468 */
  229.       w = scale(w, num, den, 186468L) ;
  230.    } else if (*p == 's' && p[1] == 'p') {
  231. /*  scaled points are already taken care of; simply round */
  232.       w = scale(w, num, den, 1L) ;
  233.    } else if (*p == 'b' && p[1] == 'p') {
  234. /*  big points need to be multiplied by 72.27 * 65536 / 72, or 65782 */
  235.       w = scale(w, num, den, 65782L) ;
  236.    } else if (*p == 'd' && p[1] == 'd') {
  237. /*  didot points need to be multiplied by 65536 * 1238 / 1157, or 70124 */
  238.       w = scale(w, num, den, 70124L) ;
  239.    } else if (*p == 'c' && p[1] == 'c') {
  240. /*  cicero need to be multiplied by 65536 * 1238 / 1157 * 12, or 841 489 */
  241.       w = scale(w, num, den, 841489L) ;
  242.    } else if (*p == 'i' && p[1] == 'n') {
  243. /*  inches need to be multiplied by 72.27 * 65536, or 4 736 286 */
  244.       w = scale(w, num, den, 4736286L) ;
  245.    } else {
  246. /*  use default values */
  247.       w = scale(w, num, den, 0L) ;
  248.       p -= 2 ;
  249.    }
  250.    p += 2 ;
  251.    *s = p ;
  252.    return(negative?-w:w) ;
  253. }
  254. /*
  255.  *   Parse the arguments to the routine, and stuff everything away
  256.  *   into those globals above.
  257.  */
  258. processargs(argc, argv)
  259. int argc ;
  260. char *argv[] ;
  261. {
  262.    char *p, *q ;
  263.    int pageno ;
  264.    long hoffset, voffset ;
  265.    int reversed ;
  266.  
  267.    if (argc < 3 || argc > 4)
  268.       usage() ;
  269.    modulo = 1 ;
  270.    argv++ ;
  271.    argc-- ;
  272.    p = argv[0] ;
  273. /*
  274.  *   Is there a modulo supplied?  Grab it if so; otherwise default to 1.
  275.  */
  276.    for (q=p; *q != 0; q++)
  277.       if (*q == ':')
  278.          break ;
  279.    if (*q == ':') {
  280.       modulo = myatol(&p) ;
  281.       if (*p != ':')
  282.          usage() ;
  283.       if (modulo < 1 || modulo > MAXPPERP)
  284.          error("! modulo must lie between 1 and 32") ;
  285.       p++ ;
  286.    }
  287. /*
  288.  *   This loop grabs all of the page specifications.
  289.  */
  290.    pagesperpage = 0 ;
  291.    while (*p != 0) {
  292.       if (pagesperpage >= MAXPPERP)
  293.          error("! too many page specifications") ;
  294.       if (*p == '-') {
  295.          reversed = 1 ;
  296.          p++ ;
  297.       } else
  298.          reversed = 0 ;
  299.       if (*p == 0 || *p == '(' || *p == ',')
  300.          pageno = 0 ;
  301.       else
  302.          pageno = myatol(&p) ;
  303.       if (*p == '(') {
  304.          p++ ;
  305.          hoffset = myatodim(&p) ;
  306.          if (*p++ != ',')
  307.             usage() ;
  308.          voffset = myatodim(&p) ;
  309.          if (*p++ != ')')
  310.             usage() ;
  311.       } else {
  312.          hoffset = 0 ;
  313.          voffset = 0 ;
  314.       }
  315.       pages[pagesperpage].hoffset = hoffset ;
  316.       pages[pagesperpage].voffset = voffset ;
  317.       pages[pagesperpage].pageno = pageno ;
  318.       pages[pagesperpage].reversed = reversed ;
  319.       pagesperpage++ ;
  320.       if (*p == ',')
  321.          p++ ;
  322.    }
  323. /*
  324.  *   Finally we get around to opening our input and output files.
  325.  */
  326.    argc-- ;
  327.    argv++ ;
  328.    if ((infile=fopen(argv[0],"rb"))==NULL) {  /* EZ ajoute binary */
  329.       strcpy(temp, argv[0]) ;
  330.       strcat(temp, ".dvi") ;
  331.       if ((infile=fopen(temp,"rb"))==NULL)  /* EZ ajoute binary */
  332.          error("! can't open input file") ;
  333.    }
  334.    argc-- ;
  335.    argv++ ;
  336.    for (q=NULL, p=argv[0]; *p; p++)
  337.       if (*p == '.')
  338.          q = p ;
  339.       else if (*p == '/' || *p == ':')
  340.          q = NULL ;
  341.    strcpy(temp, argv[0]) ;
  342.    if (q==NULL)
  343.       strcat(temp, ".dvi") ;
  344.    if (argc > 0) {
  345.       if (freopen(temp, "wb", stdout)==NULL)  /* EZ ajoute binary */
  346.          error("! can't open output file") ;
  347.    }
  348. }
  349. /*
  350.  *   Grabs an unsigned two bytes.
  351.  */
  352. long u2(where)
  353. long where ;
  354. {
  355.    return( ((long)dvibuf[where] << 8) + dvibuf[where + 1]) ;
  356. }
  357. /*
  358.  *   Grabs a longword from the file.
  359.  */
  360. long quad(where)
  361. register long where ;
  362. {
  363.    return((u2(where) << 16) + u2(where+2)) ;
  364. }
  365. /*
  366.  *   Grabs a pointer, and checks it for validity.
  367.  */
  368. long ptr(where)
  369. register long where ;
  370. {
  371.    where = quad(where) ;
  372.    if (where < -1L || where > inlength)
  373.       error("! dvi file malformed; impossible pointer") ;
  374.    return(where) ;
  375. }
  376. /*
  377.  *   This routine finds a particular page, numbered sequentially
  378.  *   from the beginning, by tracing the pointers backwards.
  379.  */
  380. long pageloc(num)
  381. long num ;
  382. {
  383.    long p ;
  384.  
  385.    if (num >= pagecount)
  386.       return(0L) ;
  387.    num++ ;
  388.    for (p = ptr(postloc+1); num < pagecount; num++)
  389.       p = ptr(p+41) ;
  390.    if (dvibuf[p] != 139)
  391.       error("! missed a bop somehow") ;
  392.    return(p) ;
  393. }
  394. /*
  395.  *   This routine simply reads the entire dvi file, and then initializes
  396.  *   some values about it.
  397.  */
  398. readdvifile() {
  399.    long p ;
  400.  
  401.    fseek(infile, 0L, 2) ;
  402.    inlength = ftell(infile) ;
  403.    fseek(infile, 0L, 0) ;
  404.    dvibuf = (unsigned char *)malloc(inlength) ;
  405.    if (dvibuf == NULL)
  406.       error("! not enough memory to hold input dvi file") ;
  407.    if (fread(dvibuf, 1, inlength, infile) != inlength)
  408.       error("! problem reading entire file into memory") ;
  409.    fclose(infile) ;
  410.    infile = NULL ;
  411.    if (inlength < 10)
  412.       error("! dvi file too short") ;
  413.    for (p=inlength - 3; p > 0; p--)
  414.       if (dvibuf[p] == 2 && dvibuf[p+1] == 0xdf /* dave fuchs */ &&
  415.                             dvibuf[p+2] == 0xdf)
  416.          break ;
  417.    if (p < 10)
  418.       error("! rather short dvi file, ain't it?") ;
  419.    postloc = ptr(p - 4) ;
  420.    if (quad(postloc + 5) != 25400000 || quad(postloc + 9) != 473628672)
  421.       error("! change this program to support non-TeX num/den values") ;
  422.    mag = quad(postloc + 13) ;
  423.    if (mag < 1 || mag > 1000000)
  424.       error("! impossible magnification value") ;
  425.    pagecount = u2(postloc + 27) ;
  426.    if (pagecount < 1 || pagecount > 1000000)
  427.       error("! impossible page count value") ;
  428. /*
  429.  *   That's enough error checking; we probably have a correct dvi file.
  430.  *   Let's convert all the values we got from the command line into
  431.  *   units that we can actually use in the dvi file.
  432.  */
  433.    for (p=0; p<pagesperpage; p++) {
  434.       scalemag(&(pages[p].hoffset)) ;
  435.       scalemag(&(pages[p].voffset)) ;
  436.    }
  437. /*
  438.  *   Now let's grab us some font pointers.
  439.  */
  440.    p = postloc + 29 ;
  441.    while (1) {
  442.       if (dvibuf[p] == 249)
  443.          break ;
  444.       if (dvibuf[p] == 138)
  445.          p++ ;
  446.       else if (dvibuf[p] == 243) {
  447.          TeXfonts[dvibuf[p+1]] = p ;
  448.          p += fontdeflen(p) ;
  449.       } else
  450.          error("! only nop's and font def's allowed in postamble") ;
  451.    }
  452. /*
  453.  *   Now we check for a landscape special.  It should be the
  454.  *   *first* thing in the page that is at all complicated.
  455.  */
  456.    p = pageloc(0L) + 45 ;
  457.    while (comlen[dvibuf[p]])
  458.       p += comlen[dvibuf[p]] ;
  459.    if (dvibuf[p] == 239 && strncmp(dvibuf + p + 2, "landscape", 9)==0) {
  460.       landscape = p ;
  461.       rem0special = 1 ;
  462.    }
  463. }
  464. /*
  465.  *   Output a single byte, keeping track of where we are.
  466.  */
  467. dvibyte(c)
  468. unsigned char c ;
  469. {
  470.    putc(c, stdout) ;
  471.    dviloc++ ;
  472. }
  473. /*
  474.  *   Send out two bytes.
  475.  */
  476. dvi2(v)
  477. long v ;
  478. {
  479.    dvibyte((unsigned char)(v >> 8)) ;
  480.    dvibyte((unsigned char)(v & 255)) ;
  481. }
  482. /*
  483.  *   Send out a longword.
  484.  */
  485. dviquad(v)
  486. long v ;
  487. {
  488.    dvi2(v >> 16) ;
  489.    dvi2(v & 65535) ;
  490. }
  491. /*
  492.  *   This routine just copies some stuff from the buffer on out.
  493.  */
  494. putbuf(where, length)
  495. long where, length ;
  496. {
  497.    register unsigned char *p ;
  498.  
  499.    for (p=dvibuf + where; length > 0; p++, length--)
  500.       dvibyte(*p) ;
  501. }
  502. /*
  503.  *   This routine outputs a string, terminated by null.
  504.  */
  505. putstr(s)
  506. register unsigned char *s ;
  507. {
  508.    while (*s)
  509.       dvibyte(*s++) ;
  510. }
  511. /*
  512.  *   Here we write the preamble to the dvi file.
  513.  */
  514. writepreamble() {
  515. /*   just copy the first 14 bytes of the file */
  516.    putbuf(0L, 14L) ;
  517. /*   and put our identifier. */
  518.    putstr("\015dvidvi output") ;
  519. }
  520. /*
  521.  *   This routine writes out a font definition.
  522.  */
  523. putfontdef(f)
  524. int f ;
  525. {
  526.    long p ;
  527.  
  528.    p = TeXfonts[f] ;
  529.    putbuf(p, fontdeflen(p)) ;
  530. }
  531. /*
  532.  *   The postamble is next.
  533.  */
  534. writepostamble() {
  535.    int i ;
  536.    long p ;
  537.    long q=20;
  538.  
  539.    p = dviloc ;
  540.    dvibyte(248) ;
  541.    dviquad(prevpp) ;
  542.    putbuf(postloc+5, q) ;
  543.    dvi2(u2(postloc+25)+1L) ; /* increase stack depth by 1 */
  544.    dvi2(outputpages) ;
  545.    for (i=0; i<256; i++)
  546.       if (fontseen[i])
  547.          putfontdef(i) ;
  548.    dvibyte(249) ;
  549.    dviquad(p) ;
  550.    dvibyte(2) ;
  551.    dviquad(0xdfdfdfdfL) ;
  552.    while (dviloc & 3)
  553.       dvibyte(0xdf) ;
  554.    fclose(stdout) ;
  555. }
  556. /*
  557.  *   This routine starts a page, by writing out a bop command.
  558.  */
  559. beginpage() {
  560.    int i ;
  561.    long p ;
  562.  
  563.    p = dviloc ;
  564.    dvibyte(139) ;
  565.    dviquad(outputpages) ;
  566.    for (i=0; i<9; i++)
  567.       dviquad(0L) ;
  568.    dviquad(prevpp) ;
  569.    prevpp = p ;
  570. }
  571. /*
  572.  *   This routine sends out a page.  We need to handle the
  573.  *   landscape special, though.
  574.  */
  575. dopage(num)
  576. long num ;
  577. {
  578.    register long p ;
  579.    register int len ;
  580.    long v, oldp ;
  581.  
  582.    p = pageloc(num) + 45 ;
  583.    while (dvibuf[p] != 140) {
  584.       if (len=comlen[dvibuf[p]]) {    /* most commands are simple */
  585.          putbuf(p, (long)len) ;
  586.          p += len ;
  587.       } else {   /* but there are a few we need to treat specially */
  588.          len = dvibuf[p] ;
  589.          if (171 <= len && len <= 235) {
  590.             p++ ;
  591.             if (len == 235)
  592.                len = dvibuf[p++] ;
  593.             else
  594.                len -= 171 ;
  595.             if (!fontseen[len]) {
  596.                putfontdef(len) ;
  597.                fontseen[len] = 1 ;
  598.             }
  599.             if (len < 64)
  600.                dvibyte(171 + len) ;
  601.             else {
  602.                dvibyte(235) ;
  603.                dvibyte(len) ;
  604.             }
  605.          } else {
  606.             v = 0 ;
  607.             oldp = p++ ;
  608.             switch(len) {
  609. case 242:      v = dvibuf[p++] ;
  610. case 241:      v = (v << 8) + dvibuf[p++] ;
  611. case 240:      v = (v << 8) + dvibuf[p++] ;
  612. case 239:      v = (v << 8) + dvibuf[p++] ;
  613. /*
  614.  *   Remove a landscape special on page 0, if one is found.
  615.  */
  616.                if (num || ! rem0special ||
  617.                     strncmp(dvibuf + oldp + len - 237, "landscape", 9))
  618.                   putbuf(oldp, v + len - 237) ;
  619.                p = oldp + v + len - 237 ;
  620.                break ;
  621. case 243: case 244: case 245: case 246:
  622.                p += len - 230 ;
  623.                p += dvibuf[p] + dvibuf[p+1] + 2 ;
  624.                break ;
  625. default:       fprintf(stderr, "Bad dvi command was %d at %ld\n", len, p) ;
  626.                error("! lost sync dvi in file lost dvi sync file in") ;
  627.             }
  628.          }
  629.       }
  630.    }
  631. }
  632. /*
  633.  *   Here we end a page.  Simple enough.
  634.  */
  635. endpage() {
  636.    outputpages++ ;
  637.    dvibyte(140) ;
  638. }
  639. /*
  640.  *   This is our main routine for output, which runs through all the
  641.  *   pages we need to output.
  642.  */
  643. writedvifile() {
  644.    long pagenum ;
  645.    int ppp ;
  646.    long actualpageno ;
  647.    struct pagespec *ps ;
  648.    long p ;
  649.  
  650.    writepreamble() ;
  651.    pagefake = (pagecount + modulo - 1) / modulo * modulo ;
  652.    for (pagenum = 0; pagenum < pagefake; pagenum += modulo) {
  653.       beginpage() ;
  654.       for (ppp = 0, ps=pages; ppp < pagesperpage; ppp++, ps++) {
  655.          if (landscape) {
  656.             putbuf(landscape, dvibuf[landscape+1]+2L) ;
  657.             landscape = 0 ;
  658.          }
  659.          if (ps->reversed)
  660.             actualpageno = pagefake - pagenum - modulo + ps->pageno ;
  661.          else
  662.             actualpageno = pagenum + ps->pageno ;
  663.          if (actualpageno < pagecount) {
  664.             if (pagesperpage)
  665.                dvibyte(141) ;
  666.             if (ps->hoffset) {
  667.                dvibyte(146) ;
  668.                dviquad(ps->hoffset) ;
  669.             }
  670.             if (ps->voffset) {
  671.                dvibyte(160) ;
  672.                dviquad(ps->voffset) ;
  673.             }
  674.             dopage(actualpageno) ;
  675.             if (pagesperpage)
  676.                dvibyte(142) ;
  677.          }
  678.       }
  679.       endpage() ;
  680.    }
  681.    writepostamble() ;
  682. }
  683. main(argc, argv)
  684. int argc ;
  685. char *argv[] ;
  686. {
  687.    processargs(argc, argv) ;
  688.    readdvifile() ;
  689.    writedvifile() ;
  690. }
  691.  
  692.