<> <> <> <> <> DIRECTORY AMFiles USING[OpenIt], AMFilesExtras USING[FullFileNameList], AMTypes USING[Error], BcdDefs USING[ VersionStamp, NameRecord, MTIndex, SGIndex, SGNull, FTNull, FTSelf, VersionID, FTIndex, NullVersion, BcdBase, NameString, MTHandle, SGHandle, FTHandle], BcdOps USING[ProcessModules, ProcessFiles], BrandXSymbolDefs USING[ rootBodyIndex, nullSymbolIndex, SymbolTableBase, SymbolModuleIndex], BrandYSymbolDefs USING[ rootBodyIndex, nullSymbolIndex, SymbolTableBase, SymbolModuleIndex], ConvertUnsafe USING[SubString, SubStringToRope], FileSegment USING[Pages], FS USING[Error, Open, OpenFile, nullOpenFile, Read, Close], LoadState USING[Acquire, Release, ConfigInfo, GlobalFrameToModule, local, ConfigID, ModuleIndex], PrincOps USING[GlobalFrameHandle], RCMapOps USING[EstablishOuter], Rope USING[ROPE, Concat, Equal, Find, Substr, Index], RTSymbolDefs USING[ SymbolTableBase, SymbolTableHandle, nullHandle, nullBase, SymbolModuleIndex], RTSymbolOps USING[ STBToModuleName, STBVersion, SubStringForName, NullModuleIndex, NullSth], RTSymbols USING[], -- EXPORTS only RTSymbolsPrivate USING[], -- EXPORTS only RTTypesBasicPrivate USING[SymbolTableIndex, FindSTI, MapStiStd, STDesc], SymbolTable USING[SetCacheSize, Release, Acquire, BaseToHandle], Table USING[Base], VersionMap USING[MapList], VersionMapDefaults USING[FileNameFromVersion, GetMapList], VM USING[Interval, Allocate, AddressForPageNumber, Free, PageNumberForAddress]; RTGetSymbolsImpl: MONITOR IMPORTS AMFiles, AMFilesExtras, AMTypes, BcdOps, FS, ConvertUnsafe, LoadState, RCMapOps, Rope, RTSymbolOps, RTTypesBasicPrivate, SymbolTable, VersionMapDefaults, VM EXPORTS RTSymbols, RTSymbolsPrivate SHARES Rope = BEGIN OPEN bx: BrandXSymbolDefs, by: BrandYSymbolDefs, XSymbolTable: SymbolTable, YSymbolTable: SymbolTable, XRCMapOps: RCMapOps, YRCMapOps: RCMapOps, RTSymbolDefs, RTSymbolOps; <> onePageSpace: VM.Interval = VM.Allocate[1]; ROPE: TYPE = Rope.ROPE; -- PUBLIC PROCS -- Outer: PUBLIC PROC[ stb: SymbolTableBase, mdi: SymbolModuleIndex, inner: PROC[base: SymbolTableBase]] = { stb1: SymbolTableBase = AcquireSTBFromMDI[stb, mdi]; inner[stb1 ! UNWIND => ReleaseSTB[stb1]]; ReleaseSTB[stb1]; }; 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; IF NOT (WITH stb SELECT FROM t: SymbolTableBase.x => t.e.stHandle.extended, t: SymbolTableBase.y => t.e.stHandle.extended, ENDCASE => ERROR) -- symbol table made by an old version of the compiler OR (WITH stb SELECT FROM t: SymbolTableBase.x => t.e.bb[bx.rootBodyIndex].type = bx.nullSymbolIndex, t: SymbolTableBase.y => t.e.bb[by.rootBodyIndex].type = by.nullSymbolIndex, ENDCASE => ERROR) THEN {modName: ROPE = STBToModuleName[stb ! UNWIND => ReleaseSTB[stb]]; ReleaseSTB[stb]; ERROR AMTypes.Error[reason: noSymbols, msg: modName]} ELSE RETURN[stb]}; 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: ROPE _ NIL] = { [sth, moduleName] _ DoAcquireSTHFromSTX[stx, TRUE]; }; DoAcquireSTHFromSTX: PROC[stx: RTTypesBasicPrivate.SymbolTableIndex, invokeGetSTHForModule: BOOL _ FALSE] RETURNS[sth: SymbolTableHandle _ nullHandle, moduleName: ROPE _ NIL] = { 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 invokeGetSTHForModule THEN sth _ GetSTHForModule[ stamp: symbolsStamp, fileName: NIL, moduleName: NIL ! ANY => CONTINUE] ELSE RETURN; } ELSE { --bcd # NIL 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 RETURN[FALSE]; moduleName _ GetModuleName[ssb, ffth.name]; sth _ GetSTHForModule[ stamp: symbolsStamp, fileName: Rope.Concat[moduleName, ".bcd"], moduleName: moduleName ! AMTypes.Error => CONTINUE]; RETURN[TRUE]; }; IF NOT invokeGetSTHForModule THEN RETURN; [] _ BcdOps.ProcessFiles[bcd, findSymbolFTI]; IF NullSth[sth] THEN sth _ GetSTHForModule[ stamp: symbolsStamp, fileName: NIL, moduleName: NIL ! ANY => 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, << of indicated bcd. Should match bcd.version>> base: sgb[sgi].base - 1, pages: sgb[sgi].pages + sgb[sgi].extraPages ! AMTypes.Error => CONTINUE] }; }; -- end ELSE (i.e. bcd # NIL) RTTypesBasicPrivate.MapStiStd[stx].sth _ sth; }; -- end DoAcquireSTHFromSTX <> 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]; <> 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]]; }; -- end NewSymbolHandle 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]}; 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, -- maybe NIL moduleName: ROPE -- maybe NIL ] RETURNS[sth: SymbolTableHandle _ nullHandle] = { bcd: BcdDefs.BcdBase; newFile: FS.OpenFile _ FS.nullOpenFile; sgb: Table.Base; ftb: Table.Base; ntb: BcdDefs.NameString; versionMapTried: BOOL _ FALSE; mth: BcdDefs.MTHandle; sSeg: BcdDefs.SGIndex; someNameMatched: BOOL _ FALSE; 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: BOOL _ TRUE; 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]) ]; }; -- end FindVersionStampedModule <> IF NOT EQStamps[stamp, BcdDefs.NullVersion] THEN { 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 THEN newFile _ AMFiles.OpenIt[fileName].openFile; DO IF newFile = FS.nullOpenFile -- no local file with that name THEN { 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; }; }; <> 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]; }; -- end GetSTHForModule <> AcquireSTBFromGFH: PUBLIC PROC[gfh: PrincOps.GlobalFrameHandle] RETURNS[stb: SymbolTableBase _ nullBase] = BEGIN 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); < sth map>> {found: BOOL; stx: RTTypesBasicPrivate.SymbolTableIndex; [stx, found] _ FindSTX[umid]; IF found THEN sth _ AcquireSTHFromSTX[stx].sth}; IF NullSth[sth] -- then try for the one referenced in the bcd THEN sth _ AcquireSTHFromSGI[bcd, mth.sseg]; IF NullSth[sth] -- then try for the named module's file (locally) THEN { 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] ! ANY => CONTINUE ]; }; IF NullSth[sth] -- then try for the original one THEN [sth: sth, moduleName: moduleName] _ AcquireSTHFromSTX[RTTypesBasicPrivate.FindSTI[[symbolsStamp: umid, bcd: bcd]]]; IF NullSth[sth] -- then give up. THEN { 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]; END; -- AcquireSTBFromGFH AcquireSTBFromSGI: PUBLIC PROC[bcd: BcdDefs.BcdBase, sgi: BcdDefs.SGIndex] <> RETURNS[stb: SymbolTableBase _ nullBase] = { 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]; ERROR AMTypes.Error[ reason: noSymbols, msg: IF sgh.file = BcdDefs.FTSelf THEN GetFileName[ssb: ssb, n: bcd.source] ELSE GetFileName[ssb: ssb, n: ftb[sgh.file].name]]; }; 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] = { 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 << version of the specified file, not necessarily of the module>> ! ANY => CONTINUE]; }; }; -- end AcquireSTHFromSGI GetModuleName: PROC[ssb: BcdDefs.NameString, n: BcdDefs.NameRecord] RETURNS[name: ROPE _ NIL] = { 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: ROPE _ NIL] = { 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: ROPE _ NIL] RETURNS[file: FS.OpenFile _ FS.nullOpenFile] = { fileNameList: LIST OF ROPE; IF shortFileNameHint # NIL THEN fileNameList _ AMFilesExtras.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: versionStamp]; }; <> AcquireBCDFromVersion: PUBLIC PROC[versionStamp: BcdDefs.VersionStamp, shortFileNameHint: ROPE _ NIL] RETURNS[bcd: BcdDefs.BcdBase] = { file: FS.OpenFile _ AcquireFCFromVersion[versionStamp, shortFileNameHint]; IF file = FS.nullOpenFile THEN RETURN[NIL] ELSE RETURN[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] = {RETURN[TRUE]}; -- NOTE XXX ReleaseBCD: PUBLIC ENTRY PROC[bcd: BcdDefs.BcdBase] = {ENABLE UNWIND => NULL; count: INT _ MAX[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: ROPE _ NIL] RETURNS[file: FS.OpenFile _ FS.nullOpenFile] = { mn: ROPE _ NIL; IF shortNameHint # NIL THEN { fileNameList: LIST OF ROPE; IF shortNameHint # NIL THEN fileNameList _ AMFilesExtras.FullFileNameList[shortNameHint]; 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; }; }; mn _ VersionMapDefaults.FileNameFromVersion [which: $Symbols, version: versionStamp ! ANY => CONTINUE]; IF mn # NIL THEN file _ AMFiles.OpenIt[mn].openFile; }; GetMapList: PUBLIC PROC RETURNS[VersionMap.MapList] = {RETURN[VersionMapDefaults.GetMapList[$Symbols]]}; <<>> <> YRCMapOps.EstablishOuter[RCMapOuterY]; -- NOTE this line should precede the next one XRCMapOps.EstablishOuter[RCMapOuterX]; YSymbolTable.SetCacheSize[pages: 512]; XSymbolTable.SetCacheSize[pages: 512]; END.