{3:}

program DVIDOC(input, output, dvifile, errfile); {4:}
label
    9999, 30; {:4} {5:}
const
    maxfonts = 100;
    maxwidths = 10000;
    terminallinelength = 150;
    stacksize = 100;
    namesize = 1000;
    namelength = 100;
    pagewidthmax = 132;
    pagelengthmax = 88; {:5} {9:}
type
    ASCIIcode = 32..126; {:9} {10:}
    textfile = packed file of char; {:10} {22:}
    eightbits = integer;
    bytefile = packed file of char; {:22} {11:}
var
    xord: array [char] of ASCIIcode;
    xchr: array [0..255] of char; {:11} {23:}
    dvifile: bytefile;
    eofdvifile: boolean;
    tfmfile: bytefile; {:23} {27:}
    curloc: integer;
    basename, curname, realnameoffile: packed array [1..namelength] of char; {:27}
{28:}
    b0, b1, b2, b3: eightbits; {:28} {32:}
    fontnum: array [0..maxfonts] of integer;
    fontname: array [0..maxfonts] of 0..namesize;
    names: array [0..namesize] of ASCIIcode;
    fontchecksum: array [0..maxfonts] of integer;
    fontscaledsize: array [0..maxfonts] of integer;
    fontdesignsize: array [0..maxfonts] of integer;
    fontspace: array [0..maxfonts] of integer;
    fontbc: array [0..maxfonts] of integer;
    fontec: array [0..maxfonts] of integer;
    widthbase: array [0..maxfonts] of integer;
    width: array [0..maxwidths] of integer;
    nf: 0..maxfonts;
    widthptr: 0..maxwidths; {:32} {35:}
    inwidth: array [0..255] of integer;
    tfmchecksum: integer; {:35} {41:}
    pixelwidth: array [0..maxwidths] of integer;
    horizconv: real;
    vertconv: real;
    truehorizconv: real;
    truevertconv: real;
    numerator, denominator: integer;
    mag: integer; {:41} {43:}
    maxpages: integer;
    horizresolution: real;
    vertresolution: real;
    newmag: integer; {:43} {44:}
    startcount: array [0..9] of integer;
    startthere: array [0..9] of boolean;
    startvals: 0..9;
    count: array [0..9] of integer; {:44} {47:}
    buffer: array [0..terminallinelength] of ASCIIcode; {:47} {49:}
    bufptr: 0..terminallinelength; {:49} {54:}
    inpostamble: boolean; {:54} {61:}
    defaultdirectory: packed array [1..9] of char; {:61} {64:}
    i: 1..namelength;
    logerrors: boolean;
    errfile: textfile;
    pagebuffer: packed array [1..pagewidthmax, 1..pagelengthmax] of ASCIIcode;
    linehwm: array [1..pagelengthmax] of 0..pagewidthmax;
    pagehwm: 0..pagelengthmax; {:64} {70:}
    h, v, w, x, y, z, hh, vv: integer;
    hstack, vstack, wstack, xstack, ystack, zstack: array [0..stacksize] of integer;
    hhstack, vvstack: array [0..stacksize] of integer; {:70} {71:}
    maxv: integer;
    maxh: integer;
    maxs: integer;
    maxvsofar, maxhsofar, maxssofar: integer;
    totalpages: integer;
    pagecount: integer; {:71} {76:}
    s: integer;
    ss: integer;
    curfont: integer; {:76} {93:}
    oldbackpointer: integer;
    newbackpointer: integer;
    started: boolean; {:93} {97:}
    postloc: integer;
    firstbackpointer: integer;
    startloc: integer; {:97} {103:}
    k, m, n, p, q: integer; {:103}
#include "dvityext.h"

    procedure initialize;
    var
	i: integer;
    begin
	setpaths; {12:}
	for i := 0 to 31 do 
	    xchr[i] := '?';
	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] := '~';
	for i := 127 to 255 do 
	    xchr[i] := '?'; {:12} {13:}
	for i := 0 to 127 do 
	    xord[chr(i)] := 32;
	for i := 32 to 126 do 
	    xord[xchr[i]] := i; {:13} {33:}
	nf := 0;
	widthptr := 0;
	fontname[0] := 0;
	fontspace[0] := 0; {:33} {45:}
	maxpages := 1000000;
	startvals := 0;
	startthere[0] := false; {:45} {55:}
	inpostamble := false; {:55} {62:}
	defaultdirectory := 'TeXfonts:'; {:62} {72:}
	maxv := 2147483548;
	maxh := 2147483548;
	maxs := stacksize + 1;
	maxvsofar := 0;
	maxhsofar := 0;
	maxssofar := 0;
	pagecount := 0; {:72} {94:}
	oldbackpointer := -1;
	started := false
    end;
{:94} {:3} {7:}

    procedure jumpout;
    begin
	goto 9999
    end; {:7} {26:}

    procedure opentfmfile;
    begin
	if testaccess(4, 3) then 
	    reset(tfmfile, realnameoffile)
	else begin
	    writeln(errfile, 'TFM file not found');
	    goto 30
	end
    end; {:26} {29:}

    procedure readtfmword;
    var
	byte: char;
    begin
	read(tfmfile, byte);
	b0 := ord(byte);
	if b0 < 0 then 
	    b0 := b0 + 256;
	read(tfmfile, byte);
	b1 := ord(byte);
	if b1 < 0 then 
	    b1 := b1 + 256;
	read(tfmfile, byte);
	b2 := ord(byte);
	if b2 < 0 then 
	    b2 := b2 + 256;
	read(tfmfile, byte);
	b3 := ord(byte);
	if b3 < 0 then 
	    b3 := b3 + 256
    end; {:29} {30:}

    function dvilength: integer;
    begin
	setpos(dvifile, -1);
	dvilength := curpos(dvifile)
    end; { dvilength }

    procedure movetobyte(n: integer);
    begin
	setpos(dvifile, n);
	curloc := n
    end; { movetobyte }
{:30}
    {34:}

    procedure printfont(f: integer);
    var
	k: 0..namesize;
    begin
	if f = nf then 
	    write(errfile, 'UNDEFINED!')
	else begin
	    for k := fontname[f] to fontname[f + 1] - 1 do 
		write(errfile, xchr[names[k]])
	end
    end; {:34}
{36:}

    function inTFM(z: integer): boolean;
    label
	9997, 9998, 9999;
    var
	k: integer;
	lh: integer;
	nw: integer;
	wp: 0..maxwidths;
	alpha, beta: integer; {37:}
    begin
	readtfmword;
	lh := (b2 * 256) + b3;
	readtfmword;
	fontbc[nf] := (b0 * 256) + b1;
	fontec[nf] := (b2 * 256) + b3;
	if fontec[nf] < fontbc[nf] then 
	    fontbc[nf] := fontec[nf] + 1;
	if (((widthptr + fontec[nf]) - fontbc[nf]) + 1) > maxwidths then begin
	    writeln(errfile, '---not loaded, DVIDOC needs larger width table');
	    goto 9998
	end;
	wp := ((widthptr + fontec[nf]) - fontbc[nf]) + 1;
	readtfmword;
	nw := (b0 * 256) + b1;
	if (nw = 0) or (nw > 256) then 
	    goto 9997;
	for k := 1 to 3 + lh do begin
	    if eofdvifile then 
		goto 9997;
	    readtfmword;
	    if k = 4 then 
		if b0 < 128 then 
		    tfmchecksum := (((((b0 * 256) + b1) * 256) + b2) * 256) + b3
		else 
		    tfmchecksum := ((((((b0 - 256) * 256) + b1) * 256) + b2) * 256) + b3
	end; {:37} {38:}
	if wp > 0 then 
	    for k := widthptr to wp - 1 do begin
		readtfmword;
		if b0 > nw then 
		    goto 9997;
		width[k] := b0
	    end; {:38} {39:} {40:}
	begin
	    alpha := 16 * z;
	    beta := 16;
	    while z >= 8388608 do begin
		z := z div 2;
		beta := beta div 2
	    end
	end {:40};
	for k := 0 to nw - 1 do begin
	    readtfmword;
	    inwidth[k] := (((((b3 * z) div 256) + (b2 * z)) div 256) + (b1 * z)) div beta;
	    if b0 > 0 then 
		if b0 < 255 then 
		    goto 9997
		else 
		    inwidth[k] := inwidth[k] - alpha
	end {:39}; {42:}
	widthbase[nf] := widthptr - fontbc[nf];
	if wp > 0 then 
	    for k := widthptr to wp - 1 do begin
		width[k] := inwidth[width[k]];
		pixelwidth[k] := round(horizconv * width[k])
	    end {:42};
	widthptr := wp;
	inTFM := true;
	goto 9999;
    9997:
	writeln(errfile, '---not loaded, TFM file is bad');
    9998:
	inTFM := false;
    9999:
	null
    end; {:36} {46:}

    function startmatch: boolean;
    var
	k: 0..9;
	match: boolean;
    begin
	match := true;
	for k := 0 to startvals do 
	    if startthere[k] and (startcount[k] <> count[k]) then 
		match := false;
	startmatch := match
    end; {:46} {48:}

    procedure copyln;
    var
	k: 0..terminallinelength;
    begin
	k := 2;
	while (k < namelength) and (curname[k] <> ' ') do begin
	    buffer[k - 3] := xord[curname[k]];
	    k := k + 1
	end;
	buffer[k - 3] := xord[' ']
    end; {:48} {50:}

    function getinteger: integer;
    var
	x: integer;
	negative: boolean;
    begin
	if buffer[bufptr] = 45 then begin
	    negative := true;
	    bufptr := bufptr + 1
	end else 
	    negative := false;
	x := 0;
	while (buffer[bufptr] >= 48) and (buffer[bufptr] <= 57) do begin
	    x := ((10 * x) + buffer[bufptr]) - 48;
	    bufptr := bufptr + 1
	end;
	if negative then 
	    getinteger := -x
	else 
	    getinteger := x
    end; {:50} {51:}

    procedure options;
    var
	j, k: integer;
    begin
	logerrors := false;
	startvals := 0;
	startthere[0] := false;
	maxpages := 1000000;
	horizresolution := 13.76582;
	vertresolution := 6.0225;
	newmag := 0;
	basename[1] := ' ';
	j := 1;
	while j < argc do begin
	    argv(j, curname);
	    if curname[1] = '-' then begin
		if curname[2] = 'e' then 
		    logerrors := true
		else if curname[2] = 's' then begin {52:}
		    copyln;
		    bufptr := 0;
		    k := 0;
		    if buffer[0] <> 32 then 
			repeat
			    if buffer[bufptr] = 42 then begin
				startthere[k] := false;
				bufptr := bufptr + 1
			    end else begin
				startthere[k] := true;
				startcount[k] := getinteger
			    end;
			    if (k < 9) and (buffer[bufptr] = 46) then begin
				k := k + 1;
				bufptr := bufptr + 1
			    end else if buffer[bufptr] = 32 then 
				startvals := k
			    else begin
				message('1.*.-5 specifies first page with \count0=1, \count2=-5.');
				goto 30
			    end
			until startvals = k {:52}
		end else if curname[2] = 'm' then begin {53:}
		    copyln;
		    bufptr := 0;
		    if buffer[0] <> 32 then begin
			maxpages := getinteger;
			if maxpages <= 0 then begin
			    message('Maxpages should be a positive number.');
			    goto 30
			end {:53}
		    end
		end else begin
		    message('Usage: dvidoc [-e] [-s<start page spec>] [-m<maxpages>] <dvi-file>');
		    goto 30
		end
	    end else if basename[1] = ' ' then 
		argv(j, basename)
	    else begin
		message('Only one input file please');
		goto 30
	    end;
	    j := j + 1
	end;
	if basename[1] = ' ' then begin
	    message('No input file specified');
	    goto 30
	end
    end; {:51} {56:}

    procedure definefont(e: integer);
    var
	f: 0..maxfonts;
	p: integer;
	n: integer;
	c, q, d: integer;
	r: 0..namelength;
	j, k: 0..namesize;
	mismatch: boolean;
    begin
	if nf = maxfonts then begin
	    message(' ', 'DVIDOC capacity exceeded (max fonts=', maxfonts: 1, ')!');
	    jumpout
	end;
	fontnum[nf] := e;
	f := 0;
	while fontnum[f] <> e do 
	    f := f + 1; {58:}
	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 then begin
	    message(' ', 'DVIDOC capacity exceeded (name size=', namesize: 1, ')!');
	    jumpout
	end;
	fontname[nf + 1] := (fontname[nf] + n) + p;
	write(errfile, 'Font ', e: 1, ': ');
	if (n + p) = 0 then 
	    write(errfile, 'null font name!')
	else 
	    for k := fontname[nf] to fontname[nf + 1] - 1 do 
		names[k] := getbyte;
	nf := nf + 1;
	printfont(nf - 1);
	nf := nf - 1 {:58};
	if inpostamble then begin
	    if f < nf then 
		writeln(errfile, '---this font was already defined!')
	end else begin
	    if f = nf then 
		writeln(errfile, '---this font wasn''t loaded before!')
	end;
	if f = nf then begin {59:} {63:}
	    for k := 1 to namelength do 
		curname[k] := ' ';
	    r := 0;
	    for k := fontname[nf] to fontname[nf + 1] - 1 do begin
		r := r + 1;
		if (r + 4) > namelength then begin
		    message(' ', 'DVIDOC capacity exceeded (max font name length=', namelength: 1, ')!');
		    jumpout
		end;
		curname[r] := xchr[names[k]]
	    end;
	    curname[r + 1] := '.';
	    curname[r + 2] := 't';
	    curname[r + 3] := 'f';
	    curname[r + 4] := 'm' {:63};
	    opentfmfile;
	    if eofdvifile then 
		write(errfile, '---not loaded, TFM file can''t be opened!')
	    else begin
		if (q <= 0) or (q >= 134217728) then 
		    write(errfile, '---not loaded, bad scale (', q: 1, ')!')
		else if (d <= 0) or (d >= 134217728) then 
		    write(errfile, '---not loaded, bad design size (', d: 1, ')!')
		else if inTFM(q) then begin {60:}
		    fontspace[nf] := q div 6;
		    if ((c <> 0) and (tfmchecksum <> 0)) and (c <> tfmchecksum) then begin
			writeln(errfile, '---beware: check sums do not agree!');
			writeln(errfile, '   (', c: 1, ' vs. ', tfmchecksum: 1, ')');
			write(errfile, '   ')
		    end;
		    write(errfile, '---loaded at size ', q: 1, ' DVI units');
		    d := round(((100.0 * horizconv) * q) / (truehorizconv * d));
		    if d <> 100 then begin
			writeln(errfile, ' ');
			write(errfile, ' (this font is magnified ', d: 1, '%)')
		    end;
		    nf := nf + 1;
		    fontspace[nf] := 0
		end {:60}
	    end;
	    writeln(errfile, ' ')
	end else begin {:59} {57:}
	    if fontchecksum[f] <> c then 
		writeln(errfile, '---check sum doesn''t match previous definition!');
	    if fontscaledsize[f] <> q then 
		writeln(errfile, '---scaled size doesn''t match previous definition!');
	    if fontdesignsize[f] <> d then 
		writeln(errfile, '---design size doesn''t match previous definition!');
	    j := fontname[f];
	    k := fontname[nf];
	    mismatch := false;
	    while j < fontname[f + 1] do begin
		if names[j] <> names[k] then 
		    mismatch := true;
		j := j + 1;
		k := k + 1
	    end;
	    if k <> fontname[nf + 1] then 
		mismatch := true;
	    if mismatch then 
		writeln(errfile, '---font name doesn''t match previous definition!');
	    writeln(errfile, ' ') {:57}
	end
    end; {:56} {66:}

    procedure flushpage;
    var
	i: 0..pagewidthmax;
	j: 0..pagelengthmax;
    begin
	for j := 1 to pagehwm do begin
	    for i := 1 to linehwm[j] do 
		write(output, xchr[pagebuffer[i, j]]);
	    writeln(output)
	end;
	write(output, chr(12))
    end; { flushpage }
{:66}
    {67:}

    procedure emptypage;
    begin
	pagehwm := 0
    end; {:67} {68:}

    procedure outchar(p, hh, vv: integer);
    var
	i: 1..pagewidthmax;
	j: 1..pagelengthmax;
	k: integer;
	c: ASCIIcode;
    begin
	if (p > 32) and (p <= 126) then 
	    c := p
	else 
	    c := xord['?'];
	if (hh > (pagewidthmax - 1)) or (vv > (pagelengthmax - 1)) then begin
	    writeln(errfile, ' ');
	    write(errfile, 'Character "', xchr[c], '" set at column ', hh + 1: 1);
	    writeln(errfile, ' and row ', vv + 1: 1, ',');
	    write(errfile, 'outside the range of DVIDOC (');
	    write(errfile, pagewidthmax: 1, ',', pagelengthmax: 1, ').');
	    writeln(errfile, ' ')
	end else begin
	    i := hh + 1;
	    j := vv + 1;
	    if j > pagehwm then begin
		for k := pagehwm + 1 to j do 
		    linehwm[k] := 0;
		pagehwm := j
	    end;
	    if i > linehwm[j] then begin
		for k := linehwm[j] + 1 to i do 
		    pagebuffer[k, j] := xord[' '];
		linehwm[j] := i
	    end;
	    pagebuffer[i, j] := c
	end
    end; {:68} {73:}

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

    function horizrulepixels(x: integer): integer;
    var
	n: integer;
    begin
	n := trunc(horizconv * x);
	if n < (horizconv * x) then 
	    horizrulepixels := n + 1
	else 
	    horizrulepixels := n
    end; { horizrulepixels }

    function vertrulepixels(x: integer): integer;
    var
	n: integer;
    begin
	n := trunc(vertconv * x);
	if n < (vertconv * x) then 
	    vertrulepixels := n + 1
	else 
	    vertrulepixels := n
    end; { vertrulepixels }
{:74}
    {77:}
    {80:}

    function specialcases(o: eightbits; p, a: integer): boolean;
    label
	46, 44, 30, 9998;
    var
	q: integer;
	k: integer;
	badchar: boolean;
	pure: boolean;
	vvv: integer;
    begin
	pure := true;
	if o in
	    [133, 134, 135, 136, 157, 158, 159, 160,
	     161, 162, 163, 164, 165, 166, 167, 168,
	     169, 170, 171, 172, 173, 174, 175, 176,
	     177, 178, 179, 180, 181, 182, 183, 184,
	     185, 186, 187, 188, 189, 190, 191, 192,
	     193, 194, 195, 196, 197, 198, 199, 200,
	     201, 202, 203, 204, 205, 206, 207, 208,
	     209, 210, 211, 212, 213, 214, 215, 216,
	     217, 218, 219, 220, 221, 222, 223, 224,
	     225, 226, 227, 228, 229, 230, 231, 232,
	     233, 234, 235, 236, 237, 238, 243, 244,
	     245, 246, 239, 240, 241, 242, 247, 248,
	     249] then
	    case o of
		133, 134, 135, 136:
		    begin
			goto 30
		    end; {83:}
		157, 158, 159, 160:
		    begin
			if abs(p) >= (5 * fontspace[curfont]) then 
			    vv := round(vertconv * (v + p))
			else 
			    vv := vv + round(vertconv * p);
			goto 44
		    end;
		161, 162, 163, 164, 165:
		    begin
			y := p;
			if abs(p) >= (5 * fontspace[curfont]) then 
			    vv := round(vertconv * (v + p))
			else 
			    vv := vv + round(vertconv * p);
			goto 44
		    end;
		166, 167, 168, 169, 170:
		    begin
			z := p;
			if abs(p) >= (5 * fontspace[curfont]) then 
			    vv := round(vertconv * (v + p))
			else 
			    vv := vv + round(vertconv * p);
			goto 44
		    end; {:83} {84:}
		171, 172, 173, 174, 175, 176, 177,
		178, 179, 180, 181, 182, 183, 184,
		185, 186, 187, 188, 189, 190, 191,
		192, 193, 194, 195, 196, 197, 198,
		199, 200, 201, 202, 203, 204, 205,
		206, 207, 208, 209, 210, 211, 212,
		213, 214, 215, 216, 217, 218, 219,
		220, 221, 222, 223, 224, 225, 226,
		227, 228, 229, 230, 231, 232, 233,
		234:
		    begin
			goto 46
		    end;
		235, 236, 237, 238:
		    begin
			goto 46
		    end;
		243, 244, 245, 246:
		    begin
			definefont(p);
			goto 30
		    end; {:84}
		239, 240, 241, 242:
		    begin {85:}
			write(errfile, 'xxx''');
			badchar := false;
			for k := 1 to p do begin
			    q := getbyte;
			    if (q < 32) or (q > 126) then 
				badchar := true;
			    write(errfile, xchr[q])
			end;
			write(errfile, '''');
			if badchar then 
			    writeln(errfile, 'non-ASCII character in xxx command!');
			goto 30
		    end; {:85}
		247:
		    begin
			writeln(errfile, 'preamble command within a page!');
			goto 9998
		    end;
		248, 249:
		    begin
			writeln(errfile, 'postamble command within a page!');
			goto 9998
		    end
	    end
	else
	    begin
		writeln(errfile, 'undefined command ', o: 1, '!');
		goto 30
	    end;
    44: {90:}
	if (v > 0) and (p > 0) then 
	    if v > (2147483647 - p) then begin
		writeln(errfile, 'arithmetic overflow! parameter changed from ', p: 1, ' to ', 2147483647 - v: 1);
		p := 2147483647 - v
	    end;
	if (v < 0) and (p < 0) then 
	    if (-v) > (p + 2147483647) then begin
		writeln(errfile, 'arithmetic overflow! parameter changed from ', p: 1, ' to ', (-v) - 2147483647: 1);
		p := (-v) - 2147483647
	    end;
	vvv := round(vertconv * (v + p));
	if abs(vvv - vv) > 2 then 
	    if vvv > vv then 
		vv := vvv - 2
	    else 
		vv := vvv + 2;
	v := v + p;
	if abs(v) > maxvsofar then begin
	    if abs(v) > (maxv + 99) then begin
		writeln(errfile, 'warning: |v|>', maxv: 1, '!');
		maxv := abs(v)
	    end;
	    maxvsofar := abs(v)
	end;
	goto 30 {:90};
    46: {91:}
	fontnum[nf] := p;
	curfont := 0;
	while fontnum[curfont] <> p do 
	    curfont := curfont + 1;
	goto 30 {:91};
    9998:
	pure := false;
    30:
	specialcases := pure
    end; {:80}

    function dopage: boolean;
    label
	41, 42, 43, 45, 30, 9998, 9999;
    var
	o: eightbits;
	p, q: integer;
	a: integer;
	i, j: integer;
	hhh: integer;
    begin
	emptypage;
	curfont := nf;
	s := 0;
	h := 0;
	v := 0;
	w := 0;
	x := 0;
	y := 0;
	z := 0;
	hh := 0;
	vv := 0;
	while true do begin {78:}
	    a := curloc;
	    o := getbyte;
	    p := firstpar(o);
	    if eofdvifile then begin
		message(' ', 'Bad DVI file: ', 'the file ended prematurely', '!');
		jumpout
	    end; {79:}
	    if o < 128 then begin {86:}
		outchar(p, hh, vv) {:86}
	    end else 
		if o in
		    [128, 129, 130, 131, 132, 137, 138, 139,
		     140, 141, 142, 143, 144, 145, 146, 147,
		     148, 149, 150, 151, 152, 153, 154, 155,
		     156] then
		    case o of
			128, 129, 130, 131:
			    begin
				outchar(p, hh, vv);
				goto 41
			    end;
			132:
			    begin
				goto 42
			    end;
			137:
			    begin
				goto 42
			    end; {81:}
			138:
			    begin
				goto 30
			    end;
			139:
			    begin
				writeln(errfile, 'bop occurred before eop!');
				goto 9998
			    end;
			140:
			    begin
				if s <> 0 then 
				    writeln(errfile, 'stack not empty at end of page (level ', s: 1, ')!');
				dopage := true;
				flushpage;
				goto 9999
			    end;
			141:
			    begin
				if s = maxssofar then begin
				    maxssofar := s + 1;
				    if s = maxs then 
					writeln(errfile, 'deeper than claimed in postamble!');
				    if s = stacksize then begin
					writeln(errfile, 'DVIDOC capacity exceeded (stack size=', stacksize: 1, ')');
					goto 9998
				    end
				end;
				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 45
			    end;
			142:
			    begin
				if s = 0 then 
				    writeln(errfile, 'Pop illegal at level zero!')
				else begin
				    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]
				end;
				ss := s;
				goto 45
			    end; {:81} {82:}
			143, 144, 145, 146:
			    begin
				if abs(p) >= fontspace[curfont] then begin
				    hh := round(horizconv * (h + p))
				end else 
				    hh := hh + round(horizconv * p);
				q := p;
				goto 43
			    end;
			147, 148, 149, 150, 151:
			    begin
				w := p;
				if abs(p) >= fontspace[curfont] then begin
				    hh := round(horizconv * (h + p))
				end else 
				    hh := hh + round(horizconv * p);
				q := p;
				goto 43
			    end;
			152, 153, 154, 155, 156:
			    begin
				x := p;
				if abs(p) >= fontspace[curfont] then begin
				    hh := round(horizconv * (h + p))
				end else 
				    hh := hh + round(horizconv * p);
				q := p;
				goto 43
			    end
		    end
		else {:82}
		    if specialcases(o, p, a) then 
			goto 30
		    else 
			goto 9998 {:79};
    41: {87:}
	    if p < 0 then 
		p := 255 - (((-1) - p) mod 256)
	    else if p >= 256 then 
		p := p mod 256;
	    if (p < fontbc[curfont]) or (p > fontec[curfont]) then 
		q := 2147483647
	    else 
		q := width[widthbase[curfont] + p];
	    if q = 2147483647 then begin
		writeln(errfile, 'character ', p: 1, ' invalid in font ');
		printfont(curfont);
		if curfont <> nf then 
		    write(errfile, '!')
	    end;
	    if o >= 133 then 
		goto 30;
	    if q = 2147483647 then 
		q := 0
	    else 
		hh := hh + pixelwidth[widthbase[curfont] + p];
	    goto 43 {:87};
    42: {88:}
	    q := signedquad;
	    if (p > 0) and (q > 0) then 
		for i := hh to (hh + horizrulepixels(q)) - 1 do 
		    for j := vv downto (vv - vertrulepixels(p)) + 1 do 
			outchar(xord['-'], i, j);
	    if o = 137 then 
		goto 30;
	    hh := hh + horizrulepixels(q);
	    goto 43 {:88};
    43: {89:}
	    if (h > 0) and (q > 0) then 
		if h > (2147483647 - q) then begin
		    writeln(errfile, 'arithmetic overflow! parameter changed from ', q: 1, ' to ', 2147483647 - h: 1);
		    q := 2147483647 - h
		end;
	    if (h < 0) and (q < 0) then 
		if (-h) > (q + 2147483647) then begin
		    writeln(errfile, 'arithmetic overflow! parameter changed from ', q: 1, ' to ', (-h) - 2147483647: 1);
		    q := (-h) - 2147483647
		end;
	    hhh := round(horizconv * (h + q));
	    if abs(hhh - hh) > 2 then 
		if hhh > hh then 
		    hh := hhh - 2
		else 
		    hh := hhh + 2;
	    h := h + q;
	    if abs(h) > maxhsofar then begin
		if abs(h) > (maxh + 99) then begin
		    writeln(errfile, 'warning: |h|>', maxh: 1, '!');
		    maxh := abs(h)
		end;
		maxhsofar := abs(h)
	    end;
	    goto 30 {:89};
    45:
	    null;
    30:
	    null
	end {:78};
    9998:
	writeln(errfile, '!');
	dopage := false;
    9999:
	null
    end; {:77} {99:}

    procedure readpostamble;
    var
	k: integer;
	p, q, m: integer;
    begin
	postloc := curloc - 5;
	if signedquad <> numerator then 
	    writeln(errfile, 'numerator doesn''t match the preamble!');
	if signedquad <> denominator then 
	    writeln(errfile, 'denominator doesn''t match the preamble!');
	if signedquad <> mag then 
	    if newmag = 0 then 
		writeln(errfile, 'magnification doesn''t match the preamble!');
	maxv := signedquad;
	maxh := signedquad;
	maxs := gettwobytes;
	totalpages := gettwobytes; {101:}
	repeat
	    k := getbyte;
	    if (k >= 243) and (k < 247) then begin
		p := firstpar(k);
		definefont(p);
		writeln(errfile, ' ');
		k := 138
	    end
	until k <> 138;
	{:
	101}
	if k <> 249 then 
	    writeln(errfile, 'byte ', curloc - 1: 1, ' is not postpost!');
	{100:}
	q := signedquad;
	if q <> postloc then 
	    writeln(errfile, 'bad postamble pointer in byte ', curloc - 4: 1, '!');
	m := getbyte;
	if m <> 2 then 
	    writeln(errfile, 'identification in byte ', curloc - 1: 1, ' should be ', 2: 1, '!');
	k := curloc;
	m := 223;
	while (m = 223) and (not eofdvifile) do 
	    m := getbyte;
	if not eofdvifile then begin
	    message(' ', 'Bad DVI file: ', 'signature in byte ', curloc - 1: 1, ' should be 223', '!');
	    jumpout
	end else if curloc < (k + 4) then 
	    writeln(errfile, 'not enough signature bytes at end of file (', curloc - k: 1, ')') {:100}
    end; {:99} {102:}

begin
    initialize;
    options; {25:}
    i := 1;
    while (i < namelength) and (basename[i] <> ' ') do 
	i := i + 1;
    if i < 5 then begin
	basename[i] := '.';
	basename[i + 1] := 'd';
	basename[i + 2] := 'v';
	basename[i + 3] := 'i';
	basename[i + 4] := ' '
    end;
    if ((i >= 5) and (i < (namelength - 4))) and ((((basename[i - 4] <> '.') or (basename[i - 3] <> 'd')) or (basename[i - 2] <> 'v')) or (basename[i - 1] <> 'i')) then begin
	basename[i] := '.';
	basename[i + 1] := 'd';
	basename[i + 2] := 'v';
	basename[i + 3] := 'i';
	basename[i + 4] := ' '
    end;
    curname := basename;
    if testaccess(4, 0) then begin
	opendvifile;
	if eofdvifile then begin
	    message('Input file not found');
	    goto 30
	end
    end else begin
	message('Cannot open input file');
	goto 30
    end; {:25} {65:}
    if logerrors then begin
	curname := basename;
	i := 1;
	while (i <= namelength) and (curname[i] <> ' ') do 
	    i := i + 1;
	curname[i - 3] := 'e';
	curname[i - 2] := 'r';
	curname[i - 1] := 'r';
	if testaccess(2, 0) then 
	    rewrite(errfile, curname)
	else begin
	    message('Cannot create error file');
	    goto 30
	end
    end else begin
	curname := '/dev/null';
	if testaccess(2, 0) then 
	    rewrite(errfile, curname)
	else begin
	    message('Somebody stole /dev/null!');
	    goto 30
	end
    end; {:65} {104:}
    p := getbyte;
    if p <> 247 then begin
	message(' ', 'Bad DVI file: ', 'First byte isn''t start of preamble!', '!');
	jumpout
    end;
    p := getbyte;
    if p <> 2 then 
	writeln(errfile, 'identification in byte 1 should be ', 2: 1, '!'); {105:}
    numerator := signedquad;
    denominator := signedquad;
    if numerator <= 0 then begin
	message(' ', 'Bad DVI file: ', 'numerator is ', numerator: 1, '!');
	jumpout
    end;
    if denominator <= 0 then begin
	message(' ', 'Bad DVI file: ', 'denominator is ', denominator: 1, '!');
	jumpout
    end;
    horizconv := (numerator / 254000.0) * (horizresolution / denominator);
    vertconv := (numerator / 254000.0) * (vertresolution / denominator);
    mag := signedquad;
    if newmag > 0 then 
	mag := newmag
    else if mag <= 0 then begin
	message(' ', 'Bad DVI file: ', 'magnification is ', mag: 1, '!');
	jumpout
    end;
    truehorizconv := horizconv;
    horizconv := truehorizconv * (mag / 1000.0);
    truevertconv := vertconv;
    vertconv := truevertconv * (mag / 1000.0); {:105}
    p := getbyte;
    write(errfile, '''');
    while p > 0 do begin
	p := p - 1;
	write(errfile, xchr[getbyte])
    end;
    writeln(errfile, '''') {:104}; {96:}
    n := dvilength;
    if n < 53 then begin
	message(' ', 'Bad DVI file: ', 'only ', n: 1, ' bytes long', '!');
	jumpout
    end;
    m := n - 4;
    repeat
	if m = 0 then begin
	    message(' ', 'Bad DVI file: ', 'all 223s', '!');
	    jumpout
	end;
	movetobyte(m);
	k := getbyte;
	m := m - 1
    until k <> 223;
    if k <> 2 then begin
	message(' ', 'Bad DVI file: ', 'ID byte is ', k: 1, '!');
	jumpout
    end;
    movetobyte(m - 3);
    q := signedquad;
    if (q < 0) or (q > (m - 33)) then begin
	message(' ', 'Bad DVI file: ', 'post pointer ', q: 1, ' at byte ', m - 3: 1, '!');
	jumpout
    end;
    movetobyte(q);
    k := getbyte;
    if k <> 248 then begin
	message(' ', 'Bad DVI file: ', 'byte ', q: 1, ' is not post', '!');
	jumpout
    end;
    postloc := q;
    firstbackpointer := signedquad {:96};
    inpostamble := true;
    readpostamble;
    inpostamble := false; {98:}
    q := postloc;
    p := firstbackpointer;
    startloc := -1;
    if p >= 0 then 
	repeat
	    if p > (q - 46) then begin
		message(' ', 'Bad DVI file: ', 'page link ', p: 1, ' after byte ', q: 1, '!');
		jumpout
	    end;
	    q := p;
	    movetobyte(q);
	    k := getbyte;
	    if k = 139 then 
		pagecount := pagecount + 1
	    else begin
		message(' ', 'Bad DVI file: ', 'byte ', q: 1, ' is not bop', '!');
		jumpout
	    end;
	    for k := 0 to 9 do 
		count[k] := signedquad;
	    if startmatch then 
		startloc := q;
	    p := signedquad
	until p < 0;
    if startloc < 0 then begin
	message(' ', 'starting page number could not be found!');
	jumpout
    end;
    movetobyte(startloc + 1);
    oldbackpointer := startloc;
    for k := 0 to 9 do 
	count[k] := signedquad;
    p := signedquad;
    started := true {:98};
    if not inpostamble then begin {106:}
	while maxpages > 0 do begin
	    maxpages := maxpages - 1;
	    write(errfile, 'Page ');
	    for k := 0 to startvals do begin
		write(errfile, count[k]: 1);
		if k < startvals then 
		    write(errfile, '.')
		else 
		    writeln(errfile, ' ')
	    end;
	    if not dopage then begin
		message(' ', 'Bad DVI file: ', 'page ended unexpectedly', '!');
		jumpout
	    end;
	    repeat
		k := getbyte;
		if (k >= 243) and (k < 247) then begin
		    p := firstpar(k);
		    definefont(p);
		    k := 138
		end
	    until k <> 138;
	    if k = 248 then begin
		inpostamble := true;
		goto 30
	    end;
	    if k <> 139 then begin
		message(' ', 'Bad DVI file: ', 'byte ', curloc - 1: 1, ' is not bop', '!');
		jumpout
	    end; {95:}
	    newbackpointer := curloc - 1;
	    pagecount := pagecount + 1;
	    for k := 0 to 9 do 
		count[k] := signedquad;
	    if signedquad <> oldbackpointer then 
		writeln(errfile, 'backpointer in byte ', curloc - 4: 1, ' should be ', oldbackpointer: 1, '!');
	    oldbackpointer := newbackpointer {:95}
	end;
30: {:106}
	null
    end;
9999:
    null
end. {:102}
