PROCEDURE EnumPatches (p: Patch; visit: PatchProc) RAISES ANY = (* Applies "visit" to all patches reachable from "p" through any combination of "Adj"s and "Rot"s. *) CONST InitialQueueSize = 1024; VAR v: REF ARRAY OF Patch := NEW(REF ARRAY OF Patch, InitialQueueSize); nv: CARDINAL := 0; (* Invariant: The array "v[0..nv-1]" contains every patch seen. If the "mark" bit of an edge is TRUE, its patch has been seen, visited, and stored in "v". *) PROCEDURE Stack(q: Patch) = BEGIN IF nv >= NUMBER(v^) THEN WITH vNew := NEW(REF ARRAY OF Edge, 2*nv) DO SUBARRAY(vNew^, 0, nv) := v^; v := vNew END END; v[nv] := q; INC(nv) END Stack; PROCEDURE VisitAndMarkPatch (p: Patch) RAISES ANY = (* If edge "f" is unmarked, it is the first edge we have seen belonging to this patch. Puts "f" in the pile "v", and visits and marks all the edges out of "Org(c)". *) BEGIN assert visit(p); Stack(p); FOR i := 0 TO 3 DO p.edge[i].mark := TRUE END END END VisitAndMarkPatch; PROCEDURE CheckNeighbors (q: Patch) = (* Applies VisitAndMarkPatch to all patches adjacent to "p". *) BEGIN FOR i := 0 TO 3 DO WITH n = q.edge[i].adjP DO IF NOT n.edge[0].mark THEN VisitAndMarkPatch(n) END END END END CheckNeighbors; VAR ns: CARDINAL := 0; BEGIN TRY VisitandMarkPatch(p); WHILE ns < nv DO CheckNeighbors(v[ns]); INC(ns); END; FINALLY (* Erase all marks *) WHILE nv > 0 DO DEC(nv); WITH q = v[nv] DO FOR i := 0 TO 3 DO q.edge[i].mark := FALSE END END END END END EnumPatches;