202  INTRODUCTION  TFtoPL changes for C §1

1* . Introduction. The utility program converts TEX font metric (“ ”) files into equivalent property-list (“ ”) files. It also makes a thorough check of the given file, using essentially the same algorithm as TEX. Thus if TEX complains that a 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 format using the companion program .

The first program was designed by Leo Guibas in the summer of 1978. Contributions by Frank Liang, Doug Wyatt, and Lyle Ramshaw also had a significant effect on the evolution of the present code.

Extensions for an enhanced ligature mechanism were added by the author in 1989.

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 tfm file, and the output is written on pl 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 TFtoPL;

label ⟨ Labels in the outer block 3 ⟩

const ⟨ Constants in the outer block 4 ⟩

type ⟨ Types in the outer block 18 ⟩

var ⟨ Globals in the outer block 6* ⟩

procedure initialize; { this procedure gets things started properly } begin print ln(banner ); ⟨ Set initial values 7* ⟩ end;

§6  TFtoPL changes for C  FONT METRIC DATA 203

6* . 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 6* ⟩ ≡ tfm file: packed file of 0 . . 255; tfm name: packed array [1 . . FILENAMESIZE ] of char ;

See also sections 8, 16*, 19, 22, 25, 27*, 29, 32, 45, 47, 63, 65, and 89. This code is used in section 2*.

7* . On some systems you may have to do something special to read a packed file of bytes. With C under Unix, we just open the file by name and read characters from it. ⟨ Set initial values 7* ⟩ ≡

if argc < 3 then begin print ln(´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); uexit (1); end;

argv (1, tfm name); reset (tfm file, tfm name);

See also sections 17*, 28*, 33, 46, and 64. This code is used in section 2*.

16* . 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 6* ⟩ +≡ pl file: text ; pl name: array [1 . . FILENAMESIZE ] of char ;

17* . ⟨ Set initial values 7* ⟩ +≡ argv (2, pl name); rewrite(pl file, pl name);

204  BASIC OUTPUT SUBROUTINES  TFtoPL changes for C §18

27* . In order to stick to standard Pascal, we use three strings called ASCII 04 , ASCII 10 , and ASCII 14 , in terms of which we can do the appropriate conversion of ASCII codes. Three other little strings are used to produce face codes like . ⟨ Globals in the outer block 6* ⟩ +≡ ASCII 04 , ASCII 10 , ASCII 14 : ccharpointer ; { strings for output in the user’s external character set } MBL string , RI string , RCE string : ccharpointer ; { handy string constants for face codes }

28* . ⟨ Set initial values 7* ⟩ +≡ ASCII 04 ← ´ ␣␣ #$% ´ ´ ´ ; ASCII 10 ← ´ ␣ ´ ; ASCII 14 ← ´ ␣` ␣´ ; MBL string ← ´ ␣ ´ ; RI string ← ´ ␣ ␣´ ; RCE string ← ´ ␣ ´ ;

39* . 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)], pl file); put byte(RI string [1 + s], pl file); put byte(RCE string [1 + (b div 3)], pl file); end;

end;

40* . 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 43 ⟩; ⟨ Output the integer part, a, in decimal notation 41 ⟩; ⟨ Output the fraction part, f/2^{20}, in decimal notation 42 ⟩; end;

§44  TFtoPL changes for C  CHECKING FOR LIGATURE LOOPS 205

90* . ⟨ Check for ligature cycles 90* ⟩ ≡ 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 91 ⟩; 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 91 ⟩; end;

if hash ptr = hash size then begin print ln(´ ␣ ␣ ´ ´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); goto final end ; end;

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

r ← f fn(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 (´ ␣ ␣ ␣ ␣ ␣ ´ ); goto final end ; end

This code is used in section 66.

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

ifdef (´ ´ ) function f fn(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 ← f fn(h, x, y); end;

206  CHECKING FOR LIGATURE LOOPS  TFtoPL changes for C §95

95* . Pascal’s beastly convention for forward declarations prevents us from saying function f(h, x, y : index ): index here. function f fn(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;

§101  TFtoPL changes for C  INDEX 207

end; { the value 257 will break all cycles, since it’s not in hash } end; { there are no other cases } f fn ← lig z [h]; end; 101* . 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, 6, 7, 16, 17, 27, 28, 39, 40, 90, 94, 95, 101.

a: \underline{36}, \underline{40*} . abort : \underline{20}, 21. accessible: \underline{65}, 68, 69, 70, 75. acti : \underline{65}, 71. activity : \underline{65}, 66, 67, 68, 69, 70, 71, 73, 75, 98. ai : \underline{65}, 66, 70, 75, \underline{98}. argc: 7* . argv : 7* , 17* . ASCII 04 : \underline{27*} , 28* , 35. ASCII 10 : \underline{27*} , 28* , 35, 38. ASCII 14 : \underline{27*} , 28* , 35, 38. axis height : 15. b: \underline{36}, \underline{39*} . bad : \underline{47}, 50, 52, 60, 62, 70, 74, 76, 84. : 47. bad char : \underline{47}, 84, 87. bad char tail : \underline{47}. bad design: \underline{50}, 51. banner : \underline{1*} , 2* . bc: \underline{8}, 9, 11, 13, 21, 23, 24, 47, 67, 78, 90* . bchar label : \underline{63}, 64, 69, 90* . big op spacing1 : 15. big op spacing5 : 15. boolean: 45, 96. bot : 14. both z : \underline{89}, 92, 93, 95* . boundary char : \underline{63}, 64, 69, 76, 77. byte: \underline{18}, 19, 31, 38, 52, 98. c: \underline{38}, \underline{47}, \underline{52}, \underline{98}. cc: \underline{63}, 68, 69, 72, \underline{92}, 93. ccharpointer : 27* . char : 6* , 16* . char base: \underline{22}, 23, 24. char info: 11, 22, \underline{24}, 78. char info word : 9, 11, 12. : 84. chars on line: \underline{45}, 46, 47, 78. check sum: 10. check BCPL: \underline{52}, 53, 55. check fix : \underline{60}, 62. check fix tail : \underline{60}. check sum: \underline{24}, 49, 56. class : \underline{89}, 90* , 92, 95* . coding scheme: 10. correct bad char : \underline{47}, 76, 77. correct bad char tail : \underline{47}. count : \underline{47}, 75. : 84. d: \underline{47}. decr : \underline{5}, 30, 34, 35, 37, 43, 68, 92, 94* . default rule thickness : 15. delim1 : 15. delim2 : 15. delta: \underline{40*} , 42. denom1 : 15. denom2 : 15. depth: 11, \underline{24}, 81. : 81. : 62. depth base: \underline{22}, 23, 24, 62. depth index : 11, \underline{24}, 78, 81. design size: 10. : 50. design size: \underline{24}, 51. : 51. dig : \underline{29}, 30, 31, 36, 37, 40* , 41. do characters : \underline{98}, 99. do nothing : \underline{5}, 78, 93, 95* . do simple things : \underline{97}, 99. ec: \underline{8}, 9, 11, 13, 21, 23, 24, 67, 78, 90* . endif : 94* . eof : 20. eval : \underline{94*} , 95* . eval two bytes : \underline{21}. ext tag : \underline{12}, 78. exten: 12, \underline{24}, 86. exten base: \underline{22}, 23, 24, 87. : 85. : 87. extensible recipe: 9, 14. extra space: 15. f: \underline{40*} , \underline{95*} . f fn: 90* , \underline{94*} , \underline{95*} . face: 10, 27* , 39* . false: 47, 67, 69, 96. family : \underline{24}, 55. family name: 10. FILENAMESIZE : 6* , 16* . final end : \underline{3}, 20, 90* , 96, 99. fix word : \underline{9}, 10, 15, 24, 40* , 60, 62. font identifier: 10. font type: \underline{25}, 38, 48, 53, 59, 61. forward : 95* . h: \underline{89}, \underline{94*} , \underline{95*} . hash: \underline{89}, 90* , 92, 94* , 95* . hash input : 91, \underline{92}. hash list : \underline{89}, 90* , 92. hash ptr : \underline{89}, 90* , 92.

208  INDEX  TFtoPL changes for C §101

hash size: \underline{4}, 89, 90* , 92, 94* . header : 10. height : 11, \underline{24}, 80. : 80. : 62. height base: \underline{22}, 23, 24, 62. height index : 11, \underline{24}, 78, 80. hh: \underline{89}, 90* . i: \underline{47}, \underline{97}. ifdef : 94* . : 21. incr : \underline{5}, 34, 35, 36, 37, 41, 68, 72, 75, 78, 92. index : \underline{18}, 35, 36, 39* , 40* , 47, 52, 94* , 95* , 96, 98. : 90* . initialize: \underline{2*} , 99. integer : 22, 30, 40* , 92, 94* . italic: 11, \underline{24}, 82. : 82. : 62. italic base: \underline{22}, 23, 24, 62. italic index : 11, \underline{24}, 78, 82. j: \underline{31}, \underline{36}, \underline{40*} , \underline{52}. k: \underline{35}, \underline{36}, \underline{39*} , \underline{40*} , \underline{47}, \underline{52}, \underline{98}. kern: 13, \underline{24}, 62, 76. : 76. : 62. : 76. kern base: \underline{22}, 23, 24. kern flag : \underline{13}, 74, 76, 93. key : \underline{92}, \underline{94*} . l: \underline{34}, \underline{35}, \underline{36}, \underline{52}. label ptr : \underline{63}, 64, 67, 68, 69. label table: \underline{63}, 64, 67, 68, 69, 72. left : \underline{34}, 49, 51, 54, 55, 56, 57, 58, 60, 66, 69, 72,

73, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86. left z : \underline{89}, 93, 95* . level : \underline{32}, 33, 34, 71, 73, 74, 99. lf : \underline{8}, 18, 20, 21. lh: \underline{8}, 9, 21, 23, 48, 56, 57. : 70. lig kern: 4, 12, 13. lig kern base: \underline{22}, 23, 24. lig kern command : 9, 13. lig size: \underline{4}, 21, 63, 65, 67, 98. lig step: \underline{24}, 67, 69, 70, 74, 83, 90* , 91, 93. lig tag : \underline{12}, 63, 67, 78, 90* . lig z : \underline{89}, 92, 95* . : 77. : 77. : 74. : 67, 69. list tag : \underline{12}, 78, 84. mathex : \underline{25}, 53, 59, 61. mathsy : \underline{25}, 53, 59, 61. MBL string : \underline{27*} , 28* , 39* . mid : 14. nd : \underline{8}, 9, 21, 23, 62, 81. ne: \underline{8}, 9, 21, 23, 85, 87. next char : 13. nh: \underline{8}, 9, 21, 23, 62, 80. ni : \underline{8}, 9, 21, 23, 62, 82. nk : \underline{8}, 9, 21, 23, 62, 76. nl : \underline{8}, 9, 13, 21, 23, 66, 67, 69, 70, 71, 74, 83, 90* , 91. no tag : \underline{12}, 24, 78. nonexistent : \underline{24}, 76, 77, 84, 86, 87. : 52. nonzero fix : \underline{62}. np: \underline{8}, 9, 21, 58, 59. num1 : 15. num2 : 15. num3 : 15. nw : \underline{8}, 9, 21, 23, 62, 79. odd : 77. : 21. op byte: 13. organize: \underline{96}, 99. out : \underline{26}, 30, 34, 35, 36, 38, 39* , 40* , 42, 43, 49, 50, 51, 54, 55, 56, 57, 58, 60, 61, 66, 69, 72, 73, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 90* , 99.

out BCPL: \underline{35}, 54, 55.

out char : \underline{38}, 69, 72, 76, 77, 78, 84, 86.

out digs : \underline{30}, 36, 41. out face: \underline{39*} , 56. out fix : \underline{40*} , 51, 60, 76, 79, 80, 81, 82. out ln: \underline{34}, 51, 58, 66, 73, 75, 78, 83, 85. out octal : \underline{36}, 38, 39* , 49, 56. output : 2* . param: 10, 15, \underline{24}, 60. param base: \underline{22}, 23, 24. : 60. : 52. pass through: \underline{65}, 67, 69, 71. pending : \underline{89}, 95* . perfect : \underline{45}, 46, 47, 67, 69, 99. pl file: 2* , \underline{16*} , 17* , 26, 34, 39* . pl name: \underline{16*} , 17* . print : \underline{2*} , 30, 31, 47, 67, 69, 78, 84, 90* . print digs : \underline{30}, 31. print ln: \underline{2*} , 7* , 20, 47, 50, 59, 60, 67, 69, 70,

77, 78, 84, 90* , 99. print octal : \underline{31}, 47, 67, 78, 84, 90* . put byte: 39* . quad : 15. r: \underline{47}. random word : \underline{24}, 56, 57. range error : \underline{47}, 79, 80, 81, 82, 85. RCE string : \underline{27*} , 28* , 39* . read : 20. remainder : 11, 12, 13, \underline{24}, 67, 83, 84, 85, 90* . rep: 14. reset : 7* . reset tag : \underline{24}, 67, 84, 85. rewrite: 17* . RI string : \underline{27*} , 28* , 39* . right : \underline{34}, 49, 51, 54, 55, 56, 57, 58, 60, 66, 69, 71,

72, 73, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86. right z : \underline{89}, 93, 95* . rr : \underline{63}, 64, 67, 68, 69, 72. s: \underline{39*} . scheme: \underline{24}, 53, 54. seven bit safe flag : 10, 57. : 62. simple: \underline{89}, 90* , 92, 93, 95* . skip byte: 13. slant : \underline{15}. : 90* . sort ptr : \underline{63}, 68, 71, 72, 78. space: 15. space shrink : 15. space stretch: 15. stop flag : \underline{13}, 67, 70, 74, 75, 83, 90* , 91. : 52. stuff : 9. subdrop: 15. : 21. sub1 : 15. sub2 : 15. supdrop: 15. sup1 : 15. sup2 : 15. sup3 : 15. system dependencies: 2* , 38, 100. t: \underline{92}. tag : 11, 12, \underline{24}, 63, 67, 78, 84, 90* . text : 16* . tfm: 4, 18, \underline{19}, 20, 21, 22, 24, 35, 36, 37, 38, 39* ,

40* , 47, 51, 52, 53, 57, 60, 62, 67, 69, 70, 74, 75, 76, 77, 83, 86, 87, 90* , 91, 93, 96.

tfm file: 2* , \underline{6*} , 7* , 18, 20. tfm name: \underline{6*} , 7* . tfm ptr : 20, 21, \underline{96}. tfm size: \underline{4}, 18, 19, 20. TFtoPL: \underline{2*} . : 21. : 20.

: 20. : 20. : 21. : 20. : 21. : 99. : 21. : 20. : 99. toint : 40* . top: 14. true: 46, 96. uexit : 7* . unreachable: \underline{65}, 66, 67, 73. : 59. vanilla: \underline{25}, 38, 48, 53. width: 11, \underline{24}, 62, 79. : 62. width base: \underline{22}, 23, 24, 62. width index : 11, \underline{24}, 78, 79. write: 2* , 26. write ln: 2* , 34. x: \underline{94*} , \underline{95*} . x height : 15. x lig cycle: \underline{89}, 90* , 95* . y: \underline{92}, \underline{94*} , \underline{95*} . y lig cycle: \underline{89}, 90* , 95* . zz : \underline{92}, 93.

210  NAMES OF THE SECTIONS  TFtoPL changes for C §101

⟨ Build the label table 67 ⟩ Used in section 66. ⟨ Check and output the ith parameter 60 ⟩ Used in section 58. ⟨ Check for a boundary char 69 ⟩ Used in section 66. ⟨ Check for ligature cycles 90* ⟩ Used in section 66. ⟨ Check the extensible recipes 87 ⟩ Used in section 99.

⟨ Check the fix word entries 62 ⟩ Used in section 97.

⟨ Check to see if np is complete for this font type 59 ⟩ Used in section 58. ⟨ Compute the base addresses 23 ⟩ Used in section 96. ⟨ Compute the command parameters y, cc, and zz 93 ⟩ Used in section 92.

⟨ Compute the activity array 70 ⟩ Used in section 66.

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

⟨ Do the characters 78 ⟩ Used in section 98. ⟨ Do the header 48 ⟩ Used in section 97.

⟨ Do the ligatures and kerns 66 ⟩ Used in section 99.

⟨ Do the parameters 58 ⟩ Used in section 97.

⟨ Enter data for character c starting at location i in the hash table 91 ⟩ Used in sections 90* and 90*.

⟨ Globals in the outer block 6*, 8, 16*, 19, 22, 25, 27*, 29, 32, 45, 47, 63, 65, 89 ⟩ Used in section 2*. ⟨ Insert (c, r) into label table 68 ⟩ Used in section 67.

⟨ Labels in the outer block 3 ⟩ Used in section 2*.

⟨ Output a kern step 76 ⟩ Used in section 74.

⟨ Output a ligature step 77 ⟩ Used in section 74. ⟨ Output an extensible character recipe 85 ⟩ Used in section 78. ⟨ Output and correct the ligature/kern program 71 ⟩ Used in section 66. ⟨ Output any labels for step i 72 ⟩ Used in section 71.

⟨ Output either  or  75 ⟩ Used in section 74.

⟨ Output step i of the ligature/kern program 74 ⟩ Used in sections 71 and 83. ⟨ Output the applicable part of the ligature/kern program as a comment 83 ⟩ Used in section 78. ⟨ Output the character coding scheme 54 ⟩ Used in section 48. ⟨ Output the character link unless there is a problem 84 ⟩ Used in section 78. ⟨ Output the character’s depth 81 ⟩ Used in section 78. ⟨ Output the character’s height 80 ⟩ Used in section 78. ⟨ Output the character’s width 79 ⟩ Used in section 78. ⟨ Output the check sum 49 ⟩ Used in section 48. ⟨ Output the design size 51 ⟩ Used in section 48. ⟨ Output the extensible pieces that exist 86 ⟩ Used in section 85. ⟨ Output the family name 55 ⟩ Used in section 48. ⟨ Output the fraction part, f/2^{20}, in decimal notation 42 ⟩ Used in section 40*. ⟨ Output the integer part, a, in decimal notation 41 ⟩ Used in section 40*. ⟨ Output the italic correction 82 ⟩ Used in section 78. ⟨ Output the name of parameter i 61 ⟩ Used in section 60. ⟨ Output the rest of the header 56 ⟩ Used in section 48.

⟨ Output the seven bit safe flag 57 ⟩ Used in section 48.

⟨ Read the whole input file 20 ⟩ Used in section 96. ⟨ Reduce l by one, preserving the invariants 37 ⟩ Used in section 36. ⟨ Reduce negative to positive 43 ⟩ Used in section 40*.

⟨ Set initial values 7*, 17*, 28*, 33, 46, 64 ⟩ Used in section 2*.

⟨ Set subfile sizes lh, bc, …, np 21 ⟩ Used in section 96.

⟨ Set the true font type 53 ⟩ Used in section 48.

⟨ Take care of commenting out unreachable steps 73 ⟩ Used in section 71. ⟨ Types in the outer block 18 ⟩ Used in section 2*.

The TFtoPL processor

(Version 3.1, November 1989)

Section Page

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 202 Font metric data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 203 Unpacked representation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 204 Basic output subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 204 Doing it . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 205 Checking for ligature loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 205 The main program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 207 System-dependent changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 207 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 207

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.