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