<<>> <> <> <> <> <> <<>> DIRECTORY Breakpoint, BreakpointPrivate, BreakWorldArchitecture, RefTab, Rope, Shepherd, TargetArchitecture; BreakpointImpl: CEDAR PROGRAM IMPORTS Breakpoint, BreakpointPrivate, BreakWorldArchitecture, RefTab, Rope EXPORTS Breakpoint, BreakpointPrivate, BreakWorldArchitecture ~ { <> BreakAccess: PUBLIC TYPE ~ Breakpoint.BreakAccess _ Breakpoint.nullBreakAccess; BreakAccessRep: PUBLIC TYPE ~ Breakpoint.BreakAccessRep; <> 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 ]; <> SetBreakpoint: PUBLIC Breakpoint.SetBreakProc ~ { <> <> <> <> <> <> <<_ TargetArchitecture.RegisterClass.all] >> <> 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 ~ { <> 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 ~ { <> Apply: RefTab.EachPairAction ~ { <> 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]; }; <> 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]; }; <> CantSet: PUBLIC ERROR [ code: Breakpoint.ErrorCode, message: Breakpoint.ErrorMessage] ~ CODE; CantClear: PUBLIC ERROR [ code: Breakpoint.ErrorCode, message: Breakpoint.ErrorMessage] ~ CODE; <> 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; }; <<>> }.