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; onePageSpace: VM.Interval = VM.Allocate[1]; ROPE: TYPE = Rope.ROPE; OuterFromSTH: PUBLIC PROC [sth: SymbolTableHandle, inner: PROC [stb: SymbolTableBase] ] = { 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: 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 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 { 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 { 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; }; 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]]; }; 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] = { 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])]; }; 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 AND moduleName # NIL THEN fileName _ Rope.Concat[moduleName, ".bcd"]; IF fileName # NIL THEN newFile _ AMFiles.OpenIt[fileName].openFile; DO IF newFile = FS.nullOpenFile THEN { IF EQStamps[stamp, BcdDefs.NullVersion] THEN GOTO noFile ELSE { 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]; }; OuterFromGFH: PUBLIC PROC [gfh: GlobalFrameHandle, inner: PROC [stb: SymbolTableBase] ] = { stb: SymbolTableBase _ AcquireSTBFromGFH[gfh]; inner[stb ! UNWIND => ReleaseSTB[stb] ]; ReleaseSTB[stb]; }; AcquireSTBFromGFH: PUBLIC PROC [gfh: GlobalFrameHandle] RETURNS [stb: SymbolTableBase _ nullBase] = { 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); { found: BOOL; stx: RTTypesBasicPrivate.SymbolTableIndex; [stx, found] _ FindSTX[umid]; IF found THEN sth _ AcquireSTHFromSTX[stx].sth}; IF NullSth[sth] THEN sth _ AcquireSTHFromSGI[bcd, mth.sseg]; IF NullSth[sth] 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] ! UNCAUGHT => CONTINUE ]; }; IF NullSth[sth] THEN [sth: sth, moduleName: moduleName] _ AcquireSTHFromSTX[RTTypesBasicPrivate.FindSTI[[symbolsStamp: umid, bcd: bcd]]]; IF NullSth[sth] 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]; }; OuterFromSGI: PUBLIC PROC [bcd: BcdDefs.BcdBase, sgi: BcdDefs.SGIndex, inner: PROC [base: SymbolTableBase]] = { 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] = { 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]]; }; 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 ! UNCAUGHT => CONTINUE]; }; }; 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 _ 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: ROPE _ NIL] RETURNS [bcd: BcdDefs.BcdBase _ 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] = { RETURN[TRUE]; }; 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; 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 { 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]]; }; YRCMapOps.EstablishOuter[RCMapOuterY]; -- NOTE this line should precede the next one XRCMapOps.EstablishOuter[RCMapOuterX]; YSymbolTable.SetCacheSize[pages: 512]; XSymbolTable.SetCacheSize[pages: 512]; }. όRTGetSymbolsImpl.mesa Copyright c 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 Variables protected by the monitor PUBLIC PROCS Provided as a convenience for clients who want to know that they have been adequately protected against failure to release a symbol table. this may return nullHandle but will not raise any signals search the BCD's file table look for the specified file version must match bcd.version here if file is found and version matches stamp on the MODULE, maybe different than bcd.version Try the quick kill for an already acquired symbol handle associated with the stamp. Try the file name hint locally no local file with that name look for the module's original file here with a valid FC Provided as a convenience for clients who want to know that they have been adequately protected against failure to release a symbol table. raises Error if there are no symbols for the specified module First look in the umid -> sth map then try for the one referenced in the bcd then try for the named module's file (locally) then try for the original one then give up. Provided as a convenience for clients who want to know that they have been adequately protected against failure to release a symbol table. sgi identifies the symbol segment PRIVATE PROCS returns nullHandle if there are no symbols may return FS.nullOpenFile may return NIL Note: this has to change if there is ever another bcd format 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. MODULE INITIALIZATION Κ˜codešœ™Kšœ Οmœ=™HKšœ)™)K™0K˜šΟk ˜ Kšœžœ˜)Kšœžœ ˜Kšœ žœžœ˜Kšœžœš˜§Kšœžœ ˜,KšœžœF˜\KšœžœF˜\Kšœžœ˜1Kšœ žœ ˜Kšžœžœ4˜Kšœ žœO˜aKšœ žœK˜\Kšœ žœ˜Kšœžœ˜Kšœžœ0˜IKšœ žœžœ˜Kšœ žœ0˜AKšœžœ˜Kšœ žœ-˜=Kšœžœ#˜;KšžœžœH˜PK˜——šΟnœž˜Kšžœžœ‰ž˜―Kšžœ˜#Kšžœ ˜KšžœΏ˜ΓK˜—šœ"™"Kšœžœ žœ ˜+—˜Kšžœžœžœ˜—K˜Kšœ ™ K˜šŸ œžœžœ!žœ˜[KšœŠ™ŠKšœ'˜'Kšœ žœ˜(Kšœ˜K˜K˜—šŸ œžœžœžœ˜Sšœžœžœž˜K˜9K˜8Kšžœžœ˜—šžœžœž˜šœ˜Kš žœžœžœžœžœ˜,Kšžœ4žœžœžœ˜EK˜—šœ˜Kš žœžœžœžœžœ˜,Kšžœ4žœžœžœ˜EK˜—Kšžœžœžœ˜—Kšžœ˜ šžœ ˜Kšœ žœžœ˜AK˜Kšžœ0˜5K˜—K˜K˜—šŸ œžœžœ˜2šžœžœž˜K˜2K˜1Kšžœžœ˜—šœ˜K˜——šŸ œžœžœžœ˜Pšžœžœžœž˜Kšœ<˜˜>šžœΟc,˜Ešžœ˜Kšœ™šœžœ1žœžœ˜\Kš žœžœ&žœžœžœ˜˜>Kšœžœžœ˜FK˜˜K˜——šŸ œžœ=žœ ˜rKšœ>˜>Kšœžœžœ˜FK˜˜K˜——šŸ œžœžœ7žœ˜qK˜4Kšœ žœ˜)K˜˜K˜——šŸœžœžœ/žœ˜kKšœ3˜3Kšœ žœ˜Kšœ žœ˜K˜Kšžœžœžœ˜#šœ˜Kšœ˜šžœžœž˜˜Kšœ žœ)˜:—˜Kšœ žœ)˜:—Kšžœžœ˜——K˜5K˜šœ$˜$šžœžœž˜˜Kšœ žœ'˜8—˜Kšœ žœ'˜8—Kšžœžœ˜——K˜7šžœ˜šœ ˜ šœ˜šœžœžœž˜˜Kšœžœ$˜2—˜Kšœžœ$˜2—Kšžœžœ˜—Kšœ ˜ Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—šœ˜K˜——šŸœžœžœ)žœ œ žœžœ*˜ŽKšœ5™5K˜Kšœ žœ žœ˜'K˜K˜K˜Kšœžœžœ˜K˜K˜K˜Kšœžœžœ˜K˜šŸœžœ.žœžœ˜eKšœžœžœ žœ˜hKšœ žœžœ˜K˜šžœžœžœ˜Kšœžœ ˜,Kšœ,˜,Kšœ"žœ ˜0Kšœ˜—Kšžœ žœ'žœ˜WKšœ˜—K˜šžœžœ%žœ˜2KšœS™SKšœžœ˜ K˜*K˜Kšžœžœ$˜1Kšžœžœžœžœ˜%Kšœ˜K˜—š žœ žœžœžœž˜+Kšœ+˜+K˜—šžœ žœž˜Kšœ™Kšœ,˜,K˜—šž˜šžœ žœ žœ˜#Kšœ™šžœ%˜'Kšžœžœ˜šžœ˜Kšœ#™#Kš œžœžœžœžœžœžœ!˜MKšœH˜HKšœžœ˜Kšžœ žœžœžœ˜.Kšœ˜—Kšœ˜——Kšœ™K˜!Kšœžœ˜#Kšœžœ˜#Kšœžœ˜#šžœ&žœ˜.šžœ˜Kšžœžœ ˜Kšžœ žœžœ˜'—Kšœ˜—Kšœžœ˜K˜?šžœžœžœ˜Kš žœžœžœ žœžœ˜>šžœ˜Kšžœžœ ˜Kšžœžœ ˜—Kšœ˜—K˜šžœ˜Kšžœ˜Kšžœžœžœ ˜PKšžœ ˜"šžœ˜šžœ˜Kšžœžœ ˜Kšžœ žœžœ˜'—Kšœ˜——˜K˜yKšœžœ žœžœ˜-Kšœ˜—šžœ&žœ˜.Kšœ'˜'K˜K˜K˜—K˜BK˜Kšžœ˜ —Kšžœ˜—˜šž˜Kšœ žœ1˜@Kšœžœ3˜FKš œ žœ'žœžœžœ žœ ˜lKšœžœ3˜H—Kšœ˜K˜—šŸ œžœžœ!žœ˜[KšœŠ™ŠKšœ.˜.Kšœ žœ˜(Kšœ˜˜K˜——šŸœžœžœžœ'˜fKšœ=™=K˜K˜Kšœ žœ˜K˜Kšœ˜Kšœ#˜#Kšœ )˜FK˜K˜$šŸ œžœ/žœžœ˜QKšžœžœ'˜JKšœ˜K˜—Kšœ˜KšœA˜AKšœ-˜-Kšœ˜K˜Kšœžœ˜%Kšœžœ˜#K˜0Kšžœžœžœžœ˜K˜Kšœžœžœ žœ˜RK˜šœ˜Kšœ!™!Kšœžœ˜ K˜*K˜Kšžœžœ#˜0K˜šžœž˜Kšœ*™*Kšœ'˜'—šžœžœ˜Kšœ.™.šœ˜Kšœžœžœ žœ˜E—šœ˜Kšœ ˜ Kšœ(˜(K˜2Kšœžœž˜Kšœ˜—K˜—šžœž˜Kšœ™šœ"˜"˜QK˜———šžœžœ˜Kšœ ™ Kšœžœ˜/šžœžœžœ˜Kšœžœ$žœ žœ˜oKšœ+˜+K˜—Kšžœ3˜8Kšœ˜—K˜Kšžœ˜ —Kšœ˜K˜—šŸ œžœžœ4žœ˜oKšœŠ™ŠKšœ3˜3Kšœ žœ˜(Kšœ˜˜K™——šŸœžœžœ.žœ&˜yKšœ!™!Kšœžœ˜/Kšœžœ&˜GKšœ7 ˜Tšžœžœ˜Kšœžœ˜7Kš œžœžœžœ&žœ.˜…Kšžœ,˜1K˜—Kšžœ˜Kšœ˜K˜—Kšœ ™ K˜š Ÿœžœ žœžœžœ˜GKšžœžœžœ˜DKšœ˜—K˜šŸœžœž œ3žœ˜pšžœžœ*˜4š žœžœ&žœžœžœ˜9šžœA˜CKšžœžœžœ˜——Kšžœ˜—Kšžœžœ˜šœ˜K˜——šŸœžœ-žœ*˜vKšœ*™*Kšœžœ˜/Kšœžœ˜/Kšœžœ˜7K˜"K˜Kšžœžœžœ˜"šžœ ˜+Kšžœžœžœ ˜JKšžœ˜Kšžœžœ˜ K˜—šžœ˜šžœ˜Kšœ˜K˜#Kšœžœ!˜)Kšžœžœžœžœ˜&šœ˜Kšœ_˜_Kšœžœ žœžœ˜-Kšœ˜—K˜K˜K˜K˜IK˜—šžœ˜Kšœ žœ(˜6˜}Kšœžœžœ˜—Kšœ˜——Kšœ˜K˜—š Ÿ œžœ1žœžœžœ˜cKšœS˜SKšœ*˜*Kšœ?˜?šœ˜K˜——š Ÿ œžœ1žœžœžœ˜aKšœS˜SKšœ*˜*Kšžœžœ"˜Cšœ˜K˜——š Ÿœžœžœžœ žœ˜\Kšœžœ˜7K˜˜K˜——šŸœžœ:žœžœžœžœ žœ˜‘Kšœ™Kšœžœžœžœ˜Kšžœžœžœ<˜[šžœžœžœ˜š žœ žœžœžœ žœ žœž˜SKš œžœžœžœžœ˜Qšžœžœžœ˜ šžœA˜CKšžœžœ˜—Kšžœ ˜Kšœžœ˜K˜—Kšžœ˜—K˜—Kšœ>˜>K˜K˜—šŸœžœžœ9žœžœžœžœ˜Kšœ™KšœžœB˜JKšžœžœžœ˜=šœ˜K˜——š Ÿœžœžœžœ žœ˜TKšžœžœžœ˜Kšœžœ ˜Kšœžœžœ*˜;Kšžœ/˜1šžœ ˜Kšžœžœ#˜2Kšžœ˜—Kšœžœžœžœ˜@Kšžœ2˜4K˜K˜—š Ÿœžœ œžœžœžœ˜OKšœ<™