2  INTRODUCTION  MWEAVE §1

1* . Introduction. This program converts a file to a TEX file. It was written by D. E. Knuth in October, 1981; a somewhat similar SAIL program had been developed in March, 1979, although the earlier program used a top-down parsing method that is quite different from the present scheme.

The code uses a few features of the local Pascal compiler that may need to be changed in other installations:

1) Case statements have a default.

2) Input-output routines may need to be adapted for use with a particular character set and/or for printing messages on the user’s terminal.

These features are also present in the Pascal version of TEX, where they are used in a similar (but more complex) way. System-dependent portions of can be identified by looking at the entries for ‘system dependencies’ in the index below.

The “banner line” defined here should be changed whenever is modified.

For the Modula-2 versions of , we add a second decimal point and number to the main version number, so we can differentiate between changes to the standard and changes local to .

define banner ≡ ´ ␣ ␣ ␣ ␣ ␣ ␣ ´

§42  MWEAVE  INTRODUCTION 3

42* . Several types of identifiers are distinguished by their ilk :

normal identifiers are part of the Pascal program and will appear in italic type. roman identifiers are index entries that appear after in the file. wildcard identifiers are index entries that appear after in the file. typewriter identifiers are index entries that appear after in the file. array like, begin like, …, var like identifiers are Pascal reserved words whose ilk explains how they are

to be treated when Pascal code is being formatted. Finally, if c is an ASCII code, an ilk equal to char like + c denotes a reserved word that will be converted

4  INITIALIZING THE TABLE OF RESERVED WORDS  MWEAVE §63

to character c. define normal = 0 { ordinary identifiers have normal ilk } define roman = 1 { normal index entries have roman ilk } define wildcard = 2 { user-formatted index entries have wildcard ilk } define typewriter = 3 { ‘typewriter type’ entries have typewriter ilk } define reserved (#) ≡ (ilk [#] > typewriter ) { tells if a name is a reserved word } define array like = 4 { array, file, set } define begin like = 5 { begin } define case like = 6 { case } define const like = 7 { const, label, type } define div like = 8 { div, mod } define do like = 9 { do, then } define else like = 10 { else } define end like = 11 { end } define for like = 12 { for, if, while, with } define goto like = 13 { implementation, definition, packed } define if like = 14 { not used for — see for like } define in like = 15 { in } define nil like = 16 { nil } define proc like = 17 { procedure, module } define record like = 18 { record } define repeat like = 19 { repeat } define to like = 20 { to } define until like = 21 { until, end } define var like = 22 { var } define loop like = 23 { loop } define elsif like = 24 { elsif } define of like = 25 { of } define char like = 26 { and, or, not, in } 63* . Initializing the table of reserved words. We have to get Modula-2’s reserved words into the hash table, and the simplest way to do this is to insert them every time is run. A few macros permit us to do the initialization with a compact program.

define sid14 (#) ≡ buffer [14] ← #; cur name ← id lookup define sid13 (#) ≡ buffer [13] ← #; sid14 define sid12 (#) ≡ buffer [12] ← #; sid13 define sid11 (#) ≡ buffer [11] ← #; sid12 define sid10 (#) ≡ buffer [10] ← #; sid11 define sid9 (#) ≡ buffer [9] ← #; sid10 define sid8 (#) ≡ buffer [8] ← #; sid9 define sid7 (#) ≡ buffer [7] ← #; sid8 define sid6 (#) ≡ buffer [6] ← #; sid7 define sid5 (#) ≡ buffer [5] ← #; sid6 define sid4 (#) ≡ buffer [4] ← #; sid5 define sid3 (#) ≡ buffer [3] ← #; sid4 define sid2 (#) ≡ buffer [2] ← #; sid3 define sid1 (#) ≡ buffer [1] ← #; sid2 define id2 ≡ id first ← 13; sid13 define id3 ≡ id first ← 12; sid12 define id4 ≡ id first ← 11; sid11 define id5 ≡ id first ← 10; sid10 define id6 ≡ id first ← 9; sid9 define id7 ≡ id first ← 8; sid8 define id8 ≡ id first ← 7; sid7 define id9 ≡ id first ← 6; sid6 define id10 ≡ id first ← 5; sid5 define id11 ≡ id first ← 4; sid4 define id12 ≡ id first ← 3; sid3 define id13 ≡ id first ← 2; sid2 define id14 ≡ id first ← 1; sid1

§64  MWEAVE  INITIALIZING THE TABLE OF RESERVED WORDS 5

⟨ Globals in the outer block 9 ⟩ +≡ cur name: name pointer ; { points to the identifier just inserted } 64* . The intended use of the macros above might not be immediately obvious, but the riddle is answered by the following: ⟨ Store all the reserved words 64* ⟩ ≡

id loc ← 15; id3 ( )( )( )(char like + and sign); id5 ( )( )( )( )( )(array like); id5 ( )( )( )( )( )(begin like); id2 ( )( )(to like); id4 ( )( )( )( )(case like); id5 ( )( )( )( )( )(const like); id3 ( )( )( )(div like); id2 ( )( )(do like); id10 ( )( )( )( )( )( )( )( )( )( )(goto like); id4 ( )( )( )( )(else like); id5 ( )( )( )( )( )(elsif like); id3 ( )( )( )(end like); id4 ( )( )( )( )(goto like); id6 ( )( )( )( )( )( )(goto like); id3 ( )( )( )(for like); id4 ( )( )( )( )(goto like); id2 ( )( )(for like); id14 ( )( )( )( )( )( )( )( )( )( )( )( )( )( )(goto like); id6 ( )( )( )( )( )( )(goto like); id2 ( )( )(char like + set element sign); id5 ( )( )( )( )( )(const like); id4 ( )( )( )( )(loop like); id6 ( )( )( )( )( )( )(proc like); id3 ( )( )( )(div like); id3 ( )( )( )(nil like); id3 ( )( )( )(char like + not sign); id2 ( )( )(of like); id2 ( )( )(char like + or sign); id7 ( )( )( )( )( )( )( )(goto like); id9 ( )( )( )( )( )( )( )( )( )(proc like); id9 ( )( )( )( )( )( )( )( )( )(goto like); id6 ( )( )( )( )( )( )(record like); id6 ( )( )( )( )( )( )(repeat like); id6 ( )( )( )( )( )( )(goto like); id3 ( )( )( )(array like); id4 ( )( )( )( )(do like); id2 ( )( )(to like); id4 ( )( )( )( )(const like); id5 ( )( )( )( )( )(until like); id3 ( )( )( )(var like); id5 ( )( )( )( )( )(for like); id4 ( )( )( )( )(for like);

This code is used in section 261.

86* . Control codes in , which begin with ‘ ’, are converted into a numeric code designed to simplify ’s logic; for example, larger numbers are given to the control codes that denote more significant milestones, and the code of new module should be the largest of all. Some of these numeric control codes take the place of ASCII control codes that will not otherwise appear in the output of the scanning routines.

define ignore = 0 { control code of no interest to } define verbatim = ´ 2 { extended ASCII alpha will not appear } define force line = ´ 3 { extended ASCII beta will not appear } define vertical bar = 15 { control code for vertical bar character } define begin regular comment = 16 { control code for beginning of comments } define end regular comment = 17 { control code for ending of comments } define begin comment = ´ 11 { ASCII tab mark will not appear } define end comment = ´ 12 { ASCII line feed will not appear } define octal = ´ 14 { ASCII form feed will not appear } define hex = ´ 15 { ASCII carriage return will not appear } define double dot = ´ 40 { ASCII space will not appear except in strings } define no underline = ´ 175 { this code will be intercepted without confusion } define underline = ´ 176 { this code will be intercepted without confusion } define param = ´ 177 { ASCII delete will not appear } define xref roman = ´ 203 { control code for ‘ ’ } define xref wildcard = ´ 204 { control code for ‘ ’ } define xref typewriter = ´ 205 { control code for ‘ ’ } define TeX string = ´ 206 { control code for ‘ ’ } define check sum = ´ 207 { control code for ‘ $’ } define join = ´ 210 { control code for ‘ ’ } define thin space = ´ 211 { control code for ‘ ’ } define math break = ´ 212 { control code for ‘ ’ } define line break = ´ 213 { control code for ‘ ’ } define big line break = ´ 214 { control code for ‘ #’ } define no line break = ´ 215 { control code for ‘ ’ } define pseudo semi = ´ 216 { control code for ‘ ’ } define format = ´ 217 { control code for ‘ ’ } define definition = ´ 220 { control code for ‘ ’ } define begin Pascal = ´ 221 { control code for ‘ ’ } define module name = ´ 222 { control code for ‘ ’ } define new module = ´ 223 { control code for ‘ ␣’ and ‘ ’ } 92* . ⟨ Do special things when c = , , , ; goto done at end 92* ⟩ ≡

if c = then begin c ← buffer [loc]; if (c ≠ ␣ ) ∧ (c ≠ tab mark ) ∧ (c ≠ ) then incr (loc) else begin decr (loc); bal ← 0; goto done;

end { an error message will occur in phase two } end

else if (c = ) ∧ (buffer [loc] ≠ ) then incr (loc)

else if c = begin regular comment then incr (bal )

else if c = end regular comment then begin decr (bal ); if bal = 0 then goto done; end

else if (c = ) ∧ (buffer [loc] = ) then begin incr (bal ); incr (loc); end

else if (c = ) ∧ (buffer [loc] = ) then begin decr (bal ); incr (loc); c ← end regular comment ; if bal = 0 then goto done; end

This code is used in section 91.

97* . Note that the following code converts ‘ ’ and ‘ ’ to internal characters which are converted back to ASCII when output. Adjacent vertical bar characters (´ ´ ), which represent the Modula-2 usage of that character rather than that of WEB, are handled the same way.

define compress (#) ≡

begin if loc ≤ limit then begin c ← #; incr (loc); end; end

⟨ Compress two-symbol combinations like ‘ ’ 97* ⟩ ≡ : if buffer [loc] = then compress (double dot )

else if buffer [loc] = then compress ( ); : if buffer [loc] = then compress (left arrow ); : if buffer [loc] = then compress (equivalence sign); : if buffer [loc] = then compress (greater or equal ); : if buffer [loc] = then compress (less or equal )

else if buffer [loc] = then compress (not equal ); : if buffer [loc] = then compress (begin regular comment )

else if buffer [loc] = then compress ( ); : if buffer [loc] = then compress (end regular comment ); : if buffer [loc] = then compress (vertical bar );

This code is used in section 95.

111* . The Pascal xref subroutine stores references to identifiers in Pascal text material beginning with the current value of next control and continuing until next control is ‘ ’ or ‘ ’, or until the next “milestone” is passed (i.e., next control ≥ format ). If next control ≥ format when Pascal xref is called, nothing will happen; but if next control = upon entry, the procedure assumes that this is the ‘ ’ preceding Pascal text that is to be processed.

The program uses the fact that our internal code numbers satisfy the relations xref roman = identifier + roman and xref wildcard = identifier +wildcard and xref typewriter = identifier +typewriter and normal = 0. An implied ‘ ’ is inserted after function, procedure, program, and var. procedure Pascal xref ; { makes cross references for Pascal identifiers }

label exit ;

var p: name pointer ; { a referenced name }

begin while next control < format do

begin if (next control ≥ identifier ) ∧ (next control ≤ xref typewriter ) then begin p ← id lookup(next control − identifier ); new xref (p); if (ilk [p] = proc like) ∨ (ilk [p] = var like) then xref switch ← def flag ; { implied ‘ ’ } end;

next control ← get next ;

if (next control = ) ∨ (next control = begin regular comment ) then return; end;

exit : end;

112* . The outer xref subroutine is like Pascal xref but it begins with next control ≠ and ends with next control ≥ format . Thus, it handles Pascal text with embedded comments. procedure outer xref ; { extension of Pascal xref }

var bal : eight bits ; { brace level in comment }

begin while next control < format do if next control ≠ begin regular comment then Pascal xref else begin bal ← skip comment (1); next control ← ;

while bal > 0 do begin Pascal xref ; if next control = then bal ← skip comment (bal ) else bal ← 0; { an error will be reported in phase two } end; end;

end;

124* . In particular, the finish line procedure is called near the very beginning of phase two. We initialize the output variables in a slightly tricky way so that the first line of the output file will be ‘ ’. ⟨ Set initial values 10 ⟩ +≡

out ptr ← 1; out line ← 1; out buf [1] ← ; write(tex file, ´ ␣ ´ ); 136* . The copy comment uses and returns a brace-balance value, following the conventions of skip comment above. Instead of copying the TEX material into the output buffer, this procedure copies it into the token memory. The abbreviation app tok (t) is used to append token t to the current token list, and it also makes sure that it is possible to append at least one further token without overflow.

define app tok (#) ≡ begin if tok ptr + 2 > max toks then overflow (´ ´ ); tok mem[tok ptr ] ← #; incr (tok ptr ); end

function copy comment (bal : eight bits ): eight bits ; { copies TEX code in comments } label done; var c: ASCII code; { current character being copied }

begin loop

begin if loc > limit then begin get line;

if input has ended then

begin err print (´ ␣ ␣ ␣ ␣ ´ ); loc ← 1; ⟨ Clear bal and goto done 138* ⟩; end;

end; c ← buffer [loc]; incr (loc); if c = then goto done; if (c = ) ∧ (buffer [loc] = ) then

begin incr (loc); c ← end regular comment ; app tok ( ); end

else begin app tok (c);

end; ⟨ Copy special things when c = , , , ; goto done at end 137* ⟩; end;

done: copy comment ← bal ; end;

137* . ⟨ Copy special things when c = , , , ; goto done at end 137* ⟩ ≡

if c = then begin incr (loc); if buffer [loc − 1] ≠ then

begin err print (´ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); loc ← loc − 2; decr (tok ptr ); ⟨ Clear bal and goto done 138* ⟩; end;

end else if (c = ) ∧ (buffer [loc] ≠ ) then

begin app tok (buffer [loc]); incr (loc); end

else if c = begin regular comment then incr (bal )

else if c = end regular comment then begin decr (bal ); if bal = 0 then goto done; end

else if (c = ) ∧ (buffer [loc] = ) then begin incr (bal ); incr (loc); end

This code is used in section 136*.

138* . When the comment has terminated abruptly due to an error, we output enough right braces to keep TEX happy. ⟨ Clear bal and goto done 138* ⟩ ≡

app tok ( ␣ ); { this is done in case the previous character was ‘ ’ } repeat app tok (end regular comment ); decr (bal ); until bal = 0; goto done;

This code is used in sections 136* and 137*.

§183  MWEAVE  INITIALIZING THE SCRAPS 11

183* . Initializing the scraps. If we are going to use the powerful production mechanism just developed, we must get the scraps set up in the first place, given a Pascal text. A table of the initial scraps corresponding to Pascal tokens appeared above in the section on parsing; our goal now is to implement that table. We shall do this by implementing a subroutine called Pascal parse that is analogous to the Pascal xref routine used during phase one.

Like Pascal xref , the Pascal parse procedure starts with the current value of next control and it uses the operation next control ← get next repeatedly to read Pascal text until encountering the next ‘ ’ or ‘ ’, or until next control ≥ format . The scraps corresponding to what it reads are appended into the cat and trans arrays, and scrap ptr is advanced.

Like prod , this procedure has to split into pieces so that each part is short enough to be handled by Pascal compilers that discriminate against long subroutines. This time there are two split-off routines, called easy cases and sub cases .

After studying Pascal parse, we will look at the sub-procedures app comment , app octal , and app hex that are used in some of its branches.

⟨ Declaration of the app comment procedure 195 ⟩

⟨ Declaration of the app octal and app hex procedures 196 ⟩

⟨ Declaration of the easy cases procedure 186* ⟩

⟨ Declaration of the sub cases procedure 192* ⟩ procedure Pascal parse; { creates scraps from Pascal tokens }

label reswitch, exit ;

var j: 0 . . long buf size; { index into buffer }

p: name pointer ; { identifier designator } begin while next control < format do

begin ⟨ Append the scrap appropriate to next control 185 ⟩;

next control ← get next ;

if (next control = ) ∨ (next control = begin regular comment ) then return; end;

12  INITIALIZING THE SCRAPS  MWEAVE §186

exit : end; 186* . The easy cases each result in straightforward scraps. ⟨ Declaration of the easy cases procedure 186* ⟩ ≡ procedure easy cases ; { a subprocedure of Pascal parse }

begin case next control of

set element sign: sc3 ( )( )( )(math); double dot : sc3 ( )( )( )(math); $ , % , , : sc2 ( )(next control )(math); # : if in def part then

begin pound found ← true; sc2 ( )( # )(math); end

else sc2 ( )( )(math); : sc2 ( )( )(math); : sc2 ( )( )(math); ignore, xref roman, xref wildcard , xref typewriter : do nothing ; , : sc1 (next control )(open); , : sc1 (next control )(close); : sc4 ( )( )( )( )(math); : sc3 ( )(opt )( )(math); , , , , , , , , , , : sc1 (next control )(simp); : sc1 ( )(semi ); : sc2 ( )( )(open); : sc2 ( )( )(close); , vertical bar : sc4 ( )( )( )(force)(semi ); : sc1 ( )(colon); ⟨ Cases involving nonstandard ASCII characters 188* ⟩ exponent : sc3 ( )( )( )(exp); begin comment : sc2 ( )( )(math); end comment : sc2 ( )( )(math); octal : app octal ; hex : app hex ; check sum: sc2 ( )( )(simp); force line: sc2 ( )( )(simp); thin space: sc2 ( )( )(math); math break : sc2 (opt )( )(simp); line break : comment scrap(force); big line break : comment scrap(big force); no line break : begin app(big cancel ); app( ); app( ␣ ); comment scrap(big cancel );

end; pseudo semi : sc0 (semi ); join: sc2 ( )( )(math); othercases sc1 (next control )(math) endcases; end;

This code is used in section 183*.

188* . Some nonstandard ASCII characters may have entered by means of standard ones. They are converted to TEX control sequences so that it is possible to keep from stepping beyond standard ASCII. ⟨ Cases involving nonstandard ASCII characters 188* ⟩ ≡ not equal : sc2 ( )( )(math); less or equal : sc2 ( )( )(math); greater or equal : sc2 ( )( )(math); equivalence sign: begin sc2 ( )( )(math);

if ¬pound found then in def part ← false; end;

and sign: sc2 ( )( )(math); or sign: sc2 ( )( )(math); not sign: sc2 ( )( )(math); left arrow : sc2 ( )( )(math);

This code is used in section 186*.

191* . ⟨ Append an identifier scrap 191* ⟩ ≡ begin p ← id lookup(normal ); case ilk [p] of normal , array like, const like, div like, of like, for like, goto like, nil like, to like: sub cases (p); ⟨ Cases that generate more than one scrap 193* ⟩ othercases begin next control ← ilk [p] − char like; goto reswitch;

end { and, in, not, or } endcases; end

This code is used in section 185.

192* . The sub cases also result in straightforward scraps. ⟨ Declaration of the sub cases procedure 192* ⟩ ≡ procedure sub cases (p : name pointer ); { a subprocedure of Pascal parse }

begin case ilk [p] of normal : sc1 (id flag + p)(simp); { not a reserved word } array like: sc1 (res flag + p)(alpha); { array, file, set } const like: sc3 (force)(backup)(res flag + p)(intro); { const, label, type } div like: sc3 (math bin)(res flag + p)( )(math); { div, mod } for like: sc2 (force)(res flag + p)(alpha); { for, if, while, with } goto like: sc1 (res flag + p)(intro); { packed } nil like: sc1 (res flag + p)(simp); { nil } of like: sc1 (res flag + p)(omega); { of } to like: sc3 (math rel )(res flag + p)( )(math); { to } end; end;

This code is used in section 183*.

193* . ⟨ Cases that generate more than one scrap 193* ⟩ ≡ begin like: begin sc4 (force)(backup)(res flag + p)(force)(beginning ); sc0 (intro);

end; { begin } case like: begin sc0 (casey ); sc2 (force)(res flag + p)(alpha);

end; { case } do like: begin sc2 (res flag + p)(force)(omega); sc0 (beginning ); sc0 (intro);

end; { do, then } elsif like: begin ⟨ Append terminator if not already present 194 ⟩;

sc0 (close); sc0 (terminator ); sc1 (res flag + p)(alpha); end;

else like: begin sc4 (force)(backup)(res flag + p)(force)(terminator );

end; { else } end like: begin ⟨ Append terminator if not already present 194 ⟩;

sc4 (force)(backup)(res flag + p)(break space)(close); end; { end }

loop like: begin sc1 (force)(alpha); sc2 (res flag + p)(force)(omega); sc0 (beginning ); sc0 (intro);

end; { loop } proc like: begin sc4 (force)(backup)(res flag + p)(cancel )(proc); sc3 (indent )( )( ␣ )(intro);

end; { function, procedure, program } record like: begin sc1 (res flag + p)(alpha); sc0 (omega); sc0 (beginning );

end; { record } repeat like: begin sc4 (force)(indent )(res flag + p)(force)(beginning ); sc0 (intro);

end; { repeat } until like: begin ⟨ Append terminator if not already present 194 ⟩;

sc3 (force)(backup)(res flag + p)(close); sc0 (clause); end; { until }

var like: begin sc4 (force)(backup)(res flag + p)(cancel )(var head ); sc0 (intro);

end; { var }

This code is used in section 191*.

198* . The outer parse routine is to Pascal parse as outer xref is to Pascal xref : It constructs a sequence of scraps for Pascal text until next control ≥ format . Thus, it takes care of embedded comments. procedure outer parse; { makes scraps from Pascal tokens and comments }

var bal : eight bits ; { brace level in comment }

p, q: text pointer ; { partial comments } begin while next control < format do

if next control ≠ begin regular comment then Pascal parse

else begin ⟨ Make sure that there is room for at least seven more tokens, three more texts, and one

more scrap 199 ⟩; app( ); app( ); app( ); bal ← copy comment (1); next control ← ignore; while bal > 0 do

begin p ← text ptr ; freeze text ; q ← Pascal translate; { at this point we have tok ptr + 6 ≤ max toks }

app(tok flag + p); app(inner tok flag + q);

if next control = then begin next control ← ignore; bal ← copy comment (bal ); end

else bal ← 0; { an error has been reported }

end; app(force); app comment ; { the full comment becomes a scrap } end;

end; 207* . The real work associated with token output is done by make output . This procedure appends an end translation token to the current token list, and then it repeatedly calls get output and feeds characters to the output buffer until reaching the end translation sentinel. It is possible for make output to be called recursively, since a module name may include embedded Pascal text; however, the depth of recursion never exceeds one level, since module names cannot be inside of module names.

A procedure called output Pascal does the scanning, translation, and output of Pascal text within ‘ … ’ brackets, and this procedure uses make output to output the current token list. Thus, the recursive call of make output actually occurs when make output calls output Pascal while outputting the name of a module. procedure make output ; forward ; procedure output Pascal ; { outputs the current token list }

var save tok ptr , save text ptr , save next control : sixteen bits ; { values to be restored }

p: text pointer ; { translation of the Pascal text } begin save tok ptr ← tok ptr ; save text ptr ← text ptr ; save next control ← next control ; next control ← ignore; p ← Pascal translate; app(p + inner tok flag ); make output ; { output the list } stat if text ptr > max txt ptr then max txt ptr ← text ptr ; if tok ptr > max tok ptr then max tok ptr ← tok ptr ; tats text ptr ← save text ptr ; tok ptr ← save tok ptr ; { forget the tokens } next control ← save next control ; { restore next control to original state } end;

222* . In the TEX part of a module, we simply copy the source text, except that index entries are not copied and Pascal text within … is translated. ⟨ Translate the TEX part of the current module 222* ⟩ ≡

in def part ← false; repeat next control ← copy TeX ;

case next control of

: begin next control ← ignore; init stack ; output Pascal ;

end; : out ( ); octal : ⟨ Translate an octal constant appearing in TEX text 223 ⟩; hex : ⟨ Translate a hexadecimal constant appearing in TEX text 224 ⟩; TeX string , xref roman, xref wildcard , xref typewriter , module name: begin loc ← loc − 2;

next control ← get next ; { skip to }

if next control = TeX string then err print (´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); end;

begin comment , end comment , check sum, thin space, math break , line break , big line break ,

no line break , join, pseudo semi : err print (´ ␣ ␣ ´ ´ ␣ ␣ ␣ ␣ ␣ ´ );

othercases do nothing

endcases; until next control ≥ format

This code is used in section 220.

227* . ⟨ Start a macro definition 227* ⟩ ≡ begin sc2 ( )( )(intro); { this will produce ‘define ’ } in def part ← true; pound found ← false; next control ← get next ; if next control ≠ identifier then err print (´ ␣ ␣ ␣ ´ ) else sc1 (id flag + id lookup(normal ))(math); next control ← get next ; end

This code is used in section 225.

229* . Finally, when the TEX and definition parts have been treated, we have next control ≥ begin Pascal . We will make the global variable this module point to the current module name, if it has a name. ⟨ Globals in the outer block 9 ⟩ +≡ this module: name pointer ; { the current module name, or zero } in def part , pound found : boolean; { flags to determine context of use of pound sign and vertical bar }

230* . ⟨ Translate the Pascal part of the current module 230* ⟩ ≡ this module ← 0; in def part ← false; if next control ≤ module name then

begin emit space if needed ; init stack ;

if next control = begin Pascal then next control ← get next

else begin this module ← cur module; ⟨ Check that = or ≡ follows this module name, and emit the

scraps to start the module definition 231 ⟩; end;

while next control ≤ module name do begin outer parse; ⟨ Emit the scrap for a module name if present 232 ⟩; end; finish Pascal ; end

This code is used in section 220.

§265  MWEAVE  INDEX 17

265* . Index. If you have read and understood the code for Phase III above, you know what is in this index and how it got here. All modules in which an identifier is used are listed with that identifier, except that reserved words are indexed only when they appear in format definitions, and the appearances of identifiers in module names are not indexed. Underlined entries correspond to where the identifier was declared. Error messages, control sequences put into the output, and a few other things like “recursion” are indexed here too.

The following sections were changed by the change file: 1, 42, 63, 64, 86, 92, 97, 111, 112, 124, 136, 137, 138, 183, 186, 188, 191, 192, 193, 198, 207, 222, 227, 229, 230, 265.