RTGetSymbolsImpl.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Bob Hagmann On May 7, 1984 3:33:31 pm PDT
Russ Atkinson (RRA) April 7, 1986 7:11:11 pm PST
DIRECTORY
AMFiles USING [FullFileNameList, OpenIt],
AMTypes USING [Error],
BasicTime USING [GMT],
BcdDefs USING [BcdBase, FTHandle, FTIndex, FTNull, FTSelf, MTHandle, MTIndex, NameRecord, NameString, NullVersion, SGHandle, SGIndex, SGNull, VersionID, VersionStamp],
BcdOps USING [ProcessModules, ProcessFiles],
BrandXSymbolDefs USING [nullSymbolIndex, rootBodyIndex, SymbolModuleIndex, SymbolTableBase],
BrandYSymbolDefs USING [rootBodyIndex, nullSymbolIndex, SymbolTableBase, SymbolModuleIndex],
ConvertUnsafe USING [SubString, SubStringToRope],
FileSegment USING [Pages],
FS USING [Close, Error, nullOpenFile, Open, OpenFile, Read],
LoadState USING [Acquire, ConfigID, ConfigInfo, GlobalFrameToModule, local, ModuleIndex, Release],
PrincOps USING [GlobalFrameHandle],
RCMapOps USING [EstablishOuter],
Rope USING [Concat, Equal, Find, Index, ROPE, SkipTo, Substr],
RTSymbolDefs USING [nullBase, nullHandle, SymbolModuleIndex, SymbolTableBase, SymbolTableHandle],
RTSymbolOps USING [NullModuleIndex, NullSth, STBToModuleName, STBVersion, SubStringForName],
RTSymbols USING [],
RTSymbolsPrivate USING [],
RTTypesBasicPrivate USING [FindSTI, MapStiStd, STDesc, SymbolTableIndex],
RuntimeError USING [UNCAUGHT],
SymbolTable USING [Acquire, BaseToHandle, Release, SetCacheSize],
Table USING [Base],
VersionMap USING [MapList, MapAndNameList, ShortNameToNames],
VersionMapDefaults USING [FileNameFromVersion, GetMapList],
VM USING [AddressForPageNumber, Allocate, Free, Interval, PageNumberForAddress];
RTGetSymbolsImpl: MONITOR
IMPORTS AMFiles, AMTypes, BcdOps, FS, ConvertUnsafe, LoadState, RCMapOps, Rope, RTSymbolOps, RTTypesBasicPrivate, RuntimeError, SymbolTable, VersionMap, VersionMapDefaults, VM
EXPORTS RTSymbols, RTSymbolsPrivate
SHARES Rope = {
OPEN bx: BrandXSymbolDefs, by: BrandYSymbolDefs, XSymbolTable: SymbolTable, YSymbolTable: SymbolTable, XRCMapOps: RCMapOps, YRCMapOps: RCMapOps, PrincOps, RTSymbolDefs, RTSymbolOps, RuntimeError;
Variables protected by the monitor
onePageSpace: VM.Interval = VM.Allocate[1];
ROPE: TYPE = Rope.ROPE;
PUBLIC PROCS
OuterFromSTH: PUBLIC PROC [sth: SymbolTableHandle, inner: PROC [stb: SymbolTableBase] ] = {
Provided as a convenience for clients who want to know that they have been adequately protected against failure to release a symbol table.
stb: SymbolTableBase ← AcquireSTB[sth];
inner[stb ! UNWIND => ReleaseSTB[stb] ];
ReleaseSTB[stb];
};
AcquireSTB: PUBLIC PROC [sth: SymbolTableHandle] RETURNS [stb: SymbolTableBase] = {
stb ← WITH sth SELECT FROM
t: SymbolTableHandle.x => [x[XSymbolTable.Acquire[t.e]]],
t: SymbolTableHandle.y => [y[YSymbolTable.Acquire[t.e]]]
ENDCASE => ERROR;
WITH stb SELECT FROM
t: SymbolTableBase.x => {
IF NOT t.e.stHandle.extended THEN GO TO foo;
IF t.e.bb[bx.rootBodyIndex].type = bx.nullSymbolIndex THEN GO TO foo;
};
t: SymbolTableBase.y => {
IF NOT t.e.stHandle.extended THEN GO TO foo;
IF t.e.bb[by.rootBodyIndex].type = by.nullSymbolIndex THEN GO TO foo;
};
ENDCASE => GO TO foo;
RETURN[stb];
EXITS foo => {
modName: ROPE = STBToModuleName[stb ! UNWIND => ReleaseSTB[stb]];
ReleaseSTB[stb];
ERROR AMTypes.Error[reason: noSymbols, msg: modName];
};
};
ReleaseSTB: PUBLIC PROC [stb: SymbolTableBase] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => XSymbolTable.Release[t.e];
t: SymbolTableBase.y => YSymbolTable.Release[t.e]
ENDCASE => ERROR;
};
BaseToHandle: PUBLIC PROC [stb: SymbolTableBase] RETURNS [SymbolTableHandle] = {
RETURN[WITH stb SELECT FROM
t: SymbolTableBase.x => [x[XSymbolTable.BaseToHandle[t.e]]],
t: SymbolTableBase.y => [y[YSymbolTable.BaseToHandle[t.e]]],
ENDCASE => ERROR];
};
STPages: PUBLIC PROC [sth: SymbolTableHandle] RETURNS [CARDINAL] = {
RETURN[WITH sth SELECT FROM
t: SymbolTableHandle.x => t.e.span.pages,
t: SymbolTableHandle.y => t.e.span.pages,
ENDCASE => ERROR];
};
AcquireSTHFromSTX: PUBLIC PROC [stx: RTTypesBasicPrivate.SymbolTableIndex] RETURNS [sth: SymbolTableHandle ← nullHandle, moduleName: ROPENIL] = {
this may return nullHandle but will not raise any signals
[sth, moduleName] ← DoAcquireSTHFromSTX[stx, TRUE];
};
DoAcquireSTHFromSTX: PROC [stx: RTTypesBasicPrivate.SymbolTableIndex, invokeGetSTHForModule: BOOLFALSE] RETURNS [sth: SymbolTableHandle ← nullHandle, moduleName: ROPENIL] = {
symbolsStamp: BcdDefs.VersionStamp;
bcd: BcdDefs.BcdBase;
IF NOT NullSth[RTTypesBasicPrivate.MapStiStd[stx].sth]
THEN RETURN[sth: RTTypesBasicPrivate.MapStiStd[stx].sth];
symbolsStamp ← RTTypesBasicPrivate.MapStiStd[stx].symbolsStamp;
bcd ← RTTypesBasicPrivate.MapStiStd[stx].bcd;
IF bcd = NIL
THEN {
IF NOT invokeGetSTHForModule THEN RETURN;
sth ← GetSTHForModule[stamp: symbolsStamp, fileName: NIL, moduleName: NIL
! UNCAUGHT => CONTINUE];
}
ELSE {
sgb: Table.Base = LOOPHOLE[bcd + bcd.sgOffset];
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
ssb: BcdDefs.NameString = LOOPHOLE[bcd + bcd.ssOffset];
fti: BcdDefs.FTIndex;
sgi: BcdDefs.SGIndex = RTTypesBasicPrivate.MapStiStd[stx].sgi;
IF sgi = BcdDefs.SGNull -- search the BCD's file table (find a DEFs)
THEN {
search the BCD's file table
findSymbolFTI: PROC [ffth: BcdDefs.FTHandle, ffti: BcdDefs.FTIndex] RETURNS [stop: BOOL] = {
IF NOT EQStamps[ffth.version, symbolsStamp] THEN GO TO nope;
moduleName ← GetModuleName[ssb, ffth.name];
sth ← GetSTHForModule[stamp: symbolsStamp, fileName: Rope.Concat[moduleName, ".bcd"], moduleName: moduleName
! AMTypes.Error => GO TO nope];
RETURN[TRUE];
EXITS nope => RETURN [FALSE];
};
IF NOT invokeGetSTHForModule THEN RETURN;
[] ← BcdOps.ProcessFiles[bcd, findSymbolFTI];
IF NullSth[sth] THEN
sth ← GetSTHForModule[stamp: symbolsStamp, fileName: NIL, moduleName: moduleName
! UNCAUGHT => CONTINUE];
RTTypesBasicPrivate.MapStiStd[stx].sth ← sth;
RETURN;
}
ELSE fti ← sgb[sgi].file;
IF fti = BcdDefs.FTSelf
THEN {
file: FS.OpenFile = FileFromBcdBase[bcd];
moduleName ← GetModuleName[ssb, bcd.source];
IF file # FS.nullOpenFile THEN {
p: FileSegment.Pages = [file: file, span: [base: sgb[sgi].base - 1, pages: sgb[sgi].pages + sgb[sgi].extraPages]];
sth ← IF IsXBCD[bcd] THEN [x[p]] ELSE [y[p]];
};
}
ELSE {
look for the specified file
fileName: ROPE = GetFileName[ssb, ftb[fti].name];
moduleName ← GetModuleName[ssb, ftb[fti].name];
sth ← NewSymbolHandle[fileName: fileName, version: ftb[fti].version,  base: sgb[sgi].base - 1, pages: sgb[sgi].pages + sgb[sgi].extraPages
! AMTypes.Error => CONTINUE]
};
};
RTTypesBasicPrivate.MapStiStd[stx].sth ← sth;
};
version must match bcd.version
NewSymbolHandle: PUBLIC PROC [fileName: ROPE, base: CARDINAL, pages: CARDINAL, version: BcdDefs.VersionStamp ← BcdDefs.NullVersion] RETURNS [sth: SymbolTableHandle ← nullHandle] = {
file: FS.OpenFile ← FS.nullOpenFile;
stb: SymbolTableBase;
symbolsStamp: BcdDefs.VersionStamp;
isXBCD: BOOL = TRUE; -- NOTE XXX
IF EQStamps[version, BcdDefs.NullVersion]
THEN file ← AMFiles.OpenIt[fileName].openFile
ELSE file ← AcquireFCFromVersion[version, fileName];
IF file = FS.nullOpenFile THEN ERROR AMTypes.Error[reason: noSymbols, msg: fileName];
here if file is found and version matches
sth ← IF isXBCD THEN [x[[file: file, span: [base: base, pages: pages]]]]
ELSE [y[[file: file, span: [base: base, pages: pages]]]];
stb ← AcquireSTB[sth];
symbolsStamp ← STBVersion[stb];
ReleaseSTB[stb];
[] ← RTTypesBasicPrivate.FindSTI[[symbolsStamp: symbolsStamp, sth: sth]];
};
RCMapOuterX: PROC [stb: bx.SymbolTableBase, mdi: bx.SymbolModuleIndex, inner: PROC [base: bx.SymbolTableBase]] = {
stb1: SymbolTableBase = AcquireSTBFromMDI[[x[stb]], [x[mdi]]];
inner[NARROW[stb1, SymbolTableBase.x].e ! UNWIND => ReleaseSTB[stb1]];
ReleaseSTB[stb1];
};
RCMapOuterY: PROC [stb: by.SymbolTableBase, mdi: by.SymbolModuleIndex, inner: PROC [base: by.SymbolTableBase]] = {
stb1: SymbolTableBase = AcquireSTBFromMDI[[y[stb]], [y[mdi]]];
inner[NARROW[stb1, SymbolTableBase.y].e ! UNWIND => ReleaseSTB[stb1]];
ReleaseSTB[stb1];
};
OuterFromMDI: PUBLIC PROC [stb: SymbolTableBase, mdi: SymbolModuleIndex, inner: PROC [base: SymbolTableBase]] = {
stb1: SymbolTableBase = AcquireSTBFromMDI[stb, mdi];
inner[stb1 ! UNWIND => ReleaseSTB[stb1]];
ReleaseSTB[stb1];
};
AcquireSTBFromMDI: PUBLIC PROC [stb: SymbolTableBase, mdi: SymbolModuleIndex] RETURNS [SymbolTableBase] = {
fileNameDesc, modNameDesc: ConvertUnsafe.SubString;
fileName: ROPE;
modName: ROPE;
IF NullModuleIndex[mdi] THEN ERROR;
modNameDesc ← SubStringForName[
stb,
WITH stb SELECT FROM
t: SymbolTableBase.x =>
[x[t.e.mdb[NARROW[mdi, SymbolModuleIndex.x].e].moduleId]],
t: SymbolTableBase.y =>
[y[t.e.mdb[NARROW[mdi, SymbolModuleIndex.y].e].moduleId]],
ENDCASE => ERROR];
modName ← ConvertUnsafe.SubStringToRope[modNameDesc];
fileNameDesc ← SubStringForName[stb,
WITH stb SELECT FROM
t: SymbolTableBase.x =>
[x[t.e.mdb[NARROW[mdi, SymbolModuleIndex.x].e].fileId]],
t: SymbolTableBase.y =>
[y[t.e.mdb[NARROW[mdi, SymbolModuleIndex.y].e].fileId]],
ENDCASE => ERROR];
fileName ← ConvertUnsafe.SubStringToRope[fileNameDesc];
RETURN[
AcquireSTB[
GetSTHForModule[
(WITH stb SELECT FROM
t: SymbolTableBase.x =>
t.e.mdb[NARROW[mdi, SymbolModuleIndex.x].e].stamp,
t: SymbolTableBase.y =>
t.e.mdb[NARROW[mdi, SymbolModuleIndex.y].e].stamp,
ENDCASE => ERROR),
fileName,
modName
]
]
];
};
GetSTHForModule: PUBLIC PROC [stamp: BcdDefs.VersionStamp, fileName: ROPE, moduleName: ROPE] RETURNS [sth: SymbolTableHandle ← nullHandle] = {
stamp on the MODULE, maybe different than bcd.version
bcd: BcdDefs.BcdBase;
newFile: FS.OpenFile ← FS.nullOpenFile;
sgb: Table.Base;
ftb: Table.Base;
ntb: BcdDefs.NameString;
versionMapTried: BOOLFALSE;
mth: BcdDefs.MTHandle;
sSeg: BcdDefs.SGIndex;
someNameMatched: BOOLFALSE;
FindVersionStampedModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOL] = {
umid: BcdDefs.VersionStamp = (IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version);
namesMatch: BOOLTRUE;
IF moduleName # NIL THEN {
thisMN: ROPE = GetModuleName[ntb, mth.name];
namesMatch ← Rope.Equal[moduleName, thisMN];
someNameMatched ← someNameMatched OR namesMatch;
};
RETURN[namesMatch AND (EQStamps[stamp, BcdDefs.NullVersion] OR EQStamps[stamp, umid])];
};
IF NOT EQStamps[stamp, BcdDefs.NullVersion] THEN {
Try the quick kill for an already acquired symbol handle associated with the stamp.
found: BOOL;
stx: RTTypesBasicPrivate.SymbolTableIndex;
[stx, found] ← FindSTX[stamp];
IF found THEN sth ← DoAcquireSTHFromSTX[stx].sth;
IF NOT NullSth[sth] THEN RETURN[sth];
};
IF fileName = NIL AND moduleName # NIL THEN
fileName ← Rope.Concat[moduleName, ".bcd"];
IF fileName # NIL THEN
Try the file name hint locally
newFile ← AMFiles.OpenIt[fileName].openFile;
DO
IF newFile = FS.nullOpenFile THEN {
no local file with that name
IF EQStamps[stamp, BcdDefs.NullVersion]
THEN GOTO noFile
ELSE {
look for the module's original file
fn: ROPE = IF moduleName = NIL THEN NIL ELSE Rope.Concat[moduleName, ".bcd"];
newFile ← VersionToReadableFile[versionStamp: stamp, shortNameHint: fn];
versionMapTried ← TRUE;
IF newFile = FS.nullOpenFile THEN GOTO noFile;
};
};
here with a valid FC
bcd ← AcquireBCDFromCap[newFile];
sgb ← LOOPHOLE[bcd + bcd.sgOffset];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
ntb ← LOOPHOLE[bcd + bcd.ssOffset];
IF bcd.versionIdent # BcdDefs.VersionID THEN {
IF versionMapTried
THEN GOTO oldSymbols
ELSE {newFile ← FS.nullOpenFile; LOOP};
};
someNameMatched ← FALSE;
mth ← BcdOps.ProcessModules[bcd, FindVersionStampedModule].mth;
IF mth = NIL THEN {
IF NOT versionMapTried THEN {newFile ← FS.nullOpenFile; LOOP};
IF someNameMatched
THEN GOTO wrongVersion
ELSE GOTO noSymbols;
};
sSeg ← mth.sseg;
IF sSeg = BcdDefs.SGNull
OR sgb[sSeg].pages = 0
OR ((NOT bcd.definitions) AND (sgb[sSeg].extraPages = 0)) -- compressed symbols
OR sgb[sSeg].file # BcdDefs.FTSelf
THEN {
IF versionMapTried
THEN GOTO noSymbols
ELSE {newFile ← FS.nullOpenFile; LOOP};
};
{
p: FileSegment.Pages = [file: newFile, span: [base: sgb[sSeg].base - 1, pages: sgb[sSeg].pages + sgb[sSeg].extraPages] ];
sth ← IF IsXBCD[bcd] THEN [x[p]] ELSE [y[p]];
};
IF EQStamps[stamp, BcdDefs.NullVersion] THEN {
stb: SymbolTableBase = AcquireSTB[sth];
stamp ← STBVersion[stb];
ReleaseSTB[stb];
};
[] ← RTTypesBasicPrivate.FindSTI[[symbolsStamp: stamp, sth: sth]];
ReleaseBCD[bcd];
RETURN[sth];
ENDLOOP;
EXITS
noFile => ERROR AMTypes.Error[reason: noSymbols, msg: fileName];
oldSymbols => ERROR AMTypes.Error[reason: noSymbols, msg: moduleName];
noSymbols => ERROR AMTypes.Error[reason: noSymbols, msg: IF moduleName = NIL THEN fileName ELSE moduleName];
wrongVersion => ERROR AMTypes.Error[reason: noSymbols, msg: moduleName];
};
OuterFromGFH: PUBLIC PROC [gfh: GlobalFrameHandle, inner: PROC [stb: SymbolTableBase] ] = {
Provided as a convenience for clients who want to know that they have been adequately protected against failure to release a symbol table.
stb: SymbolTableBase ← AcquireSTBFromGFH[gfh];
inner[stb ! UNWIND => ReleaseSTB[stb] ];
ReleaseSTB[stb];
};
AcquireSTBFromGFH: PUBLIC PROC [gfh: GlobalFrameHandle] RETURNS [stb: SymbolTableBase ← nullBase] = {
raises Error if there are no symbols for the specified module
bcd: BcdDefs.BcdBase;
bcdns: BcdDefs.NameString;
moduleName: ROPE;
mth: BcdDefs.MTHandle;
config: LoadState.ConfigID;
moduleIndex: LoadState.ModuleIndex;
umid: BcdDefs.VersionStamp; -- functional version stamp of the module
ftb: Table.Base;
sth: SymbolTableHandle ← nullHandle;
FindModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = {
RETURN[(mth.gfi <= moduleIndex) AND (moduleIndex < (mth.gfi + mth.ngfi))];
};
LoadState.local.Acquire[];
[config, moduleIndex] ← LoadState.local.GlobalFrameToModule[gfh];
bcd ← LoadState.local.ConfigInfo[config].bcd;
LoadState.local.Release[];
bcdns ← LOOPHOLE[bcd + bcd.ssOffset];
ftb ← LOOPHOLE[bcd + bcd.ftOffset];
[mth,] ← BcdOps.ProcessModules[bcd, FindModule];
IF mth = NIL THEN ERROR;
umid ← (IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version);
{
First look in the umid -> sth map
found: BOOL;
stx: RTTypesBasicPrivate.SymbolTableIndex;
[stx, found] ← FindSTX[umid];
IF found THEN sth ← AcquireSTHFromSTX[stx].sth};
IF NullSth[sth] THEN
then try for the one referenced in the bcd
sth ← AcquireSTHFromSGI[bcd, mth.sseg];
IF NullSth[sth] THEN {
then try for the named module's file (locally)
n: BcdDefs.NameRecord
= IF mth.file = BcdDefs.FTSelf THEN mth.name ELSE ftb[mth.file].name;
sth ← GetSTHForModule[
stamp: umid,
fileName: GetFileName[ssb: bcdns, n: n],
moduleName: GetModuleName[ssb: bcdns, n: mth.name]
! UNCAUGHT => CONTINUE
];
};
IF NullSth[sth] THEN
then try for the original one
[sth: sth, moduleName: moduleName]
← AcquireSTHFromSTX[RTTypesBasicPrivate.FindSTI[[symbolsStamp: umid, bcd: bcd]]];
IF NullSth[sth] THEN {
then give up.
sgb: Table.Base = LOOPHOLE[bcd + bcd.sgOffset];
IF moduleName = NIL THEN {
n: BcdDefs.NameRecord = IF sgb[mth.sseg].file = BcdDefs.FTSelf THEN mth.name ELSE ftb[sgb[mth.sseg].file].name;
moduleName ← GetFileName[ssb: bcdns, n: n];
};
ERROR AMTypes.Error[reason: noSymbols, msg: moduleName];
};
stb ← AcquireSTB[sth];
RETURN[stb];
};
OuterFromSGI: PUBLIC PROC [bcd: BcdDefs.BcdBase, sgi: BcdDefs.SGIndex, inner: PROC [base: SymbolTableBase]] = {
Provided as a convenience for clients who want to know that they have been adequately protected against failure to release a symbol table.
stb: SymbolTableBase ← AcquireSTBFromSGI[bcd, sgi];
inner[stb ! UNWIND => ReleaseSTB[stb] ];
ReleaseSTB[stb];
};
AcquireSTBFromSGI: PUBLIC PROC [bcd: BcdDefs.BcdBase, sgi: BcdDefs.SGIndex] RETURNS [stb: SymbolTableBase ← nullBase] = {
sgi identifies the symbol segment
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
sgh: BcdDefs.SGHandle = @LOOPHOLE[bcd + bcd.sgOffset, Table.Base][sgi];
sth: SymbolTableHandle ← AcquireSTHFromSGI[bcd, sgi]; -- try for the referenced one
IF NullSth[sth] THEN {
ssb: BcdDefs.NameString = LOOPHOLE[bcd + bcd.ssOffset];
msg: ROPE = IF sgh.file = BcdDefs.FTSelf THEN GetFileName[ssb: ssb, n: bcd.source] ELSE GetFileName[ssb: ssb, n: ftb[sgh.file].name];
ERROR AMTypes.Error[reason: noSymbols, msg: msg];
};
RETURN[AcquireSTB[sth]];
};
PRIVATE PROCS
EQStamps: PROC [s1, s2: BcdDefs.VersionStamp] RETURNS [BOOL] = INLINE {
RETURN[s1.net = s2.net AND s1.host = s2.host AND s1.time = s2.time];
};
FindSTX: PROC [stamp: BcdDefs.VersionStamp] RETURNS [stx: RTTypesBasicPrivate.SymbolTableIndex, found: BOOL] = {
FOR stx IN [1..RTTypesBasicPrivate.MapStiStd.length)
DO IF RTTypesBasicPrivate.MapStiStd[stx] = NIL THEN EXIT;
IF EQStamps[stamp, RTTypesBasicPrivate.MapStiStd[stx].symbolsStamp]
THEN RETURN[stx, TRUE];
ENDLOOP;
RETURN[0, FALSE];
};
AcquireSTHFromSGI: PROC [bcd: BcdDefs.BcdBase, sgi: BcdDefs.SGIndex] RETURNS [sth: SymbolTableHandle ← nullHandle] = {
returns nullHandle if there are no symbols
sgb: Table.Base = LOOPHOLE[bcd + bcd.sgOffset];
ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset];
ssb: BcdDefs.NameString = LOOPHOLE[bcd + bcd.ssOffset];
sgh: BcdDefs.SGHandle ← @sgb[sgi];
IF sgh.class # symbols THEN ERROR;
IF (sgh.pages = 0) -- empty symbol segment
OR ((NOT bcd.definitions) AND (sgh.extraPages = 0)) -- compressed symbols
OR sgh.file = BcdDefs.FTNull
THEN RETURN;
IF sgh.file = BcdDefs.FTSelf
THEN {
stb: SymbolTableBase;
symbolsStamp: BcdDefs.VersionStamp;
file: FS.OpenFile = FileFromBcdBase[bcd];
IF file = FS.nullOpenFile THEN RETURN;
{
p: FileSegment.Pages = [file: file, span: [base: sgh.base-1, pages: sgh.pages+sgh.extraPages]];
sth ← IF IsXBCD[bcd] THEN [x[p]] ELSE [y[p]];
};
stb ← AcquireSTB[sth];
symbolsStamp ← STBVersion[stb];
ReleaseSTB[stb];
[] ← RTTypesBasicPrivate.FindSTI[[symbolsStamp: symbolsStamp, sth: sth]];
}
ELSE {
fileName: ROPE ← GetFileName[ssb, ftb[sgh.file].name];
sth ← NewSymbolHandle[fileName: fileName, base: sgh.base - 1, pages: sgh.pages+sgh.extraPages, version: ftb[sgh.file].version
! UNCAUGHT => CONTINUE];
};
};
GetModuleName: PROC [ssb: BcdDefs.NameString, n: BcdDefs.NameRecord] RETURNS [name: ROPENIL] = {
ssd: ConvertUnsafe.SubString = [base: @ssb.string, offset: n, length: ssb.size[n]];
name ← ConvertUnsafe.SubStringToRope[ssd];
name ← name.Substr[start: 0, len: name.Index[pos1: 0, s2: "."]]
};
GetFileName: PROC [ssb: BcdDefs.NameString, n: BcdDefs.NameRecord] RETURNS [name: ROPENIL] = {
ssd: ConvertUnsafe.SubString = [base: @ssb.string, offset: n, length: ssb.size[n]];
name ← ConvertUnsafe.SubStringToRope[ssd];
IF Rope.Find[name, "."] = -1 THEN name ← Rope.Concat[name, ".bcd"];
};
FileFromBcdBase: PROC [bcd: BcdDefs.BcdBase] RETURNS [fc: FS.OpenFile ← FS.nullOpenFile] = {
ssb: BcdDefs.NameString = LOOPHOLE[bcd + bcd.ssOffset];
fc ← AcquireFCFromVersion[ versionStamp: bcd.version, shortFileNameHint: Rope.Concat[GetModuleName[ssb, bcd.source], ".bcd"] ];
};
AcquireFCFromVersion: PROC [ versionStamp: BcdDefs.VersionStamp, shortFileNameHint: ROPENIL] RETURNS [file: FS.OpenFile ← FS.nullOpenFile] = {
may return FS.nullOpenFile
fileNameList: LIST OF ROPE;
IF shortFileNameHint # NIL THEN fileNameList ← AMFiles.FullFileNameList[shortFileNameHint];
IF fileNameList # NIL THEN {
FOR fileNames: LIST OF ROPE ← fileNameList, fileNames.rest UNTIL fileNames = NIL DO
file ← FS.Open[fileNames.first ! FS.Error => {file ← FS.nullOpenFile; CONTINUE}];
IF file # FS.nullOpenFile THEN {
IF EQStamps[GetBCDVersionInfo[file].fileVersionStamp, versionStamp]
THEN RETURN[file];
FS.Close[file];
file ← FS.nullOpenFile;
};
ENDLOOP;
};
file ← VersionToReadableFile[versionStamp, shortFileNameHint];
};
AcquireBCDFromVersion: PUBLIC PROC [versionStamp: BcdDefs.VersionStamp, shortFileNameHint: ROPENIL] RETURNS [bcd: BcdDefs.BcdBase ← NIL] = {
may return NIL
file: FS.OpenFile ← AcquireFCFromVersion[versionStamp, shortFileNameHint];
IF file # FS.nullOpenFile THEN bcd ← AcquireBCDFromCap[file];
};
AcquireBCDFromCap: ENTRY PROC [file: FS.OpenFile] RETURNS [bcd: BcdDefs.BcdBase] = {
ENABLE UNWIND => NULL;
size: NAT; -- pages
bcd ← LOOPHOLE[VM.AddressForPageNumber[onePageSpace.page]];
FS.Read[file: file, from: 0, nPages: 1, to: bcd];
IF bcd.extended
THEN size ← MAX[1, bcd.nPages - bcd.rtPages.pages]
ELSE size ← bcd.nPages;
bcd ← LOOPHOLE[VM.AddressForPageNumber[VM.Allocate[size].page]];
FS.Read[file: file, from: 0, nPages: size, to: bcd];
};
IsXBCD: PROC [bcd: BcdDefs.BcdBase--only the first page!!--] RETURNS [BOOL] = {
Note: this has to change if there is ever another bcd format
RETURN[TRUE];
};
ReleaseBCD: PUBLIC ENTRY PROC [bcd: BcdDefs.BcdBase] = {
ENABLE UNWIND => NULL;
count: INTMAX[1, IF bcd.extended THEN bcd.nPages - bcd.rtPages.pages ELSE bcd.nPages];
VM.Free[[page: VM.PageNumberForAddress[bcd], count: count]];
};
GetBCDVersionInfo: ENTRY PROC [file: FS.OpenFile] RETURNS [fileVersionIdent: CARDINAL, fileVersionStamp: BcdDefs.VersionStamp, isXBCD: BOOL] = {
ENABLE UNWIND => NULL;
bcd: BcdDefs.BcdBase = LOOPHOLE[VM.AddressForPageNumber[onePageSpace.page]];
FS.Read[file: file, from: 0, nPages: 1, to: bcd];
fileVersionIdent ← bcd.versionIdent;
fileVersionStamp ← bcd.version;
isXBCD ← IsXBCD[bcd];
};
VersionToReadableFile: PUBLIC PROC [versionStamp: BcdDefs.VersionStamp, shortNameHint: ROPENIL] RETURNS [file: FS.OpenFile ← FS.nullOpenFile] = {
mn: ROPENIL;
created: BasicTime.GMT;
IF shortNameHint # NIL THEN {
fileNameList: LIST OF ROPE;
IF shortNameHint # NIL THEN fileNameList ← AMFiles.FullFileNameList[shortNameHint];
IF fileNameList # NIL THEN {
FOR names: LIST OF ROPE ← fileNameList, names.rest UNTIL names = NIL DO
file ← FS.Open[names.first ! FS.Error => {file ← FS.nullOpenFile; CONTINUE}];
IF file # FS.nullOpenFile THEN {
IF EQStamps[GetBCDVersionInfo[file].fileVersionStamp, versionStamp]
THEN RETURN[file];
FS.Close[file];
file ← FS.nullOpenFile;
};
ENDLOOP;
};
};
[mn, created] ← VersionMapDefaults.FileNameFromVersion[
which: $Symbols, version: versionStamp
! UNCAUGHT => CONTINUE];
IF mn # NIL THEN file ← AMFiles.OpenIt[mn, created].openFile;
IF shortNameHint # NIL AND file = NIL THEN {
We are about to lose it. But we can try the short name against the version map to get a long name, then remove the version and try the resulting long name to try for the most recent remote version. This may help with incremental searches.
names: VersionMap.MapAndNameList ← VersionMap.ShortNameToNames[GetMapList[], shortNameHint];
FOR each: VersionMap.MapAndNameList ← names, each.rest WHILE each # NIL DO
name: ROPE ← each.first.name;
name ← Rope.Substr[name, 0, Rope.SkipTo[name, 0, "!"]];
file ← FS.Open[name ! FS.Error => LOOP];
IF EQStamps[GetBCDVersionInfo[file].fileVersionStamp, versionStamp]
THEN RETURN[file];
ENDLOOP;
file ← FS.nullOpenFile;
};
};
GetMapList: PUBLIC PROC RETURNS [VersionMap.MapList] = {
RETURN[VersionMapDefaults.GetMapList[$Symbols]];
};
MODULE INITIALIZATION
YRCMapOps.EstablishOuter[RCMapOuterY]; -- NOTE this line should precede the next one
XRCMapOps.EstablishOuter[RCMapOuterX];
YSymbolTable.SetCacheSize[pages: 512];
XSymbolTable.SetCacheSize[pages: 512];
}.