BreakpointImpl.mesa
Copyright Ó 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved.
Peter B. Kessler, April 19, 1990 10:38 am PDT
Laurie Horton, October 16, 1991 1:27 am PDT
Katsuyuki Komatsu March 5, 1992 1:32 pm PST
DIRECTORY
Breakpoint,
BreakpointPrivate,
BreakWorldArchitecture,
RefTab,
Rope,
Shepherd,
TargetArchitecture;
BreakpointImpl: CEDAR PROGRAM
IMPORTS Breakpoint, BreakpointPrivate, BreakWorldArchitecture, RefTab, Rope
EXPORTS Breakpoint, BreakpointPrivate, BreakWorldArchitecture
~ {
Public Types EXPORTed to BreakWorldArchitecture
BreakAccess: PUBLIC TYPE ~ Breakpoint.BreakAccess ← Breakpoint.nullBreakAccess;
BreakAccessRep: PUBLIC TYPE ~ Breakpoint.BreakAccessRep;
Public Types EXPORTed to Breakpoint
BreakAccessData: PUBLIC TYPE ~ REF BreakAccessDataRep ← Breakpoint.nullBreakAccessData;
BreakAccessDataRep: PUBLIC TYPE ~ RECORD [
breakTable: RefTab.Ref ← NIL
];
Break: PUBLIC TYPE ~ REF BreakRep ← Breakpoint.nullBreak;
BreakRep: PUBLIC TYPE ~ RECORD [
breakAccess: Breakpoint.BreakAccess,
address: BreakWorldArchitecture.Address,
patch: Shepherd.Patch,
clientData: Breakpoint.ClientData
];
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: BOOLFALSE]
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];
};
Public Errors exported to Breakpoint.
CantSet: PUBLIC ERROR [
code: Breakpoint.ErrorCode, message: Breakpoint.ErrorMessage] ~ CODE;
CantClear: PUBLIC ERROR [
code: Breakpoint.ErrorCode, message: Breakpoint.ErrorMessage] ~ CODE;
Target-Dependent Procedure dispatch
registry: BreakpointPrivate.Registry ← NIL;
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]
ELSE
RETURN[LAST[CARD]];
};
RetrieveTargetBreaks: PUBLIC PROC[targetName: Rope.ROPE] RETURNS[BreakpointPrivate.TargetBreaks] ~ {
i: CARD ← RetrieveTargetBreaksInner[targetName];
IF i # LAST[CARD] THEN
RETURN[registry[i]]
ELSE
ERROR;
};
}.