Public Procedures EXPORTed to Breakpoint
SetBreakpoint:
PUBLIC Breakpoint.SetBreakProc ~ {
PROCEDURE [
address: BreakWorldArchitecture.Address,
clientData: ClientData,
breakProc: BreakProc,
breakData: BreakData,
damages: TargetArchitecture.RegisterClass
← TargetArchitecture.RegisterClass.all]
RETURNS [Break];
breakWorld: BreakWorldArchitecture.BreakWorld ← address.breakWorld;
worldAccess: BreakWorldArchitecture.WorldAccess ← BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld];
targetBreaks: BreakpointPrivate.TargetBreaks ← BreakpointPrivate.RetrieveTargetBreaks[worldAccess.name];
breakProcDataSegment: BreakWorldArchitecture.Address ← worldAccess.procs.getProcDataSegment[breakWorld, breakProc];
RETURN[targetBreaks.SetBreakpoint[address, clientData, breakProc, breakProcDataSegment, breakData, damages]]
};
ClearBreakpoint:
PUBLIC Breakpoint.ClearBreakProc ~ {
PROCEDURE [break: Break] RETURNS [];
breakWorld: BreakWorldArchitecture.BreakWorld ← break.address.breakWorld;
worldAccess: BreakWorldArchitecture.WorldAccess ← BreakWorldArchitecture.WorldAccessFromBreakWorld[breakWorld];
targetBreaks: BreakpointPrivate.TargetBreaks ← BreakpointPrivate.RetrieveTargetBreaks[worldAccess.name];
targetBreaks.ClearBreakpoint[break];
RETURN;
};
NewBreakAccess:
PUBLIC
PROCEDURE []
RETURNS [Breakpoint.BreakAccess] ~{
procs: Breakpoint.BreakAccessProcs ~
NEW[Breakpoint.BreakAccessProcsRep ← [
set: Breakpoint.SetBreakpoint,
clear: Breakpoint.ClearBreakpoint,
enumerate: Breakpoint.EnumerateBreakpoints]];
data: Breakpoint.BreakAccessData ~
NEW[BreakAccessDataRep ← [
breakTable: RefTab.Create[]]];
breakAccess: Breakpoint.BreakAccess ~
NEW[Breakpoint.BreakAccessRep ←
[procs: procs, data: data]];
RETURN [breakAccess];
};
EnumerateBreakpoints:
PUBLIC Breakpoint.EnumerateBreakProc ~ {
PROCEDURE [breakWorld: BreakWorldArchitecture.BreakWorld, proc: BreakpointProc]
RETURNS [quit: BOOLEAN ← FALSE];
Apply: RefTab.EachPairAction ~ {
PROC [key: Key, val: Val] RETURNS [quit: BOOL ← FALSE]
break: Break ~ NARROW[val];
clientData: Breakpoint.ClientData ~ Breakpoint.ClientDataFromBreak[break: break];
quit ← proc[clientData: clientData];
RETURN [quit: quit];
};
breakAccess: Breakpoint.BreakAccess ~
BreakWorldArchitecture.BreakAccessFromBreakWorld[breakWorld: breakWorld];
breakTable: RefTab.Ref ~ BreakTableFromBreakAccess[breakAccess: breakAccess];
IF breakTable =
NIL
THEN {
ERROR Breakpoint.Cant[
code: $NullBreakTable, message: "EnumerateBreakpoints[nullBreakTable]"];
};
quit ← breakTable.Pairs[action: Apply];
RETURN [quit: quit];
};
RememberBreak:
PUBLIC
PROCEDURE [break: Break] ~ {
breakAccess: Breakpoint.BreakAccess ~
BreakAccessFromBreak[break: break];
breakTable: RefTab.Ref ~ BreakTableFromBreakAccess[breakAccess: breakAccess];
IF breakTable =
NIL
THEN {
ERROR Breakpoint.Cant[
code: $NullBreakTable, message: "RememberBreak[nullBreakTable]"];
};
IF
NOT breakTable.Insert[key: break, val: break]
THEN {
ERROR Breakpoint.Cant[code: $CantRememberBreak, message: "Can't remember break"];
};
RETURN;
};
ForgetBreak:
PUBLIC
PROCEDURE [break: Break] ~ {
breakAccess: Breakpoint.BreakAccess ~ BreakAccessFromBreak[break: break];
breakTable: RefTab.Ref ~ BreakTableFromBreakAccess[breakAccess: breakAccess];
IF breakTable =
NIL
THEN {
ERROR Breakpoint.Cant[
code: $NullBreakTable, message: "ForgetBreak[nullBreakTable]"];
};
IF
NOT breakTable.Delete[key: break]
THEN {
ERROR Breakpoint.Cant[code: $CantForgetBreak, message: "Can't forget break"];
};
RETURN;
};
NewBreak:
PUBLIC
PROCEDURE [
address: BreakWorldArchitecture.Address,
patch: Shepherd.Patch,
clientData: Breakpoint.ClientData]
RETURNS [Breakpoint.Break] ~ {
breakWorld: BreakWorldArchitecture.BreakWorld ~
BreakWorldArchitecture.BreakWorldFromBreakWorldAddress[address: address];
breakAccess: Breakpoint.BreakAccess ~
BreakWorldArchitecture.BreakAccessFromBreakWorld[breakWorld: breakWorld];
break: Breakpoint.Break ~
NEW[BreakRep ← [
breakAccess: breakAccess, address: address, patch: patch, clientData: clientData]];
RETURN [break];
};
IsNullBreak:
PUBLIC
PROCEDURE [break: Breakpoint.Break]
RETURNS [
BOOLEAN] ~ {
RETURN [break = Breakpoint.nullBreak];
};
AddressFromBreak:
PUBLIC
PROCEDURE [break: Breakpoint.Break]
RETURNS [BreakWorldArchitecture.Address] ~ {
IF break.IsNullBreak[]
THEN {
ERROR Breakpoint.Cant[code: $NullBreak, message: "AddressFromBreak[nullBreak]"];
};
RETURN [break.address];
};
PatchFromBreak:
PUBLIC
PROCEDURE [break: Breakpoint.Break]
RETURNS [Shepherd.Patch] ~ {
IF break.IsNullBreak[]
THEN {
ERROR Breakpoint.Cant[code: $NullBreak, message: "PatchFromBreak[nullBreak]"];
};
RETURN [break.patch];
};
ClientDataFromBreak:
PUBLIC
PROCEDURE [break: Breakpoint.Break]
RETURNS [Breakpoint.ClientData] ~ {
IF break.IsNullBreak[]
THEN {
ERROR Breakpoint.Cant[code: $NullBreak, message: "ClientDataFromBreak[nullBreak]"];
};
RETURN [break.clientData];
};
Private Procedures
BreakAccessFromBreak:
PROCEDURE [break: Break]
RETURNS [Breakpoint.BreakAccess] ~ {
IF Breakpoint.IsNullBreak[break: break]
THEN {
ERROR Breakpoint.Cant[
code: $NullBreak, message: "BreakAccessFromBreak[nullBreak]"];
};
RETURN [break.breakAccess];
};
BreakTableFromBreakAccess:
PROCEDURE [breakAccess: Breakpoint.BreakAccess]
RETURNS [RefTab.Ref] ~ {
IF breakAccess = Breakpoint.nullBreakAccess
THEN {
ERROR Breakpoint.Cant[code: $NullBreakAccess, message: "Null breakAccess"];
};
IF breakAccess.data = Breakpoint.nullBreakAccessData
THEN {
ERROR Breakpoint.Cant[code: $NullBreakAccessData, message: "Null breakAccess.data"];
};
RETURN [breakAccess.data.breakTable];
};
RegisterTargetBreaks:
PUBLIC
PROC[targetBreaks: BreakpointPrivate.TargetBreaks] ~ {
newR: BreakpointPrivate.Registry;
i:CARD;
IF registry =
NIL
THEN {
registry ← NEW[BreakpointPrivate.RegistryBody[1]];
registry[0] ← targetBreaks;
}
ELSE
IF (i ← RetrieveTargetBreaksInner[targetBreaks.targetName]) #
LAST[
CARD]
THEN {
registry[i] ← targetBreaks;
}
ELSE {
newR ← NEW[BreakpointPrivate.RegistryBody[registry.length+1]];
FOR i
IN [0..registry.length)
DO
newR[i] ← registry[i];
ENDLOOP;
newR[registry.length] ← targetBreaks;
registry ← newR;
};
};
RetrieveTargetBreaksInner:
PROC[targetName: Rope.
ROPE]
RETURNS[registryIndex:
CARD] ~ {
i: CARD;
IF registry = NIL THEN RETURN[LAST[CARD]];
FOR i ← 0, i + 1
UNTIL i = registry.length
OR Rope.Equal[targetName, registry[i].targetName]
DO
ENDLOOP;
IF i # registry.length
THEN
RETURN[i]
};
}.