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: BOOL ← FALSE]
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: 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 {
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: 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 {
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: 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 {
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: BOOL ← TRUE]
RETURNS [name: ROPE ← NIL, 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: 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];
};
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: 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] = {
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: 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;