BBBreakImpl.mesa
Russ Atkinson, March 28, 1983 2:50 pm
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 {
get the entry location
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 {
get the exit location
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
};
utility routines for breakpoint stuff
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: REFNIL]
RETURNS [BreakId] = {
ENABLE UNWIND => NULL;
RETURN [AddBreakToListInternal[loc, condProc, condData]]};
AddBreakToListInternal: PROC
[loc: BBObjectLocation.Location, condProc: CondProc ← NIL, condData: REFNIL]
RETURNS [BreakId] = TRUSTED {
bid: BreakId ←
NEW[BreakIdRep ← [
loc: loc,
index: 0,
cid: NIL,
condProc: condProc,
condData: condData ,
entry: FALSE,
exit: FALSE,
enabled: TRUE]];
set the new breakpoint
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];
first check for cases we may wish to handle quickly
IF bid = NIL OR NOT bid.enabled THEN RETURN;
IF bid.condProc # NIL THEN {
handle conditional breaks
IF NOT bid.condProc[bid, event.frame, bid.condData] THEN RETURN};
sigh, we must notify our normal handler
action ← BBAction.NewAction[event, break];
BBAction.WaitForDataTaken[action, bid];
};
END.