-- DSymTab.Mesa Edited by:
-- Bruce June 10, 1980 6:58 PM
-- Sandman May 5, 1980 6:02 PM
DIRECTORY
BcdDefs USING [
Base, BCD, FTNull, FTSelf, MTIndex, NullVersion, SGIndex, SGNull,
VersionID, VersionStamp],
BcdOps USING [
BcdBase, FTHandle, MTHandle, NameString, ProcessModules, SGHandle],
ComData,
CompilerUtil USING [PassIndex, PrefillSymbols],
Copier,
DebugOps,
DI USING [ResetLongs],
DOutput USING [Blanks, Char, Text],
DSyms,
Frames USING [Invalid],
Gf USING [Check, File, Frame, GFI, Name, Original],
LiteralOps USING [Initialize],
LoadStateOps USING [
AcquireBcd, ConfigIndex, InputLoadState, LoadStateInvalid,
MapRealToConfig, NullConfig, ReleaseBcd, ReleaseLoadState],
Lookup,
MachineDefs,
Pc,
SegmentDefs USING [
DefaultAccess, DeleteFileSegment, FileError, FileNameError,
FileHandle, FileSegmentHandle, FileSegmentAddress,
MoveFileSegment, NewFile, NewFileSegment, OldFileOnly, PageNumber, Read,
SwapIn, SwapOut, Unlock, VMtoFileSegment],
Storage: FROM "storage",
String USING [
AppendString, AppendSubString, SubString, SubStringDescriptor],
SymbolOps USING [EnterString, Initialize, Reset],
SymbolPack,
Symbols USING [
BTIndex, HTIndex, HTNull, IncludedCTXNull,
MDIndex, MDNull, mdType, MDRecord, OwnMdi, RootBti],
SymbolSegment: FROM "symbolsegment",
SymbolTable: FROM "symboltable" USING [Base, Missing],
Table: FROM "table",
TreeOps: FROM "TreeOps" USING [Initialize];
DSymTab: PROGRAM
IMPORTS BcdOps, data: ComData, CompilerUtil, Copier,
DebugOps, DI, DOutput,
Frames, Gf, LiteralOps, LoadStateOps, Lookup, SegmentDefs, Storage,
String, SymbolOps, SymbolPack, SymbolTable, Table, TreeOps
EXPORTS CompilerUtil, DSyms =
BEGIN OPEN DSyms, MachineDefs;
Head: Item ← NIL;
s: STRING ← NIL;
NoFGT: PUBLIC ERROR = CODE;
CantAttach: ERROR = CODE;
SymbolTableProblem: ERROR = CODE;
MakeSwappable: PUBLIC PROC[module:PROGRAM, pass:CompilerUtil.PassIndex]={};
FreeItems: PUBLIC PROCEDURE =
BEGIN OPEN SegmentDefs, SymbolTable;
syms, next: Item;
FOR syms ← Head, next UNTIL syms = NIL DO
next ← syms.link;
Storage.Free[syms];
ENDLOOP;
Copier.CopierReset[];
Copier.FileReset[];
Copier.FileInit["XDebug"L, BcdDefs.NullVersion];
Copier.CopierInit[FALSE];
Copier.CreateFileTable[16];
Head ← NIL;
END;
CleanItems: PUBLIC PROCEDURE =
BEGIN
syms, next, prev: Item;
prev ← NIL;
FOR syms ← Head, next UNTIL syms = NIL DO
next ← syms.link;
IF syms.table = NIL THEN
BEGIN
IF prev = NIL THEN Head ← next ELSE prev.link ← next;
Storage.Free[syms];
END
ELSE prev ← syms;
ENDLOOP;
END;
Enumerate: PUBLIC PROC [proc: PROCEDURE [Item] RETURNS [BOOLEAN]]
RETURNS [syms: Item] =
BEGIN
last: Item;
FOR syms ← Head, syms.link UNTIL syms = NIL DO
IF proc[syms] THEN
BEGIN
IF syms = Head THEN RETURN;
last.link ← syms.link; syms.link ← Head; Head ← syms;
RETURN
END;
last ← syms;
ENDLOOP;
END;
FindMod: PUBLIC PROC [name: HTIndex] RETURNS [Item] =
BEGIN OPEN Symbols;
mdb: Table.Base;
length: CARDINAL;
mdi: MDIndex;
[mdb,length] ← Table.Bounds[Symbols.mdType];
FOR mdi ← OwnMdi, mdi+SIZE[MDRecord] UNTIL
LOOPHOLE[mdi,CARDINAL] = length DO
IF mdb[mdi].moduleId = name THEN RETURN[FindMdi[mdi]];
ENDLOOP;
RETURN[NIL];
END;
FindMdi: PUBLIC PROC [mdi: MDIndex] RETURNS [Item] =
BEGIN
Find: PROC [d: Item] RETURNS[BOOLEAN] =
BEGIN
WITH sym: d SELECT FROM
hash => RETURN[FALSE];
mod => RETURN[mdi = sym.mdi];
ENDCASE => ERROR;
END;
RETURN[Enumerate[Find]];
END;
FindFrame: PUBLIC PROC [gf: MachineDefs.GFHandle] RETURNS [i: Item] =
BEGIN
Find: PROC [d: Item] RETURNS[BOOLEAN] = {RETURN[gf = d.gf]};
RETURN[Enumerate[Find]];
END;
ModuleMdi: PUBLIC PROC [hti: HTIndex, fgt: BOOLEAN ← FALSE]
RETURNS [MDIndex] =
BEGIN
syms: Item;
gf: GFHandle ← NIL;
mod: STRING ← [40];
Lookup.HtiToString[hti,mod];
gf ← Gf.Frame[mod ! Lookup.Fail => CONTINUE];
IF (syms ← FindMod[hti]) = NIL THEN
BEGIN
IF gf = NIL THEN {AttachSyms[gf,mod]; syms ← FindMod[hti]}
ELSE syms ← AddItem[hti,gf];
END;
SetSegment[syms,fgt];
WITH syms SELECT FROM
mod => RETURN[mdi];
ENDCASE => ERROR SymbolTable.Missing[NIL];
END;
GFrameMdi: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE]
RETURNS [MDIndex] =
BEGIN
syms: Item;
Gf.Check[gf];
IF (syms ← FindFrame[gf]) = NIL THEN syms ← AddItem[Symbols.HTNull,gf];
SetSegment[syms,fgt];
WITH syms SELECT FROM
mod => RETURN[mdi];
ENDCASE => ERROR SymbolTable.Missing[NIL];
END;
Stopping: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE]
RETURNS [BOOLEAN] =
BEGIN
syms: Item;
Gf.Check[gf];
IF (syms ← FindFrame[gf]) = NIL THEN syms ← AddItem[Symbols.HTNull,gf];
SetSegment[syms,fgt];
RETURN[syms.stopping];
END;
CrossJumped: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE]
RETURNS [BOOLEAN] =
BEGIN
syms: Item;
Gf.Check[gf];
IF (syms ← FindFrame[gf]) = NIL THEN syms ← AddItem[Symbols.HTNull,gf];
SetSegment[syms,fgt];
RETURN[syms.crossJumped];
END;
GFrameHti: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE]
RETURNS [HTIndex] =
BEGIN
mdi: MDIndex ← Symbols.MDNull;
i: Item;
mdi ← GFrameMdi[gf,fgt !SymbolTable.Missing => CONTINUE];
IF mdi # Symbols.MDNull THEN
RETURN[Table.Bounds[Symbols.mdType].base[mdi].moduleId];
i ← FindFrame[gf];
WITH i SELECT FROM
hash => RETURN[hti];
ENDCASE => ERROR SymbolTableProblem;
END;
ModuleToHti: PUBLIC PROC [s: STRING] RETURNS [hti: Symbols.HTIndex] =
BEGIN
mod: STRING ← [40];
desc: String.SubStringDescriptor;
String.AppendString[mod,s]; StripExtension[mod];
desc ← [base: mod, offset: 0, length: mod.length];
RETURN[SymbolOps.EnterString[@desc]];
END;
HtiFromLoadState: PROC [gf: GFHandle] RETURNS [Symbols.HTIndex] =
BEGIN
name: STRING ← [40];
Gf.Name[name,gf];
RETURN[ModuleToHti[name]];
END;
mdb: Table.Base;
Notify: Table.Notifier = {mdb ← base[Symbols.mdType]};
AddItem: PROC [hti: HTIndex, gf: GFHandle] RETURNS [syms: Item] =
BEGIN
version: BcdDefs.VersionStamp;
seg: FSHandle;
jumped, fgt: BOOLEAN;
[version: version, seg: seg, fgt: fgt, jumped:jumped] ←
SymbolSegForFrame[gf];
syms ← CacheItem[
hti:hti, gf:gf, version:version, seg:seg, fgt:fgt, jumped:jumped];
END;
CacheItem: PROC [
hti: HTIndex, gf: GFHandle, version: BcdDefs.VersionStamp,
seg: FSHandle, fgt, jumped: BOOLEAN]
RETURNS [syms: Item] =
BEGIN
mdi: Symbols.MDIndex;
syms ← Storage.Node[SIZE[ItemObject]];
IF seg = NIL THEN
BEGIN
syms↑ ← [link: Head, gf: gf, table: seg, fgtAvailable: fgt,
symbol: hash[HtiFromLoadState[gf]], outerCtx: Symbols.IncludedCTXNull,
directoryCtx: Symbols.IncludedCTXNull,
importCtx: Symbols.IncludedCTXNull, crossJumped:jumped, stopping:];
Head ← syms;
ERROR SymbolTable.Missing[NIL];
END
ELSE
BEGIN
mdi ← Copier.EnterFileSegment[hti,version,seg];
syms↑ ← [link: Head, gf: gf, table:seg, fgtAvailable:fgt,
symbol: mod[mdi], outerCtx: Symbols.IncludedCTXNull,
directoryCtx: Symbols.IncludedCTXNull,
importCtx: Symbols.IncludedCTXNull, crossJumped:jumped, stopping:];
Head ← syms;
END;
Copier.Outer[mdi,EnterContexts];
Table.AddNotify[Notify];
mdb[mdi].shared ← TRUE;
IF mdb[mdi].moduleId = Symbols.HTNull THEN
BEGIN
ssd: String.SubStringDescriptor;
IF s = NIL THEN ERROR SymbolTableProblem
ELSE ssd ← [base: s, length: s.length, offset: 0];
mdb[mdi].moduleId ← SymbolOps.EnterString[@ssd];
s ← Storage.FreeStringNil[s];
END;
[] ← Copier.EnterFileSegment[mdb[mdi].moduleId,version,seg];
Table.DropNotify[Notify];
syms.outerCtx ← Copier.FindExternalCtx[mdi,syms.outerCtx];
syms.directoryCtx ← Copier.FindExternalCtx[mdi,syms.directoryCtx];
syms.importCtx ← Copier.FindExternalCtx[mdi,syms.importCtx];
RETURN
END;
SetSegment: PROC [syms: Item, fgt: BOOLEAN] =
BEGIN
IF ~fgt OR syms.fgtAvailable THEN RETURN;
WITH syms SELECT FROM
hash => ERROR SymbolTable.Missing[NIL];
mod => ERROR NoFGT;
ENDCASE;
END;
EnterContexts: PROC [base: SymbolTable.Base] =
BEGIN
mdb: Table.Base ← Table.Bounds[Symbols.mdType].base;
ssd: String.SubStringDescriptor;
ss: String.SubString = @ssd;
Head.outerCtx ← base.mainCtx;
Head.directoryCtx ← base.stHandle.directoryCtx;
Head.importCtx ← base.stHandle.importCtx;
Head.stopping ← base.bb[Symbols.RootBti].stopping;
WITH Head SELECT FROM
mod => IF mdb[mdi].moduleId # Symbols.HTNull THEN RETURN;
ENDCASE => ERROR SymbolTableProblem;
base.SubStringForHash[ss,base.mdb[Symbols.OwnMdi].moduleId];
IF s # NIL THEN ERROR SymbolTableProblem;
s ← Storage.String[ss.length];
String.AppendSubString[s,ss];
END;
AttachSyms: PUBLIC PROC [gf: GFHandle, file: STRING] =
BEGIN
syms: Item;
mod: STRING ← [40];
version: BcdDefs.VersionStamp;
fgt, jumped: BOOLEAN;
seg: MachineDefs.FSHandle;
fh: FileHandle;
String.AppendString[mod,file]; StripExtension[mod];
String.AppendString[mod,".bcd"L];
fh ← SegmentDefs.NewFile[mod,SegmentDefs.Read,SegmentDefs.OldFileOnly !
SegmentDefs.FileNameError => {SIGNAL Lookup.Fail[mod]; CONTINUE}];
IF gf # NIL AND (syms ← FindFrame[gf]) # NIL THEN
{syms.table ← NIL; CleanItems[]};
[version:version, seg:seg, jumped:jumped, fgt:fgt] ← CompilerSeg[gf,fh !
CantAttach =>
BEGIN OPEN DOutput;
Blanks[1]; Text[mod]; Text[" is a definitions file!"L];
GOTO bad
END];
[] ← CacheItem[
hti:Symbols.HTNull, gf:gf, version:version, seg:seg, fgt:fgt,
jumped:jumped
! SymbolTable.Missing =>
BEGIN OPEN DOutput;
Blanks[1]; Text[mod]; Text[" does not have a valid symbol table!"L];
CONTINUE
END];
DebugOps.InvalidateFileCache[];
EXITS bad => NULL
END;
CompilerSeg: PROC [gf: GFHandle, file: FileHandle] RETURNS [
version: BcdDefs.VersionStamp, seg: FSHandle, fgt,jumped: BOOLEAN] =
BEGIN OPEN SegmentDefs;
sgh: BcdOps.SGHandle;
mth: BcdOps.MTHandle;
sSeg: BcdDefs.SGIndex;
bcdPages: CARDINAL ← 1;
bcd: BcdOps.BcdBase;
headerSeg: FSHandle ← NewFileSegment[file, 1, bcdPages, Read];
DO
SwapIn[headerSeg]; bcd ← FileSegmentAddress[headerSeg];
IF bcd.versionIdent # BcdDefs.VersionID THEN
{CleanupSeg[headerSeg]; RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE]};
IF bcdPages = bcd.nPages THEN EXIT;
bcdPages ← bcd.nPages;
Unlock[headerSeg]; SwapOut[headerSeg];
MoveFileSegment[headerSeg, 1, bcdPages];
ENDLOOP;
IF bcd.nConfigs # 0 THEN
{CleanupSeg[headerSeg]; RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE]};
IF bcd.definitions AND gf # NIL THEN
{CleanupSeg[headerSeg]; ERROR CantAttach};
mth ← @LOOPHOLE[bcd+bcd.mtOffset,Table.Base][FIRST[BcdDefs.MTIndex]];
sSeg ← mth.sseg; jumped ← mth.crossJumped;
sgh ← @LOOPHOLE[bcd+bcd.sgOffset,Table.Base][sSeg];
IF sSeg=BcdDefs.SGNull OR sgh.pages = 0 OR sgh.file # BcdDefs.FTSelf THEN
{CleanupSeg[headerSeg]; RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE]};
version ← bcd.version;
seg ← NewFileSegment[file, sgh.base, sgh.pages+sgh.extraPages, Read];
fgt ← sgh.extraPages # 0;
CleanupSeg[headerSeg];
END;
SymbolSegForFrame: PROCEDURE [f: GFHandle] RETURNS [
version: BcdDefs.VersionStamp, seg: FSHandle, fgt,jumped: BOOLEAN] =
BEGIN OPEN LoadStateOps, SegmentDefs, BcdDefs, BcdOps;
cgfi: GFTIndex;
config: LoadStateOps.ConfigIndex;
bcd: BcdBase;
cdesc, segdesc: SGIndex;
FindModule: PROCEDURE [mth: MTHandle, mti: MTIndex] RETURNS [BOOLEAN] =
BEGIN
IF cgfi IN [mth.gfi..mth.gfi+mth.ngfi) THEN
BEGIN
cdesc ← mth.code.sgi;
segdesc ← mth.sseg;
jumped ← mth.crossJumped;
RETURN[TRUE];
END;
RETURN[FALSE];
END;
BEGIN
f ← Gf.Original[f];
[] ← InputLoadState[ ! LoadStateInvalid => GOTO nil];
[cgfi,config] ← MapRealToConfig[Gf.GFI[f]];
IF config = NullConfig THEN ERROR Frames.Invalid[f !
UNWIND => ReleaseLoadState[]];
bcd ← AcquireBcd[config];
[] ← BcdOps.ProcessModules[bcd, FindModule];
[version: version, seg:seg, fgt: fgt] ←
FindSeg[f, bcd, segdesc, cdesc !
FileNameError, FileError => {Cleanup[bcd]; GOTO nil};
UNWIND => Cleanup[bcd]];
Cleanup[bcd];
EXITS
nil => RETURN[BcdDefs.NullVersion,NIL,FALSE,FALSE];
END;
RETURN
END;
FindSeg: PROCEDURE [
frame: GFHandle, bcd: BcdOps.BcdBase, syms, code: BcdDefs.SGIndex]
RETURNS [version: BcdDefs.VersionStamp, seg: FSHandle, fgt: BOOLEAN] =
BEGIN OPEN SegmentDefs, BcdDefs, BcdOps;
ss: String.SubStringDescriptor;
tempssb: NameString;
name: STRING ← [40];
file: FileHandle;
symsbcd: BcdOps.BcdBase;
bcdseg: FSHandle ← VMtoFileSegment[bcd];
sgb: Base ← LOOPHOLE[bcd+bcd.sgOffset];
sgh: SGHandle ← @sgb[syms];
f: FTHandle = @LOOPHOLE[bcd+bcd.ftOffset, Base][sgh.file];
BEGIN
SELECT sgh.file FROM
FTNull => RETURN[BcdDefs.NullVersion,NIL,FALSE];
FTSelf =>
BEGIN
version ← f.version;
seg ← NewFileSegment[bcdseg.file, sgh.base, sgh.pages+sgh.extraPages, Read];
fgt ← sgh.extraPages # 0;
RETURN;
END;
sgb[code].file =>
IF (file ← Gf.File[frame]) # NIL THEN GOTO found;
ENDCASE;
tempssb ← LOOPHOLE[bcd+bcd.ssOffset];
ss ← [@tempssb.string, f.name, tempssb.size[f.name]];
String.AppendSubString[name, @ss];
CheckExtension[name];
file ← DebugOps.CacheNewFile[name, DefaultAccess];
EXITS
found => NULL;
END;
seg ← NewFileSegment[file, 1, 1, Read];
SwapIn[seg];
symsbcd ← FileSegmentAddress[seg];
IF symsbcd.version # f.version THEN
BEGIN
IF name.length = 0 THEN DebugOps.FileName[name, file];
Unlock[seg];
DeleteFileSegment[seg];
IncorrectVersion[name];
RETURN[BcdDefs.NullVersion,NIL,FALSE];
END;
Unlock[seg];
MoveFileSegment[seg, sgh.base, sgh.pages+sgh.extraPages];
version ← f.version;
fgt ← sgh.extraPages # 0;
RETURN;
END;
IncorrectVersion: PROC [name: STRING] =
BEGIN OPEN DOutput;
Char[' ]; Text[name]; Text[" referenced in different versions! "L];
END;
StripExtension: PUBLIC PROCEDURE [name: STRING] =
BEGIN
i: CARDINAL;
FOR i DECREASING IN [1..name.length) DO
IF name[i] = '. THEN {name.length ← i; RETURN};
ENDLOOP;
END;
CheckExtension: PROCEDURE [s: STRING] =
BEGIN
i: CARDINAL;
FOR i DECREASING IN [1..s.length) DO
IF s[i] = '. THEN RETURN;
ENDLOOP;
String.AppendString[s,".bcd"L];
END;
CleanupSeg: PROCEDURE [seg: FSHandle] =
BEGIN
SegmentDefs.Unlock[seg];
SegmentDefs.DeleteFileSegment[seg];
END;
Cleanup: PROCEDURE [bcd: BcdOps.BcdBase] =
BEGIN
LoadStateOps.ReleaseBcd[bcd];
LoadStateOps.ReleaseLoadState[];
RETURN
END;
SymbolTablePages: CARDINAL = 20;
SymbolTableSize: CARDINAL = SymbolTablePages*MachineDefs.PageSize;
bounds: ARRAY SymbolSegment.Tables OF CARDINAL;
Initialize: PUBLIC PROCEDURE =
BEGIN
i: Table.Selector;
weights: ARRAY SymbolSegment.Tables OF CARDINAL ← ALL[1];
Table.Create[[origin: LOOPHOLE[
Storage.Pages[SymbolTablePages],CARDINAL], size: SymbolTableSize],
DESCRIPTOR[weights]];
START SymbolPack;
data.bodyRoot ← FIRST[Symbols.BTIndex];
data.definitionsOnly ← FALSE;
SymbolOps.Initialize[];
LiteralOps.Initialize[];
TreeOps.Initialize[];
CompilerUtil.PrefillSymbols[];
Copier.FileInit["XDebug"L, BcdDefs.NullVersion];
Copier.CopierInit[FALSE];
Copier.CreateFileTable[16];
FOR i IN SymbolSegment.Tables DO
bounds[i] ← Table.Bounds[i].size;
ENDLOOP;
END;
Prune: PUBLIC PROCEDURE =
BEGIN
i: Table.Selector;
DI.ResetLongs[];
FOR i IN SymbolSegment.Tables DO
Table.Trim[i, bounds[i]];
ENDLOOP;
SymbolOps.Reset[];
END;
END...