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 { 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. JBBBreakImpl.mesa Russ Atkinson, March 28, 1983 2:50 pm get the entry location get the exit location utility routines for breakpoint stuff set the new breakpoint [event: Event, id: BreakpointId, data: REF] first check for cases we may wish to handle quickly handle conditional breaks sigh, we must notify our normal handler Êû˜Jšœ™Jšœ%™%J˜šÏk ˜ šœ ˜J˜&—šœ˜ J˜6—šœ˜J˜i—šœ ˜J˜ —šœ˜ J˜—šœ˜ Jšœœ˜—Jšœœœ˜J˜—šœ œ˜Jšœ.˜5Jšœ˜Jšœ˜Jšœœœ*˜6J˜Jšœœ˜%J˜Jšœœ˜Jšœœ˜J˜Jš œ œœ œœ˜0J˜šÏn œœ˜Jš œœœ œœ˜+šœœœ˜Jšœ™J˜2J˜#Jšœœ˜J˜J˜—Jšœœ˜#Jšœœœœ˜Jšœ˜J˜J˜—šž œœ˜Jš œœœ œœ˜+šœœœ˜Jšœ™J˜1J˜#Jšœœ˜J˜J˜—Jšœœ˜#Jšœœœœ˜Jšœ˜J˜J˜—š ž œœœ œœ œ˜BJ˜'Jš œœœœœ˜ J˜8Jšœ ˜J˜—š žœœœœœœ˜HJšœœœ˜J˜šœœ˜J˜J˜ Jšœœœ˜&Jšœœ˜J˜*J˜7Jš˜—šœ˜J˜——Jšœ%™%J˜š ž œœœ œœœ˜LJšœœ˜ š œ(œœœ˜BJšœœœ˜&J˜Jšœ˜ J˜——š ž œœœœ œœ˜EJšœœœ˜Jšœœ˜ š œ(œœœ˜BJšœœœ ˜0Jšœ˜ J˜——šžœœœ˜!Jšœ6œ œœ˜OJšœ˜Jšœœœ˜Jšœ4˜:J˜—šžœ˜Jšœ6œ œœ˜OJšœ œ˜˜šœ˜Jšœ ˜ J˜ Jšœœ˜ J˜J˜Jšœœ˜Jšœœ˜ Jšœ œ˜——Jšœ™Jšœœ˜J˜5J˜Dšœœ˜ Jšœ3˜7Jšœ*˜.—J˜7Jšœ ˜J˜—š žœœœœ œœ˜FJšœœœ˜Jšœ$˜*J˜—š žœœ œœœ˜NJšœœ˜Jšœœ˜ šœœœ#˜=šœ˜Jšœ˜J˜$—šœ˜Jšœ&˜&šœœœ˜Jšœ˜Jš œ œœœ œœ˜4———šœœœ˜Jšœ˜J˜Jšœ ˜ —šœ˜J˜——šž œœœ˜Jšœœœœ˜*Jšœœœ˜š œ(œœœ˜BJ˜Jšœœœ ˜-Jšœœ˜,Jšœ˜—Jšœ ˜J˜J˜—šœ5œ˜>Jšœ+™+Jšœœ˜Jšœœ˜J˜Jšœ3™3Jš œœœœ œœ˜,šœœœ˜Jšœ™Jšœœ.œœ˜AJ˜—Jšœ'™'J˜*J˜'J˜J˜—Jšœ˜J˜J˜——…—r·