-- StmtMap.Mesa
-- Edited by:
-- Sandman on July 23, 1980 10:33 AM
-- Bruce on October 25, 1980 8:29 PM
-- Sweet on May 19, 1980 4:32 PM
DIRECTORY
Copier USING [Outer],
DOutput USING [Line],
DSyms USING [CrossJumped, GFHandle, GFrameMdi, NoFGT],
FileWindow USING [WindowForFile],
Inline USING [LongNumber],
MachineDefs USING [DestroyStream, GFHandle, NullGF],
Pc USING [CBti, BytePC, Ep, NullPC],
PcOps USING [FindCbti, cache, Item],
PrincOps USING [BytePC],
Source USING [
GetCreateDate, GFHandle, Handle, IgnoreTimeStamp, LoadWindow, Open, PrintTextLine],
State USING [GF],
String USING [AppendString],
Strings USING [AppendString],
Symbols USING [BTIndex, BTNull, CBTIndex, CBTNull, MDIndex],
SymbolSegment USING [FGTEntry],
SymbolTable USING [Base],
Time USING [Append, Unpack];
StmtMap: PROGRAM
IMPORTS
Copier, DOutput, FileWindow, DSyms, MachineDefs, Pc, PcOps, Source, State,
String, Strings, Time
EXPORTS Source =
BEGIN OPEN Pc, DSyms, MachineDefs, Symbols;
FileMissing: PUBLIC SIGNAL [name: STRING] = CODE;
MappingFailure: PUBLIC SIGNAL = CODE;
TooLong: ERROR = CODE;
PcToSource: PUBLIC PROCEDURE [
base: SymbolTable.Base, gf: GFHandle, pc: PrincOps.BytePC,
bti: BTIndex, start: BytePC]
RETURNS [currentSource: CARDINAL] =
BEGIN
-- finds i such that pc is in [fgt[i].cIndex..fgt[i+1].cIndex)
i, s, l: CARDINAL;
deltaPc: CARDINAL ← pc - start;
stride: CARDINAL ← 0;
IF bti = BTNull THEN ERROR MappingFailure;
currentSource ← base.bb[bti].sourceIndex;
WITH base.bb[bti].info SELECT FROM
External => BEGIN s ← startIndex; l ← indexLength; END;
ENDCASE => ERROR;
WITH base.bb[bti] SELECT FROM
Other => deltaPc ← deltaPc - relOffset;
ENDCASE;
IF l = 1 THEN RETURN;
FOR i IN (s..s+l) DO
WITH base.fgTable[i] SELECT FROM
normal =>
BEGIN
IF deltaObject > deltaPc THEN RETURN;
deltaPc ← deltaPc - deltaObject;
currentSource ← currentSource + deltaSource + stride;
stride ← 0;
END;
step =>
IF which = object THEN
IF delta > deltaPc THEN RETURN ELSE deltaPc ← deltaPc - delta
ELSE stride ← stride + delta;
ENDCASE;
ENDLOOP;
RETURN
END;
PCToSourceIndex: PUBLIC PROC [pc: PrincOps.BytePC, frame: GFHandle ← NullGF]
RETURNS [index: LONG CARDINAL] =
{RETURN[PCToSourceCommon[pc,frame,FALSE].index]};
PCToSourceCommon: PROC [
pc: PrincOps.BytePC, gf: GFHandle, load: BOOLEAN, s: STRING ← NIL]
RETURNS [h: Source.Handle, index: LONG CARDINAL] =
BEGIN
mdi: MDIndex;
cbti: CBTIndex;
start: BytePC;
OpenSymbols: PROC [base: SymbolTable.Base] =
BEGIN
fileId: STRING ← [40];
dot: CARDINAL;
version: LONG CARDINAL ← base.stHandle.sourceVersion.time;
Strings.AppendString[fileId,base.sourceFile];
IF fileId[dot ← fileId.length - 1] = '. THEN fileId.length ← dot;
IF s # NIL THEN String.AppendString[s,fileId];
h ← Source.Open[fileId];
IF h = NIL THEN ERROR FileMissing[fileId];
CheckTime[version,h,fileId];
IF pc = Pc.NullPC THEN RETURN;
index ← PcToSource[base, gf, pc, cbti, start];
END;
IF gf = NullGF THEN gf ← State.GF[];
h ← NIL;
cbti ← GetUserCbti[pc,gf];
IF pc # Pc.NullPC THEN start ← Pc.Ep[pc,gf].start;
mdi ← DSyms.GFrameMdi[gf,TRUE];
index ← 0;
Copier.Outer[mdi,OpenSymbols ! UNWIND => IF h # NIL THEN MachineDefs.DestroyStream[h]];
IF ~load THEN MachineDefs.DestroyStream[h];
END;
GetUserCbti: PROC [pc: PrincOps.BytePC, gf: GFHandle] RETURNS [CBTIndex] =
BEGIN
cbti: CBTIndex = Pc.CBti[pc,gf];
item: PcOps.Item;
IF cbti = CBTNull THEN RETURN[cbti];
item ← PcOps.FindCbti[cbti];
RETURN[PcOps.cache[item].userCbti];
END;
Validate: PUBLIC PROC [h: Source.Handle, gf: GFHandle] =
BEGIN
fileId: STRING ← [40];
version: LONG CARDINAL;
CheckVersion: PROC [base: SymbolTable.Base] = {
version ← base.stHandle.sourceVersion.time;
Strings.AppendString[fileId,base.sourceFile]};
Copier.Outer[DSyms.GFrameMdi[gf,FALSE],CheckVersion];
IF h = NIL THEN ERROR FileMissing[fileId];
CheckTime[version,h,fileId];
END;
CheckTime: PROC [bcd: LONG CARDINAL, sh: Source.Handle, name: STRING] =
BEGIN OPEN String;
msg: STRING ← [120];
fileTime: LONG CARDINAL;
fileTime ← Source.GetCreateDate[sh];
IF bcd = fileTime OR Source.IgnoreTimeStamp[FileWindow.WindowForFile[name]] THEN
RETURN;
AppendString[msg, "Can't use "L];
AppendString[msg,name]; AppendString[msg," of "L];
AppendTime[msg,fileTime]; AppendString[msg," instead of version created "L];
AppendTime[msg,bcd];
ERROR FileMissing[msg];
END;
AppendTime: PROC [msg: STRING, time: LONG CARDINAL] = INLINE
BEGIN Time.Append[msg,Time.Unpack[LOOPHOLE[time]]] END;
Display: PUBLIC PROC [gf: GFHandle, pc: PrincOps.BytePC, load: BOOLEAN] =
BEGIN
fileId: STRING ← [40];
file: Source.Handle;
index: LONG CARDINAL;
[file,index] ← PCToSourceCommon[pc, gf, TRUE, fileId ! DSyms.NoFGT =>
BEGIN ERROR FileMissing["-- Compressed Symbols --"L] END];
IF DSyms.CrossJumped[gf] THEN DOutput.Line[" Cross jumped!"L];
index ← Source.PrintTextLine[file,ShortenIndex[index]];
IF ~load THEN {MachineDefs.DestroyStream[file]; RETURN};
Source.LoadWindow[fileId, gf, file, index];
RETURN
END;
ShortenIndex: PROC [lc: LONG CARDINAL] RETURNS [CARDINAL] =
BEGIN
ln: Inline.LongNumber ← LOOPHOLE[lc];
IF ln.highbits # 0 THEN ERROR TooLong;
RETURN [ln.lowbits]
END;
END.