-- SymsMed.Mesa Edited by:
-- Bruce Oct 9, 1980 7:45 PM
-- Sandman July 17, 1980 11:10 AM
-- Johnsson July 21, 1980 5:19 PM
DIRECTORY
BcdDefs USING [
Base, BCD, FTNull, FTSelf, GFTIndex, MTIndex, NameRecord, NullVersion, SGIndex,
SGNull, VersionID, VersionStamp],
BcdOps USING [BcdBase, FTHandle, MTHandle, NameString, ProcessModules, SGHandle],
DebugOps USING [CacheNewFile, 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],
Lookup USING [Fail],
MachineDefs USING [
ConfigIndex, CoPilot, FileHandle, FSHandle, GFHandle, GFTIndex, NullConfig],
Segments USING [
DefaultAccess, DeleteSegment, FileProblem, FileNameProblem, SegmentAddress,
MoveSegment, NewFile, NewSegment, OldFileOnly, PageNumber, Read, SwapIn,
SwapOut, Unlock, VMtoSegment, FileFromSegment],
String USING [AppendString],
Strings USING [AppendSubString, EquivalentSubString, SubStringDescriptor],
SymbolOps USING [EnterString],
Symbols USING [HTIndex, HTNull],
SymbolTable USING [Missing],
Table USING [Base],
UserInput USING [userAbort];
SymsMed: PROGRAM
IMPORTS BcdOps, DLoadState, Strings,
DSymOps, DSyms, DebugOps, DOutput, Frames, Gf,
Lookup, Segments, String, SymbolOps, SymbolTable, UserInput
EXPORTS DSymOps =
BEGIN OPEN DSymOps, DSyms, MachineDefs;
CantAttach: ERROR = CODE;
WrongVersion: ERROR = CODE;
SymbolTableProblem: ERROR = CODE;
ssb: BcdOps.NameString;
bcd: BcdOps.BcdBase ← NIL;
sgb: BcdDefs.Base ← NIL;
sgh: BcdOps.SGHandle;
SymbolSegForFrame: PUBLIC PROCEDURE [h: SymHandle] =
BEGIN
cgfi: GFTIndex;
config: ConfigIndex;
tryBcd: BOOLEAN ← FALSE;
name: BcdDefs.NameRecord;
saveMth: BcdOps.MTHandle;
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
saveMth ← mth;
sgh ← @sgb[mth.sseg];
IF h.hti = Symbols.HTNull THEN {
ssd ← [base: @ssb.string, offset: mth.name, length: ssb.size[mth.name]];
h.hti ← SymbolOps.EnterString[@ssd]};
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];
IF sgh.file # sgb[mth.code.sgi].file THEN {
name ← f.name; h.version ← f.version; tryBcd ← TRUE} };
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];
sgb ← LOOPHOLE[bcd+bcd.sgOffset];
[] ← BcdOps.ProcessModules[bcd, FindModule ! UNWIND => Cleanup[]];
IF tryBcd THEN LookForBcd[h, name !
Segments.FileNameProblem[], Segments.FileProblem[] => CONTINUE;
UNWIND => Cleanup[]];
IF h.seg = NIL THEN FindSeg[h, saveMth !
Segments.FileNameProblem[], Segments.FileProblem[] => {Cleanup[]; GOTO nil};
UNWIND => Cleanup[]];
Cleanup[];
IF h.hti = Symbols.HTNull THEN ERROR Frames.Invalid[h.gf];
EXITS nil => RETURN;
END;
LookForBcd: PROCEDURE [h: SymHandle, name: BcdDefs.NameRecord] =
BEGIN OPEN Segments;
file: FileHandle;
filename: STRING ← [40];
MakeName[filename, name, TRUE];
file ← DebugOps.CacheNewFile[filename, Segments.DefaultAccess];
CompilerSeg[h, file ! WrongVersion => {IncorrectVersion[filename]; CONTINUE}];
END;
FindSeg: PROCEDURE [h: SymHandle, mth: BcdOps.MTHandle] =
BEGIN OPEN Segments;
file: FileHandle ← NIL;
f: BcdOps.FTHandle = @LOOPHOLE[bcd+bcd.ftOffset, BcdDefs.Base][sgh.file];
name: BcdDefs.NameRecord;
SELECT sgh.file FROM
BcdDefs.FTNull => RETURN;
BcdDefs.FTSelf => IF MachineDefs.CoPilot THEN {
name ← bcd.source; h.version ← bcd.version;
IF ~EquivalentNames[bcd, mth.name, name] THEN {
TryName[h, mth.name, TRUE !
Segments.FileNameProblem[], Segments.FileProblem[] => CONTINUE];
IF h.seg # NIL THEN RETURN} }
ELSE {
bcdseg: FSHandle ← VMtoSegment[bcd];
h.seg ← NewSegment[FileFromSegment[bcdseg], sgh.base, sgh.pages+sgh.extraPages];
h.fgt ← sgh.extraPages # 0;
h.version ← f.version;
RETURN};
sgb[mth.code.sgi].file => {
IF ~MachineDefs.CoPilot THEN file ← Gf.File[h.gf];
name ← f.name; h.version ← f.version}
ENDCASE => {name ← f.name; h.version ← f.version};
TryName[h, name, sgh.file = BcdDefs.FTSelf, file];
RETURN;
END;
TryName: PROCEDURE [
h: SymHandle, name: BcdDefs.NameRecord, force: BOOLEAN, file: FileHandle ← NIL] =
BEGIN OPEN Segments;
filename: STRING ← [40];
symsbcd: BcdOps.BcdBase;
IF file = NIL THEN {
MakeName[filename, name, force];
file ← DebugOps.CacheNewFile[filename, Segments.DefaultAccess]};
h.seg ← NewSegment[file, 1, 1];
SwapIn[h.seg];
symsbcd ← SegmentAddress[h.seg];
IF symsbcd.version # h.version THEN {
Unlock[h.seg]; DeleteSegment[h.seg]; h.seg ← NIL;
IncorrectVersion[filename];
RETURN};
Unlock[h.seg];
MoveSegment[h.seg, sgh.base, sgh.pages+sgh.extraPages];
h.fgt ← sgh.extraPages # 0;
RETURN;
END;
MakeName: PROC [
fileName: STRING, name: BcdDefs.NameRecord, force: BOOLEAN] = {
ss: Strings.SubStringDescriptor ← [@ssb.string, name, ssb.size[name]];
Strings.AppendSubString[fileName, @ss];
CheckForExtension[fileName, ".bcd"L, force]};
EquivalentNames: PROC [ bcd: BcdOps.BcdBase, n1, n2: BcdDefs.NameRecord]
RETURNS [BOOLEAN] = {
ssb: BcdOps.NameString = LOOPHOLE[bcd+bcd.ssOffset];
ss1: Strings.SubStringDescriptor ← [@ssb.string, n1, ssb.size[n1]];
ss2: Strings.SubStringDescriptor ← [@ssb.string, n2, ssb.size[n2]];
RETURN[Strings.EquivalentSubString[@ss1, @ss2]]};
Cleanup: PROC [] = {
DLoadState.ReleaseBcd[bcd]; DLoadState.Release[]};
IncorrectVersion: PROC [name: STRING] =
BEGIN OPEN DOutput;
Char[' ]; Text[name]; Text[" referenced in different versions! "L];
END;
CheckForExtension: PROCEDURE [name, ext: STRING, force: BOOLEAN ← FALSE] =
BEGIN
i: CARDINAL;
FOR i IN [0..name.length) DO
IF name[i] = '. THEN IF force THEN {name.length ← i; EXIT} ELSE RETURN;
ENDLOOP;
String.AppendString[name, ext];
RETURN
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 ← Segments.NewFile[mod,Segments.Read,Segments.OldFileOnly !
Segments.FileNameProblem[] => {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 Segments;
sgh: BcdOps.SGHandle;
mth: BcdOps.MTHandle;
ssb: BcdOps.NameString;
sSeg: BcdDefs.SGIndex;
bcdPages: CARDINAL ← 1;
bcd: BcdOps.BcdBase;
headerSeg: FSHandle ← NewSegment[file, 1, bcdPages];
ssd: Strings.SubStringDescriptor;
BEGIN
DO
SwapIn[headerSeg]; bcd ← SegmentAddress[headerSeg];
IF bcd.versionIdent # BcdDefs.VersionID THEN GOTO nogood;
IF bcdPages = bcd.nPages THEN EXIT;
bcdPages ← bcd.nPages;
Unlock[headerSeg]; SwapOut[headerSeg];
MoveSegment[headerSeg, 1, bcdPages];
ENDLOOP;
IF h.version # BcdDefs.NullVersion AND bcd.version # h.version THEN {
CleanupSeg[headerSeg]; ERROR WrongVersion};
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 ← NewSegment[file, sgh.base, sgh.pages+sgh.extraPages];
h.fgt ← sgh.extraPages # 0;
CleanupSeg[headerSeg];
EXITS nogood => CleanupSeg[headerSeg];
END;
END;
CleanupSeg: PROCEDURE [seg: FSHandle] =
BEGIN
Segments.Unlock[seg];
Segments.DeleteSegment[seg];
END;
END...