BBVOpsImpl.mesa
Russ Atkinson, June 22, 1983 6:23 pm
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;
operations that report results (including intermediate results) as they go
EXPORTED to BBVForUserExec
SetBreak: PUBLIC PROC
[report: ReportProc, world: World ← NIL, entry,exit: BOOLFALSE]
RETURNS [break: BreakIndex ← NullIndex] = TRUSTED {
set a new breakpoint at the current selection, returns BBBreak.NullIndex if not successful, world = NIL => use LocalWorld, entry forces entry-point breakpoint, exit goes to the end (can set both entry & exit breakpoints)
loc: BBObjectLocation.Location ← NIL;
msg: ROPENIL;
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: BOOLFALSE]
RETURNS [break: BreakIndex ← NullIndex] = TRUSTED {
set a new breakpoint at the current selection, returns BBBreak.NullIndex if not successful, world = NIL => use LocalWorld, entry forces entry-point breakpoint, exit goes to the end (can clear both entry & exit breakpoints)
loc: BBObjectLocation.Location ← NIL;
msg: ROPENIL;
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: BOOLFALSE]
RETURNS [break: BreakIndex ← NullIndex] = TRUSTED {
get the breakpoint (if any) associated with the current selection, returns BBBreak.NullIndex if no such breakpoint or not successful
loc: BBObjectLocation.Location ← NIL;
msg: ROPENIL;
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: BOOLFALSE] = TRUSTED {
displays the local or global frame to the put proc, args => 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: BOOLTRUE]
RETURNS [name: ROPENIL, index: INT ← -1] = {
gets the source file name and the source index for the given TV, which must be a local frame or global frame, if not successful, then name = NIL & index < 0
err: ROPENIL;
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: ROPENIL;
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];
};
default source version map operations
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]};
Viewers/Location translations
ViewerFromLocation: PUBLIC PROC
[loc: BBObjectLocation.Location] RETURNS [viewer: ViewerClasses.Viewer] = {
err: ROPENIL;
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: BOOLFALSE]
RETURNS [loc: BBObjectLocation.Location ← NIL] = TRUSTED {
err: ROPENIL;
inner: PROC = TRUSTED {
ENABLE BBObjectLocation.LocationError => GO TO out;
name, shortName: ROPENIL;
index: INT;
worldContext: BBContext.Context ← BBContext.ContextForWorld[world];
gf: TVNIL;
[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] = {
return the first breakpoint index for the given location
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: ROPENIL;
Report: PROC [report: ReportProc, severity: Severity, r1,r2,r3,r4: ROPENIL] = {
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: ROPENIL, entry, exit: BOOLFALSE] = {
decimal: ROPE ← Convert.ValueToRope[[signed[break]]];
kind: ROPEIF 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.