-- File ModuleSymbolsImpl.Mesa
-- Last edited by Lewis on 15-May-81 18:18:08
-- Last edited by Sweet on 2-Mar-81 15:15:02
DIRECTORY
BcdDefs USING [
FTIndex, FTNull, FTSelf, MTIndex, SGIndex, SGNull, VersionStamp],
Error USING [ErrorFile, WrongSymbolsVersion],
FileTable USING [Build, Destroy, HandleForFile, UnknownFile],
LongStorage USING [FreePages, Pages, PagesForWords],
ModuleSymbols USING [KnownSymbolsInfo],
PackageSymbols USING [
ConstRecord, InnerPackRecord, OPIndex, OPNull, OuterPackRecord],
PackEnviron USING [Copy, SymbolSegmentBase, SymSegHandle],
PackHeap USING [FreeSpace, GetSpace],
Segments USING [
Address, BaseFromSegment, DeleteSegment, FHandle, MoveSegment, NewSegment,
Read, SegmentAddress, SHandle, SwapIn, Unlock],
SourceBcd USING [
bcdBases, bcdHeader, EnumerateModules, ModuleNum, ModuleNumForMti],
Strings,
SymbolPack,
Symbols USING [HTIndex, HTNull, HTRecord],
SymbolSegment USING [VersionID],
SymbolTable USING [Base],
Table;
ModuleSymbolsImpl: PROGRAM
IMPORTS Error, FileTable, LongStorage, PackEnviron, PackHeap, Segments, SourceBcd,
ownSymbolPack: SymbolPack
EXPORTS ModuleSymbols =
BEGIN OPEN ModuleSymbols;
InvalidSymbols: PUBLIC ERROR = CODE;
SymbolsProblem: PUBLIC SIGNAL = CODE;
outerPackArray: PUBLIC LONG DESCRIPTOR FOR ARRAY OF PackageSymbols.OuterPackRecord;
innerPackArray: PUBLIC LONG DESCRIPTOR FOR ARRAY OF PackageSymbols.InnerPackRecord;
constArray: PUBLIC LONG DESCRIPTOR FOR ARRAY OF PackageSymbols.ConstRecord;
symbolSegmentOpen: BOOLEAN;
currentFile: Segments.FHandle;
currentSeg: Segments.SHandle;
knownSymbols: LONG DESCRIPTOR FOR ARRAY OF ModuleSymbols.KnownSymbolsInfo;
symbolPackStarted: BOOLEAN ← FALSE;
Load: PUBLIC PROC [mti: BcdDefs.MTIndex] =
BEGIN
sgi: BcdDefs.SGIndex;
fti: BcdDefs.FTIndex;
loadedBefore: BOOLEAN;
file: Segments.FHandle;
base: CARDINAL;
mNum: SourceBcd.ModuleNum;
pSymPages: CARDINAL;
codeVersion: BcdDefs.VersionStamp;
handle: PackEnviron.SymSegHandle;
sgi ← SourceBcd.bcdBases.mtb[mti].sseg;
fti ← SourceBcd.bcdBases.mtb[mti].file;
SELECT fti FROM
BcdDefs.FTNull => {SIGNAL SymbolsProblem; RETURN};
BcdDefs.FTSelf => codeVersion ← SourceBcd.bcdHeader.version;
ENDCASE => codeVersion ← SourceBcd.bcdBases.ftb[fti].version;
IF symbolSegmentOpen OR sgi = BcdDefs.SGNull THEN {SIGNAL SymbolsProblem; RETURN}
ELSE
BEGIN
mNum ← SourceBcd.ModuleNumForMti[mti];
[loadedBefore: loadedBefore, base: base, pages: pSymPages, file: file] ← knownSymbols[mNum];
IF file = currentFile THEN -- reuse (i.e. move) current file segment
Segments.MoveSegment[
seg: currentSeg,
base: base,
pages: pSymPages]
ELSE
BEGIN
IF currentSeg # NIL THEN Segments.DeleteSegment[currentSeg];
currentSeg ← Segments.NewSegment[
file: file,
base: base,
pages: pSymPages,
access: Segments.Read];
END;
symbolSegmentOpen ← TRUE;
IF ~loadedBefore THEN
BEGIN
Segments.SwapIn[seg: currentSeg, base: PackEnviron.SymbolSegmentBase];
handle ← Segments.SegmentAddress[currentSeg];
IF handle.version # codeVersion THEN
BEGIN
Error.WrongSymbolsVersion[
class: error, module: mti,
requiredVersion: codeVersion, actualVersion: handle.version];
Unload[];
ERROR InvalidSymbols;
END;
pSymPages ← LongStorage.PagesForWords[handle.constBlock.offset + handle.constBlock.size];
Segments.Unlock[currentSeg];
Segments.MoveSegment[
seg: currentSeg,
base: Segments.BaseFromSegment[currentSeg],
pages: pSymPages];
END;
currentFile ← file;
Segments.SwapIn[seg: currentSeg, base: PackEnviron.SymbolSegmentBase];
IF ~loadedBefore THEN
BEGIN
knownSymbols[mNum].pages ← pSymPages;
knownSymbols[mNum].loadedBefore ← TRUE;
END;
InstallTable[ownSymbolPack, currentSeg ! ANY => Unload[]];
END;
END;
Unload: PUBLIC PROC =
BEGIN
IF symbolSegmentOpen THEN {
Segments.Unlock[currentSeg];
IF BASE[outerPackArray] # NIL THEN PackHeap.FreeSpace[BASE[outerPackArray]];
outerPackArray ← DESCRIPTOR[NIL, 0];
IF BASE[innerPackArray] # NIL THEN PackHeap.FreeSpace[BASE[innerPackArray]];
innerPackArray ← DESCRIPTOR[NIL, 0];
IF BASE[constArray] # NIL THEN PackHeap.FreeSpace[BASE[constArray]];
constArray ← DESCRIPTOR[NIL, 0];
symbolSegmentOpen ← FALSE};
END;
InstallTable: PROC [base: SymbolTable.Base, seg: Segments.SHandle] =
BEGIN
b: Segments.Address = Segments.SegmentAddress[seg];
tB: Table.Base = LOOPHOLE[b];
p: PackEnviron.SymSegHandle = b;
IF p.versionIdent # SymbolSegment.VersionID THEN {Unload[]; ERROR InvalidSymbols};
base.cacheInfo ← NIL;
base.hashVec ← b + p.hvBlock.offset;
base.ht ← DESCRIPTOR[
b + p.htBlock.offset,
p.htBlock.size / SIZE[Symbols.HTRecord]];
base.ssb ← b + p.ssBlock.offset;
base.stHandle ← p;
base.sourceFile ← NIL;
base.notifier ← NullNotifier;
outerPackArray ← DESCRIPTOR[
PackHeap.GetSpace[p.outerPackBlock.size],
(p.outerPackBlock.size / SIZE[PackageSymbols.OuterPackRecord])];
PackEnviron.Copy[
from: (b + p.outerPackBlock.offset), to: BASE[outerPackArray],
nwords: p.outerPackBlock.size];
innerPackArray ← DESCRIPTOR[
PackHeap.GetSpace[p.innerPackBlock.size],
(p.innerPackBlock.size / SIZE[PackageSymbols.InnerPackRecord])];
PackEnviron.Copy[
from: (b + p.innerPackBlock.offset), to: BASE[innerPackArray],
nwords: p.innerPackBlock.size];
constArray ← DESCRIPTOR[
PackHeap.GetSpace[p.constBlock.size],
(p.constBlock.size / SIZE[PackageSymbols.ConstRecord])];
PackEnviron.Copy[
from: (b + p.constBlock.offset), to: BASE[constArray],
nwords: p.constBlock.size];
END;
NullNotifier: PROC [SymbolTable.Base] = {NULL};
FindProc: PUBLIC PROC [
ss: Strings.SubString] RETURNS [opi: PackageSymbols.OPIndex] =
BEGIN
hti: Symbols.HTIndex = ownSymbolPack.FindString[ss];
l, u, i: PackageSymbols.OPIndex;
IF hti = Symbols.HTNull THEN RETURN[PackageSymbols.OPNull];
l ← 1; u ← (LENGTH[outerPackArray] - 1);
WHILE l <= u DO
i ← CARDINAL[l+u]/2;
SELECT outerPackArray[i].hti FROM
> hti => u ← i-1;
< hti => l ← i+1;
ENDCASE => RETURN [i];
ENDLOOP;
RETURN [PackageSymbols.OPNull];
END;
Initialize: PUBLIC PROC [nModules: CARDINAL] =
BEGIN
FillInKnowledge: PROC [mti: BcdDefs.MTIndex] RETURNS [stop: BOOLEAN] =
BEGIN
mNum: SourceBcd.ModuleNum = SourceBcd.ModuleNumForMti[mti];
sgi: BcdDefs.SGIndex;
file: Segments.FHandle ← NIL;
base: CARDINAL;
IF SourceBcd.bcdBases.mtb[mti].tableCompiled THEN -- ignore any symbols
knownSymbols[mNum] ← [
loadedBefore: FALSE, file: NIL, base: 0, pages: 0]
ELSE
BEGIN
sgi ← SourceBcd.bcdBases.mtb[mti].sseg;
base ← SourceBcd.bcdBases.sgb[sgi].base;
file ← FileTable.HandleForFile[SourceBcd.bcdBases.sgb[sgi].file
! FileTable.UnknownFile =>
BEGIN
Error.ErrorFile[error, "was needed for symbols but could not be found"L, fti];
CONTINUE;
END ];
knownSymbols[mNum] ← [
loadedBefore: FALSE, file: file, base: base, pages: 1];
END;
RETURN[FALSE]
END;
FileTable.Build[];
symbolSegmentOpen ← FALSE;
currentFile ← NIL; currentSeg ← NIL;
knownSymbols ← DESCRIPTOR[
LongStorage.Pages[LongStorage.PagesForWords[nModules * SIZE[KnownSymbolsInfo]]],
nModules];
SourceBcd.EnumerateModules[FillInKnowledge];
-- the array in FileTableImpl could go away now
IF ~symbolPackStarted THEN
{START ownSymbolPack; symbolPackStarted ← TRUE};
END;
Finalize: PUBLIC PROC =
BEGIN
IF symbolSegmentOpen THEN Unload[];
IF currentSeg # NIL THEN Segments.DeleteSegment[currentSeg];
symbolSegmentOpen ← FALSE;
LongStorage.FreePages[BASE[knownSymbols]];
FileTable.Destroy[];
currentFile ← NIL; currentSeg ← NIL;
END;
END.