MobSymbolPack.mesa
Copyright Ó 1985, 1989, 1991 by Xerox Corporation. All rights reserved.
Satterthwaite on March 14, 1986 12:04:31 pm PST
Lewis on 27-Mar-81 10:04:27
Maxwell, August 11, 1983 2:24 pm
Paul Rovner, November 21, 1983 12:34 pm
Russ Atkinson (RRA) March 7, 1985 0:15:19 am PST
Andy Litman May 31, 1988 9:50:33 pm PDT
JKF July 22, 1989 3:56:14 pm PDT
DIRECTORY
Alloc USING [AddNotify, Base, DropNotify, Handle, InstanceData, Notifier],
CinderSysOps USING [Close, Open, OpenKind],
ConvertUnsafe USING [LS, SubString, SubStringToRope],
IO USING [STREAM],
MobComData USING [Data, data],
MobDefs USING [Base, FTIndex, FTNull, fttype, IMPIndex, IMPRecord, LFIndex, lftype, Link, LinkOffset, LinkTag, Mob, MobBase, MobOffset, ModuleIndex, MTIndex, MTNull, mttype, NameRecord, Selector, SGIndex, SGNull, sgtype, sstype, VersionStamp],
MobErrorDefs USING [InterfaceId],
MobOps USING [Configuration, Cookie, CookieObj, DoMobStream, DoSymbols, FileError, NoSymbols, WrongMobdefsVersion, WrongSymbolsVersion],
OSMiscOps USING [],
Rope USING [ActionType, Concat, FetchType, Find, MapType, MoveType, ROPE],
SymbolOps USING [DecodeBitAddr, DecodeCard, DecodeLink, FirstCtxSe, LinkMode, NextSe, STB, SubStringForName, UnderType],
Symbols USING [Base, BitAddress, BitCount, CSEIndex, CTXIndex, HashVector, ISEIndex, ISENull, Linkage, MDIndex, Name, nullName, nullType, nullUNSPEC, Type, TypeClass, UNSPEC],
SymbolTable USING [SymbolTableBaseRep],
SymbolTablePrivate USING [FGTEntryArray, FGTEntryArrayDesc, HashVectorPtr, STHeaderPtr, SymbolTableBase, SymbolTableBaseRep];
MobSymbolPack: PROGRAM
IMPORTS Alloc, CinderSysOps, ConvertUnsafe, Rope, MobComData, SymbolOps, MobOps
EXPORTS MobErrorDefs, SymbolTable = {
OPEN MobDefs, MobComData;
mtb, lfb, sgb, ftb: MobDefs.Base;
ssb: LONG STRING;
Base: TYPE = REF SymbolTableBaseRep;
SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep;
Notifier: Alloc.Notifier ~ {
mtb ¬ base[mttype];
lfb ¬ base[lftype];
sgb ¬ base[sgtype];
ftb ¬ base[fttype];
ssb ¬ base[sstype]};
Initialize: PUBLIC PROC ~ {};
Finalize: PUBLIC PROC ~ {};
ExportItemName: PUBLIC PROC[export: MobErrorDefs.InterfaceId, ep: CARDINAL, userProc: PROC[ConvertUnsafe.SubString]] ~ {
(data.table).AddNotify[Notifier];
PrintNameFromInterface[export, ep, userProc];
(data.table).DropNotify[Notifier]};
ImportItemName: PUBLIC PROC[import: MobErrorDefs.InterfaceId, ep: CARDINAL, clientMti: MobDefs.MTIndex, linkOffset: CARDINAL, link: MobDefs.Link, userProc: PROC[ConvertUnsafe.SubString]] ~ {
(data.table).AddNotify[Notifier];
IF clientMti = MobDefs.MTNull THEN RETURN;
IF mtb[clientMti].sseg # MobDefs.SGNull
THEN PrintNameFromModule[import, clientMti, linkOffset, link, userProc]
ELSE PrintNameFromInterface[import, ep, userProc];
(data.table).DropNotify[Notifier]};
VersionForModuleIndex: PROC[impb, ftb: MobDefs.Base, modIndex: MobDefs.ModuleIndex]
RETURNS[MobDefs.VersionStamp] = {
FOR impi: MobDefs.IMPIndex ¬ MobDefs.IMPIndex.FIRST,
impi + MobDefs.IMPRecord.SIZE DO
IF impb[impi].modIndex = modIndex THEN RETURN[ftb[impb[impi].file].version];
ENDLOOP };
PrintNameFromModule: PROC[
import: MobErrorDefs.InterfaceId,
importerMti: MobDefs.MTIndex,
linkOffset: CARDINAL,
link: MobDefs.Link,
userProc: PROC[ConvertUnsafe.SubString]] ~ {
key: Symbols.BitAddress ~ ComputeAddress[importerMti, linkOffset];
mobimpb, mobftb: MobDefs.Base ¬ NIL;
DoSymbols: PROC[sym: Base] = {
OPEN Symbols;
Imported: PROC[sei: Symbols.ISEIndex] RETURNS[BOOL] ~ INLINE {
RETURN[sym.seb[sei].linkSpace AND ~sym.seb[sei].extended]};
LinksMatch: PROC[link, linkInSym: MobDefs.Link] RETURNS[BOOL] ~ {
RETURN[
linkInSym.tag = link.tag AND
linkInSym.offset = link.offset AND
ftb[import.fti].version = -- link.version
VersionForModuleIndex[mobimpb, mobftb, linkInSym.modIndex]]};
importCtx: CTXIndex;
sei: ISEIndex;
type: CSEIndex;
IF sym = NIL THEN RETURN;
importCtx ¬ sym.stHandle.importCtx;
FOR iSei: ISEIndex ¬ SymbolOps.FirstCtxSe[sym, importCtx],
SymbolOps.NextSe[sym, iSei] UNTIL iSei = ISENull DO
type ¬ SymbolOps.UnderType[sym, sym.seb[iSei].idType];
WITH t~~sym.seb[type] SELECT FROM
definition =>
FOR sei ¬ SymbolOps.FirstCtxSe[sym, t.defCtx],
SymbolOps.NextSe[sym, sei] UNTIL sei = ISENull DO
IF Imported[sei] AND
LinksMatch[link, SymbolOps.DecodeLink[sym.seb[sei].idValue]]
THEN GO TO Found;
ENDLOOP;
ref =>
IF Imported[iSei] AND
SymbolOps.DecodeBitAddr[sym.seb[iSei].idValue] = key
THEN {sei ¬ iSei; GO TO Found};
ENDCASE => NULL;
REPEAT
Found => {
d: ConvertUnsafe.SubString;
d ¬ SymbolOps.SubStringForName[sym, sym.seb[sei].hash];
userProc[d ! UNWIND => {(data.table).DropNotify[Notifier]}]};
ENDLOOP};
DoMob: PROC[mob: MobDefs.MobBase, cookie: MobOps.Cookie] = {
IF mob = NIL THEN RETURN;
mobimpb ¬ LOOPHOLE[mob + mob.impOffset.units];
mobftb ¬ LOOPHOLE[mob + mob.ftOffset.units];
MobOps.DoSymbols[cookie, DoSymbols !
MobOps.Configuration => CONTINUE;
MobOps.NoSymbols => CONTINUE;
MobOps.WrongSymbolsVersion => CONTINUE]};
sgi: MobDefs.SGIndex = mtb[importerMti].sseg;
IF sgb[sgi].file # FTNull THEN {
name: Rope.ROPE ¬ GetMobName[ftb[sgb[sgi].file].name];
openFile: IO.STREAM ¬ CinderSysOps.Open[name, $read].stream;
Cleanup: PROC[] = {[] ¬ CinderSysOps.Close[openFile, FALSE]};
IF openFile # NIL THEN {
MobOps.DoMobStream[openFile, DoMob !
MobOps.FileError => {Cleanup[]; CONTINUE};
MobOps.WrongMobdefsVersion => {Cleanup[]; CONTINUE}];
Cleanup[];
};
};
};
ComputeAddress: PROC[mti: MobDefs.MTIndex, linkOffset: CARDINAL]
RETURNS[Symbols.BitAddress] ~ {
linkLength: CARDINAL ~ lfb[mtb[mti].links].length;
RETURN[[bd~((linkLength-1)-linkOffset)*BITS[MobDefs.Link]]]};
PrintNameFromInterface: PROC[
id: MobErrorDefs.InterfaceId,
ep: CARDINAL,
userProc: PROC[ConvertUnsafe.SubString]] ~ {
DoSymbols: PROC[sym: Base] = {
OPEN Symbols;
outerCtx: CTXIndex;
d: ConvertUnsafe.SubString;
IF sym = NIL THEN RETURN;
outerCtx ¬ sym.stHandle.outerCtx;
FOR sei: ISEIndex ¬ SymbolOps.FirstCtxSe[sym, outerCtx],
SymbolOps.NextSe[sym, sei] UNTIL sei = ISENull DO
SELECT SymbolOps.LinkMode[sym, sei] FROM
$val, $ref, $type =>
IF SymbolOps.DecodeCard[sym.seb[sei].idValue] = ep THEN {
d ¬ SymbolOps.SubStringForName[sym, sym.seb[sei].hash];
userProc[d !
UNWIND => {(data.table).DropNotify[Notifier]}]};
ENDCASE;
ENDLOOP};
DoMob: PROC[mob: MobDefs.MobBase, cookie: MobOps.Cookie] = {
IF mob = NIL OR ~mob.definitions THEN RETURN;
MobOps.DoSymbols[cookie, DoSymbols !
MobOps.Configuration => CONTINUE;
MobOps.NoSymbols => CONTINUE;
MobOps.WrongSymbolsVersion => CONTINUE]};
IF id.fti # FTNull THEN {
name: Rope.ROPE ¬ GetMobName[ftb[id.fti].name];
openFile: IO.STREAM ¬ CinderSysOps.Open[name, $read].stream;
LocalCleanup: PROC[] = {[] ¬ CinderSysOps.Close[openFile, FALSE]};
IF openFile # NIL THEN {
MobOps.DoMobStream[openFile, DoMob !
MobOps.FileError => {LocalCleanup[]; CONTINUE};
MobOps.WrongMobdefsVersion => {LocalCleanup[]; CONTINUE}];
LocalCleanup[];
};
};
};
GetMobName: PROC[name: NameRecord] RETURNS[rope: Rope.ROPE] ~ {
dotIndex: INT;
d: ConvertUnsafe.SubString ¬
[base~ssb, offset~name+1, length~MIN[ssb.text[name].ORD, 40]];
rope ¬ d.SubStringToRope;
dotIndex ¬ Rope.Find[rope, "."];
IF dotIndex < 0 THEN rope ¬ Rope.Concat[rope, ".mob"]};
}.