-- File: WiskOperations.mesa
-- last edit by Smokey on Sep 16, 1980 3:45 PM
-- last edit by Sandman on July 28, 1980 9:08 AM
-- last edit by Bruce on October 25, 1980 7:47 PM
DIRECTORY
BP USING [BytePC, Fail, GFHandle, Insert, Remove],
Context USING [Create, Data, Destroy, Find, Type, UniqueType],
Copier USING [Outer],
DContext USING [GetGlobal, GetModule],
DebugFormat USING [BT, EXOI],
DebugOps USING [window],
DSyms USING [GFHandle, GFrameMdi, NoFGT],
FileSW USING [GetFile, IsIt],
FileWindow USING [
Create, CreateMCR, DestroyMCR, Event, Enumerate, EnumerateProcType, LoadWindow,
NotifyProcType, SetExtension, SetMinimumWindows, SetSize, SetSourceMenu,
SetNotifyProc, WindowForFile],
Frames USING [Invalid],
Gf USING [Copied, CopiedFrame, Frame, Handle, Validate],
HeapString USING [AppendChar],
Init USING [],
Inline USING [LongNumber],
Lookup USING [Fail],
MachineDefs USING [BytePC, DestroyStream, GFHandle, NullGF, SHandle],
Menu USING [Create, Handle, ItemObject, MCRType],
Pc USING [BytePC, CacheCBti, EntryPC, EVRange, ExitPC, GetPc],
Profile USING [bitmap],
Segments USING [FHandle, FileNameProblem, NewFile, Read],
Selection USING [Clear, Convert],
Source USING [
BreakRec, FileMissing, GetGF, GFHandle, Handle, LittleParser,
LoadWindow, Open, PcToSource, SC, SetGF, Validate],
Storage USING [Free, FreeString, Node],
Streams USING [CreateStream, Handle],
String USING [EqualString],
Strings USING [AppendString],
Symbols USING [BTIndex, CBTIndex, MDIndex, RootBti],
SymbolTable USING [Base, Missing],
Table USING [Base],
TextSW USING [GetPosition, GetSelection, SetSelection],
--, RemoveSecondarySelection, SecondarySelectionFromPosition, SetSecondarySelection],
ToolWindow USING [GetName, Handle, SetName, WindowForSubwindow],
UserTerminal USING [BlinkDisplay],
Window USING [Dims, Handle];
WiskOperations: PROGRAM
IMPORTS
BP, Context, Copier, DContext, DebugOps, DSyms, FileSW, FileWindow, Frames, Gf,
HeapString, Lookup, MachineDefs, Menu, Pc, Profile, Segments, Selection, Source,
Storage, Streams, String, Strings, SymbolTable, TextSW, ToolWindow, UserTerminal
EXPORTS Init, Source =
BEGIN OPEN MachineDefs, Symbols;
RelPC: TYPE = [0..LAST[CARDINAL]/2];
-- Define Menu and related data
sourceItemsCount: CARDINAL = 6;
sourceItems: ARRAY [0..sourceItemsCount) OF Menu.ItemObject ← [
["Create", FileWindow.CreateMCR],
["Destroy", FileWindow.DestroyMCR],
["Attach", AttachMCR],
["Set Break", BreakMCR],
["Set Trace", TraceMCR],
["Clr Break", ClearMCR]];
sourceMenu: Menu.Handle =
Menu.Create[DESCRIPTOR[sourceItems], "SourceOps", TRUE];
-- Debugger Menu Command Routines
AttachMCR: Menu.MCRType = {
item: ItemHandle ← FindItem[window];
IF item = NIL THEN UserTerminal.BlinkDisplay[]
ELSE item.trustTime ← TRUE};
BreakMCR: Menu.MCRType = BEGIN SetUp[window,set,break] END;
ClearMCR: Menu.MCRType = BEGIN SetUp[window,clear,break] END;
TraceMCR: Menu.MCRType = BEGIN SetUp[window,set,trace] END;
-- Public stuff
Destroy: PUBLIC PROC [d: MachineDefs.SHandle] = {MachineDefs.DestroyStream[d]};
LoadWindow: PUBLIC PROCEDURE [
name: STRING, gf: MachineDefs.GFHandle ← MachineDefs.NullGF,
file: MachineDefs.SHandle ← NIL, position: LONG CARDINAL] =
BEGIN
w: Window.Handle = FileWindow.WindowForFile[name];
FileWindow.LoadWindow[fileName: name, position: position, s: file, sw: w];
SetGF[w, gf];
END;
Open: PUBLIC PROC [s: STRING] RETURNS [stream: Streams.Handle] =
BEGIN
file: Segments.FHandle ← NIL;
file ← Segments.NewFile[s, Segments.Read
! Segments.FileNameProblem[] => CONTINUE ];
IF file = NIL THEN SIGNAL Source.FileMissing[s];
stream ← Streams.CreateStream[file];
END;
SetSize: PUBLIC PROCEDURE =
BEGIN OPEN DebugOps.window.box;
rootDims: Window.Dims = Profile.bitmap.dims;
FileWindow.SetSize[NIL, [
place: [x: 0, y: place.y+dims.h],
dims: [w: rootDims.w, h: rootDims.h - (place.y+dims.h)]] ];
END;
SetupSourceWindow: PUBLIC PROCEDURE =
BEGIN
FileWindow.SetNotifyProc[SomethingChanged];
FileWindow.SetExtension[".mesa"L];
FileWindow.SetSourceMenu[sourceMenu];
FileWindow.SetMinimumWindows[1];
[] ← FileWindow.Create[[[x:32, y: 0], [w: 480, h: 352]]];
END;
Shorten: PROC [lc: LONG CARDINAL] RETURNS [CARDINAL] =
BEGIN OPEN ln: LOOPHOLE[lc,Inline.LongNumber];
RETURN [ln.lowbits]
END;
-- Utilities
AddDollar: PROC [w: Window.Handle] = {
s: STRING ← ToolWindow.GetName[w];
IF s[s.length-1] = '. THEN s[s.length-1] ← '$ ELSE HeapString.AppendChar[@s,'$];
ToolWindow.SetName[w,s]};
Break: PROC [sw: Window.Handle, br: Source.BreakRec] RETURNS [ok: BOOLEAN] =
BEGIN
gf: GFHandle;
pc: BytePC;
cbti: CBTIndex;
ep: Pc.EVRange;
index: CARDINAL;
getfgt: BOOLEAN ← TRUE;
mdi: Symbols.MDIndex;
SetUp: PROC [base: SymbolTable.Base] =
BEGIN
startPc: BytePC;
relPc: RelPC;
[relPc,cbti,index] ←
ExploreFGT[base, Shorten[TextSW.GetSelection[sw].left]];
IF base.bb[cbti].inline THEN ERROR BP.Fail[inInline];
ep ← base.bb[cbti].entryIndex;
startPc ← Pc.GetPc[gf,ep];
pc ← [startPc+relPc];
index ← Source.PcToSource[base, gf, pc, cbti, startPc];
END;
IF sw = NIL THEN RETURN[FALSE];
gf ← GetContext[sw !
Gf.CopiedFrame, Lookup.Fail, Source.FileMissing => GOTO nogood;
DSyms.NoFGT =>
BEGIN
IF ~getfgt OR br.bt.ex # entry THEN GOTO nogood;
getfgt ← FALSE;
CONTINUE;
END;
SymbolTable.Missing => GOTO nogood];
IF gf = NIL OR ~Gf.Validate[gf] OR Gf.Copied[gf] THEN RETURN[FALSE];
mdi ← DSyms.GFrameMdi[gf,getfgt !
DSyms.NoFGT =>
BEGIN
IF ~getfgt OR br.bt.ex # entry THEN GOTO nogood;
getfgt ← FALSE;
RETRY;
END];
Copier.Outer[mdi, SetUp ! BP.Fail => GOTO nogood];
cbti ← Pc.CacheCBti[mdi,gf,cbti];
SELECT br.bt.ex FROM
entry => pc ← Pc.EntryPC[ep,gf];
exit => pc ← Pc.ExitPC[cbti];
in => NULL;
ENDCASE;
IF br.sc=set THEN [] ← BP.Insert[gf,pc,br.bt,TRUE ! BP.Fail => GOTO nogood]
ELSE BP.Remove[gf,pc];
FixSelection[sw: sw, left: index,
right: IF br.bt.ex = in THEN index + 1
ELSE Shorten[TextSW.GetSelection[sw].right],
set: br.sc=set];
RETURN[TRUE];
EXITS
nogood => RETURN[FALSE];
END;
ClosestSource: PROC [
bti: BTIndex, index: CARDINAL, base: SymbolTable.Base]
RETURNS [closest: CARDINAL, firstPc: RelPC] =
BEGIN OPEN body: base.bb[bti];
i, start, length: CARDINAL;
currentPc: RelPC;
closest ← body.sourceIndex;
currentPc ← firstPc ← 0;
IF BASE[base.fgTable] = NIL THEN RETURN;
WITH body.info SELECT FROM
External => {start ← startIndex; length ← indexLength};
ENDCASE => RETURN;
FOR i IN [start..start+length) DO
WITH base.fgTable[i] SELECT FROM
normal =>
BEGIN
IF deltaSource + closest > index THEN RETURN;
firstPc ← currentPc ← currentPc + deltaObject;
closest ← closest + deltaSource;
END;
step =>
IF which = source THEN
IF delta + closest > index THEN RETURN
ELSE {firstPc ← currentPc; closest ← closest + delta}
ELSE currentPc ← currentPc + delta;
ENDCASE;
ENDLOOP;
END;
ExploreFGT: PROC [base: SymbolTable.Base, index: CARDINAL]
RETURNS [bestPc: RelPC, bestCbti: CBTIndex, bestSource: CARDINAL] =
BEGIN
CheckBti: PROC [bti: BTIndex] RETURNS [stop: BOOLEAN] =
BEGIN OPEN body: base.bb[bti];
source: CARDINAL;
pc: RelPC;
stop ← FALSE;
IF body.kind # Callable OR body.sourceIndex > index THEN RETURN;
[closest: source, firstPc: pc] ← ClosestSource[bti,index, base];
IF source <= bestSource THEN RETURN;
bestSource ← source; bestCbti ← LOOPHOLE[bti]; bestPc ← pc;
END;
bestPc ← 0; bestCbti ← Symbols.RootBti; bestSource ← 0;
[] ← base.EnumerateBodies[Symbols.RootBti,CheckBti];
END;
FixSelection: PROCEDURE [sw: Window.Handle, left, right: CARDINAL, set: BOOLEAN] = {
OPEN TextSW;
Selection.Clear[];
--IF set THEN [] ← SetSecondarySelection[sw,left,right,grayBox]
--ELSE RemoveSecondarySelection[sw,SecondarySelectionFromPosition[sw,left]]};
TextSW.SetSelection[sw,left,right]};
GetContext: PROCEDURE [w: Window.Handle] RETURNS [frame: GFHandle] =
BEGIN
mod: STRING ← [40];
h: Source.Handle;
retry: BOOLEAN ← TRUE;
frame ← Source.GetGF[w];
IF frame # NIL THEN RETURN;
h ← LOOPHOLE[FileSW.GetFile[w].s];
Source.LittleParser[h, mod];
IF mod.length = 0 THEN RETURN[NIL];
frame ← IF String.EqualString[mod, DContext.GetModule[]] THEN
DContext.GetGlobal[]
ELSE Gf.Frame[mod ! Frames.Invalid => CONTINUE];
Source.Validate[h,frame];
Source.SetGF[w,frame];
RETURN
END;
MakeEXOI: PROCEDURE [s: STRING] RETURNS [DebugFormat.EXOI] =
BEGIN OPEN String;
RETURN[SELECT TRUE FROM
EqualString[s,"PROC"L] => entry,
EqualString[s,"PROCEDURE"L] => entry,
EqualString[s,"RETURN"L] => exit,
ENDCASE => in];
END;
Reload: PROC [gf: GFHandle, w: Window.Handle] = {
fileId: STRING ← [40];
file: Source.Handle;
Inner: PROC [base: SymbolTable.Base] = {
Strings.AppendString[fileId,base.sourceFile]};
AddDollar[ToolWindow.WindowForSubwindow[w]];
Copier.Outer[DSyms.GFrameMdi[gf],Inner];
file ← Source.Open[fileId];
IF file = NIL THEN RETURN;
Source.LoadWindow[fileId, gf, file, TextSW.GetPosition[w,0]]};
SetUp: PROCEDURE [w: Window.Handle, sc: Source.SC, bt: DebugFormat.BT] =
BEGIN
br: Source.BreakRec;
text: STRING;
IF ~ValidateSource[w] THEN GOTO fail;
text ← Selection.Convert[string];
IF text = NIL THEN GOTO fail;
br ← [sc: sc, bt: [ex: MakeEXOI[text], bt: bt]];
Storage.FreeString[text];
IF ~Break[w, br] THEN GOTO fail;
EXITS
fail => UserTerminal.BlinkDisplay[];
END;
ValidateSource: PROC [w: Window.Handle] RETURNS [BOOLEAN] =
BEGIN OPEN Selection;
IF ~FileSW.IsIt[w] THEN RETURN[FALSE];
RETURN[Convert[subwindow] = w]
END;
-- GlobalFrame/SourceWindow correspondence stuff
GetGF: PUBLIC PROCEDURE [w: Window.Handle] RETURNS [MachineDefs.GFHandle] =
BEGIN
item: ItemHandle ← FindItem[w];
RETURN[IF item = NIL THEN NIL ELSE item.gf];
END;
GetWindow: PUBLIC PROCEDURE [gf: MachineDefs.GFHandle]
RETURNS [w: Window.Handle] =
BEGIN
proc: FileWindow.EnumerateProcType =
BEGIN
item: ItemHandle ← FindItem[sw];
IF item # NIL AND item.gf = gf THEN w ← sw;
RETURN[IF w = NIL THEN continue ELSE stop];
END;
w ← NIL;
FileWindow.Enumerate[proc];
RETURN[w]
END;
IgnoreTimeStamp: PUBLIC PROCEDURE [w: Window.Handle] RETURNS [BOOLEAN] =
BEGIN
item: ItemHandle ← FindItem[w];
RETURN[IF item = NIL THEN FALSE ELSE item.trustTime];
END;
ResetFrames: PUBLIC PROCEDURE =
BEGIN
proc: FileWindow.EnumerateProcType =
BEGIN ResetGF[sw]; RETURN[continue] END;
FileWindow.Enumerate[proc];
END;
SetGF: PUBLIC PROCEDURE [w: Window.Handle, gf: MachineDefs.GFHandle] =
BEGIN
item: ItemHandle;
AddItem[w, gf];
item ← FindItem[w];
IF item # NIL THEN item.trustTime ← TRUE; -- not clear how it could = NIL but...
END;
myContext: Context.Type = Context.UniqueType[];
ItemHandle: TYPE = POINTER TO Item;
Item: TYPE = RECORD [
trustTime: BOOLEAN,
gf: MachineDefs.GFHandle];
AddItem: PROCEDURE [sw: Window.Handle, gf: MachineDefs.GFHandle] =
BEGIN
item: ItemHandle ← FindItem[sw];
IF item # NIL THEN {item.gf ← gf; item.trustTime ← FALSE; RETURN};
item ← Storage.Node[SIZE[Item]];
item↑ ← [gf: gf, trustTime: FALSE];
Context.Create[myContext, item, DestroyItem, sw];
RETURN
END;
DeleteItem: PROCEDURE [sw: Window.Handle] = INLINE
BEGIN Context.Destroy[myContext, sw]; END;
DestroyItem: PROCEDURE [item: Context.Data, sw: Window.Handle] =
BEGIN Storage.Free[item]; END;
FindItem: PROCEDURE [sw: Window.Handle] RETURNS [item: ItemHandle] = INLINE {
RETURN[IF sw # NIL THEN Context.Find[myContext, sw] ELSE NIL]};
ResetGF: PROC [w: Window.Handle] =
BEGIN
item: ItemHandle = FindItem[w];
IF item # NIL THEN
BEGIN
item.gf ← MachineDefs.NullGF; -- forget old one (else funny breakpoints)
item.trustTime ← FALSE;
END;
END;
SomethingChanged: FileWindow.NotifyProcType =
BEGIN
SELECT event FROM
create => AddItem[sw, MachineDefs.NullGF];
destroy => DeleteItem[sw];
load => ResetGF[sw];
edit => ResetGF[sw];
reset => ResetGF[sw];
store => ResetGF[sw];
ENDCASE => ERROR;
END;
END.