§1  PK to GF changes for C  INTRODUCTION 1

2* . The banner string defined here should be changed whenever gets modified. You should update the preamble comment as well.

define banner ≡ ´ ␣ ␣ ␣ ␣ ␣ ␣´ { printed when the program starts } define preamble comment ≡ ´ ␣ ␣ ´ define comm length ≡ 17

4* . Both the input and output come from binary files. On line interaction is handled through Pascal’s standard input and output files. For C compilation terminal input and output is directed to stdin and stdout . In this program there is no terminal input. Since the terminal output is really not very interesting, it is produced only when the command line flag is presented.

define term out ≡ stdout { standard output }

define print ln(#) ≡

if verbose then write ln(term out , #)

define print (#) ≡

if verbose then write(term out , #)

program PK to GF ; const ⟨ Constants in the outer block 6* ⟩ type ⟨ Types in the outer block 33 ⟩ var ⟨ Globals in the outer block 34 ⟩ procedure initialize; { this procedure gets things started properly }

var i: integer ; { loop index for initializations }

begin set paths (PK FILE PATH BIT ); ⟨ Set initial values 45 ⟩ end;

5* . This module is deleted, because it is only useful for a non-local goto, which we don’t use in C.

6* . These constants determine the maximum length of a file name and the length of the terminal line, as well as the maximum number of run counts allowed per line of the file. (We need this to implement repeat counts.)

define name length ≡ FILENAMESIZE { from } ⟨ Constants in the outer block 6* ⟩ ≡

max counts = 400; { maximum number of run counts in a raster line }

This code is used in section 4*.

8* . It is possible that a malformed packed file (heaven forbid!) or some other error might be detected by this program. Such errors might occur in a deeply nested procedure, so the procedure called jump out has been added to transfer to the very end of the program with an error message.

define abort (#) ≡ begin verbose ← true; print ln(#); uexit (1); end

2  PACKED FILE FORMAT  PK to GF changes for C §9

25* . The final algorithm for decoding the run counts based on the above scheme might look like this, assuming a procedure called pk nyb is available to get the next nybble from the file, and assuming that the global repeat count indicates whether a row needs to be repeated. Note that this routine is recursive, but since a repeat count can never directly follow another repeat count, it can only be recursive to one level. ⟨ Packed number procedure 25* ⟩ ≡ function pk packed num: integer ;

var i, j: integer ;

begin i ← get nyb;

if i = 0 then begin repeat j ← get nyb; incr (i); until j ≠ 0; while i > 0 do

begin j ← j ∗ 16 + get nyb; decr (i);

end; pk packed num ← j − 15 + (13 − dyn f ) ∗ 16 + dyn f ; end

else if i ≤ dyn f then pk packed num ← i

else if i < 14 then pk packed num ← (i − dyn f − 1) ∗ 16 + get nyb + dyn f + 1

else begin if i = 14 then repeat count ← pk packed num else repeat count ← 1; pk packed num ← pk packed num; end;

end;

This code is used in section 62.

§33  PK to GF changes for C  INPUT AND OUTPUT 3

35* . To prepare these files for input, we reset them. An extension of Pascal is needed in the case of gf 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.

In C, we use the external test read access procedure, which also does path searching based on the user’s environment or the default path. In the course of this routine we also check the command line for the flag, and make other checks to see that it is worth running this program at all. procedure open pk file; { prepares to read packed bytes in pk file }

var j: integer ; begin verbose ← false; gf arg ← 3; if argc < 2 then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); argv (1, pk name); if pk name[1] = xchr [ ] then

begin if argc > 4 then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); if pk name[2] = xchr [ ] then

begin verbose ← true; argv (2, pk name); incr (gf arg )

end else abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); end;

print ln(banner ); if test read access (pk name, PK FILE PATH ) then

begin reset (pk file, pk name) end

else begin print pascal string (pk name); abort (´ ␣ ␣ ␣ ␣ ´ );

end; cur loc ← 0; end;

procedure open gf file; { prepares to write packed bytes in gf file } var j, k: integer ; begin if argc = gf arg then argv (argc − 1, gf name) else begin j ← name length; k ← 1;

while (j > 1) ∧ (pk name[j] ≠ xchr [ ]) do

decr (j); if (pk name[j] = xchr [ ]) then incr (j); { to avoid picking up the / } print (xchr [ ]); print (xchr [ ␣ ]); while (j < name length) ∧ (¬(pk name[j] = xchr [ ]) ∨ (pk name[j] = xchr [ ␣ ])) do

begin print (xchr [xord [pk name[j]]]); gf name[k] ← pk name[j]; incr (j); incr (k)

end; while (j < name length) ∧ ¬(pk name[j] = xchr [ ]) do

begin if pk name[j] = xchr [ ␣ ] then abort (´ ␣ ␣ ␣ ␣ ´ );

gf name[k] ← pk name[j]; print (xchr [xord [pk name[j]]]); incr (k); incr (j)

end; print (xchr [xord [pk name[j]]]); incr (j); print (xchr [xord [pk name[j]]]); print (xchr [ ␣ ]); print (xchr [ ]); print (xchr [ ]); print (xchr [ ␣ ]); gf name[k] ← xchr [ ]; incr (k); gf name[k] ← xchr [ ]; incr (k); gf name[k] ← xchr [ ␣ ]; for j ← 1 to k do print (xchr [xord [gf name[j]]]); print ln(xchr [ ]) end;

4  INPUT AND OUTPUT  PK to GF changes for C §36

rewrite(gf file, gf name); gf loc ← 0 end; 36* . We need a place to store the names of the input and output files, as well as a byte counter for the output file. And a few other things besides. ⟨ Globals in the outer block 34 ⟩ +≡ gf name, pk name: packed array [1 . . name length] of text char ;

{ names of input and output files; pascal-style origin from one }

gf loc, cur loc: integer ; { changed pk loc to cur loc } gf arg : integer ; { where command line may supply gf name } verbose: boolean;

37* . Byte output is handled by a C definition.

define gf byte(#) ≡ begin put byte(#, gf file); incr (gf loc) end 38* . We shall use a set of simple functions to read the next byte or bytes from pk file. There are seven possibilities, each of which is treated as a separate function in order to minimize the overhead for subroutine calls.

define pk byte ≡ get byte define pk loc ≡ cur loc

function get byte: integer ; { returns the next byte, unsigned } var b: eight bits ; begin if eof (pk file) then get byte ← 0 else begin read (pk 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 (pk 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 (pk file, a); read (pk 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 (pk file, a); read (pk 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 (pk file, a); read (pk file, b); read (pk 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 (pk file, a); read (pk file, b); read (pk 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 (pk file, a); read (pk file, b); read (pk file, c); read (pk 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;

40* . We put definitions here to access the functions supplied above. (signed byte is already taken care of).

define get 16 ≡ get two bytes define signed 16 ≡ signed pair define get 32 ≡ signed quad 41* . As we are writing the file, we often need to write signed and unsigned, one, two, three, and four-byte values. These routines give us that capability. procedure gf 16 (i : integer );

begin gf byte(i div 256); gf byte(i mod 256); end;

procedure gf 24 (i : integer ); begin gf byte(i div 65536); gf 16 (i mod 65536); end;

procedure gf quad (i : integer );

begin if i ≥ 0 then begin gf byte(i div 16777216); end

else begin i ← (i + 1073741824) + 1073741824; gf byte(128 + (i div 16777216));

end; gf 24 (i mod 16777216); end;

§42  PK to GF changes for C  CHARACTER UNPACKING 7

49* . Now we read and check the preamble of the file. In the preamble, we find the hppp, design size, checksum. We write the relevant parameters to the file, including the preamble comment. ⟨ Read preamble 49* ⟩ ≡

if pk byte ≠ pk pre then abort (´ ␣ ␣ ␣␣ ␣ ␣ ´ );

gf byte(pre);

if pk byte ≠ pk id then abort (´ ␣ ␣ ␣ ␣ ´ );

gf byte(gf id byte); j ← pk byte; gf byte(j); print (´ ´ );

for i ← 1 to j do begin hppp ← pk byte; gf byte(hppp); print (xchr [xord [hppp]]); end;

print ln(´ ´ ); design size ← get 32 ; checksum ← get 32 ; hppp ← get 32 ; vppp ← get 32 ; if hppp ≠ vppp then print ln(´ ␣␣ ␣ ␣ ␣ ´ ); magnification ← round (hppp ∗ 72.27 ∗ 5/65536); last eoc ← gf loc

This code is used in section 73*.

51* . ⟨ Set initial values 45 ⟩ +≡

63* . Now, the globals to help communication between these procedures, and a buffer for the raster row counts. ⟨ Globals in the outer block 34 ⟩ +≡ input byte: eight bits ; { the byte we are currently decimating } bit weight : eight bits ; { weight of the current bit } row counts : array [0 . . max counts ] of integer ; { where the row is constructed } rcp: integer ; { the row counts pointer }

8  CHARACTER UNPACKING  PK to GF changes for C §65

65* . And the main procedure. ⟨ Read and translate raster description 65* ⟩ ≡

if (c width > 0) ∧ (c height > 0) then begin bit weight ← 0; count down ← c height ∗ c width − 1; if dyn f = 14 then turn on ← get bit ; repeat count ← 0; x to go ← c width; y to go ← c height ; cur n ← c height ; count ← 0; first on ← turn on; turn on ← ¬turn on; rcp ← 0; while y to go > 0 do

begin if count = 0 then ⟨ Get next count value into count 64 ⟩; if rcp = 0 then first on ← turn on; while count ≥ x to go do

begin row counts [rcp] ← x to go; count ← count − x to go; for i ← 0 to repeat count do

begin ⟨ Output row 66 ⟩; y to go ← y to go − 1; end;

repeat count ← 0; x to go ← c width; rcp ← 0; if (count > 0) then first on ← turn on; end;

if count > 0 then begin row counts [rcp] ← count ; if rcp = 0 then first on ← turn on; rcp ← rcp + 1; if rcp > max counts then abort (´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); x to go ← x to go − count ; count ← 0; end;

end; end

This code is used in section 47.

§71  PK to GF changes for C  TERMINAL COMMUNICATION 9

71* . Terminal communication. Since this program runs entirely on command-line arguments, there is no terminal communication.

72* . The file has a dialog procedure here.

10  THE MAIN PROGRAM  PK to GF changes for C §73

73* . The main program. Now that we have all the pieces written, let us put them together. begin initialize; ⟨ Open files 39 ⟩; ⟨ Read preamble 49* ⟩; skip specials ; while flag byte ≠ pk post do

begin ⟨ Unpack and write character 47 ⟩; skip specials ; end;

while ¬eof (pk file) do i ← pk byte; ⟨ Write postamble 68 ⟩; print ln(pk loc : 1, ´ ␣ ␣ ␣ ␣´ , gf loc : 1, ´ ␣ ´ ); end.

§75  PK to GF changes for C  INDEX 11

75* . 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: 2, 4, 5, 6, 8, 25, 35, 36, 37, 38, 40, 41, 49, 51, 63, 65, 71, 72, 73, 75.

a: \underline{38*} . abort : \underline{8*} , 35* , 47, 49* , 65* , 70. argc: 35* . argv : 35* . ASCII code: \underline{42}, 44. b: \underline{38*} . backpointers: 14. banner : \underline{2*} , 35* . bit weight : 62, \underline{63*} , 65* . black : 10, 11. boc: 9, 11, \underline{12}, 13, 14, 59. boc1 : 11, \underline{12}, 59. boolean: 36* , 62, 67. byte file: \underline{33}, 34. c: \underline{38*} . c height : 52, 53, 54, \underline{55}, 56, 65* . c width: 52, 53, 54, \underline{55}, 56, 65* . car : \underline{48}, 52, 53, 54, 59, 60. cc: 27. char : 43, 50. char loc: 11, \underline{12}, 14, 61. char loc0 : \underline{11}, \underline{12}, 61. char pointer : \underline{57}, 58, 59, 60, 61. check sum: 13. checksum: 49* , \underline{50}, 68. Chinese characters: 14. chr : 43, 44, 46. comm length: \underline{2*} , 50. comment : \underline{50}. count : 64, 65* , \underline{67}. count down: 64, 65* , \underline{67}. cs : \underline{13}, 18. cur loc: 35* , \underline{36*} , 38* . cur n: 65* , 66, \underline{67}. d: \underline{38*} . decr : \underline{7}, 25* , 35* . del m: \underline{11}. del n: \underline{11}. design size: 13. design size: 49* , \underline{50}, 68. dialog : 72* . dm: \underline{11}, 27. do nothing : \underline{7}. done: 64, \underline{67}. ds : \underline{13}, 18. dx : 11, 14, 27. dy : 11, 14, 27. dyn f : 23, 24, 25* , 26, 27, 30, 31, 47, \underline{48}, 64, 65* . eight bits : \underline{33}, 38* , 62, 63* . else: 3. end: 3. end of packet : 47, \underline{48}, 52, 53, 54. endcases: \underline{3}. eoc: 9, 11, \underline{12}, 13, 47. eof : 35* , 38* , 73* . false: 35* , 64. FILENAMESIZE : 6* . first on: 65* , 66, \underline{67}. first text char : \underline{43}, 46. flag : 27. flag byte: 47, 53, 54, \underline{69}, 70, 73* . Fuchs, David Raymond: 15. get bit : \underline{62}, 64, 65* . get byte: \underline{38*} . get nyb: 25* , \underline{62}. get three bytes : \underline{38*} . get two bytes : \underline{38*} , 40* . get 16 : \underline{40*} , 53, 54. get 32 : \underline{40*} , 49* , 52, 70. gf arg : 35* , \underline{36*} . gf byte: 33, \underline{37*} , 41* , 47, 49* , 59, 61, 66, 68, 70. gf file: \underline{34}, 35* , 37* . gf id byte: \underline{11}, 49* , 68. gf loc: 35* , \underline{36*} , 37* , 47, 49* , 68, 70, 73* . gf name: 35* , \underline{36*} . gf quad : \underline{41*} , 59, 61, 68, 70. gf 16 : \underline{41*} , 66. gf 24 : \underline{41*} . height : 26. hoff : 27, 29. hor esc: 52, 53, 54, \underline{55}, 60. hppp: \underline{13}, 18, 49* , \underline{50}, 68. i: \underline{4*} , \underline{25*} , \underline{48}, \underline{70}. incr : \underline{7}, 25* , 35* , 37* , 38* . initialize: \underline{4*} , 73* . input : 4* . input byte: 62, \underline{63*} . integer : 4* , 25* , 35* , 36* , 38* , 41* , 48, 50, 55, 57,

62, 63* , 67, 69, 70. j: \underline{35*} , \underline{48}. Japanese characters: 14. jump out : 8* . Knuth, D. E.: 24. last eoc: 47, 49* , \underline{55}, 68. last text char : \underline{43}, 46. magnification: 49* , \underline{50}. max : 66, \underline{67}. max counts : \underline{6*} , 63* , 65* .

12  INDEX  PK to GF changes for C §75

max m: 11, \underline{13}, 56, \underline{57}, 59. max n: 11, \underline{13}, 56, \underline{57}, 59. max new row : \underline{12}. min m: 11, \underline{13}, 56, \underline{57}, 59. min n: 11, \underline{13}, 56, \underline{57}, 59. mmax m: 56, \underline{57}, 58, 68. mmax n: 56, \underline{57}, 58, 68. mmin m: 56, \underline{57}, 58, 68. mmin n: 56, \underline{57}, 58, 68. name length: \underline{6*} , 35* , 36* . new row 0 : 11, \underline{12}, 66. new row 1 : \underline{11}. new row 164 : \underline{11}. no op: 11, \underline{12}, 14. nop: \underline{12}. open gf file: \underline{35*} , 39. open pk file: \underline{35*} , 39. ord : 44. oriental characters: 14. othercases: \underline{3}. others : 3. output : 4* . packet length: 52, 53, 54, \underline{55}. paint switch: \underline{10}, 11. paint 0 : 11, \underline{12}, 66. paint1 : 11, \underline{12}, 66. paint2 : \underline{11}. paint3 : \underline{11}. pk byte: 33, \underline{38*} , 49* , 53, 54, 62, 70, 73* . pk file: \underline{34}, 35* , 38* , 73* . PK FILE PATH : 35* . PK FILE PATH BIT : 4* . pk id : \underline{19}, 49* . pk loc: 36* , \underline{38*} , 47, 52, 53, 54, 73* . pk name: 35* , \underline{36*} . pk no op: 18, \underline{19}. pk packed num: \underline{25*} , 62, 64. pk post : 18, \underline{19}, 70, 73* . pk pre: 18, \underline{19}, 49* . PK to GF : \underline{4*} . pk xxx1 : 18, \underline{19}. pk yyy : 18, \underline{19}. pl : 27. post : 9, 11, \underline{12}, 13, 15, 68. post post : 11, \underline{12}, 13, 15, 68. pre: 9, 11, \underline{12}, 49* . preamble comment : \underline{2*} . print : \underline{4*} , 35* , 49* . print ln: \underline{4*} , 8* , 35* , 49* , 60, 73* . print pascal string : 35* . proofing : 14. put byte: 37* . rcp: \underline{63*} , 65* , 66. read : 38* . repeat count : 25* , 65* , \underline{67}. reset : 35* . rewrite: 35* . round : 49* . row counts : \underline{63*} , 65* , 66. s hor esc: \underline{57}, 60, 61. s tfm width: \underline{57}, 60, 61. s ver esc: \underline{57}, 60, 61. scaled : 11, 13, 14, 18. set paths : 4* . signed byte: \underline{38*} , 40* , 54. signed pair : \underline{38*} , 40* . signed quad : \underline{38*} , 40* . signed trio: \underline{38*} . signed 16 : \underline{40*} , 53. skip specials : \underline{70}, 73* . skip0 : 11, \underline{12}, 66. skip1 : 11, \underline{12}, 66. skip2 : \underline{11}. skip3 : \underline{11}. stdin: 4* . stdout : 4* . system dependancies: 6* , 33. system dependencies: 15, 34, 35* , 38* , 43, 74. temp: \underline{62}. term out : \underline{4*} . test read access : 35* . text char : 36* , \underline{43}, 44. text file: \underline{43}. tfm: 27, 28, 31. tfm width: \underline{48}, 52, 53, 54, 60. this char ptr : \underline{57}, 59, 70. true: 8* , 35* , 64. turn on: 47, 64, 65* , 66, \underline{67}. uexit : 8* . undefined commands : \underline{12}. ver esc: 52, 53, 54, \underline{55}, 60. verbose: 4* , 8* , 35* , \underline{36*} . voff : 27, 29. vppp: \underline{13}, 18, 49* , \underline{50}, 68. white: 11. width: 26. word width: 52, 53, 54, \underline{55}. write: 4* . write ln: 4* . x off : \underline{48}, 52, 53, 54, 56. x to go: 65* , \underline{67}. xchr : 35* , \underline{44}, 45, 46, 49* . xord : 35* , \underline{44}, 46, 49* . xxx1 : 11, \underline{12}. xxx2 : \underline{11}. xxx3 : 11. xxx4 : \underline{11}. y off : \underline{48}, 52, 53, 54, 56. y to go: 65* , 66, \underline{67}. yyy : 11, \underline{12}, 14, 18.

14  NAMES OF THE SECTIONS  PK to GF changes for C §75

⟨ Calculate and check min m, max m, min n, and max n 56 ⟩ Used in section 47. ⟨ Constants in the outer block 6* ⟩ Used in section 4*. ⟨ Get next count value into count 64 ⟩ Used in section 65*.

⟨ Globals in the outer block 34, 36*, 44, 48, 50, 55, 57, 63*, 67, 69 ⟩ Used in section 4*. ⟨ Open files 39 ⟩ Used in section 73*. ⟨ Output row 66 ⟩ Used in section 65*.

⟨ Packed number procedure 25* ⟩ Used in section 62. ⟨ Read and translate raster description 65* ⟩ Used in section 47. ⟨ Read extended short character preamble 53 ⟩ Used in section 47. ⟨ Read long character preamble 52 ⟩ Used in section 47.

⟨ Read preamble 49* ⟩ Used in section 73*.

⟨ Read short character preamble 54 ⟩ Used in section 47. ⟨ Save character locator 60 ⟩ Used in section 47.

⟨ Set initial values 45, 46, 51*, 58 ⟩ Used in section 4*. ⟨ Types in the outer block 33, 42, 43 ⟩ Used in section 4*.

⟨ Unpack and write character 47 ⟩ Used in section 73*.

⟨ Write postamble 68 ⟩ Used in section 73*.

⟨ Write character locators 61 ⟩ Used in section 68. ⟨ Write character preamble 59 ⟩ Used in section 47.

The PKtoGF processor

(Version 1.0, 23 January 1988)

Section Page

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 Generic font file format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 2 Packed file format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2 Input and output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3 The character set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 7 Character unpacking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 7 Terminal communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 9 The main program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 10 System-dependent changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 11 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 11

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.