§203  TEX82  PART 14: COPYING BOXES 71

203. Copying boxes. Another recursive operation that acts on boxes is sometimes needed: The procedure copy node list returns a pointer to another node list that has the same structure and meaning as the original. Note that since glue specifications and token lists have reference counts, we need not make copies of them. Reference counts can never get too large to fit in a halfword, since each pointer to a node is in a different memory address, and the total number of memory addresses fits in a halfword.

(Well, there actually are also references from outside mem; if the save stack is made arbitrarily large, it would theoretically be possible to break TEX by overflowing a reference count. But who would want to do that?)

define add token ref (#) ≡ incr (token ref count (#)) { new reference to a token list }

define add glue ref (#) ≡ incr (glue ref count (#)) { new reference to a glue spec }

204. The copying procedure copies words en masse without bothering to look at their individual fields. If the node format changes—for example, if the size is altered, or if some link field is moved to another relative position—then this code may need to be changed too. function copy node list (p : pointer ): pointer ;

{ makes a duplicate of the node list that starts at p and returns a pointer to the new list } var h: pointer ; { temporary head of copied list }

q: pointer ; { previous position in new list }

r: pointer ; { current node being fabricated for new list } words : 0 . . 5; { number of words remaining to be copied }

begin h ← get avail ; q ← h;

while p ≠ null do begin ⟨ Make a copy of node p in node r 205 ⟩; link (q) ← r; q ← r; p ← link (p); end;

link (q) ← null ; q ← link (h); free avail (h); copy node list ← q;

end;

205. ⟨ Make a copy of node p in node r 205 ⟩ ≡ words ← 1; { this setting occurs in more branches than any other } if is char node(p) then r ← get avail else ⟨ Case statement to copy different types and set words to the number of initial words not yet

copied 206 ⟩; while words > 0 do

begin decr (words ); mem[r + words ] ← mem[p + words ]; end

This code is used in section 204.

72  PART 14: COPYING BOXES  TEX82 §206

206. ⟨ Case statement to copy different types and set words to the number of initial words not yet

copied 206 ⟩ ≡ case type(p) of hlist node, vlist node, unset node: begin r ← get node(box node size); mem[r + 6] ← mem[p + 6];

mem[r + 5] ← mem[p + 5]; { copy the last two words } list ptr (r) ← copy node list (list ptr (p)); { this affects mem[r + 5] } words ← 5; end;

rule node: begin r ← get node(rule node size); words ← rule node size;

end; ins node: begin r ← get node(ins node size); mem[r + 4] ← mem[p + 4]; add glue ref (split top ptr (p));

ins ptr (r) ← copy node list (ins ptr (p)); { this affects mem[r + 4] } words ← ins node size − 1; end;

whatsit node: ⟨ Make a partial copy of the whatsit node p and make r point to it; set words to the

number of initial words not yet copied 1357 ⟩; glue node: begin r ← get node(small node size); add glue ref (glue ptr (p)); glue ptr (r) ← glue ptr (p);

leader ptr (r) ← copy node list (leader ptr (p)); end;

kern node, math node, penalty node: begin r ← get node(small node size); words ← small node size;

end; ligature node: begin r ← get node(small node size); mem[lig char (r)] ← mem[lig char (p)];

{ copy font and character } lig ptr (r) ← copy node list (lig ptr (p)); end;

disc node: begin r ← get node(small node size); pre break (r) ← copy node list (pre break (p)); post break (r) ← copy node list (post break (p)); end;

mark node: begin r ← get node(small node size); add token ref (mark ptr (p)); words ← small node size; end;

adjust node: begin r ← get node(small node size); adjust ptr (r) ← copy node list (adjust ptr (p));

end; { words = 1 = small node size − 1 } othercases confusion( ) endcases

This code is used in section 205.