<> <> DIRECTORY AMBridge USING [ContextPC, FHFromTV, IsRemote, RemoteFHFromTV], AMTypes USING [TVType, TypeClass], AMViewerOps USING [FileVersion, GFToVersionStamps, OpenSource, ReportProc, SourceError, SourceFromSelection, SourceFromTV], BBBreak USING [AddBreakToList, BreakId, BreakIndex, ClearBreak, FindBreakId, NextBreak, NullIndex], BBBugOut USING [ShowOctal, ShowRope], BBContext USING [Context, ContextForWorld, GlobalFrameSearch], BBObjectLocation USING [EntryLocation, ExitLocation, IsLocationAtLocation, Location, LocationError, LocationToSource, SourceToLocation], BBSafety USING [Mother], BBVForUserExec USING [ReportProc, Severity], BBVOps USING [], BcdDefs USING [VersionStamp], Convert USING [ValueToRope], PrintTV USING [PutClosure, Print, PrintArguments, PrintVariables], Rope USING [Cat, Fetch, Flatten, ROPE, Size, Text], RTBasic USING [TV], VersionMap USING [Map, MapList], VersionMapDefaults USING [AddToMapList, FileNameFromVersion, GetMapList, SetMapList], ViewerClasses USING [Viewer], WorldVM USING [World]; BBVOpsImpl: CEDAR MONITOR IMPORTS AMBridge, AMTypes, AMViewerOps, BBBreak, BBBugOut, BBContext, BBObjectLocation, BBSafety, Convert, PrintTV, Rope, VersionMapDefaults EXPORTS BBVForUserExec, BBVOps = BEGIN OPEN BBBreak, BBVForUserExec, Rope, RTBasic; World: TYPE = WorldVM.World; SourceError: PUBLIC ERROR [reason: ROPE] = CODE; <> <> SetBreak: PUBLIC PROC [report: ReportProc, world: World _ NIL, entry,exit: BOOL _ FALSE] RETURNS [break: BreakIndex _ NullIndex] = TRUSTED { < use LocalWorld, entry forces entry-point breakpoint, exit goes to the end (can set both entry & exit breakpoints)>> loc: BBObjectLocation.Location _ NIL; msg: ROPE _ NIL; both: BOOL _ entry AND exit; inner: PROC = TRUSTED { break _ BBBreak.AddBreakToList[loc].index; }; Report[report, comment, "Setting break..."]; loc _ LocationFromSelection [world, entry, exit ! SourceError => {msg _ reason; CONTINUE}]; IF loc # NIL THEN { msg _ BBSafety.Mother[inner]; IF msg # NIL THEN GO TO noGood; ReportBreak[report, break, " set.", entry, exit]; IF NOT both THEN RETURN; loc _ BBObjectLocation.ExitLocation[loc]; IF loc = NIL THEN GO TO noGood; msg _ BBSafety.Mother[inner]; IF msg # NIL THEN GO TO noGood; ReportBreak[report, break, " set.", FALSE, exit]; RETURN; EXITS noGood => {}; }; IF msg = NIL THEN msg _ "no such location"; Report[report, fatal, "Break not set: ", msg]; }; ClearBreak: PUBLIC PROC [report: ReportProc, world: World _ NIL, entry,exit: BOOL _ FALSE] RETURNS [break: BreakIndex _ NullIndex] = TRUSTED { < use LocalWorld, entry forces entry-point breakpoint, exit goes to the end (can clear both entry & exit breakpoints)>> loc: BBObjectLocation.Location _ NIL; msg: ROPE _ NIL; both: BOOL _ entry AND exit; inner: PROC = TRUSTED { break _ BreakIndexFromLocation[loc]; IF break # NullIndex THEN [] _ BBBreak.ClearBreak[break]; }; Report[report, comment, "Clearing break..."]; loc _ LocationFromSelection [world, entry, exit ! SourceError => {msg _ reason; CONTINUE}]; IF loc # NIL THEN { msg _ BBSafety.Mother[inner]; IF msg # NIL OR break = NullIndex THEN GO TO noGood; ReportBreak[report, break, " cleared.", entry, exit]; IF NOT both THEN RETURN; loc _ BBObjectLocation.ExitLocation[loc]; IF loc = NIL THEN GO TO noGood; msg _ BBSafety.Mother[inner]; IF msg # NIL OR break = NullIndex THEN GO TO noGood; ReportBreak[report, break, " cleared.", FALSE, exit]; RETURN; EXITS noGood => {}; }; IF msg = NIL THEN msg _ "no such breakpoint"; Report[report, fatal, "Break not cleared: ", msg]; }; GetBreak: PUBLIC PROC [report: ReportProc, world: World _ NIL, entry,exit: BOOL _ FALSE] RETURNS [break: BreakIndex _ NullIndex] = TRUSTED { <> loc: BBObjectLocation.Location _ NIL; msg: ROPE _ NIL; inner: PROC = TRUSTED { break _ BreakIndexFromLocation[loc]; }; Report[report, comment, "Finding break..."]; loc _ LocationFromSelection [world, entry, exit ! SourceError => {msg _ reason; CONTINUE}]; IF loc # NIL THEN { msg _ BBSafety.Mother[inner]; IF msg = NIL AND break # NullIndex THEN { ReportBreak[report, break, " found.", entry, exit]; RETURN}; }; IF msg = NIL THEN msg _ "no such location"; Report[report, fatal, "Break not found: "]; }; DisplayFrame: PUBLIC PROC [frame: TV, put: PrintTV.PutClosure, report: ReportProc, args,vars,allVars: BOOL _ FALSE] = TRUSTED { < print arguments, vars => print variables, allVars => print all variables (otherwise just top-level variables)>> IF frame = NIL THEN RETURN; Report[report, comment, "Displaying frame..."]; IF AMTypes.TypeClass[AMTypes.TVType[frame]] # localFrame THEN { Report[report, fatal, "Not a local frame!"]; RETURN}; PrintTV.Print[tv: frame, put: put, verbose: FALSE]; BBBugOut.ShowRope[" (lf: ", put]; IF AMBridge.IsRemote[frame] THEN BBBugOut.ShowOctal [LOOPHOLE[AMBridge.RemoteFHFromTV[frame].fh, CARDINAL], put] ELSE BBBugOut.ShowOctal [LOOPHOLE[AMBridge.FHFromTV[frame], CARDINAL], put]; BBBugOut.ShowRope["B, pc: ", put]; BBBugOut.ShowOctal[AMBridge.ContextPC[frame], put]; BBBugOut.ShowRope["B)", put]; IF args THEN { BBBugOut.ShowRope["\nArguments:\n", put]; PrintTV.PrintArguments[tv: frame, put: put, breakBetweenItems: TRUE]; }; IF vars THEN { BBBugOut.ShowRope["\nVariables:\n", put]; PrintTV.PrintVariables[tv: frame, put: put, all: allVars, breakBetweenItems: TRUE]; }; BBBugOut.ShowRope["\n", put]; Report[report, success, NIL]; }; SourceFromTV: PUBLIC PROC [tv: TV, report: ReportProc, backupPC: BOOL _ TRUE] RETURNS [name: ROPE _ NIL, index: INT _ -1] = { <> err: ROPE _ NIL; passTheBuck: AMViewerOps.ReportProc = TRUSTED { Report[report, LOOPHOLE[severity], msg]; }; [name, index] _ AMViewerOps.SourceFromTV[ tv, passTheBuck ! AMViewerOps.SourceError => {err _ reason; CONTINUE}]; IF err # NIL THEN ERROR SourceError[err]; }; OpenSource: PUBLIC PROC [name: ROPE, index: INT, chars: INT _ 2, report: ReportProc] = { err: ROPE _ NIL; passTheBuck: AMViewerOps.ReportProc = TRUSTED { Report[report, LOOPHOLE[severity], msg]; }; AMViewerOps.OpenSource[ name, index, chars, passTheBuck ! AMViewerOps.SourceError => {err _ reason; CONTINUE}]; IF err # NIL THEN ERROR SourceError[err]; }; <> FileNameFromSourceVersion: PUBLIC PROC [sourceVersion: BcdDefs.VersionStamp] RETURNS [name: ROPE] = { RETURN [VersionMapDefaults.FileNameFromVersion[$Source, sourceVersion]]; }; GetVersionMapList: PUBLIC PROC RETURNS [VersionMap.MapList] = { RETURN [VersionMapDefaults.GetMapList[$Source]]}; SetVersionMapList: PUBLIC ENTRY PROC [list: VersionMap.MapList _ NIL] = { VersionMapDefaults.SetMapList[$Source, list]}; AddToVersionMapList: PUBLIC PROC [map: VersionMap.Map] = { VersionMapDefaults.AddToMapList[$Source, map]}; <> ViewerFromLocation: PUBLIC PROC [loc: BBObjectLocation.Location] RETURNS [viewer: ViewerClasses.Viewer] = { err: ROPE _ NIL; inner: PROC = { ENABLE ReportError => {err _ msg; GO TO out}; gf: TV; index: CARDINAL; name: ROPE; [gf, index] _ BBObjectLocation.LocationToSource[loc]; name _ SourceFromTV[gf, NIL].name; OpenSource[name, index, 2, NIL]; EXITS out => {}; }; mom: ROPE _ BBSafety.Mother[inner]; IF err # NIL THEN mom _ err; IF mom # NIL THEN ERROR SourceError[mom]; }; LocationFromSelection: PUBLIC PROC [world: World _ NIL, entry,exit: BOOL _ FALSE] RETURNS [loc: BBObjectLocation.Location _ NIL] = TRUSTED { err: ROPE _ NIL; inner: PROC = TRUSTED { ENABLE BBObjectLocation.LocationError => GO TO out; name, shortName: ROPE _ NIL; index: INT; worldContext: BBContext.Context _ BBContext.ContextForWorld[world]; gf: TV _ NIL; [name, index] _ AMViewerOps.SourceFromSelection[ ! AMViewerOps.SourceError => { err _ reason; GO TO sourceErr}]; shortName _ ModuleName[name]; gf _ BBContext.GlobalFrameSearch[worldContext, shortName].gf; IF gf = NIL THEN {err _ "no such module"; RETURN}; loc _ BBObjectLocation.SourceToLocation[gf, index]; IF loc = NIL THEN GO TO out; IF entry THEN { loc _ BBObjectLocation.EntryLocation[loc]; IF loc = NIL THEN GO TO out; RETURN}; IF exit THEN { loc _ BBObjectLocation.ExitLocation[loc]; IF loc = NIL THEN GO TO out; RETURN}; EXITS sourceErr => {}; out => {err _ "can't get location"}; }; mom: ROPE _ BBSafety.Mother[inner]; IF err # NIL THEN mom _ err; IF mom # NIL THEN ERROR SourceError[mom]; }; GFHToVersionStamps: PUBLIC PROC [gf: TV] RETURNS [source,object: BcdDefs.VersionStamp] = TRUSTED { [source, object] _ AMViewerOps.GFToVersionStamps[gf]; }; LocalFileVersion: PUBLIC PROC [name: ROPE] RETURNS [version: BcdDefs.VersionStamp] = TRUSTED { RETURN [AMViewerOps.FileVersion[name]]; }; ModuleName: PROC [name: ROPE] RETURNS [Rope.Text] = { <<... turns a long path name into a module name.>> size,pos: INT _ name.Size[]; start: INT _ 0; WHILE (pos _ pos - 1) >= 0 DO SELECT name.Fetch[pos] FROM '. => EXIT; ENDCASE; ENDLOOP; start _ pos; WHILE start > 0 DO SELECT name.Fetch[start _ start - 1] FROM '/, '\\, '[, '], '<, '> => { start _ start + 1; EXIT}; ENDCASE; ENDLOOP; RETURN [name.Flatten[start, pos-start]]; }; BreakIndexFromLocation: PROC [loc: BBObjectLocation.Location] RETURNS [BBBreak.BreakIndex] = { <> IF loc = NIL THEN RETURN [BBBreak.NullIndex]; FOR i: BreakIndex _ BBBreak.NextBreak[BBBreak.NullIndex], BBBreak.NextBreak[i] WHILE NOT (i = BBBreak.NullIndex) DO bid: BreakId _ BBBreak.FindBreakId[i]; IF bid # NIL THEN -- see if this one is the right one IF BBObjectLocation.IsLocationAtLocation[loc, bid.loc] THEN RETURN [i] ENDLOOP; RETURN [BBBreak.NullIndex] }; lagLagMsg, lagMsg: ROPE _ NIL; Report: PROC [report: ReportProc, severity: Severity, r1,r2,r3,r4: ROPE _ NIL] = { msg: ROPE _ Rope.Cat[r1,r2,r3,r4]; lagLagMsg _ lagMsg; lagMsg _ msg; IF report = NIL THEN { IF severity # fatal AND severity # warning THEN RETURN; ERROR ReportError[msg, severity]; }; report[msg, severity]; }; ReportBreak: PROC [report: ReportProc, break: BreakIndex, msg: ROPE _ NIL, entry, exit: BOOL _ FALSE] = { decimal: ROPE _ Convert.ValueToRope[[signed[break]]]; kind: ROPE _ IF entry THEN " (entry)" ELSE IF exit THEN " (exit)" ELSE NIL; lagLagMsg _ lagMsg; lagMsg _ msg _ Rope.Cat["Break #", decimal, kind, msg]; report[msg, success]; }; ReportError: PUBLIC ERROR [msg: ROPE, severity: Severity] = CODE; END.