-- SymsXD.Mesa Edited by:
-- Bruce September 2, 1980 2:20 PM
-- Sandman July 17, 1980 11:10 AM
-- Johnsson July 21, 1980 5:19 PM
DIRECTORY
BcdDefs USING [Base, BCD, FTNull, FTSelf, GFTIndex, MTIndex, NullVersion, SGIndex, SGNull, VersionID, VersionStamp],
BcdOps USING [BcdBase, FTHandle, MTHandle, NameString, ProcessModules, SGHandle],
DebugOps USING [CacheNewFile, FileName, InvalidateFileCache, UserAborted],
DLoadState USING [Acquire, AcquireBcd, Invalid, MapRealToConfig, Release, ReleaseBcd],
DOutput USING [Blanks, Char, Text],
DSymOps USING [CacheItem, DeleteItem, StripExtension, SymHandle, SymRec],
DSyms USING [FindFrame, Item],
Frames USING [Invalid],
Gf USING [File, GFI, Original],
ImageDefs USING [ImageVersion],
Lookup USING [Fail],
MachineDefs USING [ConfigIndex, FileHandle, FSHandle, GFHandle, GFTIndex, NullConfig, PageSize],
SegmentDefs USING [DefaultAccess, DeleteFileSegment, FileError, FileHandle, FileNameError, FileSegmentAddress, FileSegmentHandle, LongVMtoFileSegment, MoveFileSegment, NewFile, NewFileSegment, OldFileOnly, PageNumber, Read, SwapIn, SwapOut, Unlock],
Storage USING [Pages],
String USING [AppendString],
Strings USING [AppendSubString, SubStringDescriptor],
SymbolOps USING [EnterString],
Symbols USING [HTIndex, HTNull],
SymbolTable USING [Missing],
Table USING [Base, Region],
UserInput USING [userAbort];
SymsXD: PROGRAM
IMPORTS BcdOps, DLoadState, Strings,
DSymOps, DSyms, DebugOps, DOutput, Frames, Gf, ImageDefs,
Lookup, SegmentDefs, Storage, String, SymbolOps, SymbolTable, UserInput
EXPORTS DSymOps =
BEGIN OPEN DSymOps, DSyms, MachineDefs;
myVersion: PUBLIC BcdDefs.VersionStamp ← ImageDefs.ImageVersion[];
CantAttach: ERROR = CODE;
SymbolTableProblem: ERROR = CODE;
SymbolSegForFrame: PUBLIC PROCEDURE [h: SymHandle] =
BEGIN
cgfi: GFTIndex;
config: ConfigIndex;
ssb: BcdOps.NameString;
bcd: BcdOps.BcdBase;
cdesc, segdesc: BcdDefs.SGIndex;
FindModule: PROCEDURE [mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOLEAN] =
BEGIN
ssd: Strings.SubStringDescriptor;
IF cgfi IN [mth.gfi..mth.gfi+mth.ngfi) THEN
BEGIN
IF h.hti = Symbols.HTNull THEN {
ssd ← [base: @ssb.string, offset: mth.name, length: ssb.size[mth.name]];
h.hti ← SymbolOps.EnterString[@ssd]};
cdesc ← mth.code.sgi;
segdesc ← mth.sseg;
h.jumped ← mth.crossJumped;
SELECT mth.file FROM
BcdDefs.FTNull, BcdDefs.FTSelf => NULL;
ENDCASE => {
f: BcdOps.FTHandle = @LOOPHOLE[bcd+bcd.ftOffset, BcdDefs.Base][mth.file];
h.version ← f.version};
RETURN[TRUE];
END;
IF UserInput.userAbort THEN SIGNAL DebugOps.UserAborted;
RETURN[FALSE];
END;
[] ← DLoadState.Acquire[ ! DLoadState.Invalid => GOTO nil];
[cgfi,config] ← DLoadState.MapRealToConfig[Gf.GFI[Gf.Original[h.gf]]];
IF config = NullConfig THEN {
DLoadState.Release[]; ERROR Frames.Invalid[h.gf]};
bcd ← DLoadState.AcquireBcd[config];
ssb ← LOOPHOLE[bcd+bcd.ssOffset];
[] ← BcdOps.ProcessModules[bcd, FindModule ! UNWIND => Cleanup[bcd]];
FindSeg[h, bcd, segdesc, cdesc !
SegmentDefs.FileNameError, SegmentDefs.FileError => {Cleanup[bcd]; GOTO nil};
UNWIND => Cleanup[bcd]];
Cleanup[bcd];
IF h.hti = Symbols.HTNull THEN ERROR Frames.Invalid[h.gf];
EXITS nil => RETURN;
END;
FindSeg: PROCEDURE [h: SymHandle, bcd: BcdOps.BcdBase, syms, code: BcdDefs.SGIndex] =
BEGIN OPEN SegmentDefs;
sgb: BcdDefs.Base = LOOPHOLE[bcd+bcd.sgOffset];
sgh: BcdOps.SGHandle = @sgb[syms];
file: SegmentDefs.FileHandle ← NIL;
f: BcdOps.FTHandle = @LOOPHOLE[bcd+bcd.ftOffset, BcdDefs.Base][sgh.file];
symsbcd: BcdOps.BcdBase;
SELECT sgh.file FROM
BcdDefs.FTNull => RETURN;
BcdDefs.FTSelf =>
BEGIN
bcdseg: FSHandle ← LongVMtoFileSegment[bcd];
h.seg ← NewFileSegment[bcdseg.file, sgh.base, sgh.pages+sgh.extraPages, Read];
h.fgt ← sgh.extraPages # 0;
h.version ← f.version;
RETURN;
END;
sgb[code].file => file ← Gf.File[h.gf];
ENDCASE;
IF file = NIL THEN file ← OpenFile[bcd,f];
h.seg ← NewFileSegment[file, 1, 1, Read];
SwapIn[h.seg];
symsbcd ← FileSegmentAddress[h.seg];
IF symsbcd.version # f.version THEN {
Unlock[h.seg]; DeleteFileSegment[h.seg]; h.seg ← NIL;
IncorrectVersion[file]; RETURN};
Unlock[h.seg];
MoveFileSegment[h.seg, sgh.base, sgh.pages+sgh.extraPages];
h.fgt ← sgh.extraPages # 0;
RETURN;
END;
OpenFile: PROC [bcd: BcdOps.BcdBase, f: BcdOps.FTHandle]
RETURNS [fh: SegmentDefs.FileHandle] = {
ssb: BcdOps.NameString = LOOPHOLE[bcd+bcd.ssOffset];
ss: Strings.SubStringDescriptor ← [@ssb.string, f.name, ssb.size[f.name]];
name: STRING ← [40];
Strings.AppendSubString[name, @ss];
CheckExtension[name];
fh ← DebugOps.CacheNewFile[name, SegmentDefs.DefaultAccess] };
Cleanup: PROC [bcd: BcdOps.BcdBase] =
{DLoadState.ReleaseBcd[bcd]; DLoadState.Release[]};
IncorrectVersion: PROC [file: SegmentDefs.FileHandle] =
BEGIN OPEN DOutput;
name: STRING ← [40];
DebugOps.FileName[name, file];
Char[' ]; Text[name]; Text[" referenced in different versions! "L];
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;
AttachSyms: PUBLIC PROC [gf: GFHandle, file: STRING] =
BEGIN
syms: Item;
mod: STRING ← [40];
rec: SymRec ← [gf: gf, hti: Symbols.HTNull];
fh: FileHandle;
String.AppendString[mod,file]; DSymOps.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
DSymOps.DeleteItem[syms];
CompilerSeg[@rec,fh ! CantAttach =>
BEGIN OPEN DOutput;
Blanks[1]; Text[mod]; Text[" is a definitions file!"L];
GOTO bad
END];
[] ← CacheItem[@rec ! 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 [h: SymHandle, file: FileHandle] =
BEGIN OPEN SegmentDefs;
sgh: BcdOps.SGHandle;
mth: BcdOps.MTHandle;
ssb: BcdOps.NameString;
sSeg: BcdDefs.SGIndex;
bcdPages: CARDINAL ← 1;
bcd: BcdOps.BcdBase;
headerSeg: FSHandle ← NewFileSegment[file, 1, bcdPages, Read];
ssd: Strings.SubStringDescriptor;
BEGIN
DO
SwapIn[headerSeg]; bcd ← FileSegmentAddress[headerSeg];
IF bcd.versionIdent # BcdDefs.VersionID THEN GOTO nogood;
IF bcdPages = bcd.nPages THEN EXIT;
bcdPages ← bcd.nPages;
Unlock[headerSeg]; SwapOut[headerSeg];
MoveFileSegment[headerSeg, 1, bcdPages];
ENDLOOP;
IF bcd.nConfigs # 0 THEN GOTO nogood;
IF bcd.definitions AND h.gf # NIL THEN {CleanupSeg[headerSeg]; ERROR CantAttach};
mth ← @LOOPHOLE[bcd+bcd.mtOffset,Table.Base][FIRST[BcdDefs.MTIndex]];
sSeg ← mth.sseg; h.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
GOTO nogood;
ssb ← LOOPHOLE[bcd+bcd.ssOffset];
ssd ← [base: @ssb.string, offset: mth.name, length: ssb.size[mth.name]];
h.hti ← SymbolOps.EnterString[@ssd];
h.version ← bcd.version;
h.seg ← NewFileSegment[file, sgh.base, sgh.pages+sgh.extraPages, Read];
h.fgt ← sgh.extraPages # 0;
CleanupSeg[headerSeg];
EXITS nogood => CleanupSeg[headerSeg];
END;
END;
CleanupSeg: PROCEDURE [seg: FSHandle] =
BEGIN
SegmentDefs.Unlock[seg];
SegmentDefs.DeleteFileSegment[seg];
END;
SymbolTablePages: CARDINAL = 25;
SymbolTableSize: CARDINAL = SymbolTablePages*MachineDefs.PageSize;
GetRegion: PUBLIC PROCEDURE RETURNS [r: Table.Region] = {
r.origin ← LOOPHOLE[Storage.Pages[SymbolTablePages], Table.Base];
r.size ← SymbolTableSize};
END...