summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/dvitype.web
diff options
context:
space:
mode:
authorDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
committerDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
commitc6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch)
tree1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/texk/web2c/dvitype.web
parent07ee7222e389b0777456b427a55c22d0e6ffd267 (diff)
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/dvitype.web')
-rw-r--r--Build/source/texk/web2c/dvitype.web2506
1 files changed, 0 insertions, 2506 deletions
diff --git a/Build/source/texk/web2c/dvitype.web b/Build/source/texk/web2c/dvitype.web
deleted file mode 100644
index 687736dc87a..00000000000
--- a/Build/source/texk/web2c/dvitype.web
+++ /dev/null
@@ -1,2506 +0,0 @@
-% This program by D. E. Knuth is not copyrighted and can be used freely.
-% Version 1 was completed in September, 1982.
-% Slight changes were made in October, 1982, for version 0.7 of TeX.
-% Version 1.1 corrected minor bugs (May, 1983).
-% Version 2 was released with version 0.999 of TeX (July, 1983).
-% Version 2.1 corrected a bug when no fonts are present (September, 1983).
-% Version 2.2 corrected bugs in max_*_so_far and put1 (October, 1983).
-% Version 2.3 corrected spacing of accents (March, 1984).
-% Version 2.4 fixed rounding, changed oriental font conventions (April, 1984).
-% Version 2.5 improved the case of zero pages (May, 1984).
-% Version 2.6 introduced max_drift (June, 1984).
-% Version 2.7 had minor editorial changes (August, 1984).
-% Version 2.8 made default resolution 300/1 (April, 1985).
-% Version 2.9 changed negative scaling as in TeX version 2.7 (November, 1987).
-% Version 3 introduced an intermediate level of verbosity (October,1989).
-% Version 3.1 gave magnification info in final font list (November, 1989).
-% Version 3.2 doublechecked design size of each font (January, 1990).
-% Version 3.3 had more robust for loops in print_font, define_font (May, 1990).
-% Version 3.4 more robustness in presence of bad fonts (September, 1990).
-% Version 3.5 checked skipped material more strictly (March, 1995).
-% Version 3.6 gives a better help message (December, 1995).
-
-% Here is TeX material that gets inserted after \input webmac
-\def\hang{\hangindent 3em\indent\ignorespaces}
-\font\ninerm=cmr9
-\let\mc=\ninerm % medium caps for names like SAIL
-\def\PASCAL{Pascal}
-
-\def\(#1){} % this is used to make section names sort themselves better
-\def\9#1{} % this is used for sort keys in the index
-
-\def\title{DVI$\,$\lowercase{type}}
-\def\contentspagenumber{401}
-\def\topofcontents{\null
- \titlefalse % include headline on the contents page
- \def\rheader{\mainfont\hfil \contentspagenumber}
- \vfill
- \centerline{\titlefont The {\ttitlefont DVItype} processor}
- \vskip 15pt
- \centerline{(Version 3.6, December 1995)}
- \vfill}
-\def\botofcontents{\vfill
- \centerline{\hsize 5in\baselineskip9pt
- \vbox{\ninerm\noindent
- The preparation of this report
- was supported in part by the National Science
- Foundation under grants IST-8201926 and MCS-8300984,
- and by the System Development Foundation. `\TeX' is a
- trademark of the American Mathematical Society.}}}
-\pageno=\contentspagenumber \advance\pageno by 1
-
-@* Introduction.
-The \.{DVItype} utility program reads binary device-independent (``\.{DVI}'')
-files that are produced by document compilers such as \TeX, and converts them
-into symbolic form. This program has two chief purposes: (1)~It can be used to
-determine whether a \.{DVI} file is valid or invalid, when diagnosing
-compiler errors; and (2)~it serves as an example of a program that reads
-\.{DVI} files correctly, for system programmers who are developing
-\.{DVI}-related software.
-
-Goal number (2) needs perhaps a bit more explanation. Programs for
-typesetting need to be especially careful about how they do arithmetic; if
-rounding errors accumulate, margins won't be straight, vertical rules
-won't line up, and so on. But if rounding is done everywhere, even in the
-midst of words, there will be uneven spacing between the letters, and that
-looks bad. Human eyes notice differences of a thousandth of an inch in the
-positioning of lines that are close together; on low resolution devices,
-where rounding produces effects four times as great as this, the problem
-is especially critical. Experience has shown that unusual care is needed
-even on high-resolution equipment; for example, a mistake in the sixth
-significant hexadecimal place of a constant once led to a difficult-to-find
-bug in some software for the Alphatype CRS, which has a resolution of 5333
-pixels per inch (make that 5333.33333333 pixels per inch). The document
-compilers that generate \.{DVI} files make certain assumptions about the
-arithmetic that will be used by \.{DVI}-reading software, and if these
-assumptions are violated the results will be of inferior quality.
-Therefore the present program is intended as a guide to proper procedure
-in the critical places where a bit of subtlety is involved.
-
-The first \.{DVItype} program was designed by David Fuchs in 1979, and it
-@^Fuchs, David Raymond@>
-went through several versions on different computers as the format of
-\.{DVI} files was evolving to its present form. Peter Breitenlohner
-helped with the latest revisions.
-@^Breitenlohner, Peter@>
-
-The |banner| string defined here should be changed whenever \.{DVItype}
-gets modified.
-
-@d banner=='This is DVItype, Version 3.6' {printed when the program starts}
-
-@ This program is written in standard \PASCAL, except where it is necessary
-to use extensions; for example, \.{DVItype} must read files whose names
-are dynamically specified, and that would be impossible in pure \PASCAL.
-All places where nonstandard constructions are used have been listed in
-the index under ``system dependencies.''
-@!@^system dependencies@>
-
-One of the extensions to standard \PASCAL\ that we shall deal with is the
-ability to move to a random place in a binary file; another is to
-determine the length of a binary file. Such extensions are not necessary
-for reading \.{DVI} files, and they are not important for efficiency
-reasons either---an infrequently used program like \.{DVItype} does not
-have to be efficient. But they are included there because of \.{DVItype}'s
-r\^^Dole as a model of a \.{DVI} reading routine, since other \.{DVI}
-processors ought to be highly efficient. If \.{DVItype} is being used with
-\PASCAL s for which random file positioning is not efficiently available,
-the following definition should be changed from |true| to |false|; in such
-cases, \.{DVItype} will not include the optional feature that reads the
-postamble first.
-
-Another extension is to use a default |case| as in \.{TANGLE}, \.{WEAVE},
-etc.
-
-@d random_reading==true {should we skip around in the file?}
-@d othercases == others: {default for cases not listed explicitly}
-@d endcases == @+end {follows the default case in an extended |case| statement}
-@f othercases == else
-@f endcases == end
-
-@ The binary input comes from |dvi_file|, and the symbolic output is written
-on \PASCAL's standard |output| file. The term |print| is used instead of
-|write| when this program writes on |output|, so that all such output
-could easily be redirected if desired.
-
-@d print(#)==write(#)
-@d print_ln(#)==write_ln(#)
-
-@p program DVI_type(@!dvi_file,@!output);
-label @<Labels in the outer block@>@/
-const @<Constants in the outer block@>@/
-type @<Types in the outer block@>@/
-var @<Globals in the outer block@>@/
-procedure initialize; {this procedure gets things started properly}
- var i:integer; {loop index for initializations}
- begin print_ln(banner);@/
- @<Set initial values@>@/
- end;
-
-@ If the program has to stop prematurely, it goes to the
-`|final_end|'. Another label, |done|, is used when stopping normally.
-
-@d final_end=9999 {label for the end of it all}
-@d done=30 {go here when finished with a subtask}
-
-@<Labels...@>=final_end,done;
-
-@ The following parameters can be changed at compile time to extend or
-reduce \.{DVItype}'s capacity.
-
-@<Constants...@>=
-@!max_fonts=100; {maximum number of distinct fonts per \.{DVI} file}
-@!max_widths=10000; {maximum number of different characters among all fonts}
-@!line_length=79; {bracketed lines of output will be at most this long}
-@!terminal_line_length=150; {maximum number of characters input in a single
- line of input from the terminal}
-@!stack_size=100; {\.{DVI} files shouldn't |push| beyond this depth}
-@!name_size=1000; {total length of all font file names}
-@!name_length=50; {a file name shouldn't be longer than this}
-
-@ Here are some macros for common programming idioms.
-
-@d incr(#) == #:=#+1 {increase a variable by unity}
-@d decr(#) == #:=#-1 {decrease a variable by unity}
-@d do_nothing == {empty statement}
-
-@ If the \.{DVI} file is badly malformed, the whole process must be aborted;
-\.{DVItype} will give up, after issuing an error message about the symptoms
-that were noticed.
-
-Such errors might be discovered inside of subroutines inside of subroutines,
-so a procedure called |jump_out| has been introduced. This procedure, which
-simply transfers control to the label |final_end| at the end of the program,
-contains the only non-local |goto| statement in \.{DVItype}.
-@^system dependencies@>
-
-@d abort(#)==begin print(' ',#); jump_out;
- end
-@d bad_dvi(#)==abort('Bad DVI file: ',#,'!')
-@.Bad DVI file@>
-
-@p procedure jump_out;
-begin goto final_end;
-end;
-
-@* The character set.
-Like all programs written with the \.{WEB} system, \.{DVItype} can be
-used with any character set. But it uses ASCII code internally, because
-the programming for portable input-output is easier when a fixed internal
-code is used, and because \.{DVI} files use ASCII code for file names
-and certain other strings.
-
-The next few sections of \.{DVItype} have therefore been copied from the
-analogous ones in the \.{WEB} system routines. They have been considerably
-simplified, since \.{DVItype} need not deal with the controversial
-ASCII codes less than @'40 or greater than @'176.
-If such codes appear in the \.{DVI} file,
-they will be printed as question marks.
-
-@<Types...@>=
-@!ASCII_code=" ".."~"; {a subrange of the integers}
-
-@ The original \PASCAL\ compiler was designed in the late 60s, when six-bit
-character sets were common, so it did not make provision for lower case
-letters. Nowadays, of course, we need to deal with both upper and lower case
-alphabets in a convenient way, especially in a program like \.{DVItype}.
-So we shall assume that the \PASCAL\ system being used for \.{DVItype}
-has a character set containing at least the standard visible characters
-of ASCII code (|"!"| through |"~"|).
-
-Some \PASCAL\ compilers use the original name |char| for the data type
-associated with the characters in text files, while other \PASCAL s
-consider |char| to be a 64-element subrange of a larger data type that has
-some other name. In order to accommodate this difference, we shall use
-the name |text_char| to stand for the data type of the characters in the
-output file. We shall also assume that |text_char| consists of
-the elements |chr(first_text_char)| through |chr(last_text_char)|,
-inclusive. The following definitions should be adjusted if necessary.
-@^system dependencies@>
-
-@d text_char == char {the data type of characters in text files}
-@d first_text_char=0 {ordinal number of the smallest element of |text_char|}
-@d last_text_char=127 {ordinal number of the largest element of |text_char|}
-
-@<Types...@>=
-@!text_file=packed file of text_char;
-
-@ The \.{DVItype} processor converts between ASCII code and
-the user's external character set by means of arrays |xord| and |xchr|
-that are analogous to \PASCAL's |ord| and |chr| functions.
-
-@<Globals...@>=
-@!xord: array [text_char] of ASCII_code;
- {specifies conversion of input characters}
-@!xchr: array [0..255] of text_char;
- {specifies conversion of output characters}
-
-@ Under our assumption that the visible characters of standard ASCII are
-all present, the following assignment statements initialize the
-|xchr| array properly, without needing any system-dependent changes.
-
-@<Set init...@>=
-for i:=0 to @'37 do xchr[i]:='?';
-xchr[@'40]:=' ';
-xchr[@'41]:='!';
-xchr[@'42]:='"';
-xchr[@'43]:='#';
-xchr[@'44]:='$';
-xchr[@'45]:='%';
-xchr[@'46]:='&';
-xchr[@'47]:='''';@/
-xchr[@'50]:='(';
-xchr[@'51]:=')';
-xchr[@'52]:='*';
-xchr[@'53]:='+';
-xchr[@'54]:=',';
-xchr[@'55]:='-';
-xchr[@'56]:='.';
-xchr[@'57]:='/';@/
-xchr[@'60]:='0';
-xchr[@'61]:='1';
-xchr[@'62]:='2';
-xchr[@'63]:='3';
-xchr[@'64]:='4';
-xchr[@'65]:='5';
-xchr[@'66]:='6';
-xchr[@'67]:='7';@/
-xchr[@'70]:='8';
-xchr[@'71]:='9';
-xchr[@'72]:=':';
-xchr[@'73]:=';';
-xchr[@'74]:='<';
-xchr[@'75]:='=';
-xchr[@'76]:='>';
-xchr[@'77]:='?';@/
-xchr[@'100]:='@@';
-xchr[@'101]:='A';
-xchr[@'102]:='B';
-xchr[@'103]:='C';
-xchr[@'104]:='D';
-xchr[@'105]:='E';
-xchr[@'106]:='F';
-xchr[@'107]:='G';@/
-xchr[@'110]:='H';
-xchr[@'111]:='I';
-xchr[@'112]:='J';
-xchr[@'113]:='K';
-xchr[@'114]:='L';
-xchr[@'115]:='M';
-xchr[@'116]:='N';
-xchr[@'117]:='O';@/
-xchr[@'120]:='P';
-xchr[@'121]:='Q';
-xchr[@'122]:='R';
-xchr[@'123]:='S';
-xchr[@'124]:='T';
-xchr[@'125]:='U';
-xchr[@'126]:='V';
-xchr[@'127]:='W';@/
-xchr[@'130]:='X';
-xchr[@'131]:='Y';
-xchr[@'132]:='Z';
-xchr[@'133]:='[';
-xchr[@'134]:='\';
-xchr[@'135]:=']';
-xchr[@'136]:='^';
-xchr[@'137]:='_';@/
-xchr[@'140]:='`';
-xchr[@'141]:='a';
-xchr[@'142]:='b';
-xchr[@'143]:='c';
-xchr[@'144]:='d';
-xchr[@'145]:='e';
-xchr[@'146]:='f';
-xchr[@'147]:='g';@/
-xchr[@'150]:='h';
-xchr[@'151]:='i';
-xchr[@'152]:='j';
-xchr[@'153]:='k';
-xchr[@'154]:='l';
-xchr[@'155]:='m';
-xchr[@'156]:='n';
-xchr[@'157]:='o';@/
-xchr[@'160]:='p';
-xchr[@'161]:='q';
-xchr[@'162]:='r';
-xchr[@'163]:='s';
-xchr[@'164]:='t';
-xchr[@'165]:='u';
-xchr[@'166]:='v';
-xchr[@'167]:='w';@/
-xchr[@'170]:='x';
-xchr[@'171]:='y';
-xchr[@'172]:='z';
-xchr[@'173]:='{';
-xchr[@'174]:='|';
-xchr[@'175]:='}';
-xchr[@'176]:='~';
-for i:=@'177 to 255 do xchr[i]:='?';
-
-@ The following system-independent code makes the |xord| array contain a
-suitable inverse to the information in |xchr|.
-
-@<Set init...@>=
-for i:=first_text_char to last_text_char do xord[chr(i)]:=@'40;
-for i:=" " to "~" do xord[xchr[i]]:=i;
-
-@* Device-independent file format.
-Before we get into the details of \.{DVItype}, we need to know exactly
-what \.{DVI} files are. The form of such files was designed by David R.
-@^Fuchs, David Raymond@>
-Fuchs in 1979. Almost any reasonable typesetting device can be driven by
-a program that takes \.{DVI} files as input, and dozens of such
-\.{DVI}-to-whatever programs have been written. Thus, it is possible to
-print the output of document compilers like \TeX\ on many different kinds
-of equipment.
-
-A \.{DVI} file is a stream of 8-bit bytes, which may be regarded as a
-series of commands in a machine-like language. The first byte of each command
-is the operation code, and this code is followed by zero or more bytes
-that provide parameters to the command. The parameters themselves may consist
-of several consecutive bytes; for example, the `|set_rule|' command has two
-parameters, each of which is four bytes long. Parameters are usually
-regarded as nonnegative integers; but four-byte-long parameters,
-and shorter parameters that denote distances, can be
-either positive or negative. Such parameters are given in two's complement
-notation. For example, a two-byte-long distance parameter has a value between
-$-2^{15}$ and $2^{15}-1$.
-@.DVI {\rm files}@>
-
-A \.{DVI} file consists of a ``preamble,'' followed by a sequence of one
-or more ``pages,'' followed by a ``postamble.'' The preamble is simply a
-|pre| command, with its parameters that define the dimensions used in the
-file; this must come first. Each ``page'' consists of a |bop| command,
-followed by any number of other commands that tell where characters are to
-be placed on a physical page, followed by an |eop| command. The pages
-appear in the order that they were generated, not in any particular
-numerical order. If we ignore |nop| commands and \\{fnt\_def} commands
-(which are allowed between any two commands in the file), each |eop|
-command is immediately followed by a |bop| command, or by a |post|
-command; in the latter case, there are no more pages in the file, and the
-remaining bytes form the postamble. Further details about the postamble
-will be explained later.
-
-Some parameters in \.{DVI} commands are ``pointers.'' These are four-byte
-quantities that give the location number of some other byte in the file;
-the first byte is number~0, then comes number~1, and so on. For example,
-one of the parameters of a |bop| command points to the previous |bop|;
-this makes it feasible to read the pages in backwards order, in case the
-results are being directed to a device that stacks its output face up.
-Suppose the preamble of a \.{DVI} file occupies bytes 0 to 99. Now if the
-first page occupies bytes 100 to 999, say, and if the second
-page occupies bytes 1000 to 1999, then the |bop| that starts in byte 1000
-points to 100 and the |bop| that starts in byte 2000 points to 1000. (The
-very first |bop|, i.e., the one that starts in byte 100, has a pointer of $-1$.)
-
-@ The \.{DVI} format is intended to be both compact and easily interpreted
-by a machine. Compactness is achieved by making most of the information
-implicit instead of explicit. When a \.{DVI}-reading program reads the
-commands for a page, it keeps track of several quantities: (a)~The current
-font |f| is an integer; this value is changed only
-by \\{fnt} and \\{fnt\_num} commands. (b)~The current position on the page
-is given by two numbers called the horizontal and vertical coordinates,
-|h| and |v|. Both coordinates are zero at the upper left corner of the page;
-moving to the right corresponds to increasing the horizontal coordinate, and
-moving down corresponds to increasing the vertical coordinate. Thus, the
-coordinates are essentially Cartesian, except that vertical directions are
-flipped; the Cartesian version of |(h,v)| would be |(h,-v)|. (c)~The
-current spacing amounts are given by four numbers |w|, |x|, |y|, and |z|,
-where |w| and~|x| are used for horizontal spacing and where |y| and~|z|
-are used for vertical spacing. (d)~There is a stack containing
-|(h,v,w,x,y,z)| values; the \.{DVI} commands |push| and |pop| are used to
-change the current level of operation. Note that the current font~|f| is
-not pushed and popped; the stack contains only information about
-positioning.
-
-The values of |h|, |v|, |w|, |x|, |y|, and |z| are signed integers having up
-to 32 bits, including the sign. Since they represent physical distances,
-there is a small unit of measurement such that increasing |h| by~1 means
-moving a certain tiny distance to the right. The actual unit of
-measurement is variable, as explained below.
-
-@ Here is a list of all the commands that may appear in a \.{DVI} file. Each
-command is specified by its symbolic name (e.g., |bop|), its opcode byte
-(e.g., 139), and its parameters (if any). The parameters are followed
-by a bracketed number telling how many bytes they occupy; for example,
-`|p[4]|' means that parameter |p| is four bytes long.
-
-\yskip\hang|set_char_0| 0. Typeset character number~0 from font~|f|
-such that the reference point of the character is at |(h,v)|. Then
-increase |h| by the width of that character. Note that a character may
-have zero or negative width, so one cannot be sure that |h| will advance
-after this command; but |h| usually does increase.
-
-\yskip\hang|set_char_1| through |set_char_127| (opcodes 1 to 127).
-Do the operations of |set_char_0|; but use the character whose number
-matches the opcode, instead of character~0.
-
-\yskip\hang|set1| 128 |c[1]|. Same as |set_char_0|, except that character
-number~|c| is typeset. \TeX82 uses this command for characters in the
-range |128<=c<256|.
-
-\yskip\hang|set2| 129 |c[2]|. Same as |set1|, except that |c|~is two
-bytes long, so it is in the range |0<=c<65536|. \TeX82 never uses this
-command, which is intended for processors that deal with oriental languages;
-but \.{DVItype} will allow character codes greater than 255, assuming that
-they all have the same width as the character whose code is $c \bmod 256$.
-@^oriental characters@>@^Chinese characters@>@^Japanese characters@>
-
-\yskip\hang|set3| 130 |c[3]|. Same as |set1|, except that |c|~is three
-bytes long, so it can be as large as $2^{24}-1$.
-
-\yskip\hang|set4| 131 |c[4]|. Same as |set1|, except that |c|~is four
-bytes long, possibly even negative. Imagine that.
-
-\yskip\hang|set_rule| 132 |a[4]| |b[4]|. Typeset a solid black rectangle
-of height |a| and width |b|, with its bottom left corner at |(h,v)|. Then
-set |h:=h+b|. If either |a<=0| or |b<=0|, nothing should be typeset. Note
-that if |b<0|, the value of |h| will decrease even though nothing else happens.
-Programs that typeset from \.{DVI} files should be careful to make the rules
-line up carefully with digitized characters, as explained in connection with
-the |rule_pixels| subroutine below.
-
-\yskip\hang|put1| 133 |c[1]|. Typeset character number~|c| from font~|f|
-such that the reference point of the character is at |(h,v)|. (The `put'
-commands are exactly like the `set' commands, except that they simply put out a
-character or a rule without moving the reference point afterwards.)
-
-\yskip\hang|put2| 134 |c[2]|. Same as |set2|, except that |h| is not changed.
-
-\yskip\hang|put3| 135 |c[3]|. Same as |set3|, except that |h| is not changed.
-
-\yskip\hang|put4| 136 |c[4]|. Same as |set4|, except that |h| is not changed.
-
-\yskip\hang|put_rule| 137 |a[4]| |b[4]|. Same as |set_rule|, except that
-|h| is not changed.
-
-\yskip\hang|nop| 138. No operation, do nothing. Any number of |nop|'s
-may occur between \.{DVI} commands, but a |nop| cannot be inserted between
-a command and its parameters or between two parameters.
-
-\yskip\hang|bop| 139 $c_0[4]$ $c_1[4]$ $\ldots$ $c_9[4]$ $p[4]$. Beginning
-of a page: Set |(h,v,w,x,y,z):=(0,0,0,0,0,0)| and set the stack empty. Set
-the current font |f| to an undefined value. The ten $c_i$ parameters can
-be used to identify pages, if a user wants to print only part of a \.{DVI}
-file; \TeX82 gives them the values of \.{\\count0} $\ldots$ \.{\\count9}
-at the time \.{\\shipout} was invoked for this page. The parameter |p|
-points to the previous |bop| command in the file, where the first |bop|
-has $p=-1$.
-
-\yskip\hang|eop| 140. End of page: Print what you have read since the
-previous |bop|. At this point the stack should be empty. (The \.{DVI}-reading
-programs that drive most output devices will have kept a buffer of the
-material that appears on the page that has just ended. This material is
-largely, but not entirely, in order by |v| coordinate and (for fixed |v|) by
-|h|~coordinate; so it usually needs to be sorted into some order that is
-appropriate for the device in question. \.{DVItype} does not do such sorting.)
-
-\yskip\hang|push| 141. Push the current values of |(h,v,w,x,y,z)| onto the
-top of the stack; do not change any of these values. Note that |f| is
-not pushed.
-
-\yskip\hang|pop| 142. Pop the top six values off of the stack and assign
-them to |(h,v,w,x,y,z)|. The number of pops should never exceed the number
-of pushes, since it would be highly embarrassing if the stack were empty
-at the time of a |pop| command.
-
-\yskip\hang|right1| 143 |b[1]|. Set |h:=h+b|, i.e., move right |b| units.
-The parameter is a signed number in two's complement notation, |-128<=b<128|;
-if |b<0|, the reference point actually moves left.
-
-\yskip\hang|right2| 144 |b[2]|. Same as |right1|, except that |b| is a
-two-byte quantity in the range |-32768<=b<32768|.
-
-\yskip\hang|right3| 145 |b[3]|. Same as |right1|, except that |b| is a
-three-byte quantity in the range |@t$-2^{23}$@><=b<@t$2^{23}$@>|.
-
-\yskip\hang|right4| 146 |b[4]|. Same as |right1|, except that |b| is a
-four-byte quantity in the range |@t$-2^{31}$@><=b<@t$2^{31}$@>|.
-
-\yskip\hang|w0| 147. Set |h:=h+w|; i.e., move right |w| units. With luck,
-this parameterless command will usually suffice, because the same kind of motion
-will occur several times in succession; the following commands explain how
-|w| gets particular values.
-
-\yskip\hang|w1| 148 |b[1]|. Set |w:=b| and |h:=h+b|. The value of |b| is a
-signed quantity in two's complement notation, |-128<=b<128|. This command
-changes the current |w|~spacing and moves right by |b|.
-
-\yskip\hang|w2| 149 |b[2]|. Same as |w1|, but |b| is a two-byte-long
-parameter, |-32768<=b<32768|.
-
-\yskip\hang|w3| 150 |b[3]|. Same as |w1|, but |b| is a three-byte-long
-parameter, |@t$-2^{23}$@><=b<@t$2^{23}$@>|.
-
-\yskip\hang|w4| 151 |b[4]|. Same as |w1|, but |b| is a four-byte-long
-parameter, |@t$-2^{31}$@><=b<@t$2^{31}$@>|.
-
-\yskip\hang|x0| 152. Set |h:=h+x|; i.e., move right |x| units. The `|x|'
-commands are like the `|w|' commands except that they involve |x| instead
-of |w|.
-
-\yskip\hang|x1| 153 |b[1]|. Set |x:=b| and |h:=h+b|. The value of |b| is a
-signed quantity in two's complement notation, |-128<=b<128|. This command
-changes the current |x|~spacing and moves right by |b|.
-
-\yskip\hang|x2| 154 |b[2]|. Same as |x1|, but |b| is a two-byte-long
-parameter, |-32768<=b<32768|.
-
-\yskip\hang|x3| 155 |b[3]|. Same as |x1|, but |b| is a three-byte-long
-parameter, |@t$-2^{23}$@><=b<@t$2^{23}$@>|.
-
-\yskip\hang|x4| 156 |b[4]|. Same as |x1|, but |b| is a four-byte-long
-parameter, |@t$-2^{31}$@><=b<@t$2^{31}$@>|.
-
-\yskip\hang|down1| 157 |a[1]|. Set |v:=v+a|, i.e., move down |a| units.
-The parameter is a signed number in two's complement notation, |-128<=a<128|;
-if |a<0|, the reference point actually moves up.
-
-\yskip\hang|down2| 158 |a[2]|. Same as |down1|, except that |a| is a
-two-byte quantity in the range |-32768<=a<32768|.
-
-\yskip\hang|down3| 159 |a[3]|. Same as |down1|, except that |a| is a
-three-byte quantity in the range |@t$-2^{23}$@><=a<@t$2^{23}$@>|.
-
-\yskip\hang|down4| 160 |a[4]|. Same as |down1|, except that |a| is a
-four-byte quantity in the range |@t$-2^{31}$@><=a<@t$2^{31}$@>|.
-
-\yskip\hang|y0| 161. Set |v:=v+y|; i.e., move down |y| units. With luck,
-this parameterless command will usually suffice, because the same kind of motion
-will occur several times in succession; the following commands explain how
-|y| gets particular values.
-
-\yskip\hang|y1| 162 |a[1]|. Set |y:=a| and |v:=v+a|. The value of |a| is a
-signed quantity in two's complement notation, |-128<=a<128|. This command
-changes the current |y|~spacing and moves down by |a|.
-
-\yskip\hang|y2| 163 |a[2]|. Same as |y1|, but |a| is a two-byte-long
-parameter, |-32768<=a<32768|.
-
-\yskip\hang|y3| 164 |a[3]|. Same as |y1|, but |a| is a three-byte-long
-parameter, |@t$-2^{23}$@><=a<@t$2^{23}$@>|.
-
-\yskip\hang|y4| 165 |a[4]|. Same as |y1|, but |a| is a four-byte-long
-parameter, |@t$-2^{31}$@><=a<@t$2^{31}$@>|.
-
-\yskip\hang|z0| 166. Set |v:=v+z|; i.e., move down |z| units. The `|z|' commands
-are like the `|y|' commands except that they involve |z| instead of |y|.
-
-\yskip\hang|z1| 167 |a[1]|. Set |z:=a| and |v:=v+a|. The value of |a| is a
-signed quantity in two's complement notation, |-128<=a<128|. This command
-changes the current |z|~spacing and moves down by |a|.
-
-\yskip\hang|z2| 168 |a[2]|. Same as |z1|, but |a| is a two-byte-long
-parameter, |-32768<=a<32768|.
-
-\yskip\hang|z3| 169 |a[3]|. Same as |z1|, but |a| is a three-byte-long
-parameter, |@t$-2^{23}$@><=a<@t$2^{23}$@>|.
-
-\yskip\hang|z4| 170 |a[4]|. Same as |z1|, but |a| is a four-byte-long
-parameter, |@t$-2^{31}$@><=a<@t$2^{31}$@>|.
-
-\yskip\hang|fnt_num_0| 171. Set |f:=0|. Font 0 must previously have been
-defined by a \\{fnt\_def} instruction, as explained below.
-
-\yskip\hang|fnt_num_1| through |fnt_num_63| (opcodes 172 to 234). Set
-|f:=1|, \dots, |f:=63|, respectively.
-
-\yskip\hang|fnt1| 235 |k[1]|. Set |f:=k|. \TeX82 uses this command for font
-numbers in the range |64<=k<256|.
-
-\yskip\hang|fnt2| 236 |k[2]|. Same as |fnt1|, except that |k|~is two
-bytes long, so it is in the range |0<=k<65536|. \TeX82 never generates this
-command, but large font numbers may prove useful for specifications of
-color or texture, or they may be used for special fonts that have fixed
-numbers in some external coding scheme.
-
-\yskip\hang|fnt3| 237 |k[3]|. Same as |fnt1|, except that |k|~is three
-bytes long, so it can be as large as $2^{24}-1$.
-
-\yskip\hang|fnt4| 238 |k[4]|. Same as |fnt1|, except that |k|~is four
-bytes long; this is for the really big font numbers (and for the negative ones).
-
-\yskip\hang|xxx1| 239 |k[1]| |x[k]|. This command is undefined in
-general; it functions as a $(k+2)$-byte |nop| unless special \.{DVI}-reading
-programs are being used. \TeX82 generates |xxx1| when a short enough
-\.{\\special} appears, setting |k| to the number of bytes being sent. It
-is recommended that |x| be a string having the form of a keyword followed
-by possible parameters relevant to that keyword.
-
-\yskip\hang|xxx2| 240 |k[2]| |x[k]|. Like |xxx1|, but |0<=k<65536|.
-
-\yskip\hang|xxx3| 241 |k[3]| |x[k]|. Like |xxx1|, but |0<=k<@t$2^{24}$@>|.
-
-\yskip\hang|xxx4| 242 |k[4]| |x[k]|. Like |xxx1|, but |k| can be ridiculously
-large. \TeX82 uses |xxx4| when |xxx1| would be incorrect.
-
-\yskip\hang|fnt_def1| 243 |k[1]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
-Define font |k|, where |0<=k<256|; font definitions will be explained shortly.
-
-\yskip\hang|fnt_def2| 244 |k[2]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
-Define font |k|, where |0<=k<65536|.
-
-\yskip\hang|fnt_def3| 245 |k[3]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
-Define font |k|, where |0<=k<@t$2^{24}$@>|.
-
-\yskip\hang|fnt_def4| 246 |k[4]| |c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.
-Define font |k|, where |@t$-2^{31}$@><=k<@t$2^{31}$@>|.
-
-\yskip\hang|pre| 247 |i[1]| |num[4]| |den[4]| |mag[4]| |k[1]| |x[k]|.
-Beginning of the preamble; this must come at the very beginning of the
-file. Parameters |i|, |num|, |den|, |mag|, |k|, and |x| are explained below.
-
-\yskip\hang|post| 248. Beginning of the postamble, see below.
-
-\yskip\hang|post_post| 249. Ending of the postamble, see below.
-
-\yskip\noindent Commands 250--255 are undefined at the present time.
-
-@ @d set_char_0=0 {typeset character 0 and move right}
-@d set1=128 {typeset a character and move right}
-@d set_rule=132 {typeset a rule and move right}
-@d put1=133 {typeset a character}
-@d put_rule=137 {typeset a rule}
-@d nop=138 {no operation}
-@d bop=139 {beginning of page}
-@d eop=140 {ending of page}
-@d push=141 {save the current positions}
-@d pop=142 {restore previous positions}
-@d right1=143 {move right}
-@d w0=147 {move right by |w|}
-@d w1=148 {move right and set |w|}
-@d x0=152 {move right by |x|}
-@d x1=153 {move right and set |x|}
-@d down1=157 {move down}
-@d y0=161 {move down by |y|}
-@d y1=162 {move down and set |y|}
-@d z0=166 {move down by |z|}
-@d z1=167 {move down and set |z|}
-@d fnt_num_0=171 {set current font to 0}
-@d fnt1=235 {set current font}
-@d xxx1=239 {extension to \.{DVI} primitives}
-@d xxx4=242 {potentially long extension to \.{DVI} primitives}
-@d fnt_def1=243 {define the meaning of a font number}
-@d pre=247 {preamble}
-@d post=248 {postamble beginning}
-@d post_post=249 {postamble ending}
-@d undefined_commands==250,251,252,253,254,255
-
-@ The preamble contains basic information about the file as a whole. As
-stated above, there are six parameters:
-$$\hbox{|@!i[1]| |@!num[4]| |@!den[4]| |@!mag[4]| |@!k[1]| |@!x[k]|.}$$
-The |i| byte identifies \.{DVI} format; currently this byte is always set
-to~2. (The value |i=3| is currently used for an extended format that
-allows a mixture of right-to-left and left-to-right typesetting.
-Some day we will set |i=4|, when \.{DVI} format makes another
-incompatible change---perhaps in the year 2048.)
-
-The next two parameters, |num| and |den|, are positive integers that define
-the units of measurement; they are the numerator and denominator of a
-fraction by which all dimensions in the \.{DVI} file could be multiplied
-in order to get lengths in units of $10^{-7}$ meters. (For example, there are
-exactly 7227 \TeX\ points in 254 centimeters, and \TeX82 works with scaled
-points where there are $2^{16}$ sp in a point, so \TeX82 sets |num=25400000|
-and $|den|=7227\cdot2^{16}=473628672$.)
-@^sp@>
-
-The |mag| parameter is what \TeX82 calls \.{\\mag}, i.e., 1000 times the
-desired magnification. The actual fraction by which dimensions are
-multiplied is therefore $mn/1000d$. Note that if a \TeX\ source document
-does not call for any `\.{true}' dimensions, and if you change it only by
-specifying a different \.{\\mag} setting, the \.{DVI} file that \TeX\
-creates will be completely unchanged except for the value of |mag| in the
-preamble and postamble. (Fancy \.{DVI}-reading programs allow users to
-override the |mag|~setting when a \.{DVI} file is being printed.)
-
-Finally, |k| and |x| allow the \.{DVI} writer to include a comment, which is not
-interpreted further. The length of comment |x| is |k|, where |0<=k<256|.
-
-@d id_byte=2 {identifies the kind of \.{DVI} files described here}
-
-@ Font definitions for a given font number |k| contain further parameters
-$$\hbox{|c[4]| |s[4]| |d[4]| |a[1]| |l[1]| |n[a+l]|.}$$
-The four-byte value |c| is the check sum that \TeX\ (or whatever program
-generated the \.{DVI} file) found in the \.{TFM} file for this font;
-|c| should match the check sum of the font found by programs that read
-this \.{DVI} file.
-@^check sum@>
-
-Parameter |s| contains a fixed-point scale factor that is applied to the
-character widths in font |k|; font dimensions in \.{TFM} files and other
-font files are relative to this quantity, which is always positive and
-less than $2^{27}$. It is given in the same units as the other dimensions
-of the \.{DVI} file. Parameter |d| is similar to |s|; it is the ``design
-size,'' and (like~|s|) it is given in \.{DVI} units. Thus, font |k| is to be
-used at $|mag|\cdot s/1000d$ times its normal size.
-
-The remaining part of a font definition gives the external name of the font,
-which is an ASCII string of length |a+l|. The number |a| is the length
-of the ``area'' or directory, and |l| is the length of the font name itself;
-the standard local system font area is supposed to be used when |a=0|.
-The |n| field contains the area in its first |a| bytes.
-
-Font definitions must appear before the first use of a particular font number.
-Once font |k| is defined, it must not be defined again; however, we
-shall see below that font definitions appear in the postamble as well as
-in the pages, so in this sense each font number is defined exactly twice,
-if at all. Like |nop| commands, font definitions can
-appear before the first |bop|, or between an |eop| and a |bop|.
-
-@ The last page in a \.{DVI} file is followed by `|post|'; this command
-introduces the postamble, which summarizes important facts that \TeX\ has
-accumulated about the file, making it possible to print subsets of the data
-with reasonable efficiency. The postamble has the form
-$$\vbox{\halign{\hbox{#\hfil}\cr
- |post| |p[4]| |num[4]| |den[4]| |mag[4]| |l[4]| |u[4]| |s[2]| |t[2]|\cr
- $\langle\,$font definitions$\,\rangle$\cr
- |post_post| |q[4]| |i[1]| 223's$[{\G}4]$\cr}}$$
-Here |p| is a pointer to the final |bop| in the file. The next three
-parameters, |num|, |den|, and |mag|, are duplicates of the quantities that
-appeared in the preamble.
-
-Parameters |l| and |u| give respectively the height-plus-depth of the tallest
-page and the width of the widest page, in the same units as other dimensions
-of the file. These numbers might be used by a \.{DVI}-reading program to
-position individual ``pages'' on large sheets of film or paper; however,
-the standard convention for output on normal size paper is to position each
-page so that the upper left-hand corner is exactly one inch from the left
-and the top. Experience has shown that it is unwise to design \.{DVI}-to-printer
-software that attempts cleverly to center the output; a fixed position of
-the upper left corner is easiest for users to understand and to work with.
-Therefore |l| and~|u| are often ignored.
-
-Parameter |s| is the maximum stack depth (i.e., the largest excess of
-|push| commands over |pop| commands) needed to process this file. Then
-comes |t|, the total number of pages (|bop| commands) present.
-
-The postamble continues with font definitions, which are any number of
-\\{fnt\_def} commands as described above, possibly interspersed with |nop|
-commands. Each font number that is used in the \.{DVI} file must be defined
-exactly twice: Once before it is first selected by a \\{fnt} command, and once
-in the postamble.
-
-@ The last part of the postamble, following the |post_post| byte that
-signifies the end of the font definitions, contains |q|, a pointer to the
-|post| command that started the postamble. An identification byte, |i|,
-comes next; this currently equals~2, as in the preamble.
-
-The |i| byte is followed by four or more bytes that are all equal to
-the decimal number 223 (i.e., @'337 in octal). \TeX\ puts out four to seven of
-these trailing bytes, until the total length of the file is a multiple of
-four bytes, since this works out best on machines that pack four bytes per
-word; but any number of 223's is allowed, as long as there are at least four
-of them. In effect, 223 is a sort of signature that is added at the very end.
-@^Fuchs, David Raymond@>
-
-This curious way to finish off a \.{DVI} file makes it feasible for
-\.{DVI}-reading programs to find the postamble first, on most computers,
-even though \TeX\ wants to write the postamble last. Most operating
-systems permit random access to individual words or bytes of a file, so
-the \.{DVI} reader can start at the end and skip backwards over the 223's
-until finding the identification byte. Then it can back up four bytes, read
-|q|, and move to byte |q| of the file. This byte should, of course,
-contain the value 248 (|post|); now the postamble can be read, so the
-\.{DVI} reader discovers all the information needed for typesetting the
-pages. Note that it is also possible to skip through the \.{DVI} file at
-reasonably high speed to locate a particular page, if that proves
-desirable. This saves a lot of time, since \.{DVI} files used in production
-jobs tend to be large.
-
-Unfortunately, however, standard \PASCAL\ does not include the ability to
-@^system dependencies@>
-access a random position in a file, or even to determine the length of a file.
-Almost all systems nowadays provide the necessary capabilities, so \.{DVI}
-format has been designed to work most efficiently with modern operating systems.
-As noted above, \.{DVItype} will limit itself to the restrictions of standard
-\PASCAL\ if |random_reading| is defined to be |false|.
-
-@* Input from binary files.
-We have seen that a \.{DVI} file is a sequence of 8-bit bytes. The bytes
-appear physically in what is called a `|packed file of 0..255|'
-in \PASCAL\ lingo.
-
-Packing is system dependent, and many \PASCAL\ systems fail to implement
-such files in a sensible way (at least, from the viewpoint of producing
-good production software). For example, some systems treat all
-byte-oriented files as text, looking for end-of-line marks and such
-things. Therefore some system-dependent code is often needed to deal with
-binary files, even though most of the program in this section of
-\.{DVItype} is written in standard \PASCAL.
-@^system dependencies@>
-
-One common way to solve the problem is to consider files of |integer|
-numbers, and to convert an integer in the range $-2^{31}\L x<2^{31}$ to
-a sequence of four bytes $(a,b,c,d)$ using the following code, which
-avoids the controversial integer division of negative numbers:
-$$\vbox{\halign{#\hfil\cr
-|if x>=0 then a:=x div @'100000000|\cr
-|else begin x:=(x+@'10000000000)+@'10000000000; a:=x div @'100000000+128;|\cr
-\quad|end|\cr
-|x:=x mod @'100000000;|\cr
-|b:=x div @'200000; x:=x mod @'200000;|\cr
-|c:=x div @'400; d:=x mod @'400;|\cr}}$$
-The four bytes are then kept in a buffer and output one by one. (On 36-bit
-computers, an additional division by 16 is necessary at the beginning.
-Another way to separate an integer into four bytes is to use/abuse
-\PASCAL's variant records, storing an integer and retrieving bytes that are
-packed in the same place; {\sl caveat implementor!\/}) It is also desirable
-in some cases to read a hundred or so integers at a time, maintaining a
-larger buffer.
-
-We shall stick to simple \PASCAL\ in this program, for reasons of clarity,
-even if such simplicity is sometimes unrealistic.
-
-@<Types...@>=
-@!eight_bits=0..255; {unsigned one-byte quantity}
-@!byte_file=packed file of eight_bits; {files that contain binary data}
-
-@ The program deals with two binary file variables: |dvi_file| is the main
-input file that we are translating into symbolic form, and |tfm_file| is
-the current font metric file from which character-width information is
-being read.
-
-@<Glob...@>=
-@!dvi_file:byte_file; {the stuff we are \.{DVI}typing}
-@!tfm_file:byte_file; {a font metric file}
-
-@ To prepare these files for input, we |reset| them. An extension of
-\PASCAL\ is needed in the case of |tfm_file|, since we want to associate
-it with external files whose names are specified dynamically (i.e., not
-known at compile time). The following code assumes that `|reset(f,s)|'
-does this, when |f| is a file variable and |s| is a string variable that
-specifies the file name. If |eof(f)| is true immediately after
-|reset(f,s)| has acted, we assume that no file named |s| is accessible.
-@^system dependencies@>
-
-@p procedure open_dvi_file; {prepares to read packed bytes in |dvi_file|}
-begin reset(dvi_file);
-cur_loc:=0;
-end;
-@#
-procedure open_tfm_file; {prepares to read packed bytes in |tfm_file|}
-begin reset(tfm_file,cur_name);
-end;
-
-@ If you looked carefully at the preceding code, you probably asked,
-``What are |cur_loc| and |cur_name|?'' Good question. They're global
-variables: |cur_loc| is the number of the byte about to be read next from
-|dvi_file|, and |cur_name| is a string variable that will be set to the
-current font metric file name before |open_tfm_file| is called.
-
-@<Glob...@>=
-@!cur_loc:integer; {where we are about to look, in |dvi_file|}
-@!cur_name:packed array[1..name_length] of char; {external name,
- with no lower case letters}
-
-@ It turns out to be convenient to read four bytes at a time, when we are
-inputting from \.{TFM} files. The input goes into global variables
-|b0|, |b1|, |b2|, and |b3|, with |b0| getting the first byte and |b3|
-the fourth.
-
-@<Glob...@>=
-@!b0,@!b1,@!b2,@!b3: eight_bits; {four bytes input at once}
-
-@ The |read_tfm_word| procedure sets |b0| through |b3| to the next
-four bytes in the current \.{TFM} file.
-@^system dependencies@>
-
-@p procedure read_tfm_word;
-begin read(tfm_file,b0); read(tfm_file,b1);
-read(tfm_file,b2); read(tfm_file,b3);
-end;
-
-@ We shall use another set of simple functions to read the next byte or
-bytes from |dvi_file|. There are seven possibilities, each of which is
-treated as a separate function in order to minimize the overhead for
-subroutine calls.
-@^system dependencies@>
-
-@p function get_byte:integer; {returns the next byte, unsigned}
-var b:eight_bits;
-begin if eof(dvi_file) then get_byte:=0
-else begin read(dvi_file,b); incr(cur_loc); get_byte:=b;
- end;
-end;
-@#
-function signed_byte:integer; {returns the next byte, signed}
-var b:eight_bits;
-begin read(dvi_file,b); incr(cur_loc);
-if b<128 then signed_byte:=b @+ else signed_byte:=b-256;
-end;
-@#
-function get_two_bytes:integer; {returns the next two bytes, unsigned}
-var a,@!b:eight_bits;
-begin read(dvi_file,a); read(dvi_file,b);
-cur_loc:=cur_loc+2;
-get_two_bytes:=a*256+b;
-end;
-@#
-function signed_pair:integer; {returns the next two bytes, signed}
-var a,@!b:eight_bits;
-begin read(dvi_file,a); read(dvi_file,b);
-cur_loc:=cur_loc+2;
-if a<128 then signed_pair:=a*256+b
-else signed_pair:=(a-256)*256+b;
-end;
-@#
-function get_three_bytes:integer; {returns the next three bytes, unsigned}
-var a,@!b,@!c:eight_bits;
-begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c);
-cur_loc:=cur_loc+3;
-get_three_bytes:=(a*256+b)*256+c;
-end;
-@#
-function signed_trio:integer; {returns the next three bytes, signed}
-var a,@!b,@!c:eight_bits;
-begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c);
-cur_loc:=cur_loc+3;
-if a<128 then signed_trio:=(a*256+b)*256+c
-else signed_trio:=((a-256)*256+b)*256+c;
-end;
-@#
-function signed_quad:integer; {returns the next four bytes, signed}
-var a,@!b,@!c,@!d:eight_bits;
-begin read(dvi_file,a); read(dvi_file,b); read(dvi_file,c); read(dvi_file,d);
-cur_loc:=cur_loc+4;
-if a<128 then signed_quad:=((a*256+b)*256+c)*256+d
-else signed_quad:=(((a-256)*256+b)*256+c)*256+d;
-end;
-
-@ Finally we come to the routines that are used only if |random_reading| is
-|true|. The driver program below needs two such routines: |dvi_length| should
-compute the total number of bytes in |dvi_file|, possibly also
-causing |eof(dvi_file)| to be true; and |move_to_byte(n)|
-should position |dvi_file| so that the next |get_byte| will read byte |n|,
-starting with |n=0| for the first byte in the file.
-@^system dependencies@>
-
-Such routines are, of course, highly system dependent. They are implemented
-here in terms of two assumed system routines called |set_pos| and |cur_pos|.
-The call |set_pos(f,n)| moves to item |n| in file |f|, unless |n| is
-negative or larger than the total number of items in |f|; in the latter
-case, |set_pos(f,n)| moves to the end of file |f|.
-The call |cur_pos(f)| gives the total number of items in |f|, if
-|eof(f)| is true; we use |cur_pos| only in such a situation.
-
-@p function dvi_length:integer;
-begin set_pos(dvi_file,-1); dvi_length:=cur_pos(dvi_file);
-end;
-@#
-procedure move_to_byte(n:integer);
-begin set_pos(dvi_file,n); cur_loc:=n;
-end;
-
-@* Reading the font information.
-\.{DVI} file format does not include information about character widths, since
-that would tend to make the files a lot longer. But a program that reads
-a \.{DVI} file is supposed to know the widths of the characters that appear
-in \\{set\_char} commands. Therefore \.{DVItype} looks at the font metric
-(\.{TFM}) files for the fonts that are involved.
-@.TFM {\rm files}@>
-
-The character-width data appears also in other files (e.g., in \.{GF} files
-that specify bit patterns for digitized characters);
-thus, it is usually possible for \.{DVI} reading programs to get by with
-accessing only one file per font. \.{DVItype} has a comparatively easy
-task in this regard, since it needs only a few words of information from
-each font; other \.{DVI}-to-printer programs may have to go to some pains to
-deal with complications that arise when a large number of large font files
-all need to be accessed simultaneously.
-
-@ For purposes of this program, we need to know only two things about a
-given character |c| in a given font |f|: (1)~Is |c| a legal character
-in~|f|? (2)~If so, what is the width of |c|? We also need to know the
-symbolic name of each font, so it can be printed out, and we need to know
-the approximate size of inter-word spaces in each font.
-
-The answers to these questions appear implicitly in the following data
-structures. The current number of known fonts is |nf|. Each known font has
-an internal number |f|, where |0<=f<nf|; the external number of this font,
-i.e., its font identification number in the \.{DVI} file, is
-|font_num[f]|, and the external name of this font is the string that
-occupies positions |font_name[f]| through |font_name[f+1]-1| of the array
-|names|. The latter array consists of |ASCII_code| characters, and
-|font_name[nf]| is its first unoccupied position. A horizontal motion
-in the range |-4*font_space[f]<h<font_space[f]|
-will be treated as a `kern' that is not
-indicated in the printouts that \.{DVItype} produces between brackets. The
-legal characters run from |font_bc[f]| to |font_ec[f]|, inclusive; more
-precisely, a given character |c| is valid in font |f| if and only if
-|font_bc[f]<=c<=font_ec[f]| and |char_width(f)(c)<>invalid_width|.
-Finally, |char_width(f)(c)=width[width_base[f]+c]|, and |width_ptr| is the
-first unused position of the |width| array.
-
-@d char_width_end(#)==#]
-@d char_width(#)==width[width_base[#]+char_width_end
-@d invalid_width==@'17777777777
-@d invalid_font==max_fonts
-
-@<Glob...@>=
-@!font_num:array [0..max_fonts] of integer; {external font numbers}
-@!font_name:array [0..max_fonts] of 1..name_size; {starting positions
- of external font names}
-@!names:array [1..name_size] of ASCII_code; {characters of names}
-@!font_check_sum:array [0..max_fonts] of integer; {check sums}
-@!font_scaled_size:array [0..max_fonts] of integer; {scale factors}
-@!font_design_size:array [0..max_fonts] of integer; {design sizes}
-@!font_space:array [0..max_fonts] of integer; {boundary between ``small''
- and ``large'' spaces}
-@!font_bc:array [0..max_fonts] of integer; {beginning characters in fonts}
-@!font_ec:array [0..max_fonts] of integer; {ending characters in fonts}
-@!width_base:array [0..max_fonts] of integer; {index into |width| table}
-@!width:array [0..max_widths] of integer; {character widths, in \.{DVI} units}
-@!nf:0..max_fonts; {the number of known fonts}
-@!width_ptr:0..max_widths; {the number of known character widths}
-
-@ @<Set init...@>=
-nf:=0; width_ptr:=0; font_name[0]:=1;@/
-font_space[invalid_font]:=0; {for |out_space| and |out_vmove|}
-font_bc[invalid_font]:=1; font_ec[invalid_font]:=0;
-
-@ It is, of course, a simple matter to print the name of a given font.
-
-@p procedure print_font(@!f:integer); {|f| is an internal font number}
-var k:0..name_size; {index into |names|}
-begin if f=invalid_font then print('UNDEFINED!')
-@.UNDEFINED@>
-else begin for k:=font_name[f] to font_name[f+1]-1 do
- print(xchr[names[k]]);
- end;
-end;
-
-@ An auxiliary array |in_width| is used to hold the widths as they are
-input. The global variables |tfm_check_sum| and |tfm_design_size| are
-set to the check sum and design size that
-appear in the current \.{TFM} file.
-
-@<Glob...@>=
-@!in_width:array[0..255] of integer; {\.{TFM} width data in \.{DVI} units}
-@!tfm_check_sum:integer; {check sum found in |tfm_file|}
-@!tfm_design_size:integer; {design size found in |tfm_file|, in \.{DVI} units}
-@!tfm_conv:real; {\.{DVI} units per absolute \.{TFM} unit}
-
-@ Here is a procedure that absorbs the necessary information from a
-\.{TFM} file, assuming that the file has just been successfully reset
-so that we are ready to read its first byte. (A complete description of
-\.{TFM} file format appears in the documentation of \.{TFtoPL} and will
-not be repeated here.) The procedure does not check the \.{TFM} file
-for validity, nor does it give explicit information about what is
-wrong with a \.{TFM} file that proves to be invalid; \.{DVI}-reading
-programs need not do this, since \.{TFM} files are almost always valid,
-and since the \.{TFtoPL} utility program has been specifically designed
-to diagnose \.{TFM} errors. The procedure simply returns |false| if it
-detects anything amiss in the \.{TFM} data.
-
-There is a parameter, |z|, which represents the scaling factor being
-used to compute the font dimensions; it must be in the range $0<z<2^{27}$.
-
-@p function in_TFM(@!z:integer):boolean; {input \.{TFM} data or return |false|}
-label 9997, {go here when the format is bad}
- 9998, {go here when the information cannot be loaded}
- 9999; {go here to exit}
-var k:integer; {index for loops}
-@!lh:integer; {length of the header data, in four-byte words}
-@!nw:integer; {number of words in the width table}
-@!wp:0..max_widths; {new value of |width_ptr| after successful input}
-@!alpha,@!beta:integer; {quantities used in the scaling computation}
-begin @<Read past the header data; |goto 9997| if there is a problem@>;
-@<Store character-width indices at the end of the |width| table@>;
-@<Read and convert the width values, setting up the |in_width| table@>;
-@<Move the widths from |in_width| to |width|, and append |pixel_width| values@>;
-width_ptr:=wp; in_TFM:=true; goto 9999;
-9997: print_ln('---not loaded, TFM file is bad');
-@.TFM file is bad@>
-9998: in_TFM:=false;
-9999: end;
-
-@ @<Read past the header...@>=
-read_tfm_word; lh:=b2*256+b3;
-read_tfm_word; font_bc[nf]:=b0*256+b1; font_ec[nf]:=b2*256+b3;
-if font_ec[nf]<font_bc[nf] then font_bc[nf]:=font_ec[nf]+1;
-if width_ptr+font_ec[nf]-font_bc[nf]+1>max_widths then
- begin print_ln('---not loaded, DVItype needs larger width table');
-@.DVItype needs larger...@>
- goto 9998;
- end;
-wp:=width_ptr+font_ec[nf]-font_bc[nf]+1;
-read_tfm_word; nw:=b0*256+b1;
-if (nw=0)or(nw>256) then goto 9997;
-for k:=1 to 3+lh do
- begin if eof(tfm_file) then goto 9997;
- read_tfm_word;
- if k=4 then
- if b0<128 then tfm_check_sum:=((b0*256+b1)*256+b2)*256+b3
- else tfm_check_sum:=(((b0-256)*256+b1)*256+b2)*256+b3
- else if k=5 then
- if b0<128 then
- tfm_design_size:=round(tfm_conv*(((b0*256+b1)*256+b2)*256+b3))
- else goto 9997;
- end;
-
-@ @<Store character-width indices...@>=
-if wp>0 then for k:=width_ptr to wp-1 do
- begin read_tfm_word;
- if b0>nw then goto 9997;
- width[k]:=b0;
- end;
-
-@ The most important part of |in_TFM| is the width computation, which
-involves multiplying the relative widths in the \.{TFM} file by the
-scaling factor in the \.{DVI} file. This fixed-point multiplication
-must be done with precisely the same accuracy by all \.{DVI}-reading programs,
-in order to validate the assumptions made by \.{DVI}-writing programs
-like \TeX82.
-
-Let us therefore summarize what needs to be done. Each width in a \.{TFM}
-file appears as a four-byte quantity called a |fix_word|. A |fix_word|
-whose respective bytes are $(a,b,c,d)$ represents the number
-$$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
-b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr
--16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$
-(No other choices of $a$ are allowed, since the magnitude of a \.{TFM}
-dimension must be less than 16.) We want to multiply this quantity by the
-integer~|z|, which is known to be less than $2^{27}$.
-If $|z|<2^{23}$, the individual multiplications $b\cdot z$, $c\cdot z$,
-$d\cdot z$ cannot overflow; otherwise we will divide |z| by 2, 4, 8, or
-16, to obtain a multiplier less than $2^{23}$, and we can compensate for
-this later. If |z| has thereby been replaced by $|z|^\prime=|z|/2^e$, let
-$\beta=2^{4-e}$; we shall compute
-$$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$ if $a=0$,
-or the same quantity minus $\alpha=2^{4+e}z^\prime$ if $a=255$.
-This calculation must be
-done exactly, for the reasons stated above; the following program does the
-job in a system-independent way, assuming that arithmetic is exact on
-numbers less than $2^{31}$ in magnitude.
-
-@<Read and convert the width values...@>=
-@<Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$@>;
-for k:=0 to nw-1 do
- begin read_tfm_word;
- in_width[k]:=(((((b3*z)div@'400)+(b2*z))div@'400)+(b1*z))div beta;
- if b0>0 then if b0<255 then goto 9997
- else in_width[k]:=in_width[k]-alpha;
- end
-
-@ @<Replace |z|...@>=
-begin alpha:=16;
-while z>=@'40000000 do
- begin z:=z div 2; alpha:=alpha+alpha;
- end;
-beta:=256 div alpha; alpha:=alpha*z;
-end
-
-@ A \.{DVI}-reading program usually works with font files instead of
-\.{TFM} files, so \.{DVItype} is atypical in that respect. Font files
-should, however, contain exactly the same character width data that is
-found in the corresponding \.{TFM}s; check sums are used to help
-ensure this. In addition, font files usually also contain the widths of
-characters in pixels, since the device-independent character widths of
-\.{TFM} files are generally not perfect multiples of pixels.
-
-The |pixel_width| array contains this information; when |width[k]| is the
-device-independent width of some character in \.{DVI} units, |pixel_width[k]|
-is the corresponding width of that character in an actual font.
-The macro |char_pixel_width| is set up to be analogous to |char_width|.
-
-@d char_pixel_width(#)==pixel_width[width_base[#]+char_width_end
-
-@<Glob...@>=
-@!pixel_width:array[0..max_widths] of integer; {actual character widths,
- in pixels}
-@!conv:real; {converts \.{DVI} units to pixels}
-@!true_conv:real; {converts unmagnified \.{DVI} units to pixels}
-@!numerator,@!denominator:integer; {stated conversion ratio}
-@!mag:integer; {magnification factor times 1000}
-
-@ The following code computes pixel widths by simply rounding the \.{TFM}
-widths to the nearest integer number of pixels, based on the conversion factor
-|conv| that converts \.{DVI} units to pixels. However, such a simple
-formula will not be valid for all fonts, and it will often give results that
-are off by $\pm1$ when a low-resolution font has been carefully
-hand-fitted. For example, a font designer often wants to make the letter `m'
-a pixel wider or narrower in order to make the font appear more consistent.
-\.{DVI}-to-printer programs should therefore input the correct pixel width
-information from font files whenever there is a chance that it may differ.
-A warning message may also be desirable in the case that at least one character
-is found whose pixel width differs from |conv*width| by more than a full pixel.
-@^system dependencies@>
-
-@d pixel_round(#)==round(conv*(#))
-
-@<Move the widths from |in_width| to |width|, and append |pixel_width| values@>=
-if in_width[0]<>0 then goto 9997; {the first width should be zero}
-width_base[nf]:=width_ptr-font_bc[nf];
-if wp>0 then for k:=width_ptr to wp-1 do
- if width[k]=0 then
- begin width[k]:=invalid_width; pixel_width[k]:=0;
- end
- else begin width[k]:=in_width[width[k]];
- pixel_width[k]:=pixel_round(width[k]);
- end
-
-@* Optional modes of output.
-\.{DVItype} will print different quantities of information based on some
-options that the user must specify: The |out_mode| level is set to one of
-five values (|errors_only|, |terse|, |mnemonics_only|,
-|verbose|, |the_works|), giving
-different degrees of output; and the listing can be confined to a
-restricted subset of the pages by specifying the desired starting page and
-the maximum number of pages. Furthermore there is an option to specify the
-resolution of an assumed discrete output device, so that pixel-oriented
-calculations will be shown; and there is an option to override the
-magnification factor that is stated in the \.{DVI} file.
-
-The starting page is specified by giving a sequence of 1 to 10 numbers or
-asterisks separated by dots. For example, the specification `\.{1.*.-5}'
-can be used to refer to a page output by \TeX\ when $\.{\\count0}=1$
-and $\.{\\count2}=-5$. (Recall that |bop| commands in a \.{DVI} file
-are followed by ten `count' values.) An asterisk matches any number,
-so the `\.*' in `\.{1.*.-5}' means that \.{\\count1} is ignored when
-specifying the first page. If several pages match the given specification,
-\.{DVItype} will begin with the earliest such page in the file. The
-default specification `\.*' (which matches all pages) therefore denotes
-the page at the beginning of the file.
-
-When \.{DVItype} begins, it engages the user in a brief dialog so that the
-options will be specified. This part of \.{DVItype} requires nonstandard
-\PASCAL\ constructions to handle the online interaction; so it may be
-preferable in some cases to omit the dialog and simply to stick to the
-default options (|out_mode=the_works|, starting page `\.*',
-|max_pages=1000000|, |resolution=300.0|, |new_mag=0|). On other hand, the
-system-dependent routines that are needed are not complicated, so it will
-not be terribly difficult to introduce them.
-@^system dependencies@>
-
-@d errors_only=0 {value of |out_mode| when minimal printing occurs}
-@d terse=1 {value of |out_mode| for abbreviated output}
-@d mnemonics_only=2 {value of |out_mode| for medium-quantity output}
-@d verbose=3 {value of |out_mode| for detailed tracing}
-@d the_works=4 {|verbose|, plus check of postamble if |random_reading|}
-
-@<Glob...@>=
-@!out_mode:errors_only..the_works; {controls the amount of output}
-@!max_pages:integer; {at most this many |bop..eop| pages will be printed}
-@!resolution:real; {pixels per inch}
-@!new_mag:integer; {if positive, overrides the postamble's magnification}
-
-@ The starting page specification is recorded in two global arrays called
-|start_count| and |start_there|. For example, `\.{1.*.-5}' is represented
-by |start_there[0]=true|, |start_count[0]=1|, |start_there[1]=false|,
-|start_there[2]=true|, |start_count[2]=-5|.
-We also set |start_vals=2|, to indicate that count 2 was the last one
-mentioned. The other values of |start_count| and |start_there| are not
-important, in this example.
-
-@<Glob...@>=
-@!start_count:array[0..9] of integer; {count values to select starting page}
-@!start_there:array[0..9] of boolean; {is the |start_count| value relevant?}
-@!start_vals:0..9; {the last count considered significant}
-@!count:array[0..9] of integer; {the count values on the current page}
-
-@ @<Set init...@>=
-out_mode:=the_works; max_pages:=1000000; start_vals:=0; start_there[0]:=false;
-
-@ Here is a simple subroutine that tests if the current page might be the
-starting page.
-
-@p function start_match:boolean; {does |count| match the starting spec?}
-var k:0..9; {loop index}
-@!match:boolean; {does everything match so far?}
-begin match:=true;
-for k:=0 to start_vals do
- if start_there[k]and(start_count[k]<>count[k]) then match:=false;
-start_match:=match;
-end;
-
-@ The |input_ln| routine waits for the user to type a line at his or her
-terminal; then it puts ASCII-code equivalents for the characters on that line
-into the |buffer| array. The |term_in| file is used for terminal input,
-and |term_out| for terminal output.
-@^system dependencies@>
-
-@<Glob...@>=
-@!buffer:array[0..terminal_line_length] of ASCII_code;
-@!term_in:text_file; {the terminal, considered as an input file}
-@!term_out:text_file; {the terminal, considered as an output file}
-
-@ Since the terminal is being used for both input and output, some systems
-need a special routine to make sure that the user can see a prompt message
-before waiting for input based on that message. (Otherwise the message
-may just be sitting in a hidden buffer somewhere, and the user will have
-no idea what the program is waiting for.) We shall invoke a system-dependent
-subroutine |update_terminal| in order to avoid this problem.
-@^system dependencies@>
-
-@d update_terminal == break(term_out) {empty the terminal output buffer}
-
-@ During the dialog, \.{DVItype} will treat the first blank space in a
-line as the end of that line. Therefore |input_ln| makes sure that there
-is always at least one blank space in |buffer|.
-@^system dependencies@>
-
-@p procedure input_ln; {inputs a line from the terminal}
-var k:0..terminal_line_length;
-begin update_terminal; reset(term_in);
-if eoln(term_in) then read_ln(term_in);
-k:=0;
-while (k<terminal_line_length)and not eoln(term_in) do
- begin buffer[k]:=xord[term_in^]; incr(k); get(term_in);
- end;
-buffer[k]:=" ";
-end;
-
-@ The global variable |buf_ptr| is used while scanning each line of input;
-it points to the first unread character in |buffer|.
-
-@<Glob...@>=
-@!buf_ptr:0..terminal_line_length; {the number of characters read}
-
-@ Here is a routine that scans a (possibly signed) integer and computes
-the decimal value. If no decimal integer starts at |buf_ptr|, the
-value 0 is returned. The integer should be less than $2^{31}$ in
-absolute value.
-
-@p function get_integer:integer;
-var x:integer; {accumulates the value}
-@!negative:boolean; {should the value be negated?}
-begin if buffer[buf_ptr]="-" then
- begin negative:=true; incr(buf_ptr);
- end
-else negative:=false;
-x:=0;
-while (buffer[buf_ptr]>="0")and(buffer[buf_ptr]<="9") do
- begin x:=10*x+buffer[buf_ptr]-"0"; incr(buf_ptr);
- end;
-if negative then get_integer:=-x @+ else get_integer:=x;
-end;
-
-@ The selected options are put into global variables by the |dialog|
-procedure, which is called just as \.{DVItype} begins.
-@^system dependencies@>
-
-@p procedure dialog;
-label 1,2,3,4,5;
-var k:integer; {loop variable}
-begin rewrite(term_out); {prepare the terminal for output}
-write_ln(term_out,banner);
-@<Determine the desired |out_mode|@>;
-@<Determine the desired |start_count| values@>;
-@<Determine the desired |max_pages|@>;
-@<Determine the desired |resolution|@>;
-@<Determine the desired |new_mag|@>;
-@<Print all the selected options@>;
-end;
-
-@ @<Determine the desired |out_mode|@>=
-1: write(term_out,'Output level (default=4, ? for help): ');
-out_mode:=the_works; input_ln;
-if buffer[0]<>" " then
- if (buffer[0]>="0")and(buffer[0]<="4") then out_mode:=buffer[0]-"0"
- else begin write(term_out,'Type 4 for complete listing,');
- write(term_out,' 0 for errors and fonts only,');
- write_ln(term_out,' 1 or 2 or 3 for something in between.');
- goto 1;
- end
-
-@ @<Determine the desired |start...@>=
-2: write(term_out,'Starting page (default=*): ');
-start_vals:=0; start_there[0]:=false;
-input_ln; buf_ptr:=0; k:=0;
-if buffer[0]<>" " then
- repeat if buffer[buf_ptr]="*" then
- begin start_there[k]:=false; incr(buf_ptr);
- end
- else begin start_there[k]:=true; start_count[k]:=get_integer;
- end;
- if (k<9)and(buffer[buf_ptr]=".") then
- begin incr(k); incr(buf_ptr);
- end
- else if buffer[buf_ptr]=" " then start_vals:=k
- else begin write(term_out,'Type, e.g., 1.*.-5 to specify the ');
- write_ln(term_out,'first page with \count0=1, \count2=-5.');
- goto 2;
- end;
- until start_vals=k
-
-@ @<Determine the desired |max_pages|@>=
-3: write(term_out,'Maximum number of pages (default=1000000): ');
-max_pages:=1000000; input_ln; buf_ptr:=0;
-if buffer[0]<>" " then
- begin max_pages:=get_integer;
- if max_pages<=0 then
- begin write_ln(term_out,'Please type a positive number.');
- goto 3;
- end;
- end
-
-@ @<Determine the desired |resolution|@>=
-4: write(term_out,'Assumed device resolution');
-write(term_out,' in pixels per inch (default=300/1): ');
-resolution:=300.0; input_ln; buf_ptr:=0;
-if buffer[0]<>" " then
- begin k:=get_integer;
- if (k>0)and(buffer[buf_ptr]="/")and
- (buffer[buf_ptr+1]>"0")and(buffer[buf_ptr+1]<="9") then
- begin incr(buf_ptr); resolution:=k/get_integer;
- end
- else begin write(term_out,'Type a ratio of positive integers;');
- write_ln(term_out,' (1 pixel per mm would be 254/10).');
- goto 4;
- end;
- end
-
-@ @<Determine the desired |new_mag|@>=
-5: write(term_out,'New magnification (default=0 to keep the old one): ');
-new_mag:=0; input_ln; buf_ptr:=0;
-if buffer[0]<>" " then
- if (buffer[0]>="0")and(buffer[0]<="9") then new_mag:=get_integer
- else begin write(term_out,'Type a positive integer to override ');
- write_ln(term_out,'the magnification in the DVI file.');
- goto 5;
- end
-
-@ After the dialog is over, we print the options so that the user
-can see what \.{DVItype} thought was specified.
-
-@<Print all the selected options@>=
-print_ln('Options selected:');
-@.Options selected@>
-print(' Starting page = ');
-for k:=0 to start_vals do
- begin if start_there[k] then print(start_count[k]:1)
- else print('*');
- if k<start_vals then print('.')
- else print_ln(' ');
- end;
-print_ln(' Maximum number of pages = ',max_pages:1);
-print(' Output level = ',out_mode:1);
-case out_mode of
-errors_only: print_ln(' (showing bops, fonts, and error messages only)');
-terse: print_ln(' (terse)');
-mnemonics_only: print_ln(' (mnemonics)');
-verbose: print_ln(' (verbose)');
-the_works: if random_reading then print_ln(' (the works)')
- else begin out_mode:=verbose;
- print_ln(' (the works: same as level 3 in this DVItype)');
- end;
-end;@/
-print_ln(' Resolution = ',resolution:12:8,' pixels per inch');
-if new_mag>0 then print_ln(' New magnification factor = ',new_mag/1000:8:3)
-
-@* Defining fonts.
-When |out_mode=the_works|, \.{DVItype} reads the postamble first and loads
-all of the fonts defined there; then it processes the pages. In this
-case, a \\{fnt\_def} command should match a previous definition if and only
-if the \\{fnt\_def} being processed is not in the postamble. But if
-|out_mode<the_works|, \.{DVItype} reads the pages first and the postamble
-last, so the conventions are reversed: a \\{fnt\_def} should match a previous
-\\{fnt\_def} if and only if the current one is a part of the postamble.
-
-A global variable |in_postamble| is provided to tell whether we are
-processing the postamble or not.
-
-@<Glob...@>=
-@!in_postamble:boolean; {are we reading the postamble?}
-
-@ @<Set init...@>=
-in_postamble:=false;
-
-@ The following subroutine does the necessary things when a \\{fnt\_def}
-command is being processed.
-
-@p procedure define_font(@!e:integer); {|e| is an external font number}
-var f:0..max_fonts;
-@!p:integer; {length of the area/directory spec}
-@!n:integer; {length of the font name proper}
-@!c,@!q,@!d,@!m:integer; {check sum, scaled size, design size, magnification}
-@!r:0..name_length; {index into |cur_name|}
-@!j,@!k:0..name_size; {indices into |names|}
-@!mismatch:boolean; {do names disagree?}
-begin if nf=max_fonts then abort('DVItype capacity exceeded (max fonts=',
- max_fonts:1,')!');
-@.DVItype capacity exceeded...@>
-font_num[nf]:=e; f:=0;
-while font_num[f]<>e do incr(f);
-@<Read the font parameters into position for font |nf|, and
- print the font name@>;
-if ((out_mode=the_works)and in_postamble)or@|
- ((out_mode<the_works)and not in_postamble) then
- begin if f<nf then print_ln('---this font was already defined!');
-@.this font was already defined@>
- end
-else begin if f=nf then print_ln('---this font wasn''t loaded before!');
-@.this font wasn't loaded before@>
- end;
-if f=nf then @<Load the new font, unless there are problems@>
-else @<Check that the current font definition matches the old one@>;
-end;
-
-@ @<Check that the current...@>=
-begin if font_check_sum[f]<>c then
- print_ln('---check sum doesn''t match previous definition!');
-@.check sum doesn't match@>
-if font_scaled_size[f]<>q then
- print_ln('---scaled size doesn''t match previous definition!');
-@.scaled size doesn't match@>
-if font_design_size[f]<>d then
- print_ln('---design size doesn''t match previous definition!');
-@.design size doesn't match@>
-j:=font_name[f]; k:=font_name[nf];
-if font_name[f+1]-j<>font_name[nf+1]-k then mismatch:=true
-else begin mismatch:=false;
- while j<font_name[f+1] do
- begin if names[j]<>names[k] then mismatch:=true;
- incr(j); incr(k);
- end;
- end;
-if mismatch then print_ln('---font name doesn''t match previous definition!');
-@.font name doesn't match@>
-end
-
-@ @<Read the font parameters into position for font |nf|...@>=
-c:=signed_quad; font_check_sum[nf]:=c;@/
-q:=signed_quad; font_scaled_size[nf]:=q;@/
-d:=signed_quad; font_design_size[nf]:=d;@/
-if (q<=0) or (d<=0) then m:=1000
-else m:=round((1000.0*conv*q)/(true_conv*d));
-p:=get_byte; n:=get_byte;
-if font_name[nf]+n+p>name_size then
- abort('DVItype capacity exceeded (name size=',name_size:1,')!');
-@.DVItype capacity exceeded...@>
-font_name[nf+1]:=font_name[nf]+n+p;
-if showing then print(': ')
- {when |showing| is true, the font number has already been printed}
-else print('Font ',e:1,': ');
-if n+p=0 then print('null font name!')
-@.null font name@>
-else for k:=font_name[nf] to font_name[nf+1]-1 do names[k]:=get_byte;
-print_font(nf);
-if not showing then if m<>1000 then print(' scaled ',m:1)
-@.scaled@>
-
-@ @<Load the new font, unless there are problems@>=
-begin @<Move font name into the |cur_name| string@>;
-open_tfm_file;
-if eof(tfm_file) then
- print('---not loaded, TFM file can''t be opened!')
-@.TFM file can\'t be opened@>
-else begin if (q<=0)or(q>=@'1000000000) then
- print('---not loaded, bad scale (',q:1,')!')
-@.bad scale@>
- else if (d<=0)or(d>=@'1000000000) then
- print('---not loaded, bad design size (',d:1,')!')
-@.bad design size@>
- else if in_TFM(q) then @<Finish loading the new font info@>;
- end;
-if out_mode=errors_only then print_ln(' ');
-end
-
-@ @<Finish loading...@>=
-begin font_space[nf]:=q div 6; {this is a 3-unit ``thin space''}
-if (c<>0)and(tfm_check_sum<>0)and(c<>tfm_check_sum) then
- begin print_ln('---beware: check sums do not agree!');
-@.beware: check sums do not agree@>
-@.check sums do not agree@>
- print_ln(' (',c:1,' vs. ',tfm_check_sum:1,')');
- print(' ');
- end;
-if abs(tfm_design_size-d)>2 then
- begin print_ln('---beware: design sizes do not agree!');
-@.beware: design sizes do not agree@>
-@.design sizes do not agree@>
- print_ln(' (',d:1,' vs. ',tfm_design_size:1,')');
- print(' ');
- end;
-print('---loaded at size ',q:1,' DVI units');
-d:=round((100.0*conv*q)/(true_conv*d));
-if d<>100 then
- begin print_ln(' '); print(' (this font is magnified ',d:1,'%)');
- end;
-@.this font is magnified@>
-incr(nf); {now the new font is officially present}
-end
-
-@ If |p=0|, i.e., if no font directory has been specified, \.{DVItype}
-is supposed to use the default font directory, which is a
-system-dependent place where the standard fonts are kept.
-The string variable |default_directory| contains the name of this area.
-@^system dependencies@>
-
-@d default_directory_name=='TeXfonts:' {change this to the correct name}
-@d default_directory_name_length=9 {change this to the correct length}
-
-@<Glob...@>=
-@!default_directory:packed array[1..default_directory_name_length] of char;
-
-@ @<Set init...@>=
-default_directory:=default_directory_name;
-
-@ The string |cur_name| is supposed to be set to the external name of the
-\.{TFM} file for the current font. This usually means that we need to
-prepend the name of the default directory, and
-to append the suffix `\.{.TFM}'. Furthermore, we change lower case letters
-to upper case, since |cur_name| is a \PASCAL\ string.
-@^system dependencies@>
-
-@<Move font name into the |cur_name| string@>=
-for k:=1 to name_length do cur_name[k]:=' ';
-if p=0 then
- begin for k:=1 to default_directory_name_length do
- cur_name[k]:=default_directory[k];
- r:=default_directory_name_length;
- end
-else r:=0;
-for k:=font_name[nf] to font_name[nf+1]-1 do
- begin incr(r);
- if r+4>name_length then
- abort('DVItype capacity exceeded (max font name length=',
- name_length:1,')!');
-@.DVItype capacity exceeded...@>
- if (names[k]>="a")and(names[k]<="z") then
- cur_name[r]:=xchr[names[k]-@'40]
- else cur_name[r]:=xchr[names[k]];
- end;
-cur_name[r+1]:='.'; cur_name[r+2]:='T'; cur_name[r+3]:='F'; cur_name[r+4]:='M'
-
-@* Low level output routines.
-Simple text in the \.{DVI} file is saved in a buffer until |line_length-2|
-characters have accumulated, or until some non-simple \.{DVI} operation
-occurs. Then the accumulated text is printed on a line, surrounded by
-brackets. The global variable |text_ptr| keeps track of the number of
-characters currently in the buffer.
-
-@<Glob...@>=
-@!text_ptr:0..line_length; {the number of characters in |text_buf|}
-@!text_buf:array[1..line_length] of ASCII_code; {saved characters}
-
-@ @<Set init...@>=
-text_ptr:=0;
-
-@ The |flush_text| procedure will empty the buffer if there is something in it.
-
-@p procedure flush_text;
-var k:0..line_length; {index into |text_buf|}
-begin if text_ptr>0 then
- begin if out_mode>errors_only then
- begin print('[');
- for k:=1 to text_ptr do print(xchr[text_buf[k]]);
- print_ln(']');
- end;
- text_ptr:=0;
- end;
-end;
-
-@ And the |out_text| procedure puts something in it.
-
-@p procedure out_text(c:ASCII_code);
-begin if text_ptr=line_length-2 then flush_text;
-incr(text_ptr); text_buf[text_ptr]:=c;
-end;
-
-@* Translation to symbolic form.
-The main work of \.{DVItype} is accomplished by the |do_page| procedure,
-which produces the output for an entire page, assuming that the |bop|
-command for that page has already been processed. This procedure is
-essentially an interpretive routine that reads and acts on the \.{DVI}
-commands.
-
-@ The definition of \.{DVI} files refers to six registers,
-$(h,v,w,x,y,z)$, which hold integer values in \.{DVI} units. In practice,
-we also need registers |hh| and |vv|, the pixel analogs of $h$ and $v$,
-since it is not always true that |hh=pixel_round(h)| or
-|vv=pixel_round(v)|.
-
-The stack of $(h,v,w,x,y,z)$ values is represented by eight arrays
-called |hstack|, \dots, |zstack|, |hhstack|, and |vvstack|.
-
-@<Glob...@>=
-@!h,@!v,@!w,@!x,@!y,@!z,@!hh,@!vv:integer; {current state values}
-@!hstack,@!vstack,@!wstack,@!xstack,@!ystack,@!zstack:
- array [0..stack_size] of integer; {pushed down values in \.{DVI} units}
-@!hhstack,@!vvstack:
- array [0..stack_size] of integer; {pushed down values in pixels}
-
-@ Three characteristics of the pages (their |max_v|, |max_h|, and
-|max_s|) are specified in the postamble, and a warning message
-is printed if these limits are exceeded. Actually |max_v| is set to
-the maximum height plus depth of a page, and |max_h| to the maximum width,
-for purposes of page layout. Since characters can legally be set outside
-of the page boundaries, it is not an error when |max_v| or |max_h| is
-exceeded. But |max_s| should not be exceeded.
-
-The postamble also specifies the total number of pages; \.{DVItype}
-checks to see if this total is accurate.
-
-@<Glob...@>=
-@!max_v:integer; {the value of |abs(v)| should probably not exceed this}
-@!max_h:integer; {the value of |abs(h)| should probably not exceed this}
-@!max_s:integer; {the stack depth should not exceed this}
-@!max_v_so_far,@!max_h_so_far,@!max_s_so_far:integer; {the record high levels}
-@!total_pages:integer; {the stated total number of pages}
-@!page_count:integer; {the total number of pages seen so far}
-
-@ @<Set init...@>=
-max_v:=@'17777777777-99; max_h:=@'17777777777-99; max_s:=stack_size+1;@/
-max_v_so_far:=0; max_h_so_far:=0; max_s_so_far:=0; page_count:=0;
-
-@ Before we get into the details of |do_page|, it is convenient to
-consider a simpler routine that computes the first parameter of each
-opcode.
-
-@d four_cases(#)==#,#+1,#+2,#+3
-@d eight_cases(#)==four_cases(#),four_cases(#+4)
-@d sixteen_cases(#)==eight_cases(#),eight_cases(#+8)
-@d thirty_two_cases(#)==sixteen_cases(#),sixteen_cases(#+16)
-@d sixty_four_cases(#)==thirty_two_cases(#),thirty_two_cases(#+32)
-
-@p function first_par(o:eight_bits):integer;
-begin case o of
-sixty_four_cases(set_char_0),sixty_four_cases(set_char_0+64):
- first_par:=o-set_char_0;
-set1,put1,fnt1,xxx1,fnt_def1: first_par:=get_byte;
-set1+1,put1+1,fnt1+1,xxx1+1,fnt_def1+1: first_par:=get_two_bytes;
-set1+2,put1+2,fnt1+2,xxx1+2,fnt_def1+2: first_par:=get_three_bytes;
-right1,w1,x1,down1,y1,z1: first_par:=signed_byte;
-right1+1,w1+1,x1+1,down1+1,y1+1,z1+1: first_par:=signed_pair;
-right1+2,w1+2,x1+2,down1+2,y1+2,z1+2: first_par:=signed_trio;
-set1+3,set_rule,put1+3,put_rule,right1+3,w1+3,x1+3,down1+3,y1+3,z1+3,
- fnt1+3,xxx1+3,fnt_def1+3: first_par:=signed_quad;
-nop,bop,eop,push,pop,pre,post,post_post,undefined_commands: first_par:=0;
-w0: first_par:=w;
-x0: first_par:=x;
-y0: first_par:=y;
-z0: first_par:=z;
-sixty_four_cases(fnt_num_0): first_par:=o-fnt_num_0;
-end;
-end;
-
-@ Here is another subroutine that we need: It computes the number of
-pixels in the height or width of a rule. Characters and rules will line up
-properly if the sizes are computed precisely as specified here. (Since
-|conv| is computed with some floating-point roundoff error, in a
-machine-dependent way, format designers who are tailoring something for a
-particular resolution should not plan their measurements to come out to an
-exact integer number of pixels; they should compute things so that the
-rule dimensions are a little less than an integer number of pixels, e.g.,
-4.99 instead of 5.00.)
-
-@p function rule_pixels(x:integer):integer;
- {computes $\lceil|conv|\cdot x\rceil$}
-var n:integer;
-begin n:=trunc(conv*x);
-if n<conv*x then rule_pixels:=n+1 @+ else rule_pixels:=n;
-end;
-
-@ Strictly speaking, the |do_page| procedure is really a function with
-side effects, not a `\&{procedure}'\thinspace; it returns the value |false|
-if \.{DVItype} should be aborted because of some unusual happening. The
-subroutine is organized as a typical interpreter, with a multiway branch
-on the command code followed by |goto| statements leading to routines that
-finish up the activities common to different commands. We will use the
-following labels:
-
-@d fin_set=41 {label for commands that set or put a character}
-@d fin_rule=42 {label for commands that set or put a rule}
-@d move_right=43 {label for commands that change |h|}
-@d move_down=44 {label for commands that change |v|}
-@d show_state=45 {label for commands that change |s|}
-@d change_font=46 {label for commands that change |cur_font|}
-
-@ Some \PASCAL\ compilers severely restrict the length of procedure bodies,
-so we shall split |do_page| into two parts, one of which is
-called |special_cases|. The different parts communicate with each other
-via the global variables mentioned above, together with the following ones:
-
-@<Glob...@>=
-@!s:integer; {current stack size}
-@!ss:integer; {stack size to print}
-@!cur_font:integer; {current internal font number}
-@!showing:boolean; {is the current command being translated in full?}
-
-@ Here is the overall setup.
-
-@p @t\4@>@<Declare the function called |special_cases|@>@;
-function do_page:boolean;
-label fin_set,fin_rule,move_right,show_state,done,9998,9999;
-var o:eight_bits; {operation code of the current command}
-@!p,@!q:integer; {parameters of the current command}
-@!a:integer; {byte number of the current command}
-@!hhh:integer; {|h|, rounded to the nearest pixel}
-begin cur_font:=invalid_font; {set current font undefined}
-s:=0; h:=0; v:=0; w:=0; x:=0; y:=0; z:=0; hh:=0; vv:=0;
- {initialize the state variables}
-while true do @<Translate the next command in the \.{DVI} file;
- |goto 9999| with |do_page=true| if it was |eop|;
- |goto 9998| if premature termination is needed@>;
-9998: print_ln('!'); do_page:=false;
-9999: end;
-
-@ Commands are broken down into ``major'' and ``minor'' categories:
-A major command is always shown in full, while a minor one is
-put into the buffer in abbreviated form. Minor commands, which
-account for the bulk of most \.{DVI} files, involve horizontal spacing
-and the typesetting of characters in a line; these are shown in full
-only if |out_mode>=verbose|.
-
-@d show(#)==begin flush_text; showing:=true; print(a:1,': ',#);
- end
-@d major(#)==if out_mode>errors_only then show(#)
-@d minor(#)==if out_mode>terse then
- begin showing:=true; print(a:1,': ',#);
- end
-@d error(#)==if not showing then show(#) else print(' ',#)
-
-@<Translate the next command...@>=
-begin a:=cur_loc; showing:=false;
-o:=get_byte; p:=first_par(o);
-if eof(dvi_file) then bad_dvi('the file ended prematurely');
-@.the file ended prematurely@>
-@<Start translation of command |o| and |goto| the appropriate label to
- finish the job@>;
-fin_set: @<Finish a command that either sets or puts a character, then
- |goto move_right| or |done|@>;
-fin_rule: @<Finish a command that either sets or puts a rule, then
- |goto move_right| or |done|@>;
-move_right: @<Finish a command that sets |h:=h+q|, then |goto done|@>;
-show_state: @<Show the values of |ss|, |h|, |v|, |w|, |x|, |y|, |z|,
- |hh|, and |vv|; then |goto done|@>;
-done: if showing then print_ln(' ');
-end
-
-@ The multiway switch in |first_par|, above, was organized by the length
-of each command; the one in |do_page| is organized by the semantics.
-
-@<Start translation...@>=
-if o<set_char_0+128 then @<Translate a |set_char| command@>
-else case o of
- four_cases(set1): begin major('set',o-set1+1:1,' ',p:1); goto fin_set;
- end;
- four_cases(put1): begin major('put',o-put1+1:1,' ',p:1); goto fin_set;
- end;
- set_rule: begin major('setrule'); goto fin_rule;
- end;
- put_rule: begin major('putrule'); goto fin_rule;
- end;
- @t\4@>@<Cases for commands |nop|, |bop|, \dots, |pop|@>@;
- @t\4@>@<Cases for horizontal motion@>@;
- othercases if special_cases(o,p,a) then goto done@+else goto 9998
- endcases
-
-@ @<Declare the function called |special_cases|@>=
-function special_cases(@!o:eight_bits;@!p,@!a:integer):boolean;
-label change_font,move_down,done,9998;
-var q:integer; {parameter of the current command}
-@!k:integer; {loop index}
-@!bad_char:boolean; {has a non-ASCII character code appeared in this \\{xxx}?}
-@!pure:boolean; {is the command error-free?}
-@!vvv:integer; {|v|, rounded to the nearest pixel}
-begin pure:=true;
-case o of
-@t\4@>@<Cases for vertical motion@>@;
-@t\4@>@<Cases for fonts@>@;
-four_cases(xxx1): @<Translate an |xxx| command and |goto done|@>;
-pre: begin error('preamble command within a page!'); goto 9998;
- end;
-@.preamble command within a page@>
-post,post_post: begin error('postamble command within a page!'); goto 9998;
-@.postamble command within a page@>
- end;
-othercases begin error('undefined command ',o:1,'!');
- goto done;
-@.undefined command@>
- end
-endcases;
-move_down: @<Finish a command that sets |v:=v+p|, then |goto done|@>;
-change_font: @<Finish a command that changes the current font,
- then |goto done|@>;
-9998: pure:=false;
-done: special_cases:=pure;
-end;
-
-@ @<Cases for commands |nop|, |bop|, \dots, |pop|@>=
-nop: begin minor('nop'); goto done;
- end;
-bop: begin error('bop occurred before eop!'); goto 9998;
-@.bop occurred before eop@>
- end;
-eop: begin major('eop');
- if s<>0 then error('stack not empty at end of page (level ',
- s:1,')!');
-@.stack not empty...@>
- do_page:=true; print_ln(' '); goto 9999;
- end;
-push: begin major('push');
- if s=max_s_so_far then
- begin max_s_so_far:=s+1;
- if s=max_s then error('deeper than claimed in postamble!');
-@.deeper than claimed...@>
-@.push deeper than claimed...@>
- if s=stack_size then
- begin error('DVItype capacity exceeded (stack size=',
- stack_size: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; incr(s); ss:=s-1; goto show_state;
- end;
-pop: begin major('pop');
- if s=0 then error('(illegal at level zero)!')
- else begin decr(s); 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 show_state;
- end;
-
-@ Rounding to the nearest pixel is best done in the manner shown here, so as
-to be inoffensive to the eye: When the horizontal motion is small, like a
-kern, |hh| changes by rounding the kern; but when the motion is large, |hh|
-changes by rounding the true position |h| so that accumulated rounding errors
-disappear. We allow a larger space in the negative direction than in
-the positive one, because \TeX\ makes comparatively
-large backspaces when it positions accents.
-
-@d out_space(#)==if (p>=font_space[cur_font])or(p<=-4*font_space[cur_font]) then
- begin out_text(" "); hh:=pixel_round(h+p);
- end
- else hh:=hh+pixel_round(p);
- minor(#,' ',p:1); q:=p; goto move_right
-
-@<Cases for horizontal motion@>=
-four_cases(right1):begin out_space('right',o-right1+1:1);
- end;
-w0,four_cases(w1):begin w:=p; out_space('w',o-w0:1);
- end;
-x0,four_cases(x1):begin x:=p; out_space('x',o-x0:1);
- end;
-
-@ Vertical motion is done similarly, but with the threshold between
-``small'' and ``large'' increased by a factor of five. The idea is to make
-fractions like ``$1\over2$'' round consistently, but to absorb accumulated
-rounding errors in the baseline-skip moves.
-
-@d out_vmove(#)==if abs(p)>=5*font_space[cur_font] then vv:=pixel_round(v+p)
- else vv:=vv+pixel_round(p);
- major(#,' ',p:1); goto move_down
-
-@<Cases for vertical motion@>=
-four_cases(down1):begin out_vmove('down',o-down1+1:1);
- end;
-y0,four_cases(y1):begin y:=p; out_vmove('y',o-y0:1);
- end;
-z0,four_cases(z1):begin z:=p; out_vmove('z',o-z0:1);
- end;
-
-@ @<Cases for fonts@>=
-sixty_four_cases(fnt_num_0): begin major('fntnum',p:1);
- goto change_font;
- end;
-four_cases(fnt1): begin major('fnt',o-fnt1+1:1,' ',p:1);
- goto change_font;
- end;
-four_cases(fnt_def1): begin major('fntdef',o-fnt_def1+1:1,' ',p:1);
- define_font(p); goto done;
- end;
-
-@ @<Translate an |xxx| command and |goto done|@>=
-begin major('xxx '''); bad_char:=false;
-if p<0 then error('string of negative length!');
-@.string of negative length@>
-for k:=1 to p do
- begin q:=get_byte;
- if (q<" ")or(q>"~") then bad_char:=true;
- if showing then print(xchr[q]);
- end;
-if showing then print('''');
-if bad_char then error('non-ASCII character in xxx command!');
-@.non-ASCII character...@>
-goto done;
-end
-
-@ @<Translate a |set_char|...@>=
-begin if (o>" ")and(o<="~") then
- begin out_text(p); minor('setchar',p:1);
- end
-else major('setchar',p:1);
-goto fin_set;
-end
-
-@ @<Finish a command that either sets or puts a character...@>=
-if p<0 then p:=255-((-1-p) mod 256)
-else if p>=256 then p:=p mod 256; {width computation for oriental fonts}
-@^oriental characters@>@^Chinese characters@>@^Japanese characters@>
-if (p<font_bc[cur_font])or(p>font_ec[cur_font]) then q:=invalid_width
-else q:=char_width(cur_font)(p);
-if q=invalid_width then
- begin error('character ',p:1,' invalid in font ');
-@.character $c$ invalid...@>
- print_font(cur_font);
- if cur_font<>invalid_font then
- print('!'); {the invalid font has `\.!' in its name}
- end;
-if o>=put1 then goto done;
-if q=invalid_width then q:=0
-else hh:=hh+char_pixel_width(cur_font)(p);
-goto move_right
-
-@ @<Finish a command that either sets or puts a rule...@>=
-q:=signed_quad;
-if showing then
- begin print(' height ',p:1,', width ',q:1);
- if out_mode>mnemonics_only then
- if (p<=0)or(q<=0) then print(' (invisible)')
- else print(' (',rule_pixels(p):1,'x',rule_pixels(q):1,' pixels)');
- end;
-if o=put_rule then goto done;
-if showing then if out_mode>mnemonics_only then print_ln(' ');
-hh:=hh+rule_pixels(q); goto move_right
-
-@ A sequence of consecutive rules, or consecutive characters in a fixed-width
-font whose width is not an integer number of pixels, can cause |hh| to drift
-far away from a correctly rounded value. \.{DVItype} ensures that the
-amount of drift will never exceed |max_drift| pixels.
-
-Since \.{DVItype} is intended to diagnose strange errors, it checks
-carefully to make sure that |h| and |v| do not get out of range.
-Normal \.{DVI}-reading programs need not do this.
-
-@d infinity==@'17777777777 {$\infty$ (approximately)}
-@d max_drift=2 {we insist that abs|(hh-pixel_round(h))<=max_drift|}
-
-@<Finish a command that sets |h:=h+q|, then |goto done|@>=
-if (h>0)and(q>0) then if h>infinity-q then
- begin error('arithmetic overflow! parameter changed from ',
-@.arithmetic overflow...@>
- q:1,' to ',infinity-h:1);
- q:=infinity-h;
- end;
-if (h<0)and(q<0) then if -h>q+infinity then
- begin error('arithmetic overflow! parameter changed from ',
- q:1, ' to ',(-h)-infinity:1);
- q:=(-h)-infinity;
- end;
-hhh:=pixel_round(h+q);
-if abs(hhh-hh)>max_drift then
- if hhh>hh then hh:=hhh-max_drift
- else hh:=hhh+max_drift;
-if showing then if out_mode>mnemonics_only then
- begin print(' h:=',h:1);
- if q>=0 then print('+');
- print(q:1,'=',h+q:1,', hh:=',hh:1);
- end;
-h:=h+q;
-if abs(h)>max_h_so_far then
- begin if abs(h)>max_h+99 then
- begin error('warning: |h|>',max_h:1,'!');
-@.warning: |h|...@>
- max_h:=abs(h);
- end;
- max_h_so_far:=abs(h);
- end;
-goto done
-
-@ @<Finish a command that sets |v:=v+p|, then |goto done|@>=
-if (v>0)and(p>0) then if v>infinity-p then
- begin error('arithmetic overflow! parameter changed from ',
-@.arithmetic overflow...@>
- p:1,' to ',infinity-v:1);
- p:=infinity-v;
- end;
-if (v<0)and(p<0) then if -v>p+infinity then
- begin error('arithmetic overflow! parameter changed from ',
- p:1, ' to ',(-v)-infinity:1);
- p:=(-v)-infinity;
- end;
-vvv:=pixel_round(v+p);
-if abs(vvv-vv)>max_drift then
- if vvv>vv then vv:=vvv-max_drift
- else vv:=vvv+max_drift;
-if showing then if out_mode>mnemonics_only then
- begin print(' v:=',v:1);
- if p>=0 then print('+');
- print(p:1,'=',v+p:1,', vv:=',vv:1);
- end;
-v:=v+p;
-if abs(v)>max_v_so_far then
- begin if abs(v)>max_v+99 then
- begin error('warning: |v|>',max_v:1,'!');
-@.warning: |v|...@>
- max_v:=abs(v);
- end;
- max_v_so_far:=abs(v);
- end;
-goto done
-
-@ @<Show the values of |ss|, |h|, |v|, |w|, |x|, |y|, |z|...@>=
-if showing then if out_mode>mnemonics_only then
- begin print_ln(' ');
- print('level ',ss:1,':(h=',h:1,',v=',v:1,
- ',w=',w:1,',x=',x:1,',y=',y:1,',z=',z:1,
- ',hh=',hh:1,',vv=',vv:1,')');
- end;
-goto done
-
-@ @<Finish a command that changes the current font...@>=
-font_num[nf]:=p; cur_font:=0;
-while font_num[cur_font]<>p do incr(cur_font);
-if cur_font=nf then
- begin cur_font:=invalid_font;
- error('invalid font selection: font ',p:1,' was never defined!');
- end;
-if showing then if out_mode>mnemonics_only then
- begin print(' current font is '); print_font(cur_font);
- end;
-goto done
-
-@* Skipping pages.
-A routine that's much simpler than |do_page| is used to pass over
-pages that are not being translated. The |skip_pages| subroutine
-is assumed to begin just after the preamble has been read, or just
-after a |bop| has been processed. It continues until either finding a
-|bop| that matches the desired starting page specifications, or until
-running into the postamble.
-
-@p @t\4@>@<Declare the procedure called |scan_bop|@>@;
-procedure skip_pages(@!bop_seen:boolean);
-label 9999; {end of this subroutine}
-var p:integer; {a parameter}
-@!k:0..255; {command code}
-@!down_the_drain:integer; {garbage}
-begin showing:=false;
-while true do
- begin if not bop_seen then
- begin scan_bop;
- if in_postamble then goto 9999;
- if not started then if start_match then
- begin started:=true; goto 9999;
- end;
- end;
- @<Skip until finding |eop|@>;
- bop_seen:=false;
- end;
-9999:end;
-
-@ @<Skip until finding |eop|@>=
-repeat if eof(dvi_file) then bad_dvi('the file ended prematurely');
-@.the file ended prematurely@>
- k:=get_byte;
- p:=first_par(k);
- case k of
- set_rule,put_rule: down_the_drain:=signed_quad;
- four_cases(fnt_def1): begin define_font(p);
- print_ln(' ');
- end;
- four_cases(xxx1): while p>0 do
- begin down_the_drain:=get_byte; decr(p);
- end;
- bop,pre,post,post_post,undefined_commands:
- bad_dvi('illegal command at byte ',cur_loc-1:1);
-@.illegal command at byte n@>
- othercases do_nothing
- endcases;
-until k=eop;
-
-@ Global variables called |old_backpointer| and |new_backpointer|
-are used to check whether the back pointers are properly set up.
-Another one tells whether we have already found the starting page.
-
-@<Glob...@>=
-@!old_backpointer:integer; {the previous |bop| command location}
-@!new_backpointer:integer; {the current |bop| command location}
-@!started:boolean; {has the starting page been found?}
-
-@ @<Set init...@>=
-old_backpointer:=-1; started:=false;
-
-@ The |scan_bop| procedure reads \.{DVI} commands following the preamble
-or following |eop|, until finding either |bop| or the postamble.
-
-@<Declare the procedure called |scan_bop|@>=
-procedure scan_bop;
-var k:0..255; {command code}
-begin repeat if eof(dvi_file) then bad_dvi('the file ended prematurely');
-@.the file ended prematurely@>
- k:=get_byte;
- if (k>=fnt_def1)and(k<fnt_def1+4) then
- begin define_font(first_par(k)); k:=nop;
- end;
-until k<>nop;
-if k=post then in_postamble:=true
-else begin if k<>bop then bad_dvi('byte ',cur_loc-1:1,' is not bop');
-@.byte n is not bop@>
- new_backpointer:=cur_loc-1; incr(page_count);
- for k:=0 to 9 do count[k]:=signed_quad;
- if signed_quad<>old_backpointer
- then print_ln('backpointer in byte ',cur_loc-4:1,
- ' should be ',old_backpointer:1,'!');
-@.backpointer...should be p@>
- old_backpointer:=new_backpointer;
- end;
-end;
-
-@* Using the backpointers.
-The routines in this section of the program are brought into play only
-if |random_reading| is |true| (and only if |out_mode=the_works|).
-First comes a routine that illustrates how to find the postamble quickly.
-
-@<Find the postamble, working back from the end@>=
-n:=dvi_length;
-if n<53 then bad_dvi('only ',n:1,' bytes long');
-@.only n bytes long@>
-m:=n-4;
-repeat if m=0 then bad_dvi('all 223s');
-@.all 223s@>
-move_to_byte(m); k:=get_byte; decr(m);
-until k<>223;
-if k<>id_byte then bad_dvi('ID byte is ',k:1);
-@.ID byte is wrong@>
-move_to_byte(m-3); q:=signed_quad;
-if (q<0)or(q>m-33) then bad_dvi('post pointer ',q:1,' at byte ',m-3:1);
-@.post pointer is wrong@>
-move_to_byte(q); k:=get_byte;
-if k<>post then bad_dvi('byte ',q:1,' is not post');
-@.byte n is not post@>
-post_loc:=q; first_backpointer:=signed_quad
-
-@ Note that the last steps of the above code save the locations of the
-|post| byte and the final |bop|. We had better declare these global
-variables, together with two more that we will need shortly.
-
-@<Glob...@>=
-@!post_loc:integer; {byte location where the postamble begins}
-@!first_backpointer:integer; {the pointer following |post|}
-@!start_loc:integer; {byte location of the first page to process}
-@!after_pre:integer; {byte location immediately following the preamble}
-
-@ The next little routine shows how the backpointers can be followed
-to move through a \.{DVI} file in reverse order. Ordinarily a \.{DVI}-reading
-program would do this only if it wants to print the pages backwards or
-if it wants to find a specified starting page that is not necessarily the
-first page in the file; otherwise it would of course be simpler and faster
-just to read the whole file from the beginning.
-
-@<Count the pages and move to the starting page@>=
-q:=post_loc; p:=first_backpointer; start_loc:=-1;
-if p<0 then in_postamble:=true
-else begin repeat
- {now |q| points to a |post| or |bop| command; |p>=0| is prev pointer}
- if p>q-46 then
- bad_dvi('page link ',p:1,' after byte ',q:1);
-@.page link wrong...@>
- q:=p; move_to_byte(q); k:=get_byte;
- if k=bop then incr(page_count)
- else bad_dvi('byte ',q:1,' is not bop');
-@.byte n is not bop@>
- for k:=0 to 9 do count[k]:=signed_quad;
- p:=signed_quad;
- if start_match then
- begin start_loc:=q; old_backpointer:=p;
- end;
- until p<0;
- if start_loc<0 then abort('starting page number could not be found!');
-@.starting page number...@>
- if old_backpointer<0 then start_loc:=after_pre; {we want to check everything}
- move_to_byte(start_loc);
- end;
-if page_count<>total_pages then
- print_ln('there are really ',page_count:1,' pages, not ',total_pages:1,'!')
-@.there are really n pages@>
-
-@* Reading the postamble.
-Now imagine that we are reading the \.{DVI} file and positioned just
-four bytes after the |post| command. That, in fact, is the situation,
-when the following part of \.{DVItype} is called upon to read, translate,
-and check the rest of the postamble.
-
-@p procedure read_postamble;
-var k:integer; {loop index}
-@!p,@!q,@!m:integer; {general purpose registers}
-begin showing:=false; post_loc:=cur_loc-5;
-print_ln('Postamble starts at byte ',post_loc:1,'.');
-@.Postamble starts at byte n@>
-if signed_quad<>numerator then
- print_ln('numerator doesn''t match the preamble!');
-@.numerator doesn't match@>
-if signed_quad<>denominator then
- print_ln('denominator doesn''t match the preamble!');
-@.denominator doesn't match@>
-if signed_quad<>mag then if new_mag=0 then
- print_ln('magnification doesn''t match the preamble!');
-@.magnification doesn't match@>
-max_v:=signed_quad; max_h:=signed_quad;@/
-print('maxv=',max_v:1,', maxh=',max_h:1);@/
-max_s:=get_two_bytes; total_pages:=get_two_bytes;@/
-print_ln(', maxstackdepth=',max_s:1,', totalpages=',total_pages:1);
-if out_mode<the_works then
- @<Compare the \\{lust} parameters with the accumulated facts@>;
-@<Process the font definitions of the postamble@>;
-@<Make sure that the end of the file is well-formed@>;
-end;
-
-@ No warning is given when |max_h_so_far| exceeds |max_h| by less than~100,
-since 100 units is invisibly small; it's approximately the wavelength of
-visible light, in the case of \TeX\ output. Rounding errors can be expected
-to make |h| and |v| slightly more than |max_h| and |max_v|, every once in
-a~while; hence small discrepancies are not cause for alarm.
-
-@<Compare the \\{lust}...@>=
-begin if max_v+99<max_v_so_far then
- print_ln('warning: observed maxv was ',max_v_so_far:1);
-@.warning: observed maxv...@>
-@.observed maxv was x@>
-if max_h+99<max_h_so_far then
- print_ln('warning: observed maxh was ',max_h_so_far:1);
-@.warning: observed maxh...@>
-@.observed maxh was x@>
-if max_s<max_s_so_far then
- print_ln('warning: observed maxstackdepth was ',max_s_so_far:1);
-@.warning: observed maxstack...@>
-@.observed maxstackdepth was x@>
-if page_count<>total_pages then
- print_ln('there are really ',page_count:1,' pages, not ',total_pages:1,'!');
-end
-@.there are really n pages@>
-
-@ When we get to the present code, the |post_post| command has
-just been read.
-
-@<Make sure that the end of the file is well-formed@>=
-q:=signed_quad;
-if q<>post_loc then
- print_ln('bad postamble pointer in byte ',cur_loc-4:1,'!');
-@.bad postamble pointer@>
-m:=get_byte;
-if m<>id_byte then print_ln('identification in byte ',cur_loc-1:1,
-@.identification...should be n@>
- ' should be ',id_byte:1,'!');
-k:=cur_loc; m:=223;
-while (m=223)and not eof(dvi_file) do m:=get_byte;
-if not eof(dvi_file) then bad_dvi('signature in byte ',cur_loc-1:1,
-@.signature...should be...@>
- ' should be 223')
-else if cur_loc<k+4 then
- print_ln('not enough signature bytes at end of file (',
-@.not enough signature bytes...@>
- cur_loc-k:1,')');
-
-@ @<Process the font definitions...@>=
-repeat k:=get_byte;
-if (k>=fnt_def1)and(k<fnt_def1+4) then
- begin p:=first_par(k); define_font(p); print_ln(' '); k:=nop;
- end;
-until k<>nop;
-if k<>post_post then
- print_ln('byte ',cur_loc-1:1,' is not postpost!')
-@.byte n is not postpost@>
-
-@* The main program.
-Now we are ready to put it all together. This is where \.{DVItype} starts,
-and where it ends.
-
-@p begin initialize; {get all variables initialized}
-dialog; {set up all the options}
-@<Process the preamble@>;
-if out_mode=the_works then {|random_reading=true|}
- begin @<Find the postamble, working back from the end@>;
- in_postamble:=true; read_postamble; in_postamble:=false;
- @<Count the pages and move to the starting page@>;
- end;
-skip_pages(false);
-if not in_postamble then @<Translate up to |max_pages| pages@>;
-if out_mode<the_works then
- begin if not in_postamble then skip_pages(true);
- if signed_quad<>old_backpointer then
- print_ln('backpointer in byte ',cur_loc-4:1,
- ' should be ',old_backpointer:1,'!');
-@.backpointer...should be p@>
- read_postamble;
- end;
-final_end:end.
-
-@ The main program needs a few global variables in order to do its work.
-
-@<Glob...@>=
-@!k,@!m,@!n,@!p,@!q:integer; {general purpose registers}
-
-@ A \.{DVI}-reading program that reads the postamble first need not look at the
-preamble; but \.{DVItype} looks at the preamble in order to do error
-checking, and to display the introductory comment.
-
-@<Process the preamble@>=
-open_dvi_file;
-p:=get_byte; {fetch the first byte}
-if p<>pre then bad_dvi('First byte isn''t start of preamble!');
-@.First byte isn't...@>
-p:=get_byte; {fetch the identification byte}
-if p<>id_byte then
- print_ln('identification in byte 1 should be ',id_byte:1,'!');
-@.identification...should be n@>
-@<Compute the conversion factors@>;
-p:=get_byte; {fetch the length of the introductory comment}
-print('''');
-while p>0 do
- begin decr(p); print(xchr[get_byte]);
- end;
-print_ln('''');
-after_pre:=cur_loc
-
-@ The conversion factor |conv| is figured as follows: There are exactly
-|n/d| decimicrons per \.{DVI} unit, and 254000 decimicrons per inch,
-and |resolution| pixels per inch. Then we have to adjust this
-by the stated amount of magnification.
-
-@<Compute the conversion factors@>=
-numerator:=signed_quad; denominator:=signed_quad;
-if numerator<=0 then bad_dvi('numerator is ',numerator:1);
-@.numerator is wrong@>
-if denominator<=0 then bad_dvi('denominator is ',denominator:1);
-@.denominator is wrong@>
-print_ln('numerator/denominator=',numerator:1,'/',denominator:1);
-tfm_conv:=(25400000.0/numerator)*(denominator/473628672)/16.0;
-conv:=(numerator/254000.0)*(resolution/denominator);
-mag:=signed_quad;
-if new_mag>0 then mag:=new_mag
-else if mag<=0 then bad_dvi('magnification is ',mag:1);
-@.magnification is wrong@>
-true_conv:=conv; conv:=true_conv*(mag/1000.0);
-print_ln('magnification=',mag:1,'; ',conv:16:8,' pixels per DVI unit')
-
-@ The code shown here uses a convention that has proved to be useful:
-If the starting page was specified as, e.g., `\.{1.*.-5}', then
-all page numbers in the file are displayed by showing the values of
-counts 0, 1, and~2, separated by dots. Such numbers can, for example,
-be displayed on the console of a printer when it is working on that
-page.
-
-@<Translate up to...@>=
-begin while max_pages>0 do
- begin decr(max_pages);
- print_ln(' '); print(cur_loc-45:1,': beginning of page ');
- for k:=0 to start_vals do
- begin print(count[k]:1);
- if k<start_vals then print('.')
- else print_ln(' ');
- end;
- if not do_page then bad_dvi('page ended unexpectedly');
-@.page ended unexpectedly@>
- scan_bop;
- if in_postamble then goto done;
- end;
-done:end
-
-@* System-dependent changes.
-This section should be replaced, if necessary, by changes to the program
-that are necessary to make \.{DVItype} work at a particular installation.
-It is usually best to design your change file so that all changes to
-previous sections preserve the section numbering; then everybody's version
-will be consistent with the printed program. More extensive changes,
-which introduce new sections, can be inserted here; then only the index
-itself will get a new section number.
-@^system dependencies@>
-
-@* Index.
-Pointers to error messages appear here together with the section numbers
-where each ident\-i\-fier is used.