-- File BcdSymbolPack.mesa
-- Last edited by Satterthwaite on September 20, 1982 1:03 pm
-- Last edited by Lewis on 27-Mar-81 10:04:27
DIRECTORY
Alloc: TYPE USING [AddNotify, DropNotify, Handle, Notifier],
BcdComData: TYPE USING [table],
BcdDefs: TYPE USING [
Base, fttype, FTIndex, FTNull, FTSelf, lftype, Link,
mttype, MTIndex, MTNull, MTRecord, NameRecord,
sgtype, SGIndex, SGNull, sstype, VersionID, VersionStamp],
BcdErrorDefs: TYPE USING [InterfaceId],
BcdFileDefs: TYPE USING [CapabilityForFile, UnknownFile],
BcdOps: TYPE USING [BcdBase, NameString],
File: TYPE USING [Capability, nullCapability],
FileSegment: TYPE USING [Pages],
OSMiscOps: TYPE USING [FindFile, FileError],
Space: TYPE USING [
Handle, nullHandle, virtualMemory,
Create, Delete, LongPointer, Map],
Strings: TYPE USING [
AppendString, AppendSubString, EqualSubStrings,
String, SubString, SubStringDescriptor],
Symbols: TYPE USING [
ISEIndex, CSEIndex, CTXIndex, BitAddress, ISENull],
SymbolTable: TYPE USING [
Base, Handle, nullHandle, Acquire, Missing, Release];
BcdSymbolPack: PROGRAM
IMPORTS
Alloc, BcdFileDefs, data: BcdComData, OSMiscOps, Space, Strings,
SymbolTable
EXPORTS BcdErrorDefs = {
OPEN BcdDefs;
InterfaceId: TYPE ~ BcdErrorDefs.InterfaceId;
mtb, lfb, sgb, ftb: BcdDefs.Base;
ssb: BcdOps.NameString;
Notifier: Alloc.Notifier ~ {
mtb ← base[mttype]; lfb ← base[lftype];
sgb ← base[sgtype]; ftb ← base[fttype];
ssb ← base[sstype]};
nullPages: SymbolTable.Handle ~ SymbolTable.nullHandle;
initialized: BOOL ← FALSE;
Initialize: PUBLIC PROC ~ {
IF initialized THEN Finalize[];
initialized ← TRUE};
Finalize: PUBLIC PROC ~ {initialized ← FALSE};
ExportItemName: PUBLIC PROC [
export: InterfaceId, ep: CARDINAL,
userProc: PROC [Strings.SubString]] ~ {
symbolPages: SymbolTable.Handle;
(data.table).AddNotify[Notifier];
symbolPages ← InterfaceSymbols[export];
IF symbolPages # nullPages THEN
PrintNameFromInterface[symbolPages, ep, userProc];
(data.table).DropNotify[Notifier]};
ImportItemName: PUBLIC PROC [
import: InterfaceId, ep: CARDINAL,
clientMti: BcdDefs.MTIndex, linkOffset: CARDINAL,
userProc: PROC [Strings.SubString]] ~ {
symbolPages: SymbolTable.Handle;
(data.table).AddNotify[Notifier];
IF clientMti = BcdDefs.MTNull THEN RETURN;
symbolPages ← ModuleSymbols[clientMti];
IF symbolPages # nullPages THEN
PrintNameFromModule[symbolPages, clientMti, linkOffset, userProc]
ELSE {
symbolPages ← InterfaceSymbols[import];
IF symbolPages # nullPages THEN
PrintNameFromInterface[symbolPages, ep, userProc]};
(data.table).DropNotify[Notifier]};
ModuleSymbols: PROC [mti: BcdDefs.MTIndex]
RETURNS [symbolPages: SymbolTable.Handle] ~ {
sgi: BcdDefs.SGIndex ~ mtb[mti].sseg;
IF sgi = BcdDefs.SGNull THEN symbolPages ← nullPages
ELSE {
symbolPages.file ← BcdFileDefs.CapabilityForFile[sgb[sgi].file
! BcdFileDefs.UnknownFile => {GO TO notFound}];
symbolPages.span ← [base~sgb[sgi].base, pages~sgb[sgi].pages]};
EXITS
notFound => RETURN [nullPages]};
PrintNameFromModule: PROC [
symbolPages: SymbolTable.Handle,
importerMti: BcdDefs.MTIndex,
linkOffset: CARDINAL,
userProc: PROC [Strings.SubString]] ~ {
symbols: SymbolTable.Base ← NIL;
symbols ← SymbolTable.Acquire[symbolPages
! SymbolTable.Missing => {CONTINUE}];
IF symbols # NIL THEN {
OPEN Symbols;
key: Symbols.BitAddress ~ ComputeAddress[importerMti, linkOffset];
iCtx: CTXIndex ~ symbols.stHandle.importCtx;
sei: ISEIndex;
type: CSEIndex;
Imported: PROC [sei: Symbols.ISEIndex] RETURNS [BOOL] ~ INLINE {
RETURN [symbols.seb[sei].linkSpace AND ~symbols.seb[sei].extended]};
FOR iSei: ISEIndex ← symbols.FirstCtxSe[iCtx], symbols.NextSe[iSei] UNTIL iSei = ISENull DO
type ← symbols.UnderType[symbols.seb[iSei].idType];
WITH t~~symbols.seb[type] SELECT FROM
definition =>
FOR sei ← symbols.FirstCtxSe[t.defCtx], symbols.NextSe[sei] UNTIL sei = ISENull DO
IF Imported[sei] AND symbols.seb[sei].idValue = key THEN GO TO Found;
ENDLOOP;
ref =>
IF Imported[iSei] AND symbols.seb[iSei].idValue = key THEN {
sei ← iSei; GO TO Found};
ENDCASE => NULL;
REPEAT
Found => {
d: Strings.SubStringDescriptor;
symbols.SubStringForHash[@d, symbols.seb[sei].hash];
userProc[@d
! UNWIND => {
SymbolTable.Release[symbols]; (data.table).DropNotify[Notifier]}]};
ENDLOOP;
SymbolTable.Release[symbols]}};
ComputeAddress: PROC [mti: BcdDefs.MTIndex, linkOffset: CARDINAL]
RETURNS [Symbols.BitAddress] ~ {
linkLength: CARDINAL ~ (WITH m~~mtb[mti] SELECT FROM
direct => m.length,
indirect => lfb[m.links].length,
multiple => lfb[m.links].length,
ENDCASE => ERROR);
RETURN [[wd~(linkLength-1)-linkOffset, bd~0]]};
InterfaceSymbols: PROC [id: InterfaceId] RETURNS [symbolPages: SymbolTable.Handle] ~ {
s: STRING ← [100];
file: File.Capability ← File.nullCapability;
headerSpace: Space.Handle ← Space.nullHandle;
DeleteHeader: PROC ~ {
IF headerSpace # Space.nullHandle THEN {
Space.Delete[headerSpace];
headerSpace ← Space.nullHandle}};
IF id.fti # FTNull THEN {
s: STRING ← [100];
GetBcdName[s, ftb[id.fti].name];
file ← OSMiscOps.FindFile[s, $read ! OSMiscOps.FileError => {CONTINUE}]};
IF file = File.nullCapability THEN symbolPages ← nullPages
ELSE {
ENABLE {
UNWIND => {NULL};
ANY => {GO TO badFile}};
BcdBase: PROC [p: LONG POINTER] RETURNS [BcdDefs.Base] ~ INLINE {
RETURN [LOOPHOLE[p, BcdDefs.Base]]};
bcd: BcdOps.BcdBase;
bcdPages: CARDINAL ← 8;
iMtb, iFtb, iSgb: BcdDefs.Base;
iSsb: BcdOps.NameString;
iMti: BcdDefs.MTIndex;
iSgi: BcdDefs.SGIndex;
d1, d2: Strings.SubStringDescriptor;
DO
headerSpace ← Space.Create[size~bcdPages, parent~Space.virtualMemory];
headerSpace.Map[window~[file~file, base~1]];
bcd ← headerSpace.LongPointer[];
IF bcd.versionIdent # BcdDefs.VersionID THEN GO TO badFile;
IF bcdPages >= bcd.nPages THEN EXIT;
bcdPages ← bcd.nPages;
Space.Delete[headerSpace]; headerSpace ← Space.nullHandle
ENDLOOP;
IF bcd.nConfigs # 0 OR ~bcd.definitions THEN
GO TO badFile; -- no packaged bcd's (for now)
iSsb ← LOOPHOLE[bcd + bcd.ssOffset];
iMtb ← BcdBase[bcd + bcd.mtOffset];
iFtb ← BcdBase[bcd + bcd.ftOffset];
iSgb ← BcdBase[bcd + bcd.sgOffset];
d1 ← [base~@ssb.string, offset~id.name, length~ssb.size[id.name]];
d2.base ← @iSsb.string;
iMti ← BcdDefs.MTIndex.FIRST;
UNTIL iMti = bcd.mtLimit DO
d2.offset ← iMtb[iMti].name;
d2.length ← iSsb.size[iMtb[iMti].name];
IF Strings.EqualSubStrings[@d1, @d2] THEN EXIT;
iMti ← iMti + (WITH m~~iMtb[iMti] SELECT FROM
direct => BcdDefs.MTRecord.direct.SIZE + m.length*BcdDefs.Link.SIZE,
indirect => BcdDefs.MTRecord.indirect.SIZE,
multiple => BcdDefs.MTRecord.multiple.SIZE,
ENDCASE => ERROR);
REPEAT
FINISHED =>
IF bcd.nModules = 1 THEN iMti ← BcdDefs.MTIndex.FIRST ELSE GOTO badFile;
ENDLOOP;
iSgi ← iMtb[iMti].sseg;
IF iSgi = BcdDefs.SGNull OR iSgb[iSgi].pages = 0
OR iSgb[iSgi].file # BcdDefs.FTSelf OR bcd.version # ftb[id.fti].version
THEN GO TO badFile;
symbolPages ← [
file~file,
span~[base~iSgb[iSgi].base, pages~iSgb[iSgi].pages]];
DeleteHeader[];
EXITS
badFile => {DeleteHeader[]; symbolPages ← nullPages}};
RETURN};
GetBcdName: PROC [s: Strings.String, n: NameRecord] ~ {
d: Strings.SubStringDescriptor ←
[base~@ssb.string, offset~n, length~MIN[ssb.size[n], 40]];
s.length ← 0;
Strings.AppendSubString[s, @d];
FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN RETURN ENDLOOP;
Strings.AppendString[s, ".bcd"L]};
PrintNameFromInterface: PROC [
symbolPages: SymbolTable.Handle,
ep: CARDINAL,
userProc: PROC [Strings.SubString]] ~ {
symbols: SymbolTable.Base ← NIL;
symbols ← SymbolTable.Acquire[symbolPages
! SymbolTable.Missing => {CONTINUE}];
IF symbols # NIL THEN {
OPEN Symbols;
outerCtx: CTXIndex ~ symbols.stHandle.outerCtx;
d: Strings.SubStringDescriptor;
FOR sei: ISEIndex ← symbols.FirstCtxSe[outerCtx], symbols.NextSe[sei]
UNTIL sei = ISENull DO
SELECT symbols.LinkMode[sei] FROM
val, ref, type =>
IF symbols.seb[sei].idValue = ep THEN {
symbols.SubStringForHash[@d, symbols.seb[sei].hash];
userProc[@d
! UNWIND => {
SymbolTable.Release[symbols]; (data.table).DropNotify[Notifier]}]};
ENDCASE;
ENDLOOP;
SymbolTable.Release[symbols]}};
}.