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: 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[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]}};
}.