-- 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.