BcdSymbolPack.mesa
Copyright © 1985 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
DIRECTORY
Alloc: TYPE USING [AddNotify, DropNotify, Notifier],
BcdComData: TYPE USING [table],
BcdDefs: TYPE USING [Base, BcdBase, fttype, FTIndex, FTNull, FTSelf, lftype, Link, mttype, MTIndex, MTNull, MTRecord, NameRecord, NameString, sgtype, SGIndex, SGNull, sstype, VersionID, VersionStamp],
BcdErrorDefs: TYPE USING [InterfaceId],
BcdFileDefs: TYPE USING [CapabilityForFile, UnknownFile],
ConvertUnsafe: TYPE USING [EqualSubStrings, SubString, SubStringToRope],
FileSegment: TYPE USING [Pages],
FS: TYPE USING [nullOpenFile, OpenFile, Read, Open, Error],
Rope: TYPE USING [Concat, Find, ROPE],
Symbols: TYPE USING [ISEIndex, CSEIndex, CTXIndex, BitAddress, ISENull],
SymbolTable: TYPE USING [Base, Handle, nullHandle, Acquire, Missing, Release],
VM: TYPE USING [AddressForPageNumber, Allocate, Free, Interval, nullInterval];
BcdSymbolPack: PROGRAM
IMPORTS Alloc, BcdFileDefs, ConvertUnsafe, FS, Rope, SymbolTable, VM, data: BcdComData
EXPORTS BcdErrorDefs = { OPEN BcdDefs;
InterfaceId: TYPE ~ BcdErrorDefs.InterfaceId;
mtb, lfb, sgb, ftb: BcdDefs.Base;
ssb: BcdDefs.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: BOOLFALSE;
Initialize: PUBLIC PROC ~ {
IF initialized THEN Finalize[];
initialized ← TRUE};
Finalize: PUBLIC PROC ~ {initialized ← FALSE};
ExportItemName: PUBLIC PROC[
export: InterfaceId, ep: CARDINAL,
userProc: PROC[ConvertUnsafe.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[ConvertUnsafe.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-1, pages~sgb[sgi].pages]};
EXITS
notFound => RETURN[nullPages]};
PrintNameFromModule: PROC[
symbolPages: SymbolTable.Handle,
importerMti: BcdDefs.MTIndex,
linkOffset: CARDINAL,
userProc: PROC[ConvertUnsafe.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: ConvertUnsafe.SubString;
d ← symbols.SubStringForName[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] ~ {
file: FS.OpenFile ← FS.nullOpenFile;
headerInterval: VM.Interval ← VM.nullInterval;
DeleteHeader: PROC ~ {
IF headerInterval # VM.nullInterval THEN {
headerInterval.Free[];
headerInterval ← VM.nullInterval}};
IF id.fti # FTNull THEN {
name: Rope.ROPE;
name ← GetBcdName[ftb[id.fti].name];
file ← FS.Open[name: name ! FS.Error => CONTINUE]};
IF file = FS.nullOpenFile 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: BcdDefs.BcdBase;
bcdPages: CARDINAL ← 8;
iMtb, iFtb, iSgb: BcdDefs.Base;
iSsb: BcdDefs.NameString;
iMti: BcdDefs.MTIndex;
iSgi: BcdDefs.SGIndex;
d1, d2: ConvertUnsafe.SubString;
DO
headerInterval ← VM.Allocate[bcdPages];
bcd ← VM.AddressForPageNumber[headerInterval.page];
file.Read[from~0, nPages~bcdPages, to~bcd];
IF bcd.versionIdent # BcdDefs.VersionID THEN GO TO badFile;
IF bcdPages >= bcd.nPages THEN EXIT;
bcdPages ← bcd.nPages;
headerInterval.Free[]; headerInterval ← VM.nullInterval
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 d1.EqualSubStrings[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-1, pages~iSgb[iSgi].pages]];
DeleteHeader[];
EXITS
badFile => {DeleteHeader[]; symbolPages ← nullPages}};
RETURN};
GetBcdName: PROC[n: NameRecord] RETURNS[name: Rope.ROPE] ~ {
dotIndex: INT;
d: ConvertUnsafe.SubString ←
[base~@ssb.string, offset~n, length~MIN[ssb.size[n], 40]];
name ← d.SubStringToRope;
dotIndex ← name.Find["."];
IF dotIndex < 0 THEN name ← name.Concat[".bcd"]};
PrintNameFromInterface: PROC[
symbolPages: SymbolTable.Handle,
ep: CARDINAL,
userProc: PROC[ConvertUnsafe.SubString]] ~ {
symbols: SymbolTable.Base ← NIL;
symbols ← SymbolTable.Acquire[symbolPages ! SymbolTable.Missing => {CONTINUE}];
IF symbols # NIL THEN {
OPEN Symbols;
outerCtx: CTXIndex ~ symbols.stHandle.outerCtx;
d: ConvertUnsafe.SubString;
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 {
d ← symbols.SubStringForName[symbols.seb[sei].hash];
userProc[d
! UNWIND => {
SymbolTable.Release[symbols]; (data.table).DropNotify[Notifier]}]};
ENDCASE;
ENDLOOP;
SymbolTable.Release[symbols]}};
}.