102  INTRODUCTION  VFtoVP changes for C §1

1* . Introduction. The utility program converts a virtual font (“ ”) file and its associated TEX font metric (“ ”) file into an equivalent virtual-property-list (“ ”) file. It also makes a thorough check of the given files, using algorithms that are essentially the same as those used by device drivers and by TEX. Thus if TEX or a driver complains that a or file is “bad,” this program will pinpoint the source or sources of badness. A file output by this program can be edited with a normal text editor, and the result can be converted back to and format using the companion program .

is an extended version of the program , which is part of the standard TEXware library. The idea of a virtual font was inspired by the work of David R. Fuchs who designed a similar set of conventions in 1984 while developing a device driver for ArborText, Inc. He wrote a somewhat similar program called .

The banner string defined here should be changed whenever gets modified. define banner ≡ ´ ␣ ␣ ␣ ␣ ␣ ´ { printed when the program starts }

2* . This program is written entirely in standard Pascal, except that it occasionally has lower case letters in strings that are output. Such letters can be converted to upper case if necessary. The input is read from vf file and tfm file; the output is written on vpl file. Error messages and other remarks are written on the output file, which the user may choose to assign to the terminal if the system permits it.

The term print is used instead of write when this program writes on the output file, so that all such output can be easily deflected.

define print (#) ≡ write(#) define print ln(#) ≡ write ln(#)

program VFtoVP ; label ⟨ Labels in the outer block 3 ⟩ const ⟨ Constants in the outer block 4* ⟩ type ⟨ Types in the outer block 5 ⟩ var ⟨ Globals in the outer block 7* ⟩ procedure initialize; { this procedure gets things started properly }

var k: integer ; { all-purpose index for initialization }

begin set paths (TFM FILE PATH BIT + VF FILE PATH BIT ); ⟨ Set initial values 11* ⟩ end;

4* . The following parameters can be changed at compile time to extend or reduce ’s capacity.

define name length ≡ FILENAMESIZE ⟨ Constants in the outer block 4* ⟩ ≡

tfm size = 30000; { maximum length of tfm data, in bytes } vf size = 10000; { maximum length of vf data, in bytes } max fonts = 300; { maximum number of local fonts in the vf file } lig size = 5000; { maximum length of lig kern program, in words } hash size = 5003;

{ preferably a prime number, a bit larger than the number of character pairs in lig/kern steps } max stack = 50; { maximum depth of stack in character packets }

This code is used in section 2*.

§6  VFtoVP changes for C  VIRTUAL FONTS 103

7* . A file is organized as a stream of 8-bit bytes, using conventions borrowed from and files. Thus, a device driver that knows about and format will already contain most of the mechanisms necessary to process files. We shall assume that format is understood; the conventions in the documentation (see, for example, TEX: The Program, part 31) are adopted here to define format.

A preamble appears at the beginning, followed by a sequence of character definitions, followed by a postamble. More precisely, the first byte of every file must be the first byte of the following “preamble command”:

pre 247 i[1] k[1] x[k] cs [4] ds [4]. Here i is the identification byte of , currently 202. The string x is merely a comment, usually indicating the source of the file. Parameters cs and ds are respectively the check sum and the design size of the virtual font; they should match the first two words in the header of the file, as described below.

After the pre command, the preamble continues with font definitions; every font needed to specify “actual” characters in later set char commands is defined here. The font definitions are exactly the same in files as they are in files, except that the scaled size s is relative and the design size d is absolute:

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.

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.

fnt def3 245 k[3] c[4] s[4] d[4] a[1] l[1] n[a + l]. Define font k, where 0 ≤ k < 2^{24}.

fnt def4 246 k[4] c[4] s[4] d[4] a[1] l[1] n[a + l]. Define font k, where −2^{31} ≤ k < 2^{31}. These font numbers k are “local”; they have no relation to font numbers defined in the file that uses this virtual font. The dimension s, which represents the scaled size of the local font being defined, is a fix word relative to the design size of the virtual font. Thus if the local font is to be used at the same size as the design size of the virtual font itself, s will be the integer value 2^{20}. The value of s must be positive and less than 2^{24} (thus less than 16 when considered as a fix word ). The dimension d is a fix word in units of printer’s points; hence it is identical to the design size found in the corresponding file.

define id byte = 202 ⟨ Globals in the outer block 7* ⟩ ≡ vf file: packed file of byte; { files that contain binary data } vf name: packed array [1 . . FILENAMESIZE ] of char ;

See also sections 10*, 12, 20*, 23, 26, 29, 30, 37, 42, 49*, 51, 54, 67, 69, 85, 87, 111, and 123. This code is used in section 2*.

104  FONT METRIC DATA  VFtoVP changes for C §10

10* . Font metric data. The idea behind files is that typesetting routines like TEX need a compact way to store the relevant information about several dozen fonts, and computer centers need a compact way to store the relevant information about several hundred fonts. files are compact, and most of the information they contain is highly relevant, so they provide a solution to the problem.

The information in a file appears in a sequence of 8-bit bytes. Since the number of bytes is always a multiple of 4, we could also regard the file as a sequence of 32-bit words; but TEX uses the byte interpretation, and so does . Note that the bytes are considered to be unsigned numbers. ⟨ Globals in the outer block 7* ⟩ +≡ tfm file: packed file of byte; tfm name: packed array [1 . . FILENAMESIZE ] of char ;

11* . We don’t have to do anything special to read a packed file of bytes, but we do want to use environment variables to find the input files. ⟨ Set initial values 11* ⟩ ≡

if argc ≠ 4 then begin print ln(´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); uexit (1); end; { Use path searching to find the input files. }

argv (1, vf name);

if test read access (vf name, VF FILE PATH ) then reset (vf file, vf name)

else begin print pascal string (vf name); print ln(´ ␣ ␣ ␣ ␣ ´ ); uexit (1);

end; argv (2, tfm name); if test read access (tfm name, TFM FILE PATH ) then reset (tfm file, tfm name) else begin print pascal string (tfm name); print ln(´ ␣ ␣ ␣ ␣ ´ ); uexit (1);

end; print ln(banner );

See also sections 21*, 50*, 55, 68, and 86. This code is used in section 2*.

20* . So that is what  files hold. The next question is, “What about  files?” A complete answer to

that question appears in the documentation of the companion program, , so it will not be repeated here. Suffice it to say that a file is an ordinary Pascal text file, and that the output of uses only a subset of the possible constructions that might appear in a file. Furthermore, hardly anybody really wants to look at the formal definition of format, because it is almost self-explanatory when you see an example or two. ⟨ Globals in the outer block 7* ⟩ +≡ vpl file: text ; vpl name: packed array [1 . . FILENAMESIZE ] of char ;

21* . ⟨ Set initial values 11* ⟩ +≡ argv (3, vpl name); rewrite(vpl file, vpl name);

§22  VFtoVP changes for C  UNPACKING THE TFM FILE 105

24* . The input may, of course, be all screwed up and not a file at all. So we begin cautiously.

define abort (#) ≡ begin print ln(#); print ln(´ ␣ ␣ ␣ ´ ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); uexit (1); end

⟨ Read the whole file 24* ⟩ ≡ read (tfm file, tfm[0]); if tfm[0] > 127 then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); if eof (tfm file) then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); read (tfm file, tfm[1]); lf ← tfm[0] ∗ ´ 400 + tfm[1]; if lf = 0 then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ´ ␣ ´ ); if 4 ∗ lf − 1 > tfm size then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); for tfm ptr ← 2 to 4 ∗ lf − 1 do

begin if eof (tfm file) then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); read (tfm file, tfm[tfm ptr ]); end;

if ¬eof (tfm file) then

begin print ln(´  ´  ´ ␣    ␣     ␣    ␣  ␣   ␣   ␣  ␣   ␣   ␣  ´ );

  print ln(´ ␣ ´  ´ ␣       ␣  ␣  ␣  ␣     ´       ´ ␣  ´ );

end

This code is used in section 131.

106  UNPACKING THE VF FILE  VFtoVP changes for C §30

31* . Again we cautiously verify that we’ve been given decent data.

define read vf (#) ≡ read (vf file, #) define vf abort (#) ≡

begin print ln(#); print ln(´ ␣ ␣ ␣ ´ ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); uexit (1); end

⟨ Read the whole file 31* ⟩ ≡ read vf (temp byte); if temp byte ≠ pre then vf abort (´ ␣ ␣ ␣ ´ ´ ␣` ´ ´ ´ ); ⟨ Read the preamble command 32 ⟩; ⟨ Read and store the font definitions and character packets 33 ⟩; ⟨ Read and verify the postamble 34 ⟩

This code is used in section 131.

36* . The font area may need to be separated from the font name on some systems. Here we simply reproduce the font area and font name (with no space or punctuation between them). ⟨ Print the name of the local font 36* ⟩ ≡

print (´ ␣´ , font ptr : 1, ´ ␣´ ); for k ← font start [font ptr ] + 14 to vf ptr − 1 do print (xchr [vf [k]]); k ← font start [font ptr ] + 5; print (´ ␣ ␣´ ); print real ((((vf [k] ∗ 256 + vf [k + 1]) ∗ 256 + vf [k + 2])/´ 4000000 ) ∗ real dsize, 2, 2); print ln(´ ´ )

This code is used in section 35.

§39  VFtoVP changes for C  UNPACKING THE VF FILE 107

39* . We use the vf array to store a list of all valid characters in the local font, beginning at location font chars [f]. ⟨ Read the local font’s file and record the characters it contains 39* ⟩ ≡

font chars [font ptr ] ← vf ptr ; ⟨ Move font name into the cur name string 44* ⟩; if ¬test read access (cur name, TFM FILE PATH ) then

print ln(´ ␣ ␣ ␣ ␣ ´ ´ ␣ ␣ ´ ) else begin reset (tfm file, cur name); font bc ← 0; font ec ← 256;

{ will cause error if not modified soon } read tfm word ; if b2 < 128 then

begin font lh ← b2 ∗ 256 + b3 ; read tfm word ;

if (b0 < 128) ∧ (b2 < 128) then begin font bc ← b0 ∗ 256 + b1 ; font ec ← b2 ∗ 256 + b3 ; end;

end; if font bc ≤ font ec then

if font ec > 255 then print ln(´ ␣ ␣ ␣ ␣ ´ )

else begin for k ← 0 to 3 + font lh do begin read tfm word ; if k = 4 then ⟨ Check the check sum 40 ⟩; if k = 5 then ⟨ Check the design size 41 ⟩; end;

for k ← font bc to font ec do begin read tfm word ; if b0 > 0 then { character k exists in the font }

begin vf [vf ptr ] ← k; incr (vf ptr );

if vf ptr = vf size then vf abort (´ ´ ´ ␣ ␣ ␣ ␣ ´ ); end; end; end;

if eof (tfm file) then print ln(´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); end;

incr (vf ptr ) { leave space for character search later }

This code is used in section 35.

43* . (No initialization to be done. Keep this module to preserve numbering.)

44* . The string cur name is supposed to be set to the external name of the file for the current font. This usually means that we need to, at most sites, append the suffix “.tfm”. ⟨ Move font name into the cur name string 44* ⟩ ≡

for k ← 1 to name length do cur name[k] ← ´ ␣´ ; r ← 0; for k ← font start [font ptr ] + 14 to vf ptr − 1 do

begin incr (r); if r + 4 > name length then vf abort (´ ␣ ␣ ␣ ␣ ␣ ´ ); cur name[r] ← xchr [vf [k]]; end;

cur name[r + 1] ← ´ ´ ; cur name[r + 2] ← ´ ´ ; cur name[r + 3] ← ´ ´ ; cur name[r + 4] ← ´ ´

This code is used in section 39*.

108  BASIC OUTPUT SUBROUTINES  VFtoVP changes for C §48

49* . In order to stick to standard Pascal, we use an xchr array to do appropriate conversion of ASCII codes. Three other little strings are used to produce face codes like . ⟨ Globals in the outer block 7* ⟩ +≡ ASCII 04 , ASCII 10 , ASCII 14 : ccharpointer ; { strings for output in the user’s external character set } xchr : packed array [0 . . 255] of char ; MBL string , RI string , RCE string : ccharpointer ; { handy string constants for face codes }

50* . ⟨ Set initial values 11* ⟩ +≡ ASCII 04 ← ´ ␣␣ #$% ´ ´ ´ ; ASCII 10 ← ´ ␣ ´ ; ASCII 14 ← ´ ␣` ´ ; for k ← 0 to 255 do xchr [k] ← ´ ´ ; for k ← 0 to ´ 37 do

begin xchr [k + ´ 40 ] ← ASCII 04 [k + 1]; xchr [k + ´ 100 ] ← ASCII 10 [k + 1]; xchr [k + ´ 140 ] ← ASCII 14 [k + 1]; end;

MBL string ← ´ ␣ ´ ; RI string ← ´ ␣ ␣´ ; RCE string ← ´ ␣ ´ ;

61* . The property value might be a “face” byte, which is output in the curious code mentioned earlier, provided that it is less than 18. procedure out face(k : index ); { outputs a face }

var s: 0 . . 1; { the slope }

b: 0 . . 8; { the weight and expansion } begin if tfm[k] ≥ 18 then out octal (k, 1) else begin out (´ ␣ ␣´ ); { specify face-code format }

s ← tfm[k] mod 2; b ← tfm[k] div 2; put byte(MBL string [1 + (b mod 3)], vpl file); put byte(RI string [1 + s], vpl file); put byte(RCE string [1 + (b div 3)], vpl file); end;

end;

62* . And finally, the value might be a fix word , which is output in decimal notation with just enough decimal places for to recover every bit of the given fix word .

All of the numbers involved in the intermediate calculations of this procedure will be nonnegative and less than 10 · 2^{24}. procedure out fix (k : index ); { outputs a fix word }

var a: 0 . . ´ 7777 ; { accumulator for the integer part } f: integer ; { accumulator for the fraction part } j: 0 . . 12; { index into dig } delta: integer ; { amount if allowable inaccuracy }

begin out (´ ␣ ␣´ ); { specify real format } a ← (tfm[k] ∗ 16) + (tfm[k + 1] div 16); f ← ((tfm[k + 1] mod 16) ∗ toint (´ 400 ) + tfm[k + 2]) ∗ ´ 400 + tfm[k + 3]; if a > ´ 3777 then ⟨ Reduce negative to positive 65 ⟩; ⟨ Output the integer part, a, in decimal notation 63 ⟩; ⟨ Output the fraction part, f/2^{20}, in decimal notation 64 ⟩; end;

§66  VFtoVP changes for C  CHECKING FOR LIGATURE LOOPS 109

112* . ⟨ Check for ligature cycles 112* ⟩ ≡ hash ptr ← 0; y lig cycle ← 256; for hh ← 0 to hash size do hash[hh] ← 0; { clear the hash table } for c ← bc to ec do

if tag (c) = lig tag then begin i ← remainder (c); if tfm[lig step(i)] > stop flag then i ← 256 ∗ tfm[lig step(i) + 2] + tfm[lig step(i) + 3]; ⟨ Enter data for character c starting at location i in the hash table 113 ⟩; end;

if bchar label < nl then begin c ← 256; i ← bchar label ; ⟨ Enter data for character c starting at location i in the hash table 113 ⟩; end;

if hash ptr = hash size then begin print ln(´ ␣ ␣ ´ ´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); uexit (1); end;

for hh ← 1 to hash ptr do begin r ← hash list [hh]; if class [r] > simple then { make sure f is defined }

r ← lig f (r, (hash[r] − 1) div 256, (hash[r] − 1) mod 256); end;

if y lig cycle < 256 then begin print (´ ␣ ␣ ␣ ␣ ␣´ ); if x lig cycle = 256 then print (´ ´ ) else print octal (x lig cycle); print (´ ␣ ␣´ ); print octal (y lig cycle); print ln(´ ´ ); out (´ ␣ ␣ ␣ ␣ ␣ ´ ); uexit (1); end

This code is used in section 88.

116* . Evaluation of f(x, y) is handled by two mutually recursive procedures. Kind of a neat algorithm, generalizing a depth-first search.

ifdef (´ ´ ) function lig f (h, x, y : index ): index ;

begin end; { compute f for arguments known to be in hash[h] }

endif (´ ´ ) function eval (x, y : index ): index ; { compute f(x, y) with hashtable lookup }

var key : integer ; { value sought in hash table } begin key ← 256 ∗ x + y + 1; h ← (1009 ∗ key ) mod hash size; while hash[h] > key do

if h > 0 then decr (h) else h ← hash size; if hash[h] < key then eval ← y { not in ordered hash table } else eval ← lig f (h, x, y); end;

110  CHECKING FOR LIGATURE LOOPS  VFtoVP changes for C §117

117* . Pascal’s beastly convention for forward declarations prevents us from saying function f(h, x, y : index ): index here. function lig f (h, x, y : index ): index ;

begin case class [h] of simple: do nothing ; left z : begin class [h] ← pending ; lig z [h] ← eval (lig z [h], y); class [h] ← simple;

end; right z : begin class [h] ← pending ; lig z [h] ← eval (x, lig z [h]); class [h] ← simple;

end; both z : begin class [h] ← pending ; lig z [h] ← eval (eval (x, lig z [h]), y); class [h] ← simple;

end; pending : begin x lig cycle ← x; y lig cycle ← y; lig z [h] ← 257; class [h] ← simple;

end; { the value 257 will break all cycles, since it’s not in hash } end; { there are no other cases } lig f ← lig z [h]; end;

§118  VFtoVP changes for C  OUTPUTTING THE VF INFO 111

124* . ⟨ Do the packet for character c 124* ⟩ ≡ if packet start [c] = vf size then bad vf (´ ␣ ␣ ␣ ␣´ , c : 1) else begin left ; out (´ ´ ); out ln; top ← 0; wstack [0] ← 0; xstack [0] ← 0; ystack [0] ← 0;

zstack [0] ← 0; vf ptr ← packet start [c]; vf limit ← packet end [c] + 1; f ← 0; while vf ptr < vf limit do

begin o ← vf [vf ptr ]; incr (vf ptr );

if ((o ≥ set char 0 )∧(o ≤ set char 0 +127))∨((o ≥ set1 )∧(o ≤ set1 +3))∨((o ≥ put1 )∧(o ≤ put1 +3))

then begin if o ≥ set1 then

if o ≥ put1 then c ← get bytes (o − put1 + 1, false)

else c ← get bytes (o − set1 + 1, false) else c ← o; if f = font ptr then bad vf (´ ␣´ , c : 1, ´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ) else begin vf [font start [f + 1] − 1] ← c; { store c in the “hole” we left }

k ← font chars [f]; while vf [k] ≠ c do incr (k); if k = font start [f + 1] − 1 then

bad vf (´ ␣´ , c : 1, ´ ␣ ␣ ␣´ , f : 1, ´ ␣ ␣ ␣ ´ ) else begin if o ≥ put1 then out (´ ´ );

left ; out (´ ´ ); out char (c); if o ≥ put1 then out (´ ´ ); right ; end; end; end

else case o of

⟨ Cases of instructions that can appear in character packets 126* ⟩improper DVI for VF :

bad vf (´ ␣ ␣ ␣´ , o : 1, ´ ␣ ␣ ␣ ´ ); end; { there are no other cases }

end; if top > 0 then

begin bad vf (´ ␣ ␣ ␣ ´ ); repeat out (´ ´ ); decr (top); until top = 0; end;

right ;

end

This code is used in section 133.

125* . A procedure called get bytes helps fetch the parameters of commands. function get bytes (k : integer ; is signed : boolean): integer ;

var a: integer ; { accumulator } begin if vf ptr + k > vf limit then

begin bad vf (´ ␣ ␣ ´ ); k ← vf limit − vf ptr ; end;

a ← vf [vf ptr ]; if (k = 4) ∨ is signed then

if a ≥ 128 then a ← a − 256; incr (vf ptr ); while k > 1 do

begin a ← a ∗ 256 + vf [vf ptr ]; incr (vf ptr ); decr (k);

end; get bytes ← a; end;

112  OUTPUTTING THE VF INFO  VFtoVP changes for C §126

126* . Let’s look at the simplest cases first, in order to get some experience.

define four cases (#) ≡ #, # + 1, # + 2, # + 3 define eight cases (#) ≡ four cases (#), four cases (# + 4) define sixteen cases (#) ≡ eight cases (#), eight cases (# + 8) define thirty two cases (#) ≡ sixteen cases (#), sixteen cases (# + 16) define sixty four cases (#) ≡ thirty two cases (#), thirty two cases (# + 32)

⟨ Cases of instructions that can appear in character packets 126* ⟩ ≡ nop: do nothing ; push: begin if top = max stack then

begin print ln(´ ␣ ´ ); uexit (1); end;

incr (top); wstack [top] ← wstack [top − 1]; xstack [top] ← xstack [top − 1]; ystack [top] ← ystack [top − 1]; zstack [top] ← zstack [top − 1]; out (´ ´ ); out ln; end;

pop: if top = 0 then bad vf (´ ␣ ␣ ␣ ´ )

else begin decr (top); out (´ ´ ); out ln;

end; set rule, put rule: begin if o = put rule then out (´ ´ );

left ; out (´ ´ ); out as fix (get bytes (4, true)); out as fix (get bytes (4, true)); if o = put rule then out (´ ´ ); right ; end;

See also sections 127, 128, and 130. This code is used in section 124*.

129* . Before we typeset a character we make sure that it exists. (These cases moved outside the case statement, section 124.)

§136  VFtoVP changes for C  INDEX 113

136* . Index. Pointers to error messages appear here together with the section numbers where each identifier is used.

The following sections were changed by the change file: 1, 2, 4, 7, 10, 11, 20, 21, 24, 31, 36, 39, 43, 44, 49, 50, 61, 62, 112, 116, 117, 124, 125, 126, 129, 136.

a: \underline{37}, \underline{45}, \underline{47}, \underline{58}, \underline{62*} , \underline{125*} . abort : \underline{24*} , 25. abs : 120. accessible: \underline{87}, 90, 91, 92, 97. acti : \underline{87}, 93. activity : \underline{87}, 88, 89, 90, 91, 92, 93, 95, 97, 133. ai : \underline{87}, 88, 92, 97, \underline{133}. argc: 11* . argv : 11* , 21* . ASCII 04 : \underline{49*} , 50* . ASCII 10 : \underline{49*} , 50* . ASCII 14 : \underline{49*} , 50* . axis height : 19. b: \underline{45}, \underline{58}, \underline{61*} . bad : \underline{69}, 72, 74, 82, 84, 92, 96, 98, 106. : 69. : 39* . : 119. bad char : \underline{69}, 106, 109. bad char tail : \underline{69}. bad design: \underline{72}, 73. bad vf : \underline{119}, 120, 122, 124* , 125* , 126* , 128, 130. bal : \underline{118}. banner : \underline{1*} , 11* . bc: \underline{12}, 13, 15, 17, 25, 27, 28, 69, 89, 100, 112* . bchar label : \underline{85}, 86, 91, 112* . big op spacing1 : 19. big op spacing5 : 19. boolean: 30, 67, 118, 125* , 131, 133. bop: 8. bot : 18. both z : \underline{111}, 114, 115, 117* . boundary char : \underline{85}, 86, 91, 98, 99. byte: \underline{5}, 7* , 10* , 23, 30, 37, 45, 47, 53, 60, 74,

123, 133. b0 : \underline{37}, 38, 39* , 40, 41. b1 : \underline{37}, 38, 39* , 40, 41. b2 : \underline{37}, 38, 39* , 40, 41. b3 : \underline{37}, 38, 39* , 40, 41. c: \underline{47}, \underline{60}, \underline{69}, \underline{74}, \underline{131}, \underline{133}. cc: 8, 46, \underline{85}, 90, 91, 94, \underline{114}, 115. ccharpointer : 49* . char : 7* , 10* , 20* , 37, 42, 49* . char base: \underline{26}, 27, 28. char info: 15, 26, \underline{28}, 100. char info word : 13, 15, 16. : 46.

: 124* . chars on line: \underline{67}, 68, 69, 100, 119. check sum: 14. : 32. : 40. check BCPL: \underline{74}, 75, 77. check fix : \underline{82}, 84. check fix tail : \underline{82}. check sum: \underline{28}, 32, 71, 78. class : \underline{111}, 112* , 114, 117* . coding scheme: 14. correct bad char : \underline{69}, 98, 99. correct bad char tail : \underline{69}. count : \underline{30}, 32, 46, 97. cs : 7* . cur name: \underline{37}, 39* , 44* . : 106. d: \underline{69}. decr : \underline{5}, 45, 52, 56, 57, 59, 65, 90, 114, 116* , 118,

114  INDEX  VFtoVP changes for C §136

124* , 125* , 126* , 130. default directory : \underline{42}. default directory name: \underline{42}. default directory name length: \underline{42}. default rule thickness : 19. delim1 : 19. delim2 : 19. delta: \underline{62*} , 64. denom1 : 19. denom2 : 19. depth: 15, \underline{28}, 103. : 103. : 84. depth base: \underline{26}, 27, 28, 84. depth index : 15, \underline{28}, 100, 103. design size: 14. : 72. : 41. design size: \underline{28}, 32, 73, 120. : 73. dig : \underline{51}, 52, 53, 58, 59, 62* , 63. : 46. do characters : \underline{133}, 134. do map: 100, \underline{133}. do nothing : \underline{5}, 100, 115, 117* , 126* . do simple things : \underline{132}, 134. down1 : \underline{8}, 127. ds : 7* . dvi : 8. ec: \underline{12}, 13, 15, 17, 25, 27, 28, 89, 100, 112* . eight cases : \underline{126*} . endif : 116* . eof : 24* , 32, 33, 34, 38, 39* , 45. eop: 8. eval : \underline{116*} , 117* . eval two bytes : \underline{25}. exit : \underline{5}, 114, 118, 131, 133. ext tag : \underline{16}, 100. exten: 16, \underline{28}, 108. exten base: \underline{26}, 27, 28, 109. : 107. : 109. extensible recipe: 13, 18. extra space: 19. f: \underline{62*} , \underline{117*} , \underline{132}, \underline{133}. face: 14, 49* , 61* . false: 33, 69, 89, 91, 118, 119, 124* , 128, 130,

131, 133. family : \underline{28}, 77. family name: 14. : 33. FILENAMESIZE : 4* , 7* , 10* , 20* . final end : \underline{3}, 100, 131, 133, 134. fix word : 7* , 8, \underline{13}, 14, 19, 28, 62* , 82, 84, 120. fnt def1 : 7* , \underline{8}, 35. fnt def2 : \underline{7*} . fnt def3 : \underline{7*} . fnt def4 : \underline{7*} . fnt num 0 : \underline{8}, 128. fnt num0 : 8. fnt1 : \underline{8}, 128. fnt4 : 8. font identifier: 14. : 44* . font bc: \underline{37}, 39* . font chars : \underline{30}, 39* , 124* . font ec: \underline{37}, 39* . font lh: \underline{37}, 39* . font number : \underline{30}, 35, 128. font ptr : \underline{30}, 33, 35, 36* , 39* , 40, 41, 44* , 121,

124* , 128. font start : \underline{30}, 33, 35, 36* , 40, 41, 44* , 119,

121, 122, 124* . font type: \underline{29}, 60, 70, 75, 81, 83. forward : 117* . four cases : \underline{126*} , 127, 128, 130. Fuchs, David Raymond: 1* . get bytes : 124* , \underline{125*} , 126* , 127, 128, 130. get vf : \underline{45}. h: \underline{111}, \underline{116*} , \underline{117*} . hash: \underline{111}, 112* , 114, 116* , 117* . hash input : 113, \underline{114}. hash list : \underline{111}, 112* , 114. hash ptr : \underline{111}, 112* , 114. hash size: \underline{4*} , 111, 112* , 114, 116* . header : 14. height : 15, \underline{28}, 102. : 102. : 84. height base: \underline{26}, 27, 28, 84. height index : 15, \underline{28}, 100, 102. hh: \underline{111}, 112* . i: \underline{69}, \underline{132}. : 35. : 39* . id byte: \underline{7*} , 32. ifdef : 116* . : 35. : 122. : 122. improper DVI for VF : \underline{8}, 124* . : 25. : 46. incr : \underline{5}, 32, 33, 34, 35, 39* , 44* , 56, 57, 58, 59, 63, 90, 94, 97, 100, 114, 118, 124* , 125* , 126* , 128, 130.

index : \underline{22}, 47, 57, 58, 61* , 62* , 69, 74, 116* ,

117* , 131, 133. : 112* . initialize: \underline{2*} , 134. integer : 2* , 26, 30, 37, 45, 47, 52, 62* , 114, 116* ,

118, 120, 123, 125* , 131, 132, 133. is signed : \underline{125*} . italic: 15, \underline{28}, 104. : 104. : 84. italic base: \underline{26}, 27, 28, 84. italic index : 15, \underline{28}, 100, 104. j: \underline{53}, \underline{58}, \underline{62*} , \underline{74}, \underline{118}. k: \underline{2*} , \underline{45}, \underline{47}, \underline{57}, \underline{58}, \underline{61*} , \underline{62*} , \underline{69}, \underline{74}, \underline{118}, \underline{120},

\underline{125*} , \underline{131}, \underline{132}, \underline{133}.

kern: 17, \underline{28}, 84, 98.

: 98. : 84. : 98. kern base: \underline{26}, 27, 28. kern flag : \underline{17}, 96, 98, 115. key : \underline{114}, \underline{116*} . l: \underline{37}, \underline{56}, \underline{57}, \underline{58}, \underline{74}, \underline{118}. label ptr : \underline{85}, 86, 89, 90, 91. label table: \underline{85}, 86, 89, 90, 91, 94. left : \underline{56}, 71, 73, 76, 77, 78, 79, 80, 82, 88, 91, 94, 95, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 119, 121, 122, 124* , 126* , 130. left z : \underline{111}, 115, 117* . level : \underline{54}, 55, 56, 93, 95, 96, 134. lf : \underline{12}, 22, 24* , 25. lh: \underline{12}, 13, 25, 27, 70, 78, 79. : 92. lig f : 112* , \underline{116*} , \underline{117*} . lig kern: 4* , 16, 17. lig kern base: \underline{26}, 27, 28. lig kern command : 13, 17. lig size: \underline{4*} , 25, 85, 87, 89, 133. lig step: \underline{28}, 89, 91, 92, 96, 105, 112* , 113, 115. lig tag : \underline{16}, 85, 89, 100, 112* . lig z : \underline{111}, 114, 117* . : 99. : 99. : 96. : 89, 91. list tag : \underline{16}, 100, 106. long char : \underline{8}, 33, 46. : 35. mathex : \underline{29}, 75, 81, 83. mathsy : \underline{29}, 75, 81, 83. max fonts : \underline{4*} , 30, 35. max stack : \underline{4*} , 123, 126* . MBL string : \underline{49*} , 50* , 61* . mid : 18. : 124* . : 126* . : 124* . name length: \underline{4*} , 37, 44* . nd : \underline{12}, 13, 25, 27, 84, 103. ne: \underline{12}, 13, 25, 27, 107, 109. : 46. next char : 17. nh: \underline{12}, 13, 25, 27, 84, 102. ni : \underline{12}, 13, 25, 27, 84, 104. nil: 5. nk : \underline{12}, 13, 25, 27, 84, 98. nl : \underline{12}, 13, 17, 25, 27, 88, 89, 91, 92, 93, 96,

105, 112* , 113. no tag : \underline{16}, 28, 100. nonexistent : \underline{28}, 46, 98, 99, 106, 108, 109. : 74. nonzero fix : \underline{84}. nop: \underline{8}, 126* . not found : \underline{5}, 118. np: \underline{12}, 13, 25, 80, 81. num1 : 19. num2 : 19. num3 : 19. nw : \underline{12}, 13, 25, 27, 84, 101. o: \underline{123}. odd : 99. : 25. op byte: 17. organize: \underline{131}, 134. out : \underline{48}, 52, 56, 57, 58, 60, 61* , 62* , 64, 65, 71,

72, 73, 76, 77, 78, 79, 80, 82, 83, 88, 91, 94, 95, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 112* , 119, 121, 122, 124* , 126* , 127, 128, 130, 134. out as fix : \underline{120}, 126* , 127.

out BCPL: \underline{57}, 76, 77.

out char : \underline{60}, 91, 94, 98, 99, 100, 106, 108, 124* .

out digs : \underline{52}, 58, 63.
out face: \underline{61*} , 78.

out fix : \underline{62*} , 73, 82, 98, 101, 102, 103, 104, 120, 121.

out hex : \underline{130}.

out ln: \underline{56}, 73, 80, 88, 95, 97, 100, 105, 107, 121,

124* , 126* , 127, 128, 130. out octal : \underline{58}, 60, 61* , 71, 78, 121. output : 2* . : 120. packet end : \underline{30}, 46, 124* . packet found : \underline{30}, 33, 35, 46. packet start : \underline{30}, 33, 46, 124* . param: 14, 19, \underline{28}, 82. param base: \underline{26}, 27, 28. : 82. : 74. pass through: \underline{87}, 89, 91, 93. pending : \underline{111}, 117* . perfect : \underline{67}, 68, 69, 89, 91, 119, 134. pl : 8, \underline{30}, 46. pop: \underline{8}, 126* . post : \underline{8}, 9, 33, 34. pre: 7* , \underline{8}, 31* , 35. print : \underline{2*} , 32, 36* , 52, 53, 69, 89, 91, 100, 106, 112* . print digs : \underline{52}, 53. print ln: \underline{2*} , 11* , 24* , 31* , 32, 33, 34, 36* , 39* , 40, 41, 46, 69, 72, 81, 82, 89, 91, 92, 99, 100, 106, 112* , 119, 126* , 134.

print octal : \underline{53}, 69, 89, 100, 106, 112* .

print pascal string : 11* .

print real : 36* . push: \underline{8}, 126* . put byte: 61* . put rule: \underline{8}, 126* . put1 : \underline{8}, 124* . quad : 19. r: \underline{69}. random word : \underline{28}, 78, 79. range error : \underline{69}, 101, 102, 103, 104, 107. RCE string : \underline{49*} , 50* , 61* . read : 24* , 31* , 38. read tfm: \underline{38}. read tfm word : \underline{38}, 39* . read vf : \underline{31*} , 32, 33, 34, 45. real : 30. real dsize: \underline{30}, 32, 36* . remainder : 15, 16, 17, \underline{28}, 89, 105, 106, 107, 112* . rep: 18. reset : 11* , 39* . reset tag : \underline{28}, 89, 106, 107. return: \underline{5}. rewrite: 21* . RI string : \underline{49*} , 50* , 61* . right : \underline{56}, 71, 73, 76, 77, 78, 79, 80, 82, 88, 91,

93, 94, 95, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 119, 121, 122, 124* , 126* , 130.

right z : \underline{111}, 115, 117* . right1 : \underline{8}, 127. rr : \underline{85}, 86, 89, 90, 91, 94. s: \underline{61*} . scheme: \underline{28}, 75, 76. set char 0 : \underline{8}, 124* . set paths : 2* . set rule: \underline{8}, 126* . set1 : \underline{8}, 124* . seven bit safe flag : 14, 79. short char0 : 8. short char241 : 8. : 84. simple: \underline{111}, 112* , 114, 115, 117* . sixteen cases : \underline{126*} . sixty four cases : \underline{126*} , 128. skip byte: 17. slant : \underline{19}. : 112* . sort ptr : \underline{85}, 90, 93, 94, 100. space: 19. space shrink : 19. space stretch: 19. : 126* . stop flag : \underline{17}, 89, 92, 96, 97, 105, 112* , 113. : 74. string balance: \underline{118}, 119, 122, 130. stuff : 13. subdrop: 19. : 25. sub1 : 19. sub2 : 19. supdrop: 19. sup1 : 19. sup2 : 19. sup3 : 19. system dependencies: 2* , 11* , 36* , 38, 42, 44* , 60, 135. t: \underline{114}. tag : 15, 16, \underline{28}, 85, 89, 100, 106, 112* . temp byte: \underline{30}, 31* , 32, 33, 34, 35, 46. test read access : 11* , 39* . text : 20* . tfm: 4* , 8, 22, \underline{23}, 24* , 25, 26, 28, 32, 46, 47, 57, 58, 59, 60, 61* , 62* , 69, 73, 74, 75, 79, 82, 84, 89, 91, 92, 96, 97, 98, 99, 105, 108, 109, 112* , 113, 115, 118, 120, 121, 131. ´ : 39* . tfm file: 2* , \underline{10*} , 11* , 22, 24* , 38, 39* . TFM FILE PATH : 11* , 39* . TFM FILE PATH BIT : 2* . tfm name: \underline{10*} , 11* . tfm ptr : 24* , 25, \underline{131}. tfm size: \underline{4*} , 22, 23, 24* . tfm width: 46, \underline{47}. : 25. : 24* . : 32. : 24* . : 24* , 32. : 24* , 31* . : 25. : 24* , 32. : 25. : 134. : 25. : 24* , 34. thirty two cases : \underline{126*} . : 134. : 119. toint : 62* . top: 18, \underline{123}, 124* , 126* , 127. : 39* . true: 46, 68, 118, 126* , 127, 131, 133. uexit : 11* , 24* , 31* , 112* , 126* . : 128. unreachable: \underline{87}, 88, 89, 95. : 81. vanilla: \underline{29}, 60, 70, 75. vf : 4* , \underline{30}, 32, 35, 36* , 39* , 40, 41, 44* , 118, 119,

121, 122, 124* , 125* , 130, 131. : 34. vf abort : \underline{31*} , 32, 35, 39* , 44* , 46. vf count : \underline{30}, 32, 33, 34, 45. vf file: 2* , \underline{7*} , 11* , 30, 31* , 32, 33, 34, 45. VF FILE PATH : 11* . VF FILE PATH BIT : 2* . vf input : \underline{131}. vf limit : \underline{123}, 124* , 125* , 130. vf name: \underline{7*} , 11* . vf ptr : \underline{30}, 32, 33, 35, 36* , 39* , 44* , 46, 124* ,

125* , 130, \underline{131}. vf read : 35, \underline{45}, 46. vf size: \underline{4*} , 30, 32, 33, 39* , 46, 123, 124* , 131,

132, 133. vf store: \underline{32}, 35, 46. VFtoVP : \underline{2*} . vpl file: 2* , \underline{20*} , 21* , 48, 56, 61* . vpl name: \underline{20*} , 21* . width: 15, \underline{28}, 47, 84, 101. : 84. width base: \underline{26}, 27, 28, 84. width index : 15, \underline{28}, 100, 101. write: 2* , 48. write ln: 2* , 56. : 32. wstack : \underline{123}, 124* , 126* , 127. w0 : \underline{8}, 127. w1 : \underline{8}, 127. x: \underline{116*} , \underline{117*} , \underline{120}. x height : 19. x lig cycle: \underline{111}, 112* , 117* . xchr : 32, 36* , 44* , \underline{49*} , 50* , 57, 60, 119, 122, 130. xstack : \underline{123}, 124* , 126* , 127. xxx1 : \underline{8}, 130. xxx4 : \underline{8}. x0 : \underline{8}, 127. x1 : \underline{8}, 127. y: \underline{114}, \underline{116*} , \underline{117*} . y lig cycle: \underline{111}, 112* , 117* . ystack : \underline{123}, 124* , 126* , 127. y0 : \underline{8}, 127. y1 : \underline{8}, 127. zstack : \underline{123}, 124* , 126* , 127. zz : \underline{114}, 115. z0 : \underline{8}, 127. z1 : \underline{8}, 127.

118  NAMES OF THE SECTIONS  VFtoVP changes for C §136

⟨ Build the label table 89 ⟩ Used in section 88. ⟨ Cases of instructions that can appear in character packets 126*, 127, 128, 130 ⟩ Used in section 124*. ⟨ Check and output the ith parameter 82 ⟩ Used in section 80. ⟨ Check for a boundary char 91 ⟩ Used in section 88. ⟨ Check for ligature cycles 112* ⟩ Used in section 88.

⟨ Check the check sum 40 ⟩ Used in section 39*.

⟨ Check the design size 41 ⟩ Used in section 39*. ⟨ Check the extensible recipes 109 ⟩ Used in section 134.

⟨ Check the fix word entries 84 ⟩ Used in section 132.

⟨ Check to see if np is complete for this font type 81 ⟩ Used in section 80. ⟨ Compute the base addresses 27 ⟩ Used in section 131. ⟨ Compute the command parameters y, cc, and zz 115 ⟩ Used in section 114.

⟨ Compute the activity array 92 ⟩ Used in section 88.

⟨ Constants in the outer block 4* ⟩ Used in section 2*.

⟨ Do the characters 100 ⟩ Used in section 133. ⟨ Do the header 70 ⟩ Used in section 132.

⟨ Do the ligatures and kerns 88 ⟩ Used in section 134.

⟨ Do the local fonts 121 ⟩ Used in section 132.

⟨ Do the packet for character c 124* ⟩ Used in section 133.

⟨ Do the parameters 80 ⟩ Used in section 132.

⟨ Do the virtual font title 119 ⟩ Used in section 132. ⟨ Enter data for character c starting at location i in the hash table 113 ⟩ Used in sections 112* and 112*.

⟨ Globals in the outer block 7*, 10*, 12, 20*, 23, 26, 29, 30, 37, 42, 49*, 51, 54, 67, 69, 85, 87, 111, 123 ⟩

Used in section 2*. ⟨ Insert (c, r) into label table 90 ⟩ Used in section 89.

⟨ Labels in the outer block 3 ⟩ Used in section 2*. ⟨ Move font name into the cur name string 44* ⟩ Used in section 39*.

⟨ Output a kern step 98 ⟩ Used in section 96.

⟨ Output a ligature step 99 ⟩ Used in section 96. ⟨ Output an extensible character recipe 107 ⟩ Used in section 100. ⟨ Output and correct the ligature/kern program 93 ⟩ Used in section 88. ⟨ Output any labels for step i 94 ⟩ Used in section 93.

⟨ Output either  or  97 ⟩ Used in section 96.

⟨ Output step i of the ligature/kern program 96 ⟩ Used in sections 93 and 105. ⟨ Output the applicable part of the ligature/kern program as a comment 105 ⟩ Used in section 100. ⟨ Output the character coding scheme 76 ⟩ Used in section 70. ⟨ Output the character link unless there is a problem 106 ⟩ Used in section 100. ⟨ Output the character’s depth 103 ⟩ Used in section 100. ⟨ Output the character’s height 102 ⟩ Used in section 100. ⟨ Output the character’s width 101 ⟩ Used in section 100. ⟨ Output the check sum 71 ⟩ Used in section 70. ⟨ Output the design size 73 ⟩ Used in section 70. ⟨ Output the extensible pieces that exist 108 ⟩ Used in section 107. ⟨ Output the family name 77 ⟩ Used in section 70. ⟨ Output the font area and name 122 ⟩ Used in section 121. ⟨ Output the fraction part, f/2^{20}, in decimal notation 64 ⟩ Used in section 62*. ⟨ Output the integer part, a, in decimal notation 63 ⟩ Used in section 62*. ⟨ Output the italic correction 104 ⟩ Used in section 100. ⟨ Output the name of parameter i 83 ⟩ Used in section 82. ⟨ Output the rest of the header 78 ⟩ Used in section 70.

⟨ Output the seven bit safe flag 79 ⟩ Used in section 70.

⟨ Print the name of the local font 36* ⟩ Used in section 35.

§136  VFtoVP changes for C  NAMES OF THE SECTIONS 119

⟨ Read and store a character packet 46 ⟩ Used in section 33. ⟨ Read and store a font definition 35 ⟩ Used in section 33. ⟨ Read and store the font definitions and character packets 33 ⟩ Used in section 31*. ⟨ Read and verify the postamble 34 ⟩ Used in section 31*. ⟨ Read the local font’s file and record the characters it contains 39* ⟩ Used in section 35. ⟨ Read the preamble command 32 ⟩ Used in section 31*.

⟨ Read the whole file 24* ⟩ Used in section 131. ⟨ Read the whole file 31* ⟩ Used in section 131.

⟨ Reduce l by one, preserving the invariants 59 ⟩ Used in section 58. ⟨ Reduce negative to positive 65 ⟩ Used in section 62*.

⟨ Set initial values 11*, 21*, 50*, 55, 68, 86 ⟩ Used in section 2*.

⟨ Set subfile sizes lh, bc, …, np 25 ⟩ Used in section 131.

⟨ Set the true font type 75 ⟩ Used in section 70.

⟨ Take care of commenting out unreachable steps 95 ⟩ Used in section 93. ⟨ Types in the outer block 5, 22 ⟩ Used in section 2*.

The VFtoVP processor

(Version 1.2, September 1990)

Section Page

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 102 Virtual fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 103 Font metric data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 104 Unpacking the TFM file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 105 Unpacking the VF file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 106 Basic output subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 108 Outputting the TFM info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 109 Checking for ligature loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 109 Outputting the VF info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 111 The main program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 113 System-dependent changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 113 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 113

The preparation of this program was supported in part by the National Science Foundation and by the System Development Foundation. ‘TEX’ is a trademark of the American Mathematical Society.