<> <> DIRECTORY BBAction USING [Action, NewAction, WaitForDataTaken], BBBreak USING [BreakId, BreakIdRep, BreakList, CondProc, NullIndex], BBObjectLocation USING [BreakpointHandler, ClearBreakpoint, EntryLocation, ExitLocation, Location, SetBreakpoint, TVToLocation], BBSafety USING [Mother], BBZones USING [GetQuantizedZone], Rope USING [ROPE], RTBasic USING [TV]; BBBreakImpl: CEDAR MONITOR IMPORTS BBAction, BBObjectLocation, BBSafety, BBZones EXPORTS BBBreak SHARES BBBreak = BEGIN OPEN BBBreak, BBObjectLocation, Rope, RTBasic; z: ZONE _ BBZones.GetQuantizedZone[]; LastBreakIdNumber: INT _ 0; headBreakList: BreakList _ NIL; BreakError: PUBLIC ERROR [reason: ROPE] = CODE; BreakEntry: PUBLIC PROC [proc: TV] RETURNS [index: INT] = TRUSTED { inner: PROC = TRUSTED { <> loc: Location _ EntryLocation[TVToLocation[proc]]; bid: BreakId _ AddBreakToList[loc]; bid.enabled _ bid.entry _ TRUE; index _ bid.index; }; msg: ROPE _ BBSafety.Mother[inner]; IF msg = NIL THEN RETURN; ERROR BreakError[msg]; }; BreakExit: PUBLIC PROC [proc: TV] RETURNS [index: INT] = TRUSTED { inner: PROC = TRUSTED { <> loc: Location _ ExitLocation[TVToLocation[proc]]; bid: BreakId _ AddBreakToList[loc]; bid.enabled _ bid.exit _ TRUE; index _ bid.index; }; msg: ROPE _ BBSafety.Mother[inner]; IF msg = NIL THEN RETURN; ERROR BreakError[msg]; }; ClearBreak: PUBLIC PROC [index: INT] RETURNS [BreakId] = TRUSTED { bid: BreakId _ RemBreakFromList[index]; IF bid = NIL THEN RETURN [NIL]; [] _ BBObjectLocation.ClearBreakpoint[bid.loc, bid.cid]; RETURN [bid]}; ClearAllBreaks: PUBLIC ENTRY PROC [condProc: CondProc _ NIL] = TRUSTED { ENABLE UNWIND => NULL; bl: BreakList _ headBreakList; WHILE bl # NIL DO bid: BreakId _ bl.first; bl _ bl.rest; IF condProc # bid.condProc THEN LOOP; bid.enabled _ FALSE; [] _ RemBreakFromListInternal[bid.index]; [] _ BBObjectLocation.ClearBreakpoint[bid.loc, bid.cid] ENDLOOP }; <> FindBreakLag: PUBLIC PROC [index: LONG INTEGER] RETURNS [lag: BreakList] = { lag _ NIL; FOR bl: BreakList _ headBreakList, bl.rest WHILE NOT (bl = NIL) DO IF bl.first.index >= index THEN EXIT; lag _ bl ENDLOOP}; FindBreakId: PUBLIC ENTRY PROC [index: INT] RETURNS [id: BreakId] = { ENABLE UNWIND => NULL; id _ NIL; FOR bl: BreakList _ headBreakList, bl.rest WHILE NOT (bl = NIL) DO IF bl.first.index = index THEN RETURN [bl.first] ENDLOOP}; AddBreakToList: PUBLIC ENTRY PROC [loc: BBObjectLocation.Location, condProc: CondProc _ NIL, condData: REF _ NIL] RETURNS [BreakId] = { ENABLE UNWIND => NULL; RETURN [AddBreakToListInternal[loc, condProc, condData]]}; AddBreakToListInternal: PROC [loc: BBObjectLocation.Location, condProc: CondProc _ NIL, condData: REF _ NIL] RETURNS [BreakId] = TRUSTED { bid: BreakId _ NEW[BreakIdRep _ [ loc: loc, index: 0, cid: NIL, condProc: condProc, condData: condData , entry: FALSE, exit: FALSE, enabled: TRUE]]; <> bidl: BreakList _ LIST[bid]; lag: BreakList _ FindBreakLag[LastBreakIdNumber + 1]; bid.cid _ BBObjectLocation.SetBreakpoint[loc, MyBreakHandler, bid]; IF lag = NIL THEN {bidl.rest _ headBreakList; headBreakList _ bidl} ELSE {bidl.rest _ lag.rest; lag.rest _ bidl}; LastBreakIdNumber _ bid.index _ LastBreakIdNumber + 1; RETURN [bid]}; RemBreakFromList: PUBLIC ENTRY PROC [index: INT] RETURNS [BreakId] = { ENABLE UNWIND => NULL; RETURN [RemBreakFromListInternal[index]]}; RemBreakFromListInternal: PROC [index: INT] RETURNS [bid: BreakId] = TRUSTED { bidl: BreakList _ NIL; bid _ NIL; IF headBreakList # NIL AND headBreakList.first.index = index THEN { bidl _ headBreakList; headBreakList _ headBreakList.rest} ELSE { lag: BreakList _ FindBreakLag[index]; IF lag # NIL THEN { bidl _ lag.rest; lag.rest _ IF bidl # NIL THEN bidl.rest ELSE NIL}}; IF bidl # NIL THEN { bid _ bidl.first; bid.index _ 0; FREE[@bidl]}; }; NextBreak: PUBLIC ENTRY PROC [index: INT _ NullIndex] RETURNS [INT] = { ENABLE UNWIND => NULL; FOR bl: BreakList _ headBreakList, bl.rest WHILE NOT (bl = NIL) DO bid: BreakId _ bl.first; IF index = NullIndex THEN RETURN [bid.index]; IF index = bid.index THEN index _ NullIndex; ENDLOOP; RETURN [NullIndex]; }; MyBreakHandler: BBObjectLocation.BreakpointHandler = TRUSTED { <<[event: Event, id: BreakpointId, data: REF]>> action: BBAction.Action _ NIL; bid: BreakId _ NARROW[data]; <> IF bid = NIL OR NOT bid.enabled THEN RETURN; IF bid.condProc # NIL THEN { <> IF NOT bid.condProc[bid, event.frame, bid.condData] THEN RETURN}; <> action _ BBAction.NewAction[event, break]; BBAction.WaitForDataTaken[action, bid]; }; END.