/* dviread.c --- Read dvi file; from dvitype.web.  */

#include <stdarg.h>
#include <stdlib.h>
#include "web2c.h"
#include "dvi2html.h"

#define tfatal printf		/* FOR NOW!!! */
#define fatal printf		/* FOR NOW!!! */

int debug = 0;

#define maxfonts 100
#define maxwidths 10000
#define linelength 79
#define terminallinelength 150
#define stacksize 100
#define namesize 1000
#define namelength 256
typedef schar ASCIIcode;
typedef file_ptr /* of char */ textfile;
typedef unsigned char eightbits;
typedef file_ptr /* of eightbits */ bytefile;
ASCIIcode xord[128];
char xchr[256];
bytefile dvifile;
bytefile tfmfile;
integer curloc;
char curname[namelength + 1], realnameoffile[namelength + 1];
eightbits b0, b1, b2, b3;
integer fontnum[maxfonts + 1];
integer fontname[maxfonts + 1];
ASCIIcode names[namesize + 1];
integer fontchecksum[maxfonts + 1];
integer fontscaledsize[maxfonts + 1];
integer fontdesignsize[maxfonts + 1];
integer fontspace[maxfonts + 1];
integer fontbc[maxfonts + 1];
integer fontec[maxfonts + 1];
integer widthbase[maxfonts + 1];
integer width[maxwidths + 1];
integer nf;
integer widthptr;
integer inwidth[256];
integer tfmchecksum;
integer pixelwidth[maxwidths + 1];
real conv;
real trueconv;
integer numerator, denominator;
integer mag;
schar outmode;
integer maxpages;
real resolution;
integer newmag;
integer startcount[10];
boolean startthere[10];
schar startvals;
integer count[10];
ASCIIcode buffer[terminallinelength + 1];
integer bufptr;
boolean inpostamble;
integer textptr;
ASCIIcode textbuf[linelength + 1];
integer h, v, w, x, y, z, hh, vv;
integer hstack[stacksize + 1], vstack[stacksize + 1], wstack[stacksize + 1],
 xstack[stacksize + 1], ystack[stacksize + 1], zstack[stacksize + 1];
integer hhstack[stacksize + 1], vvstack[stacksize + 1];
integer maxv;
integer maxh;
integer maxs;
integer maxvsofar, maxhsofar, maxssofar;
integer totalpages;
integer pagecount;
integer s;
integer ss;
integer curfont;
boolean showing;
integer oldbackpointer;
integer newbackpointer;
boolean started;
integer postloc;
integer firstbackpointer;
integer startloc;
integer k, m, n, p, q;

char font_name[256];
int font_size;
int font_charwidth;

#include "dvitype.h"
/* External procedures for dvitype                              */
/*   Written by: H. Trickey, 2/19/83 (adapted from TeX's ext.c) */

#include <string.h>

#define TRUE    1
#define FALSE   0

integer argc;
char *fontpath;
extern char *getenv ();

/*
 * setpaths is called to set up the pointer fontpath
 * as follows:  if the user's environment has a value for TEXFONTS
 * then use it;  otherwise, use defaultfontpath.
 */
setpaths ()
{
register char *envpath;

   if ((envpath = getenv ("TEXFONTS")) != NULL)
      fontpath = envpath;
   else
      fontpath = TEXFONTS;
}

#define namelength 256		/* should agree with dvitype.ch */
					     /* extern char curname[],realnameoffile[];*//* these have size namelength */

/*
 *      testaccess(amode,filepath)
 *
 *  Test whether or not the file whose name is in the global curname
 *  can be opened for reading (if mode=READACCESS)
 *  or writing (if mode=WRITEACCESS).
 *
 *  The filepath argument is one of the ...FILEPATH constants defined below.
 *  If the filename given in curname does not begin with '/', we try 
 *  prepending all the ':'-separated areanames in the appropriate path to the
 *  filename until access can be made, if it ever can.
 *
 *  The realnameoffile global array will contain the name that yielded an
 *  access success.
 */

#define READACCESS 4
#define WRITEACCESS 2

#define NOFILEPATH 0
#define FONTFILEPATH 3

static packrealnameoffile (char **cpp);

testaccess (amode, filepath)
     int amode, filepath;
{
register boolean ok;
register char *p;
char *curpathplace;
int f;

   switch (filepath) {
   case NOFILEPATH:
      curpathplace = NULL;
      break;
   case FONTFILEPATH:
      curpathplace = fontpath;
      break;
   }
   if (curname[0] == '/')	/* file name has absolute path */
      curpathplace = NULL;
   do {
      packrealnameoffile (&curpathplace);
      if (amode == READACCESS) {
FILE *temp;

	 /* use system call "access" to see if we could read it */
	 ok = FALSE;
	 if ((temp = fopen (realnameoffile, "rb")) != NULL)
	    ok = TRUE;
	 if (ok) {
	    fclose (temp);
	 } else {
	    tfatal ("(dviread) Cannot open `%s'\n", realnameoffile);
	 }
      } else {
	 /* WRITEACCESS: use creat to see if we could create it, but close
	    the file again if we're OK, to let pc open it for real */
	 f = creat (realnameoffile, 0666);
	 ok = (f >= 0);
	 if (ok)
	    (void) close (f);
      }
   } while (!ok && curpathplace != NULL);
   if (ok) {			/* pad realnameoffile with blanks, as Pascal
				   wants */
      for (p = realnameoffile; *p != '\0'; p++)
	 /* nothing: find end of string */ ;
      while (p < &(realnameoffile[namelength]))
	 *p++ = ' ';
   }
   return (ok);
}

/*
 * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp,
 * followed by '/', followed by the characters in curname up until the
 * first blank there, and finally a '\0'.  The cpp pointer is left pointing
 * at the next directory in the path.
 * But: if *cpp == NULL, then we are supposed to use curname as is.
 */
static packrealnameoffile (cpp)
     char **cpp;
{
register char *p, *realname;

   realname = realnameoffile;
   if ((p = *cpp) != NULL) {
      while ((*p != ',') && (*p != '\0')) {
	 *realname++ = *p++;
	 if (realname == &(realnameoffile[namelength - 1]))
	    break;
      }
      if (*p == '\0')
	 *cpp = NULL;		/* at end of path now */
      else
	 *cpp = p + 1;		/* else get past ':' */
#ifndef ARM
      *realname++ = '/';	/* separate the area from the name to follow */
#endif
   }
   /* now append curname to realname... */
   p = curname + 1;
   while (*p != ' ') {
      if (realname >= &(realnameoffile[namelength - 1])) {
	 tfatal ("(dviread) Full file name is too long\n");
	 break;
      }
      *realname++ = *p++;
   }
   *realname = '\0';
}

static char **gargv;

argv (n, buf)
     int n;
     char buf[];
{
   (void) sprintf (buf + 1, "%s ", gargv[n]);
}

int main (ac, av)
     int ac;
     char **av;
{
   argc = ac;
   gargv = av;
   main_body ();
   exit(0);
}

#define char_index      strchr

/* Open a file; don't return if error */
FILE *openf (name, mode)
     char *name, *mode;
{
FILE *result;
char *cp;

   --name;			/* All names are indexed starting at 1 */
   cp = char_index (name, ' ');
   if (cp)
      *cp = '\0';
   result = fopen (name, mode);
   if (result)
      return (result);
   perror (name);
   exit (1);
 /*NOTREACHED*/}

/* Print real number r in format n:m */
printreal (r, n, m)
     double r;
     int n, m;
{
char fmt[50];

   (void) sprintf (fmt, "%%%d.%df", n, m);
   (void) fprintf (stderr, fmt, r);
}

/* Return true on end of line or eof of file, else false */
eoln (f)
     FILE *f;
{
register int c;

   if (feof (f))
      return (1);
   c = getc (f);
   if (c != EOF)
      (void) ungetc (c, f);
   return (c == '\n' || c == EOF);
}

/* Return true on end of file, else false */
#undef eof
int eof (f)
     FILE *f;
{
register int c;

   if (feof (f))
      return (1);
   c = getc (f);
   if (c != EOF)
      (void) ungetc (c, f);
   return (c == EOF);
}

integer zround (f)
     double f;
{
   if (f >= 0.0)
      return (f + 0.5);
   return (f - 0.5);
}

static int oldhh = -1;
static int oldvv = -1;
static int draw_rule = false;

initialize ()
{
integer i;

   setpaths ();
   {
register integer for_end;

      i = 0;
      for_end = 31;
      if (i <= for_end)
	 do
	    xchr[i] = '?';
	 while (i++ < for_end);
   }
   xchr[32] = ' ';
   xchr[33] = '!';
   xchr[34] = '"';
   xchr[35] = '#';
   xchr[36] = '$';
   xchr[37] = '%';
   xchr[38] = '&';
   xchr[39] = '\'';
   xchr[40] = '(';
   xchr[41] = ')';
   xchr[42] = '*';
   xchr[43] = '+';
   xchr[44] = ',';
   xchr[45] = '-';
   xchr[46] = '.';
   xchr[47] = '/';
   xchr[48] = '0';
   xchr[49] = '1';
   xchr[50] = '2';
   xchr[51] = '3';
   xchr[52] = '4';
   xchr[53] = '5';
   xchr[54] = '6';
   xchr[55] = '7';
   xchr[56] = '8';
   xchr[57] = '9';
   xchr[58] = ':';
   xchr[59] = ';';
   xchr[60] = '<';
   xchr[61] = '=';
   xchr[62] = '>';
   xchr[63] = '?';
   xchr[64] = '@';
   xchr[65] = 'A';
   xchr[66] = 'B';
   xchr[67] = 'C';
   xchr[68] = 'D';
   xchr[69] = 'E';
   xchr[70] = 'F';
   xchr[71] = 'G';
   xchr[72] = 'H';
   xchr[73] = 'I';
   xchr[74] = 'J';
   xchr[75] = 'K';
   xchr[76] = 'L';
   xchr[77] = 'M';
   xchr[78] = 'N';
   xchr[79] = 'O';
   xchr[80] = 'P';
   xchr[81] = 'Q';
   xchr[82] = 'R';
   xchr[83] = 'S';
   xchr[84] = 'T';
   xchr[85] = 'U';
   xchr[86] = 'V';
   xchr[87] = 'W';
   xchr[88] = 'X';
   xchr[89] = 'Y';
   xchr[90] = 'Z';
   xchr[91] = '[';
   xchr[92] = '\\';
   xchr[93] = ']';
   xchr[94] = '^';
   xchr[95] = '_';
   xchr[96] = '`';
   xchr[97] = 'a';
   xchr[98] = 'b';
   xchr[99] = 'c';
   xchr[100] = 'd';
   xchr[101] = 'e';
   xchr[102] = 'f';
   xchr[103] = 'g';
   xchr[104] = 'h';
   xchr[105] = 'i';
   xchr[106] = 'j';
   xchr[107] = 'k';
   xchr[108] = 'l';
   xchr[109] = 'm';
   xchr[110] = 'n';
   xchr[111] = 'o';
   xchr[112] = 'p';
   xchr[113] = 'q';
   xchr[114] = 'r';
   xchr[115] = 's';
   xchr[116] = 't';
   xchr[117] = 'u';
   xchr[118] = 'v';
   xchr[119] = 'w';
   xchr[120] = 'x';
   xchr[121] = 'y';
   xchr[122] = 'z';
   xchr[123] = '{';
   xchr[124] = '|';
   xchr[125] = '}';
   xchr[126] = '~';
   {
register integer for_end;

      i = 127;
      for_end = 255;
      if (i <= for_end)
	 do
	    xchr[i] = '?';
	 while (i++ < for_end);
   }
   {
register integer for_end;

      i = 0;
      for_end = 127;
      if (i <= for_end)
	 do
	    xord[chr (i)] = 32;
	 while (i++ < for_end);
   }
   {
register integer for_end;

      i = 32;
      for_end = 126;
      if (i <= for_end)
	 do
	    xord[xchr[i]] = i;
	 while (i++ < for_end);
   }
   nf = 0;
   widthptr = 0;
   fontname[0] = 0;
   fontspace[0] = 0;
   outmode = 3;
   maxpages = 1000000L;
   startvals = 0;
   startthere[0] = false;
   inpostamble = false;
   textptr = 0;
   maxv = 2147483548L;
   maxh = 2147483548L;
   maxs = stacksize + 1;
   maxvsofar = 0;
   maxhsofar = 0;
   maxssofar = 0;
   pagecount = 0;
   oldbackpointer = -1;
   started = false;
}

opendvifile ()
{
   if (argc != 2) {
      tfatal ("(dviread) %s\n", "Usage: dvitype <dvi-file>");
      uexit (1);
   }
   argv (1, curname);
   if (testaccess (4, 0))
      reset (dvifile, realnameoffile);
   else {
      tfatal ("(dviread) %s\n", "DVI file not found");
      uexit (1);
   }
   curloc = 0;
}

opentfmfile ()
{
   if (testaccess (4, 3))
      reset (tfmfile, realnameoffile);
   else {

      tfatal ("(dviread) TFM file not found (`%s')", realnameoffile);
      uexit (1);
   }
}

readtfmword ()
{
   read (tfmfile, b0);
   read (tfmfile, b1);
   read (tfmfile, b2);
   read (tfmfile, b3);
}

integer getbyte ()
{
register integer Result;
eightbits b;

   if (eof (dvifile)) {
      tfatal ("(dviread) End of file detected.\n");
      Result = 0;
   } else {

      read (dvifile, b);
      if (feof (dvifile))
	 tfatal ("(dviread) Last byte of file has been read.\n");
      curloc = curloc + 1;
      Result = b;
   }
   return (Result);
}

integer signedbyte ()
{
register integer Result;
eightbits b;

   read (dvifile, b);
   curloc = curloc + 1;
   if (b < 128)
      Result = b;
   else
      Result = b - 256;
   return (Result);
}

integer gettwobytes ()
{
register integer Result;
eightbits a, b;

   read (dvifile, a);
   read (dvifile, b);
   curloc = curloc + 2;
   Result = a * 256 + b;
   return (Result);
}

integer signedpair ()
{
register integer Result;
eightbits a, b;

   read (dvifile, a);
   read (dvifile, b);
   curloc = curloc + 2;
   if (a < 128)
      Result = a * 256 + b;
   else
      Result = (a - 256) * 256 + b;
   return (Result);
}

integer getthreebytes ()
{
register integer Result;
eightbits a, b, c;

   read (dvifile, a);
   read (dvifile, b);
   read (dvifile, c);
   curloc = curloc + 3;
   Result = (a * 256 + b) * 256 + c;
   return (Result);
}

integer signedtrio ()
{
register integer Result;
eightbits a, b, c;

   read (dvifile, a);
   read (dvifile, b);
   read (dvifile, c);
   curloc = curloc + 3;
   if (a < 128)
      Result = (a * 256 + b) * 256 + c;
   else
      Result = ((a - 256) * 256 + b) * 256 + c;
   return (Result);
}

integer signedquad ()
{
register integer Result;
eightbits a, b, c, d;

   read (dvifile, a);
   read (dvifile, b);
   read (dvifile, c);
   read (dvifile, d);
   curloc = curloc + 4;
   a = a & 255;
   b = b & 255;
   c = c & 255;
   d = d & 255;
   Result = (a << 24) | (b << 16) | (c << 8) | d;
   return (Result);
}

integer dvilength ()
{
register integer Result;

   zfseek (dvifile, 0, 2);
   Result = ftell (dvifile);
   return (Result);
}

zmovetobyte (n)
     integer n;
{
   zfseek (dvifile, n, 0);
}

zprintfont (f)
     integer f;
{
integer k;
static char fname[256];
char *dest = &fname[0];

   if (f == nf)
      (void) Fputs (stderr, "UNDEFINED!");
   else {

      {
register integer for_end;

	 k = fontname[f];
	 for_end = fontname[f + 1] - 1;
	 if (k <= for_end)
	    do
	       (void) putc ((*dest++ = xchr[names[k]]), stderr);
	    while (k++ < for_end);
      }
   }
   *dest = '\0';
   strcpy (font_name, fname);
}

setfontname (f)
     integer f;
{
integer k;
static char fname[256];
char *dest = &fname[0];

   if (f == nf)
      (void) Fputs (stderr, "UNDEFINED!");
   else {

      {
register integer for_end;

	 k = fontname[f];
	 for_end = fontname[f + 1] - 1;
	 if (k <= for_end)
	    do
	       *dest++ = xchr[names[k]];
	    while (k++ < for_end);
      }
   }
   *dest = '\0';
   strcpy (font_name, fname);
}

boolean zinTFM (z)
     integer z;
{				/* 9997 9998 9999 */
register boolean Result;
integer k;
integer lh;
integer nw;
integer wp;
integer alpha, beta;

   readtfmword ();
   lh = b2 * 256 + b3;
   readtfmword ();
   fontbc[nf] = b0 * 256 + b1;
   fontec[nf] = b2 * 256 + b3;
   if (fontec[nf] < fontbc[nf])
      fontbc[nf] = fontec[nf] + 1;
   if (widthptr + fontec[nf] - fontbc[nf] + 1 > maxwidths) {
      tfatal ("(dviread) Internal error: width table overflow");
      goto lab9998;
   }
   wp = widthptr + fontec[nf] - fontbc[nf] + 1;
   readtfmword ();
   nw = b0 * 256 + b1;
   if ((nw == 0) || (nw > 256))
      goto lab9997;
   {
register integer for_end;

      k = 1;
      for_end = 3 + lh;
      if (k <= for_end)
	 do {
	    if (eof (tfmfile))
	       goto lab9997;
	    readtfmword ();
	    if (k == 4)
	       if (b0 < 128)
		  tfmchecksum = ((b0 * 256 + b1) * 256 + b2) * 256 + b3;
	       else
		  tfmchecksum =
		   (((b0 - 256) * 256 + b1) * 256 + b2) * 256 + b3;
	 }
	 while (k++ < for_end);
   }
   if (wp > 0) {
register integer for_end;

      k = widthptr;
      for_end = wp - 1;
      if (k <= for_end)
	 do {
	    readtfmword ();
	    if (b0 > nw)
	       goto lab9997;
	    width[k] = b0;
	 }
	 while (k++ < for_end);
   }
   {
      alpha = 16 * z;
      beta = 16;
      while (z >= 8388608L) {

	 z = z / 2;
	 beta = beta / 2;
      }
   }
   {
register integer for_end;

      k = 0;
      for_end = nw - 1;
      if (k <= for_end)
	 do {
	    readtfmword ();
	    inwidth[k] = (((((b3 * z) / 256) + (b2 * z)) / 256) + (b1
								   * z)) /
	     beta;
	    if (b0 > 0)
	       if (b0 < 255)
		  goto lab9997;
	       else
		  inwidth[k] = inwidth[k] - alpha;
	 }
	 while (k++ < for_end);
   }
   if (inwidth[0] != 0)
      goto lab9997;
   widthbase[nf] = widthptr - fontbc[nf];
   if (wp > 0) {
register integer for_end;

      k = widthptr;
      for_end = wp - 1;
      if (k <= for_end)
	 do
	    if (width[k] == 0) {
	       width[k] = 2147483647L;
	       pixelwidth[k] = 0;
	    } else {

	       width[k] = inwidth[width[k]];
	       pixelwidth[k] = round (conv * (width[k]));
	    }
	 while (k++ < for_end);
   }
   widthptr = wp;
   Result = true;
   goto lab9999;
 lab9997:tfatal ("(dviread) TFM file is bad");
 lab9998:Result = false;
 lab9999:;
   fclose (tfmfile);		/* gt */
   return (Result);
}

boolean startmatch ()
{
register boolean Result;
schar k;
boolean match;

   match = true;
   {
register integer for_end;

      k = 0;
      for_end = startvals;
      if (k <= for_end)
	 do
	    if (startthere[k] && (startcount[k] != count[k]))
	       match = false;
	 while (k++ < for_end) ;
   }
   Result = match;
   return (Result);
}

inputln ()
{
integer k;

   flush (stderr);
   if (eoln (stdin))
      readln (stdin);
   k = 0;
   while ((k < terminallinelength) && !eoln (stdin)) {

      buffer[k] = xord[getc (stdin)];
      k = k + 1;
   }
   buffer[k] = 32;
}

integer getinteger ()
{
register integer Result;
integer x;
boolean negative;

   if (buffer[bufptr] == 45) {
      negative = true;
      bufptr = bufptr + 1;
   } else
      negative = false;
   x = 0;
   while ((buffer[bufptr] >= 48) && (buffer[bufptr] <= 57)) {

      x = 10 * x + buffer[bufptr] - 48;
      bufptr = bufptr + 1;
   }
   if (negative)
      Result = -(integer) x;
   else
      Result = x;
   return (Result);
}

dialog ()
{
   /* 1 2 3 4 5 */ integer k;

 lab1:
   outmode = 2;
 lab2:
   startvals = 0;
 lab3:
   maxpages = 1000000L;
 lab4:
   resolution = 72000.0;
 lab5:
   newmag = 0;

}

zdefinefont (e)
     integer e;
{
integer f;
integer p;
integer n;
integer c, q, d;
integer r;
integer j, k;
boolean mismatch;

   if (nf == maxfonts) {
      tfatal ("(dviread) Too many fonts in dvi file");
      uexit (1);
   }
   fontnum[nf] = e;
   f = 0;
   while (fontnum[f] != e)
      f = f + 1;
   c = signedquad ();
   fontchecksum[nf] = c;
   q = signedquad ();
   fontscaledsize[nf] = q;
   d = signedquad ();
   fontdesignsize[nf] = d;
   p = getbyte ();
   n = getbyte ();
   if (fontname[nf] + n + p > namesize) {
      tfatal ("(dviread) name capacity exceeded");
      uexit (1);
   }
   fontname[nf + 1] = fontname[nf] + n + p;
   if (n + p == 0)
      (void) Fputs (stderr, "null font name!");
   else {
register integer for_end;

      k = fontname[nf];
      for_end = fontname[nf + 1] - 1;
      if (k <= for_end)
	 do
	    names[k] = getbyte ();
	 while (k++ < for_end);
   }
   nf = nf + 1;
   setfontname (nf - 1);
   nf = nf - 1;
   if (((outmode == 3) && inpostamble) || ((outmode < 3) && !inpostamble)) {
      if (f < nf)
	 tfatal ("(dviread) bad dvi file (repeated font def)");
   } else {

      if (f == nf)
	 tfatal ("(dviread) bad dvi file (fontsel before fontdef)");
   }
   if (f == nf) {
      {
register integer for_end;

	 k = 1;
	 for_end = namelength;
	 if (k <= for_end)
	    do
	       curname[k] = ' ';
	    while (k++ < for_end);
      }
      r = 0;
      {
register integer for_end;

	 k = fontname[nf];
	 for_end = fontname[nf + 1] - 1;
	 if (k <= for_end)
	    do {
	       r = r + 1;
	       if (r + 4 > namelength) {
		  tfatal ("(dviread) capacity exceeded (font name too long)");
		  uexit (1);
	       }
	       curname[r] = xchr[names[k]];
	    }
	    while (k++ < for_end);
      }
      curname[r + 1] = '.';
      curname[r + 2] = 't';
      curname[r + 3] = 'f';
      curname[r + 4] = 'm';
      opentfmfile ();
      if (eof (tfmfile))
	 (void) Fputs (stderr, "---not loaded, TFM file can't be opened!");
      else {

	 if ((q <= 0) || (q >= 134217728L))
	    tfatal ("(dviread) bad dvi file (scale)");
	 else if ((d <= 0) || (d >= 134217728L))
	    tfatal ("(dviread) bad tfm file (bad design size)");
	 else if (inTFM (q)) {
	    fontspace[nf] = q / 6;
	    if ((c != 0) && (tfmchecksum != 0) && (c != tfmchecksum)) {
	       fatal ("(dviread) WARNING: tfm checksum does not match");
	    }
	    d = round ((100.0 * conv * q) / ((double) (trueconv * d)));
	    font_size = q;
	    /*WIMP*/ nf = nf + 1;
	    fontspace[nf] = 0;
	 }
      }
   } else {

      if (fontchecksum[f] != c)
	 tfatal
	  ("(dviread) inconsistency (check sum doesn't match previous definition)");
      if (fontscaledsize[f] != q)
	 tfatal
	  ("(dviread) inconsistency (scaled size doesn't match previous definition)");
      if (fontdesignsize[f] != d)
	 tfatal
	  ("(dviread) inconsistency (design size doesn't match previous definition)");
      j = fontname[f];
      k = fontname[nf];
      mismatch = false;
      while (j < fontname[f + 1]) {

	 if (names[j] != names[k])
	    mismatch = true;
	 j = j + 1;
	 k = k + 1;
      }
      if (k != fontname[nf + 1])
	 mismatch = true;
      if (mismatch)
	 tfatal
	  ("(dviread) inconsistency (font name doesn't match previous definition)");
   }
}

flushtext ()
{
integer k;

   if (textptr > 0) {
      if (outmode > 0) {
register integer for_end;

	 k = 1;
	 if (xchr[textbuf[k]] == ' ')
	    k++;			       /****** FUDGE!!! ******/
	 for_end = textptr;
	 if (k <= for_end) {
char text[256];
char *textp = &text[0];

	    do {
	       *textp++ = xchr[textbuf[k]];
	    } while (k++ < for_end);
	    *textp = '\0';
	    DRAW_text (oldhh, oldvv, hh + font_charwidth, vv, text);
	    /*WIMPHOOK*/ oldhh = -1;
	    oldvv = -1;
	 }
      }
      textptr = 0;
   }
}

zouttext (c)
     ASCIIcode c;
{
//   if (textptr == linelength - 2)
      flushtext ();
   textptr = textptr + 1;
   textbuf[textptr] = c;
}

integer zfirstpar (o)
     eightbits o;
{
register integer Result;

   switch (o) {
   case 0:
   case 1:
   case 2:
   case 3:
   case 4:
   case 5:
   case 6:
   case 7:
   case 8:
   case 9:
   case 10:
   case 11:
   case 12:
   case 13:
   case 14:
   case 15:
   case 16:
   case 17:
   case 18:
   case 19:
   case 20:
   case 21:
   case 22:
   case 23:
   case 24:
   case 25:
   case 26:
   case 27:
   case 28:
   case 29:
   case 30:
   case 31:
   case 32:
   case 33:
   case 34:
   case 35:
   case 36:
   case 37:
   case 38:
   case 39:
   case 40:
   case 41:
   case 42:
   case 43:
   case 44:
   case 45:
   case 46:
   case 47:
   case 48:
   case 49:
   case 50:
   case 51:
   case 52:
   case 53:
   case 54:
   case 55:
   case 56:
   case 57:
   case 58:
   case 59:
   case 60:
   case 61:
   case 62:
   case 63:
   case 64:
   case 65:
   case 66:
   case 67:
   case 68:
   case 69:
   case 70:
   case 71:
   case 72:
   case 73:
   case 74:
   case 75:
   case 76:
   case 77:
   case 78:
   case 79:
   case 80:
   case 81:
   case 82:
   case 83:
   case 84:
   case 85:
   case 86:
   case 87:
   case 88:
   case 89:
   case 90:
   case 91:
   case 92:
   case 93:
   case 94:
   case 95:
   case 96:
   case 97:
   case 98:
   case 99:
   case 100:
   case 101:
   case 102:
   case 103:
   case 104:
   case 105:
   case 106:
   case 107:
   case 108:
   case 109:
   case 110:
   case 111:
   case 112:
   case 113:
   case 114:
   case 115:
   case 116:
   case 117:
   case 118:
   case 119:
   case 120:
   case 121:
   case 122:
   case 123:
   case 124:
   case 125:
   case 126:
   case 127:
      Result = o - 0;
      break;
   case 128:
   case 133:
   case 235:
   case 239:
   case 243:
      Result = getbyte ();
      break;
   case 129:
   case 134:
   case 236:
   case 240:
   case 244:
      Result = gettwobytes ();
      break;
   case 130:
   case 135:
   case 237:
   case 241:
   case 245:
      Result = getthreebytes ();
      break;
   case 143:
   case 148:
   case 153:
   case 157:
   case 162:
   case 167:
      Result = signedbyte ();
      break;
   case 144:
   case 149:
   case 154:
   case 158:
   case 163:
   case 168:
      Result = signedpair ();
      break;
   case 145:
   case 150:
   case 155:
   case 159:
   case 164:
   case 169:
      Result = signedtrio ();
      break;
   case 131:
   case 132:
   case 136:
   case 137:
   case 146:
   case 151:
   case 156:
   case 160:
   case 165:
   case 170:
   case 238:
   case 242:
   case 246:
      Result = signedquad ();
      break;
   case 138:
   case 139:
   case 140:
   case 141:
   case 142:
   case 247:
   case 248:
   case 249:
   case 250:
   case 251:
   case 252:
   case 253:
   case 254:
   case 255:
      Result = 0;
      break;
   case 147:
      Result = w;
      break;
   case 152:
      Result = x;
      break;
   case 161:
      Result = y;
      break;
   case 166:
      Result = z;
      break;
   case 171:
   case 172:
   case 173:
   case 174:
   case 175:
   case 176:
   case 177:
   case 178:
   case 179:
   case 180:
   case 181:
   case 182:
   case 183:
   case 184:
   case 185:
   case 186:
   case 187:
   case 188:
   case 189:
   case 190:
   case 191:
   case 192:
   case 193:
   case 194:
   case 195:
   case 196:
   case 197:
   case 198:
   case 199:
   case 200:
   case 201:
   case 202:
   case 203:
   case 204:
   case 205:
   case 206:
   case 207:
   case 208:
   case 209:
   case 210:
   case 211:
   case 212:
   case 213:
   case 214:
   case 215:
   case 216:
   case 217:
   case 218:
   case 219:
   case 220:
   case 221:
   case 222:
   case 223:
   case 224:
   case 225:
   case 226:
   case 227:
   case 228:
   case 229:
   case 230:
   case 231:
   case 232:
   case 233:
   case 234:
      Result = o - 171;
      break;
   }
   return (Result);
}

integer zrulepixels (x)
     integer x;
{
register integer Result;
integer n;

   n = trunc (conv * x);
   if (n < conv * x)
      Result = n + 1;
   else
      Result = n;
   return (Result);
}

boolean zspecialcases (o, p, a)
     eightbits o;
     integer p, a;
{				/* 46 44 30 9998 */
register boolean Result;
integer q;
integer k;
boolean badchar;
boolean pure;
integer vvv;

   pure = true;
   switch (o) {
   case 157:
   case 158:
   case 159:
   case 160:
      {
	 if (abs (p) >= 5 * fontspace[curfont])
	    vv = round (conv * (v + p));
	 else
	    vv = vv + round (conv * (p));
	 if (outmode > 0) {
	    flushtext ();
	    showing = true;
	 }
	 goto lab44;
      }
      break;
   case 161:
   case 162:
   case 163:
   case 164:
   case 165:
      {
	 y = p;
	 if (abs (p) >= 5 * fontspace[curfont])
	    vv = round (conv * (v + p));
	 else
	    vv = vv + round (conv * (p));
	 if (outmode > 0) {
	    flushtext ();
	    showing = true;
	 }
	 goto lab44;
      }
      break;
   case 166:
   case 167:
   case 168:
   case 169:
   case 170:
      {
	 z = p;
	 if (abs (p) >= 5 * fontspace[curfont])
	    vv = round (conv * (v + p));
	 else
	    vv = vv + round (conv * (p));
	 if (outmode > 0) {
	    flushtext ();
	    showing = true;
	 }
	 goto lab44;
      }
      break;
   case 171:
   case 172:
   case 173:
   case 174:
   case 175:
   case 176:
   case 177:
   case 178:
   case 179:
   case 180:
   case 181:
   case 182:
   case 183:
   case 184:
   case 185:
   case 186:
   case 187:
   case 188:
   case 189:
   case 190:
   case 191:
   case 192:
   case 193:
   case 194:
   case 195:
   case 196:
   case 197:
   case 198:
   case 199:
   case 200:
   case 201:
   case 202:
   case 203:
   case 204:
   case 205:
   case 206:
   case 207:
   case 208:
   case 209:
   case 210:
   case 211:
   case 212:
   case 213:
   case 214:
   case 215:
   case 216:
   case 217:
   case 218:
   case 219:
   case 220:
   case 221:
   case 222:
   case 223:
   case 224:
   case 225:
   case 226:
   case 227:
   case 228:
   case 229:
   case 230:
   case 231:
   case 232:
   case 233:
   case 234:
      {
	 if (outmode > 0) {
	    flushtext ();
	    showing = true;
	    DRAW_selfont (p);
	 /*WIMPHOOK*/}
	 goto lab46;
      }
      break;
   case 235:
   case 236:
   case 237:
   case 238:
      {
	 if (outmode > 0) {
	    flushtext ();
	    showing = true;
	    DRAW_selfont (p);
	 /*WIMPHOOK*/}
	 goto lab46;
      }
      break;
   case 243:
   case 244:
   case 245:
   case 246:
      {
	 if (outmode > 0) {
	    flushtext ();
	    showing = true;
	 }
	 definefont (p);
	 DRAW_deffont (p, font_name, font_size >> 12, mag);
	 /*WIMPHOOK*/ goto lab30;
      }
      break;
   case 239:
   case 240:
   case 241:
   case 242:
      {
	 if (outmode > 0) {
	    flushtext ();
	    showing = true;
	    /* We regressed a version since IAY was working from 1.0 and we
	       were at 1.1 -- so let's redo this 'fix' */
	    /* tfatal ("BARF %ld%s%s", (long)a , ": " , "xxx '" ) ; */
	 }
	 badchar = false;
	 if (p < 0)
	    if (!showing) {
	       flushtext ();
	       showing = true;
	       tfatal ("(dviread) bad dvi file (string of negative length)");
	    } else
	       tfatal ("(dviread) bad dvi file (string of negative length)");
	 {
register integer for_end;
static char xxx[4096];
char *xp = xxx;

	    k = 1;
	    for_end = p;
	    if (k <= for_end)
	       do {
		  q = getbyte ();
		  if ((q < 32) || (q > 126))
		     badchar = true;
		  if (showing) { // I believe these are \special's
		     // (void) putc (xchr[q], stderr);
		     *xp++ = xchr[q]; *xp = '\0';
		  }
	       }
	       while (k++ < for_end);

	 if (showing) { // Not sure why this quote is printed
	    // (void) putc ('\'', stderr);
	    DRAW_special(xxx);
	 }
	 }
	 if (badchar)
	    if (!showing) {
	       flushtext ();
	       showing = true;
	       tfatal
		("(dviread) bad dvi file (non-ASCII character in xxx command)");
	    } else
	       tfatal
		("(dviread) bad dvi file (non-ASCII character in xxx command)");
	 goto lab30;
      }
      break;
   case 247:
      {
	 if (!showing) {
	    flushtext ();
	    showing = true;
	    tfatal
	     ("(dviread) bad dvi file (preamble command within a page)");
	 } else
	    tfatal
	     ("(dviread) bad dvi file (preamble command within a page)");
	 goto lab9998;
      }
      break;
   case 248:
   case 249:
      {
	 if (!showing) {
	    flushtext ();
	    showing = true;
	    tfatal
	     ("(dviread) bad dvi file (postamble command within a page)");
	 } else
	    tfatal
	     ("(dviread) bad dvi file (postamble command within a page)");
	 goto lab9998;
      }
      break;
   default:
      {
	 if (!showing) {
	    flushtext ();
	    showing = true;
	    tfatal ("(dviread) bad dfi file (undefined command)");
	 } else
	    tfatal ("(dviread) bad dfi file (undefined command)");
	 goto lab30;
      }
      break;
   }
 lab44:if ((v > 0) && (p > 0))
      if (v > 2147483647L - p) {
	 if (!showing) {
	    flushtext ();
	    showing = true;
	    fatal
	     ("(dviread) WARNING: arithmetic overflow! parameter changed from %d to %d",
	      p, 2147483647L - v);
	 } else
	    fatal
	     ("(dviread) WARNING: arithmetic overflow! parameter changed from %d to %d",
	      p, 2147483647L - v);
	 p = 2147483647L - v;
      }
   if ((v < 0) && (p < 0))
      if (-(integer) v > p + 2147483647L) {
	 if (!showing) {
	    flushtext ();
	    showing = true;
	    fatal
	     ("(dviread) WARNING: arithmetic overflow! parameter changed from %d to %d",
	      p, (int) (-v - 2147483647L));
	 } else
	    fatal
	     ("(dviread) WARNING: arithmetic overflow! parameter changed from %d to %d",
	      p, (int) (-v - 2147483647L));
	 p = (-(integer) v) - 2147483647L;
      }
   vvv = round (conv * (v + p));
   if (abs (vvv - vv) > 2)
      if (vvv > vv)
	 vv = vvv - 2;
      else
	 vv = vvv + 2;
   v = v + p;
   if (abs (v) > maxvsofar) {
      if (abs (v) > maxv + 99) {
	 if (!showing) {
	    flushtext ();
	    showing = true;
/*
        tfatal ("%ld%s%s%ld%c",  (long)a , ": " , "warning: |v|>" , (long)maxv , '!' ) ; 
*/
	 } else
/*
      tfatal ("%c%s%ld%c",  ' ' , "warning: |v|>" , (long)maxv , '!' ) ; 
*/
	    maxv = abs (v);
      }
      maxvsofar = abs (v);
   }
   goto lab30;
 lab46:fontnum[nf] = p;
   curfont = 0;
   while (fontnum[curfont] != p)
      curfont = curfont + 1;
   goto lab30;
 lab9998:pure = false;
 lab30:Result = pure;
   return (Result);
}

boolean dopage ()
{
   /* 41 42 43 45 30 9998 9999 */ register boolean Result;
eightbits o;
integer p, q;
integer a;
integer hhh;

   curfont = nf;
   s = 0;
   h = 0;
   v = 0;
   w = 0;
   x = 0;
   y = 0;
   z = 0;
   hh = 0;
   vv = 0;
   DRAW_startpage ();
   /*WIMPHOOK*/ while (true) {

      a = curloc;
      showing = false;
      o = getbyte ();
      p = firstpar (o);
      if (eof (dvifile)) {
	 tfatal ("(dviread) bad dvi file (the file ended prematurely)");
	 uexit (1);
      }
      if (o < 128) {
	 if ((o > 32) && (o <= 126)) {
	    outtext (p);
	    if (outmode >= 2) {
	       showing = true;
	       font_charwidth = pixelwidth[widthbase[curfont] + p];
	       if ((oldhh == -1) && (oldvv == -1)) {
		  oldhh = hh;
		  oldvv = vv;	/* Note start of rectangle */
	       /*WIMP*/}
	    }
	 } else if (outmode > 0) {
	    flushtext ();
	    showing = true;
	    DRAW_char (hh, vv, p);
	 /*WIMPHOOK*/}
	 goto lab41;
      } else
	 switch (o) {
	 case 128:
	 case 129:
	 case 130:
	 case 131:
	    {
	       if (outmode > 0) {
		  flushtext ();
		  showing = true;
/*
          tfatal ("%ld%s%s%ld%c%ld",  (long)a , ": " , "set" , (long)o - 127 , ' ' , (long)p ) ; 
*/
	       }
	       goto lab41;
	    }
	    break;
	 case 133:
	 case 134:
	 case 135:
	 case 136:
	    {
	       if (outmode > 0) {
		  flushtext ();
		  showing = true;
/*
          tfatal ("%ld%s%s%ld%c%ld",  (long)a , ": " , "put" , (long)o - 132 , ' ' , (long)p ) ; 
*/
	       }
	       goto lab41;
	    }
	    break;
	 case 132:
	    {
	       if (outmode > 0) {
		  flushtext ();
		  showing = true;
	       }
	       draw_rule = true;
	       /*WIMP*/ goto lab42;
	    }
	    break;
	 case 137:
	    {
	       if (outmode > 0) {
		  flushtext ();
		  showing = true;
	       }
	       draw_rule = true;
	       /*WIMP*/ goto lab42;
	    }
	    break;
	 case 138:
	    {
	       if (outmode >= 2) {
		  showing = true;
/*
          tfatal ("%ld%s%s",  (long)a , ": " , "nop" ) ; 
*/
	       }
	       goto lab30;
	    }
	    break;
	 case 139:
	    {
	       if (!showing) {
		  flushtext ();
		  showing = true;
		  tfatal ("(dviread) bad dvi file (bop occurred before eop)");
	       } else
		  tfatal ("(dviread) bad dvi file (bop occurred before eop)");
	       goto lab9998;
	    }
	    break;
	 case 140:
	    {
	       if (outmode > 0) {
		  flushtext ();
		  showing = true;
	       }
	       if (s != 0)
		  if (!showing) {
		     flushtext ();
		     showing = true;
		     tfatal
		      ("(dviread) bad dvi file (stack not empty at end of page)");
		  } else
		     tfatal
		      ("(dviread) bad dvi file (stack not empty at end of page)");
	       Result = true;
	       DRAW_endpage (maxh /* page_width */ , maxv	/* page_height 
			      */ , count /* page_counters */ );
	       /*WIMPHOOK*/ goto lab9999;
	    }
	    break;
	 case 141:
	    {
	       if (outmode > 0) {
		  flushtext ();
		  showing = true;
	       }
	       if (s == maxssofar) {
		  maxssofar = s + 1;
		  if (s == maxs)
		     if (!showing) {
			flushtext ();
			showing = true;
			tfatal
			 ("(dviread) bad dvi file (deeper than claimed in postamble)");
		     } else
			tfatal
			 ("(dviread) bad dvi file (deeper than claimed in postamble)");
		  ;
		  if (s == stacksize) {
		     if (!showing) {
			flushtext ();
			showing = true;
			tfatal ("(dviread) capacity exceeded (stack)");
		     } else
			tfatal ("(dviread) capacity exceeded (stack)");
		     goto lab9998;
		  }
	       }
	       hstack[s] = h;
	       vstack[s] = v;
	       wstack[s] = w;
	       xstack[s] = x;
	       ystack[s] = y;
	       zstack[s] = z;
	       hhstack[s] = hh;
	       vvstack[s] = vv;
	       s = s + 1;
	       ss = s - 1;
	       goto lab45;
	    }
	    break;
	 case 142:
	    {
	       if (outmode > 0) {
		  flushtext ();
		  showing = true;
	       }
	       if (s == 0)
		  if (!showing) {
		     flushtext ();
		     showing = true;
		     tfatal ("(dviread) bad dvi file");
		  } else
		     tfatal ("(dviread) bad dvi file");
	       else {

		  s = s - 1;
		  hh = hhstack[s];
		  vv = vvstack[s];
		  h = hstack[s];
		  v = vstack[s];
		  w = wstack[s];
		  x = xstack[s];
		  y = ystack[s];
		  z = zstack[s];
	       }
	       ss = s;
	       goto lab45;
	    }
	    break;
	 case 143:
	 case 144:
	 case 145:
	 case 146:
	    {
#ifdef PROPER
	       if ((p >= fontspace[curfont])
		   || (p <= -4 * fontspace[curfont])) {
		  outtext (32);
		  hh = round (conv * (h + p));
	       } else
#endif
	       {
		  if (outmode > 0)
		     flushtext ();
		  hh = hh + round (conv * (p));
	       }
	       if (outmode >= 2) {
		  showing = true;
	       }
	       q = p;
	       goto lab43;
	    }
	    break;
	 case 147:
	 case 148:
	 case 149:
	 case 150:
	 case 151:
	    {
	       w = p;
#ifdef PROPER
	       if ((p >= fontspace[curfont])
		   || (p <= -4 * fontspace[curfont])) {
		  outtext (32);
		  hh = round (conv * (h + p));
	       } else
#endif
	       {
		  if (outmode > 0)
		     flushtext ();
		  hh = hh + round (conv * (p));
	       }
	       if (outmode >= 2) {
		  showing = true;
	       }
	       q = p;
	       goto lab43;
	    }
	    break;
	 case 152:
	 case 153:
	 case 154:
	 case 155:
	 case 156:
	    {
	       x = p;
#ifdef PROPER
	       if ((p >= fontspace[curfont])
		   || (p <= -4 * fontspace[curfont])) {
		  outtext (32);
		  hh = round (conv * (h + p));
	       } else
#endif
	       {
		  if (outmode > 0)
		     flushtext ();
		  hh = hh + round (conv * (p));
	       }
	       if (outmode >= 2) {
		  showing = true;
	       }
	       q = p;
	       goto lab43;
	    }
	    break;
	 default:
	    if (specialcases (o, p, a))
	       goto lab30;
	    else
	       goto lab9998;
	    break;
	 }
    lab41:if (p < 0)
	 p = 255 - ((-1 - p) % 256);
      else if (p >= 256)
	 p = p % 256;
      if ((p < fontbc[curfont]) || (p > fontec[curfont]))
	 q = 2147483647L;
      else
	 q = width[widthbase[curfont] + p];
      if (q == 2147483647L) {
	 if (!showing) {
	    flushtext ();
	    showing = true;
	    tfatal ("(dviread) bad dvi file (character invalid in font)");
	 } else
	    tfatal ("(dviread) bad dvi file (character invalid in font)");
	 printfont (curfont);
	 if (curfont != nf)
	    (void) putc ('!', stderr);
      }
      if (o >= 133)
	 goto lab30;
      if (q == 2147483647L)
	 q = 0;
      else
	 hh = hh + pixelwidth[widthbase[curfont] + p];
      goto lab43;
    lab42:q = signedquad ();
      if (showing) {
	 if ((p <= 0) || (q <= 0)) {
	    (void) Fputs (stderr, " (invisible)");
	 } else {
	    if (draw_rule) {
	       DRAW_rule (hh, vv, (long) rulepixels (p),
			  (long) rulepixels (q));
	    }
	 }
      }
      draw_rule = false;
      if (o == 137)
	 goto lab30;
      hh = hh + rulepixels (q);
      goto lab43;
    lab43:if ((h > 0) && (q > 0))
	 if (h > 2147483647L - q) {
	    if (!showing) {
	       flushtext ();
	       showing = true;
	       tfatal ("%ld%s%s%ld%s%ld", (long) a, ": ",
		       "arithmetic overflow! parameter changed from ",
		       (long) q, " to ", (long) 2147483647L - h);
	    } else
	       tfatal ("%c%s%ld%s%ld", ' ',
		       "arithmetic overflow! parameter changed from ",
		       (long) q, " to ", (long) 2147483647L - h);
	    q = 2147483647L - h;
	 }
      if ((h < 0) && (q < 0))
	 if (-(integer) h > q + 2147483647L) {
	    if (!showing) {
	       flushtext ();
	       showing = true;
	       tfatal ("%ld%s%s%ld%s%ld", (long) a, ": ",
		       "arithmetic overflow! parameter changed from ",
		       (long) q, " to ", (long) (-(integer) h) - 2147483647L);
	    } else
	       tfatal ("%c%s%ld%s%ld", ' ',
		       "arithmetic overflow! parameter changed from ",
		       (long) q, " to ", (long) (-(integer) h) - 2147483647L);
	    q = (-(integer) h) - 2147483647L;
	 }
      hhh = round (conv * (h + q));
      if (abs (hhh - hh) > 2)
	 if (hhh > hh)
	    hh = hhh - 2;
	 else
	    hh = hhh + 2;
      h = h + q;
      if (abs (h) > maxhsofar) {
	 if (abs (h) > maxh + 99) {
	    if (!showing) {
	       flushtext ();
	       showing = true;
	       tfatal ("%ld%s%s%ld%c", (long) a, ": ", "warning: |h|>",
		       (long) maxh, '!');
	    } else
	       tfatal ("%c%s%ld%c", ' ', "warning: |h|>", (long) maxh, '!');
	    maxh = abs (h);
	 }
	 maxhsofar = abs (h);
      }
      goto lab30;
    lab45:if (showing) {
      }
      goto lab30;
    lab30:;
   }
 lab9998:tfatal ("%c\n", '!');
   Result = false;
 lab9999:;
   return (Result);
}

skippages ()
{
   /* 9999 */ integer p;
unsigned char k;
integer downthedrain;

   showing = false;
   while (true) {

      if (eof (dvifile)) {
	 tfatal ("%c%s%s%c", ' ', "Bad DVI file: ",
		 "the file ended prematurely", '!');
	 uexit (1);
      }
      k = getbyte ();
      p = firstpar (k);
      switch (k) {
      case 139:
	 {
	    newbackpointer = curloc - 1;
	    pagecount = pagecount + 1;
	    {
register integer for_end;

	       k = 0;
	       for_end = 9;
	       if (k <= for_end)
		  do
		     count[k] = signedquad ();
		  while (k++ < for_end);
	    }
	    if (signedquad () != oldbackpointer)
	       tfatal ("%s%ld%s%ld%c\n", "backpointer in byte ",
		       (long) curloc - 4, " should be ",
		       (long) oldbackpointer, '!');
	    oldbackpointer = newbackpointer;
	    if (!started && startmatch ()) {
	       started = true;
	       goto lab9999;
	    }
	 }
	 break;
      case 132:
      case 137:
	 downthedrain = signedquad ();
	 break;
      case 243:
      case 244:
      case 245:
      case 246:
	 {
	    definefont (p);
	 }
	 break;
      case 239:
      case 240:
      case 241:
      case 242:
	 while (p > 0) {

	    downthedrain = getbyte ();
	    p = p - 1;
	 }
	 break;
      case 248:
	 {
	    inpostamble = true;
	    goto lab9999;
	 }
	 break;
      default:
	 ;
	 break;
      }
   }
 lab9999:;
}

readpostamble ()
{
integer k;
integer p, q, m;

   showing = false;
   postloc = curloc - 5;
   if (signedquad () != numerator)
      tfatal ("%s\n", "numerator doesn't match the preamble!");
   if (signedquad () != denominator)
      tfatal ("%s\n", "denominator doesn't match the preamble!");
   if (signedquad () != mag)
      if (newmag == 0)
	 tfatal ("%s\n", "magnification doesn't match the preamble!");
   maxv = signedquad ();
   maxh = signedquad ();
   maxs = gettwobytes ();
   totalpages = gettwobytes ();
   if (outmode < 3) {
      if (maxv + 99 < maxvsofar)
	 tfatal ("%s%ld\n", "warning: observed maxv was ", (long) maxvsofar);
      if (maxh + 99 < maxhsofar)
	 if (debug)
	    fprintf (stderr, "%s%ld\n", "warning: observed maxh was ",
		     (long) maxhsofar);
      if (maxs < maxssofar)
	 tfatal ("%s%ld\n", "warning: observed maxstackdepth was ",
		 (long) maxssofar);
      if (pagecount != totalpages)
	 tfatal ("%s%ld%s%ld%c\n", "there are really ", (long) pagecount,
		 " pages, not ", (long) totalpages, '!');
   }
   do {
      k = getbyte ();
      if ((k >= 243) && (k < 247)) {
	 p = firstpar (k);
	 definefont (p);
	 k = 138;
      }
   } while (!(k != 138));
   if (k != 249)
      tfatal ("%s%ld%s\n", "byte ", (long) curloc - 1, " is not postpost!");
   q = signedquad ();
   if (q != postloc)
      tfatal ("%s%ld%c\n", "bad postamble pointer in byte ",
	      (long) curloc - 4, '!');
   m = getbyte ();
   if (m != 2)
      tfatal ("%s%ld%s%ld%c\n", "identification in byte ", (long) curloc - 1,
	      " should be ", (long) 2, '!');
   k = curloc;
   m = 223;
   while ((m == 223) && !eof (dvifile))
      m = getbyte ();
   if (!eof (dvifile)) {
      tfatal ("%c%s%s%ld%s%c", ' ', "Bad DVI file: ", "signature in byte ",
	      (long) curloc - 1, " should be 223", '!');
      uexit (1);
   } else if (curloc < k + 4)
      tfatal ("%s%ld%c\n", "not enough signature bytes at end of file (",
	      (long) curloc - k, ')');

   /* *Should* be safe now to close the dvifile */
   fclose (dvifile);

}

main_body ()
{

   initialize ();
   dialog ();
   opendvifile ();
   DRAW_startjob ();
   p = getbyte ();
   if (p != 247) {
      tfatal ("%c%s%s%c", ' ', "Bad DVI file: ",
	      "First byte isn't start of preamble!", '!');
      uexit (1);
   }
   p = getbyte ();
   if (p != 2)
      tfatal ("%s%ld%c\n", "identification in byte 1 should be ", (long) 2,
	      '!');
   numerator = signedquad ();
   denominator = signedquad ();
   if (numerator <= 0) {
      tfatal ("%c%s%s%ld%c", ' ', "Bad DVI file: ", "numerator is ",
	      (long) numerator, '!');
      uexit (1);
   }
   if (denominator <= 0) {
      tfatal ("%c%s%s%ld%c", ' ', "Bad DVI file: ", "denominator is ",
	      (long) denominator, '!');
      uexit (1);
   }
   conv = (numerator / ((double) 254000.0)) * (resolution / ((double)
							     denominator));
   mag = signedquad ();
   if (newmag > 0)
      mag = newmag;
   else if (mag <= 0) {
      tfatal ("%c%s%s%ld%c", ' ', "Bad DVI file: ", "magnification is ",
	      (long) mag, '!');
      uexit (1);
   }
   trueconv = conv;
   conv = trueconv * (mag / ((double) 1000.0));
   p = getbyte ();
#ifndef ARM
   if (outmode == 3) {
      n = dvilength ();
      if (n < 53) {
	 (void) fprintf (stderr,
			 "%c%s%s%ld%s%c", ' ',
			 "Bad DVI file: ", "only ", (long) n, " bytes long",
			 '!');
	 uexit (1);
      }
      m = n - 4;
      do {
	 if (m == 0) {
	    (void) fprintf (stderr,
			    "%c%s%s%c", ' ', "Bad DVI file: ", "all 223s",
			    '!');
	    uexit (1);
	 }
	 movetobyte (m);
	 k = getbyte ();
	 m = m - 1;
      } while (!(k != 223));
      if (k != 2) {
	 tfatal ("%c%s%s%ld%c", ' ', "Bad DVI file: ", "ID byte is ",
		 (long) k, '!');
	 uexit (1);
      }
      movetobyte (m - 3);
      q = signedquad ();
      if ((q < 0) || (q > m - 33)) {
	 tfatal ("%c%s%s%ld%s%ld%c", ' ', "Bad DVI file: ", "post pointer ",
		 (long) q, " at byte ", (long) m - 3, '!');
	 uexit (1);
      }
      movetobyte (q);
      k = getbyte ();
      if (k != 248) {
	 tfatal ("%c%s%s%ld%s%c", ' ', "Bad DVI file: ", "byte ", (long) q,
		 " is not post", '!');
	 uexit (1);
      }
      postloc = q;
      firstbackpointer = signedquad ();
      inpostamble = true;
      readpostamble ();

      inpostamble = false;
      q = postloc;
      p = firstbackpointer;
      startloc = -1;
      if (p < 0)
	 inpostamble = true;
      else {

	 do {
	    if (p > q - 46) {
	       tfatal ("%c%s%s%ld%s%ld%c", ' ', "Bad DVI file: ",
		       "page link ", (long) p, " after byte ", (long) q, '!');
	       uexit (1);
	    }
	    q = p;
	    movetobyte (q);
	    k = getbyte ();
	    if (k == 139)
	       pagecount = pagecount + 1;
	    else {

	       tfatal ("%c%s%s%ld%s%c", ' ', "Bad DVI file: ", "byte ",
		       (long) q, " is not bop", '!');
	       uexit (1);
	    }
	    {
register integer for_end;

	       k = 0;
	       for_end = 9;
	       if (k <= for_end)
		  do
		     count[k] = signedquad ();
		  while (k++ < for_end);
	    }
	    if (startmatch ())
	       startloc = q;
	    p = signedquad ();
	 } while (!(p < 0));
	 if (startloc < 0) {
	    tfatal ("%c%s", ' ', "starting page number could not be found!");
	    uexit (1);
	 }
	 movetobyte (startloc + 1);
	 oldbackpointer = startloc;
	 {
register integer for_end;

	    k = 0;
	    for_end = 9;
	    if (k <= for_end)
	       do
		  count[k] = signedquad ();
	       while (k++ < for_end);
	 }
	 p = signedquad ();
	 started = true;
      }
      if (pagecount != totalpages)
	 tfatal ("%s%ld%s%ld%c\n", "there are really ", (long) pagecount,
		 " pages, not ", (long) totalpages, '!');
   } else
#endif
      skippages ();
   if (!inpostamble) {
      while (maxpages > 0) {

	 maxpages = maxpages - 1;
	 {
register integer for_end;

	    k = 0;
	    for_end = startvals;
	    while (k++ < for_end) ;
	 }
	 if (!dopage ()) {
	    tfatal ("%c%s%s%c", ' ', "Bad DVI file: ",
		    "page ended unexpectedly", '!');
	    uexit (1);
	 }
	 do {
	    k = getbyte ();
	    if ((k >= 243) && (k < 247)) {
	       p = firstpar (k);
	       definefont (p);
	       k = 138;
	    }
	 } while (!(k != 138));
	 if (k == 248) {
	    inpostamble = true;
	    goto lab30;
	 }
	 if (k != 139) {
	    tfatal ("%c%s%s%ld%s%c", ' ', "Bad DVI file: ", "byte ",
		    (long) curloc - 1, " is not bop", '!');
	    uexit (1);
	 }
	 newbackpointer = curloc - 1;
	 pagecount = pagecount + 1;
	 {
register integer for_end;

	    k = 0;
	    for_end = 9;
	    if (k <= for_end)
	       do
		  count[k] = signedquad ();
	       while (k++ < for_end);
	 }
	 if (signedquad () != oldbackpointer)
	    tfatal ("%s%ld%s%ld%c\n", "backpointer in byte ",
		    (long) curloc - 4, " should be ", (long) oldbackpointer,
		    '!');
	 oldbackpointer = newbackpointer;
      }
    lab30:;
   }
   if (outmode < 3) {
      if (!inpostamble)
	 skippages ();
      if (signedquad () != oldbackpointer)
	 tfatal ("%s%ld%s%ld%c\n", "backpointer in byte ", (long) curloc - 4,
		 " should be ", (long) oldbackpointer, '!');
      readpostamble ();
   }
   DRAW_endjob ();
}