DIRECTORY AMTypes USING[Error], BcdDefs USING[VersionStamp, NameRecord, MTIndex, SGIndex, SGNull, FTNull, FTSelf, VersionID, FTIndex, NullVersion], BcdOps USING[BcdBase, NameString, MTHandle, SGHandle, ProcessModules, FTHandle, ProcessFiles], BrandXSymbolDefs USING[rootBodyIndex, nullSymbolIndex, SymbolTableBase, SymbolModuleIndex], BrandYSymbolDefs USING[rootBodyIndex, nullSymbolIndex, SymbolTableBase, SymbolModuleIndex], CIFS USING[GetFC, Open, read, dontCheck, OpenFile], ConvertUnsafe USING[AppendRope, ToRope], File USING[Capability, nullCapability], FileSegment USING[Pages], LongString USING[AppendString], PilotLoadStateFormat USING[ModuleInfo, ConfigIndex], PilotLoadStateOps USING[InputLoadState, GetModule, AcquireBcd, ReleaseBcd, ReleaseLoadState, EnumerateBcds], PrincOps USING[GlobalFrameHandle], NewRCMapOps USING[EstablishOuter], Rope USING[ROPE, Flatten, Length, Fetch, Concat], RTFiles USING [SameFile], -- EXPORTS RTFilesExtra USING [], -- EXPORTS only RTFlags USING[checking], RTOS USING[EnumerateGlobalFrames, SameCode, UnRavelUSUs], RTSymbolDefs USING[SymbolTableBase, SymbolTableHandle, nullHandle, nullBase, SymbolModuleIndex], RTSymbolOps USING[STBToModuleName, STBVersion, SubStringForHash, NullModuleIndex, NullSth], RTSymbols USING[], -- EXPORTS only RTSymbolsPrivate USING[], -- EXPORTS only RTTypesBasicPrivate USING[SymbolTableIndex, MapStiStd, FindSTI, STDesc], Runtime USING[CallDebugger, ValidateGlobalFrame], Space USING[Map, LongPointer, Unmap, GetAttributes, GetWindow, GetHandle, PageFromLongPointer, Handle, Create, virtualMemory, Delete], Strings USING[SubStringDescriptor, AppendSubString, AppendString, EqualSubStrings], SymbolTable USING[SetCacheSize, Release, Acquire, Forget, anySpan], Table USING[Base], VersionMap USING[MapList], VersionMapDefaults USING[FileNameFromVersion, GetMapList]; RTGetSymbolsImpl: MONITOR IMPORTS AMTypes, BcdOps, CIFS, ConvertUnsafe, LongString, PilotLoadStateOps, NewRCMapOps, Rope, RTFiles, RTOS, RTSymbolOps, RTTypesBasicPrivate, Runtime, Space, Strings, SymbolTable, VersionMapDefaults EXPORTS RTFiles, RTFilesExtra, RTSymbols, RTSymbolsPrivate SHARES File = BEGIN OPEN bx: BrandXSymbolDefs, by: BrandYSymbolDefs, XSymbolTable: SymbolTable, YSymbolTable: SymbolTable, XRCMapOps: NewRCMapOps, YRCMapOps: NewRCMapOps, RTSymbolDefs, RTSymbolOps; onePageSpace: Space.Handle = Space.Create[size: 1, parent: Space.virtualMemory]; standardBCDSpaces: LIST OF Space.Handle _ NIL; standardBCDSpacePages: NAT = 20; standardBCDSpacesInUse: NAT _ 0; standardBCDSpacesHeld: NAT _ 0; biggerBCDSpacesInUse: NAT _ 0; OZ: BOOL _ FALSE; ROPE: TYPE = Rope.ROPE; -- PUBLIC PROCS -- Outer: PUBLIC PROC[stb: SymbolTableBase, mdi: SymbolModuleIndex, inner: PROC[base: SymbolTableBase], mesaSymbolsOK: BOOL _ FALSE] = {stb1: SymbolTableBase = AcquireSTBFromMDI[stb, mdi, mesaSymbolsOK]; inner[stb1 ! UNWIND => ReleaseSTB[stb1]]; ReleaseSTB[stb1]}; AcquireSTBForDefs: PUBLIC PROC[fileName: ROPE--ends with .bcd--] RETURNS[stb: SymbolTableBase] = { mn: STRING = [100]; dotFound: BOOL _ FALSE; FOR i: NAT IN [0..Rope.Length[fileName]) DO IF Rope.Fetch[fileName, i] = '. THEN {dotFound _ TRUE; EXIT}; ENDLOOP; IF NOT dotFound THEN fileName _ Rope.Concat[fileName, ".bcd"]; mn.length _ 0; ConvertUnsafe.AppendRope[from: fileName, to: LONG[mn]]; IF mn.length<=4 THEN ERROR AMTypes.Error[reason: noSymbols, msg: fileName]; mn.length _ mn.length-4; stb _ AcquireSTB[GetSTHForModule[stamp: BcdDefs.NullVersion, fileName: fileName, moduleName: ConvertUnsafe.ToRope[LONG[mn]]]]; IF NOT (WITH stb SELECT FROM t: SymbolTableBase.x => t.e.stHandle.definitionsFile, t: SymbolTableBase.y => t.e.stHandle.definitionsFile, ENDCASE => ERROR) THEN {ReleaseSTB[stb]; ERROR AMTypes.Error[reason: noSymbols, msg: Rope.Concat[fileName, " not a defs module"]]}; }; AcquireSTB: PUBLIC PROC[sth: SymbolTableHandle, mesaSymbolsOK: BOOL _ FALSE] 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 mesaSymbolsOK THEN RETURN[stb]; 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}; 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: BcdOps.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 {sgb: Table.Base = LOOPHOLE[bcd + bcd.sgOffset]; ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset]; ssb: BcdOps.NameString = LOOPHOLE[bcd + bcd.ssOffset]; fti: BcdDefs.FTIndex; sgi: BcdDefs.SGIndex = RTTypesBasicPrivate.MapStiStd[stx].sgi; -- maybe SGNull IF sgi = BcdDefs.SGNull -- search the BCD's file table (find a DEFs) THEN { findSymbolFTI: PROC[ffth: BcdOps.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 {OPEN Space; file: File.Capability = FileFromBcdBase[bcd]; IF file # File.nullCapability THEN {p: FileSegment.Pages = [file: file, span: [base: sgb[sgi].base, 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[sgb[sgi].file].version, base: sgb[sgi].base, 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: File.Capability _ File.nullCapability; stb: SymbolTableBase; symbolsStamp: BcdDefs.VersionStamp; isXBCD: BOOL = TRUE; -- NOTE XXX IF EQStamps[version, BcdDefs.NullVersion] THEN file _ GetReadCapability[fileName ! ANY => CONTINUE] ELSE file _ AcquireFCFromVersion[version, fileName]; IF file = File.nullCapability 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 IsFileInUse: PUBLIC PROC[file: File.Capability] RETURNS[found: BOOL _ FALSE] = { loadStateHeld: BOOL; p: PROC[c: PilotLoadStateFormat.ConfigIndex] RETURNS[stop: BOOL] = {OPEN Space; ptr: LONG POINTER = LOOPHOLE[PilotLoadStateOps.AcquireBcd[c]]; space: Handle _ RTOS.UnRavelUSUs[GetHandle[PageFromLongPointer[ptr]]]; PilotLoadStateOps.ReleaseBcd[LOOPHOLE[ptr]]; IF file.fID = GetWindow[space].file.fID THEN {found _ TRUE; RETURN[TRUE]} ELSE RETURN[FALSE]; }; IF IsFileUsed[file] THEN RETURN [TRUE]; XSymbolTable.Forget[[file: file, span: XSymbolTable.anySpan] ! ANY => {found _ TRUE; CONTINUE}]; IF found THEN RETURN; YSymbolTable.Forget[[file: file, span: YSymbolTable.anySpan] ! ANY => {found _ TRUE; CONTINUE}]; IF found THEN RETURN; [] _ PilotLoadStateOps.InputLoadState[]; loadStateHeld _ TRUE; [] _ PilotLoadStateOps.EnumerateBcds[recentfirst, p ! ANY => {loadStateHeld _ FALSE; PilotLoadStateOps.ReleaseLoadState[]}]; IF loadStateHeld THEN PilotLoadStateOps.ReleaseLoadState[]; IF found THEN RETURN; FOR x: NAT IN [1..RTTypesBasicPrivate.MapStiStd.length) DO sth: SymbolTableHandle; f: File.Capability; IF RTTypesBasicPrivate.MapStiStd[x] = NIL THEN EXIT; sth _ RTTypesBasicPrivate.MapStiStd[x].sth; IF NullSth[sth] THEN LOOP; IF sth.brand = x THEN f _ NARROW[sth, SymbolTableHandle.x].e.file ELSE f _ NARROW[sth, SymbolTableHandle.y].e.file; IF f.fID = file.fID THEN RETURN[TRUE]; ENDLOOP; }; 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, mesaSymbolsOK: BOOL _ FALSE] RETURNS[SymbolTableBase] = { fileNameDesc, modNameDesc: Strings.SubStringDescriptor; fileName: STRING = [100]; modName: STRING = [100]; IF NullModuleIndex[mdi] THEN ERROR; fileName.length _ 0; modName.length _ 0; SubStringForHash[stb, @modNameDesc, 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]; Strings.AppendSubString[modName, @modNameDesc]; SubStringForHash[stb, @fileNameDesc, 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]; Strings.AppendSubString[fileName, @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), ConvertUnsafe.ToRope[LONG[fileName]], ConvertUnsafe.ToRope[LONG[modName]]], mesaSymbolsOK]]}; GetSTHForModule: PUBLIC PROC[stamp: BcdDefs.VersionStamp, fileName: ROPE, -- maybe NIL moduleName: ROPE -- maybe NIL ] RETURNS[sth: SymbolTableHandle _ nullHandle] = { bcd: BcdOps.BcdBase; newFile: File.Capability _ File.nullCapability; sgb: Table.Base; ftb: Table.Base; ntb: BcdOps.NameString; versionMapTried: BOOL _ FALSE; mth: BcdOps.MTHandle; sSeg: BcdDefs.SGIndex; modNameDesc: Strings.SubStringDescriptor _ [base: LOOPHOLE[Rope.Flatten[moduleName]], offset: 0, length: Rope.Length[moduleName]]; someNameMatched: BOOL _ FALSE; FindVersionStampedModule: PROC[mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS[stop: BOOL] = { umid: BcdDefs.VersionStamp = IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version; nextModNameDesc: Strings.SubStringDescriptor; namesMatch: BOOL _ TRUE; IF moduleName # NIL THEN {nextModNameDesc _ [base: @ntb.string, offset: mth.name, length: ntb.size[mth.name]]; namesMatch _ Strings.EqualSubStrings[@modNameDesc, @nextModNameDesc]; 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 _ GetReadCapability[fileName ! ANY => CONTINUE]; DO IF newFile = File.nullCapability -- no local file with that name THEN {IF EQStamps[stamp, BcdDefs.NullVersion] THEN GOTO noFile ELSE { -- look for the module's original file shortName: ROPE = IF moduleName = NIL THEN NIL ELSE Rope.Concat[moduleName, ".bcd"]; cifsFile: CIFS.OpenFile = VersionToReadableFile[versionStamp: stamp, shortNameHint: shortName]; versionMapTried _ TRUE; IF cifsFile = NIL THEN GOTO noFile; newFile _ CIFS.GetFC[cifsFile ! ANY => {IF OZ THEN Runtime.CallDebugger ["CIFS.GetFC failed"]; CONTINUE}]; IF newFile = File.nullCapability 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 _ File.nullCapability; LOOP}}; someNameMatched _ FALSE; mth _ BcdOps.ProcessModules[bcd, FindVersionStampedModule].mth; IF mth = NIL THEN {IF NOT versionMapTried THEN {newFile _ File.nullCapability; 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 _ File.nullCapability; LOOP}}; {p: FileSegment.Pages = [file: newFile, span: [base: sgb[sSeg].base, 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, mesaSymbolsOK: BOOL _ FALSE] RETURNS[stb: SymbolTableBase _ nullBase] = BEGIN bcd: BcdOps.BcdBase; bcdns: BcdOps.NameString; moduleName: ROPE; module: PilotLoadStateFormat.ModuleInfo; -- a loadstate.gft entry mth: BcdOps.MTHandle; umid: BcdDefs.VersionStamp; -- functional version stamp of the module ftb: Table.Base; sth: SymbolTableHandle _ nullHandle; FindOriginal: PROCEDURE [f: PrincOps.GlobalFrameHandle] RETURNS [BOOL] = {RETURN[(f # gfh) AND (RTOS.SameCode[gfh, f] = identical) AND (~f.copied)]}; FindModule: PROC [mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = {RETURN[(mth.gfi <= module.gfi) AND (module.gfi < (mth.gfi + mth.ngfi))]}; IF RTFlags.checking THEN Runtime.ValidateGlobalFrame[gfh]; IF gfh.copied THEN gfh _ RTOS.EnumerateGlobalFrames[FindOriginal]; [] _ PilotLoadStateOps.InputLoadState[]; module _ PilotLoadStateOps.GetModule[gfh.gfi]; bcd _ PilotLoadStateOps.AcquireBcd[module.config]; PilotLoadStateOps.ReleaseLoadState[]; 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 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 sth _ GetSTHForModule[stamp: umid, fileName: GetFileName[ssb: bcdns, n: ftb[mth.file].name], 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]; msg: ROPE _ moduleName; IF msg = NIL THEN msg _ GetFileName[ssb: bcdns, n: ftb[sgb[mth.sseg].file].name]; ERROR AMTypes.Error[reason: noSymbols, msg: msg]}; stb _ AcquireSTB[sth, mesaSymbolsOK]; RETURN[stb]; END; -- AcquireSTBFromGFH AcquireSTBFromSGI: PUBLIC PROC[bcd: BcdOps.BcdBase, sgi: BcdDefs.SGIndex, -- of the symbol segment mesaSymbolsOK: BOOL _ FALSE] RETURNS[stb: SymbolTableBase _ nullBase] = { ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset]; sgh: BcdOps.SGHandle = @LOOPHOLE[bcd + bcd.sgOffset, Table.Base][sgi]; sth: SymbolTableHandle _ AcquireSTHFromSGI[bcd, sgi]; -- try for the referenced one IF NullSth[sth] THEN {ssb: BcdOps.NameString = LOOPHOLE[bcd + bcd.ssOffset]; ERROR AMTypes.Error[reason: noSymbols, msg: 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: BcdOps.BcdBase, sgi: BcdDefs.SGIndex] RETURNS [sth: SymbolTableHandle _ nullHandle] = { sgb: Table.Base = LOOPHOLE[bcd + bcd.sgOffset]; ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset]; ssb: BcdOps.NameString = LOOPHOLE[bcd + bcd.ssOffset]; sgh: BcdOps.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: File.Capability = FileFromBcdBase[bcd]; IF file = File.nullCapability THEN RETURN; {p: FileSegment.Pages = [file: file, span: [base: sgh.base, 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, pages: sgh.pages+sgh.extraPages, version: ftb[sgh.file].version ! ANY => CONTINUE]} }; -- end AcquireSTHFromSGI GetModuleName: PROC[ssb: BcdOps.NameString, n: BcdDefs.NameRecord] RETURNS[ROPE] = {nameString: STRING = [100]; ssd: Strings.SubStringDescriptor _ [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; nameString.length _ 0; Strings.AppendSubString[nameString, @ssd]; FOR i: CARDINAL IN [0..nameString.length) DO IF nameString[i] = '. THEN {nameString.length _ i; EXIT}; ENDLOOP; RETURN[ConvertUnsafe.ToRope[LONG[nameString]]]}; GetFileName: PROC[ssb: BcdOps.NameString, n: BcdDefs.NameRecord] RETURNS[ROPE] = {nameString: STRING = [100]; ssd: Strings.SubStringDescriptor _ [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; dot: BOOL _ FALSE; nameString.length _ 0; Strings.AppendSubString[nameString, @ssd]; FOR i: CARDINAL IN [0..nameString.length) DO IF nameString[i] = '. THEN {dot _ TRUE; EXIT}; ENDLOOP; IF ~dot THEN Strings.AppendString[nameString, ".bcd"]; RETURN[ConvertUnsafe.ToRope[LONG[nameString]]]}; FileFromBcdBase: PROC[bcd: BcdOps.BcdBase] RETURNS[fc: File.Capability _ File.nullCapability] = { ssb: BcdOps.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: File.Capability _ File.nullCapability] = { cifsFile: CIFS.OpenFile; IF shortFileNameHint # NIL THEN file _ GetReadCapability[shortFileNameHint]; IF file # File.nullCapability THEN {IF EQStamps[GetBCDVersionInfo[file].fileVersionStamp, versionStamp] THEN RETURN[file]; file _ File.nullCapability}; cifsFile _ VersionToReadableFile[versionStamp: versionStamp]; IF cifsFile = NIL THEN RETURN; file _ CIFS.GetFC[cifsFile ! ANY => {IF OZ THEN Runtime.CallDebugger["CIFS.GetFC failed"]; CONTINUE}]; }; AcquireBCDFromVersion: PUBLIC PROC[versionStamp: BcdDefs.VersionStamp, shortFileNameHint: ROPE _ NIL] RETURNS[bcd: BcdOps.BcdBase] = { file: File.Capability _ AcquireFCFromVersion[versionStamp, shortFileNameHint]; IF file = File.nullCapability THEN RETURN[NIL] ELSE RETURN[AcquireBCDFromCap[file]]}; AcquireBCDFromCap: ENTRY PROC[file: File.Capability] RETURNS[bcd: BcdOps.BcdBase] = { ENABLE UNWIND => NULL; space: Space.Handle; size: NAT; -- pages Space.Map[onePageSpace, [file: file, base: 1]]; bcd _ LOOPHOLE[Space.LongPointer[onePageSpace]]; IF bcd.extended THEN size _ bcd.nPages - bcd.rtPages.pages ELSE size _ bcd.nPages; Space.Unmap[onePageSpace]; IF size <= standardBCDSpacePages THEN {IF standardBCDSpaces = NIL THEN space _ Space.Create[size: standardBCDSpacePages, parent: Space.virtualMemory] ELSE {space _ standardBCDSpaces.first; standardBCDSpaces _ standardBCDSpaces.rest; standardBCDSpacesHeld _ standardBCDSpacesHeld - 1}; standardBCDSpacesInUse _ standardBCDSpacesInUse + 1 } ELSE {space _ Space.Create[size: size, parent: Space.virtualMemory]; biggerBCDSpacesInUse _ biggerBCDSpacesInUse + 1}; Space.Map[space, [file: file, base: 1]]; bcd _ LOOPHOLE[Space.LongPointer[space]]; }; IsXBCD: PROC[bcd: BcdOps.BcdBase--only the first page!!--] RETURNS[BOOL] = {RETURN[TRUE]}; -- NOTE XXX ReleaseBCD: PUBLIC ENTRY PROC[bcd: BcdOps.BcdBase] = { ENABLE UNWIND => NULL; space: Space.Handle = RTOS.UnRavelUSUs[Space.GetHandle[Space.PageFromLongPointer[bcd]]]; size: NAT _ Space.GetAttributes[space].size; Space.Unmap[space]; IF size # standardBCDSpacePages THEN {Space.Delete[space]; biggerBCDSpacesInUse _ biggerBCDSpacesInUse - 1} ELSE {standardBCDSpaces _ CONS[space, standardBCDSpaces]; standardBCDSpacesInUse _ standardBCDSpacesInUse - 1; standardBCDSpacesHeld _ standardBCDSpacesHeld + 1}; }; GetBCDVersionInfo: ENTRY PROC[file: File.Capability] RETURNS[fileVersionIdent: CARDINAL, fileVersionStamp: BcdDefs.VersionStamp, isXBCD: BOOL] = { ENABLE UNWIND => NULL; bcd: BcdOps.BcdBase; Space.Map[onePageSpace, [file: file, base: 1]]; bcd _ LOOPHOLE[Space.LongPointer[onePageSpace]]; fileVersionIdent _ bcd.versionIdent; fileVersionStamp _ bcd.version; isXBCD _ IsXBCD[bcd]; Space.Unmap[onePageSpace]; }; GetReadCapability: PROC[name: ROPE] RETURNS[f: File.Capability _ File.nullCapability] = {cifsFile: CIFS.OpenFile _ NIL; cifsFile _ CIFS.Open[Rope.Concat["/local/", name], CIFS.read ! ANY => CONTINUE]; IF cifsFile = NIL THEN RETURN; f _ CIFS.GetFC[cifsFile ! ANY => {IF OZ THEN Runtime.CallDebugger["CIFS.GetFC failed"]; CONTINUE}]}; VersionToReadableFile: PUBLIC PROC[versionStamp: BcdDefs.VersionStamp, shortNameHint: ROPE _ NIL] RETURNS[file: CIFS.OpenFile _ NIL] = {mn: ROPE _ NIL; mn _ VersionMapDefaults.FileNameFromVersion[which: $Symbols, version: versionStamp ! ANY => {IF OZ THEN Runtime.CallDebugger ["VersionMapDefaults.FileNameFromVersion failed"]; CONTINUE}]; IF mn = NIL THEN RETURN; file _ CIFS.Open[mn, CIFS.read + CIFS.dontCheck ! ANY => {IF OZ THEN Runtime.CallDebugger["CIFS.Open failed"]; CONTINUE}]; }; GetMapList: PUBLIC PROC RETURNS[VersionMap.MapList] = {RETURN[VersionMapDefaults.GetMapList[$Symbols]]}; inUseList: InUseList _ NIL; -- protected by the monitor InUseList: TYPE = LIST OF InUseEntry; InUseEntry: TYPE = RECORD [file: File.Capability, exclusive: BOOL _ FALSE, count: INT _ 0]; IncFileUse: PUBLIC ENTRY SAFE PROC [file: File.Capability, exclusive: BOOL _ TRUE] RETURNS [ok: BOOL] = TRUSTED { ENABLE UNWIND => NULL; entry: InUseList _ NIL; FOR each: InUseList _ inUseList, each.rest WHILE each # NIL DO IF RTFiles.SameFile[file, each.first.file] THEN { entry _ each; EXIT}; ENDLOOP; IF entry = NIL THEN { inUseList _ CONS[[file: file, exclusive: exclusive, count: 1], inUseList]; RETURN [TRUE]}; IF entry.first.exclusive THEN RETURN [FALSE]; IF exclusive THEN { IF entry.first.count # 0 THEN RETURN [FALSE]; entry.first.exclusive _ TRUE; }; entry.first.count _ entry.first.count + 1; RETURN [TRUE]; }; DecFileUseError: PUBLIC ERROR = CODE; DecFileUse: PUBLIC ENTRY SAFE PROC [file: File.Capability] = TRUSTED { ENABLE UNWIND => NULL; entry: InUseList _ NIL; FOR each: InUseList _ inUseList, each.rest WHILE each # NIL DO IF RTFiles.SameFile[file, each.first.file] THEN { entry _ each; EXIT}; ENDLOOP; IF entry = NIL OR entry.first.count <= 0 THEN ERROR DecFileUseError; entry.first.exclusive _ FALSE; entry.first.count _ entry.first.count - 1; }; FileUseCount: PUBLIC ENTRY SAFE PROC [file: File.Capability] RETURNS [count: INT _ 0, exclusive: BOOL _ FALSE] = TRUSTED { ENABLE UNWIND => NULL; FOR each: InUseList _ inUseList, each.rest WHILE each # NIL DO IF RTFiles.SameFile[file, each.first.file] THEN RETURN [each.first.count, each.first.exclusive]; ENDLOOP; }; IsFileUsed: PUBLIC ENTRY SAFE PROC [file: File.Capability] RETURNS [BOOL] = TRUSTED { ENABLE UNWIND => NULL; FOR each: InUseList _ inUseList, each.rest WHILE each # NIL DO IF RTFiles.SameFile[file, each.first.file] THEN RETURN [each.first.count # 0]; ENDLOOP; RETURN [FALSE]; }; YRCMapOps.EstablishOuter[RCMapOuterY]; -- NOTE this line should precede the next one XRCMapOps.EstablishOuter[RCMapOuterX]; YSymbolTable.SetCacheSize[pages: 512]; XSymbolTable.SetCacheSize[pages: 512]; END. ôRTGetSymbolsImpl.mesa Last Modified By Paul Rovner On March 31, 1983 1:34 pm Last Modified By Russ Atkinson On April 14, 1983 2:35 pm (RTFilesExtra) Variables protected by the monitor groan. backward compatibility for limited usage (for RTSymbols clients only, NOT for AMTypes) this may return nullHandle but will not raise any signals (=> search the BCD's file table) of indicated bcd. Should match bcd.version version must match bcd.version here if file is found and version matches try for the local lockbox first flush the SymbolCache enumerate the loadstate enumerate MapStiStd b: BOOL; SELECT sth FROM t: SymbolTableHandle.x => b _ TRUE; t: SymbolTableHandle.y => b _ FALSE; ENDCASE => ERROR; stamp on the MODULE, maybe different than bcd.version START GetSTHForModule body here here with a valid FC raises Error if there are no symbols for the specified module First look in the umid -> sth map returns nullHandle if there are no symbols version of the specified file, not necessarily of the module may return NIL may return NIL The following procedures and data are here to keep track of the files in use ... increments # of users of a given file. If exclusive, then the increment only takes place if the initial count was 0. If not exclusive, the increment only takes place if the file is not exclusively open. ... decrements # of users of a given file, raising DecFileUseError if the initial count = 0. ... returns # of users of a given file ... equivalent to FileUseCount[file] > 0 MODULE INITIALIZATION Ê:˜J˜šœ™Jšœ6™6JšœG™GJ˜—šÏk ˜ Jšœœ˜šœœ<˜IJ˜)—šœœ9˜EJ˜—šœœ1˜GJ˜—šœœ1˜GJ˜—Jšœœ)˜3Jšœœ˜(Jšœœ˜'Jšœ œ˜Jšœ œ˜Jšœœ˜4šœœ3˜JJ˜!—Jšœ œ˜"Jšœ œ˜"Jšœœœ"˜1Jšœœ Ïc ˜%Jšœ œž˜'Jšœœ ˜Jšœœ/˜9šœ œ:˜LJ˜—šœ œ@˜QJ˜ —Jšœ œž˜#Jšœœž˜*Jšœœ/˜HJšœœ$˜1šœœ>˜IJ˜<—šœœ4˜AJ˜—Jšœ œ2˜CJšœœ˜Jšœ œ ˜Jšœœ"˜:J˜—šœ˜šœœ˜9Jšœ-œ#˜VJ˜8—Jšœ3˜:Jšœ˜ —šœœœ,˜8J˜5J˜/J˜J˜—Jšœ"™"J˜PJšœœœœ˜.Jšœœ˜ Jšœœ˜ Jšœœ˜Jšœœ˜J˜Jšœœœ˜J˜Jšœœœ˜J˜Jšž˜J˜šÏnœœœ˜(J˜Jšœœ˜#Jšœœœ˜˜DJšœ œ˜)J˜J˜——š Ÿœœœ žœ˜@Jšœ˜šœœ ˜Jšœ œœ˜šœœœ˜(Jš œœœ œœ˜@Jšœ˜—Jšœœ œ*˜>J˜Jšœ-œ˜7Jšœœœ1˜KJ˜˜Jšœœ2˜FJšœœ˜,šœ%˜'Jšœ œœœ˜!Jšœœœ˜——J˜J˜—J™Jšœœœœ˜'J˜Jšœ™˜Jšœ(˜,J˜—šœž1˜Bšœ#˜'J˜9J˜2Jšœœœ˜J˜——šœž ˜1šœ#˜'˜DJ˜ J˜———šœž˜!šœœ˜5Jšœœ˜Jšœœœ@˜QJšœ-˜2——J˜%Jšœ˜ ——Jšœž˜J˜—šŸœœœ˜3Jšœž˜/Jšœœœ˜Jšœ#˜*šœœ˜1Jšœœ&˜FJšœ7ž˜TJ˜šœ ˜šœœ˜<šœ!˜&J˜4———Jšœ˜J˜——Jšž˜J˜JšŸœœœœ˜J˜ J˜————Jšœ™šŸœœ$˜>Jšœœœ˜Jšœ/˜6Jšœ œ ˜˜Jšœœœ-˜LJ˜šœ˜šœœA˜IJšœœ˜J˜J˜——J˜=Jšœ œœœ˜š œœœœœœ+˜ZJšœ˜ ——J˜J˜Jšœ™—šŸœœœ$˜FJšœœœ˜Jšœ˜˜Pšœ˜Jšœœœ˜Jšœœ˜&J˜———šŸœœœœ˜Sšœœœœ˜J˜Jšœœž˜J˜J˜/Jšœœ"˜0šœ ˜Jšœ&˜*Jšœ˜—J˜šœ˜ šœœ˜ JšœO˜Sšœ"˜&J˜+J˜3—J˜3J˜—šœ@˜DJ˜1——J˜(Jšœœ˜)—J˜J˜—š Ÿœœžœœœ˜JJšœœœž ˜J˜—šŸ œœœœ˜4šœœœœ˜Jšœœ>˜XJšœœ#˜,J˜šœ˜JšœG˜Kšœœ˜9J˜4J˜3———J˜J˜—šŸœœœ˜4šœœ˜#J˜'Jšœœ˜—šœœœœ˜J˜J˜/Jšœœ"˜0J˜$J˜J˜J˜—J˜J˜—šŸœœœœ,˜Wšœ œ œ˜šœ œ$œ˜Jšœ˜ ———J˜J˜—Jš Ÿ œœœœœ+˜hJ˜šœL™LJ˜—Jšœœž˜8Jšœ œœœ ˜%Jš œ œœ$œœ œ˜[J˜šŸ œ œœ˜"Jš œ#œœœœœ˜NJšœÐ™ÐJšœœœ˜Jšœœ˜šœ(œœ˜>šœ)œ˜1Jšœ ˜ Jšœ˜—Jšœ˜—šœ œœ˜Jšœ œ:˜JJšœœ˜—Jšœœœœ˜-šœ œ˜Jšœœœœ˜-Jšœœ˜J˜—Jšœ*˜*Jšœœ˜Jšœ˜J˜—Jšœ œœ˜%J˜š Ÿ œ œœœœ˜FJšœ\™\Jšœœœ˜Jšœœ˜šœ(œœ˜>šœ)œ˜1Jšœ ˜ Jšœ˜—Jšœ˜—Jš œ œœœœ˜DJšœœ˜Jšœ*˜*˜J˜——šŸ œ œœ˜$Jš œœ œœœœ˜UJšœ&™&Jšœœœ˜šœ(œœ˜>šœ)˜/Jšœ*˜0—Jšœ˜—J˜J˜—šŸ œœœœœœœœ˜UJšœ(™(Jšœœœ˜šœ(œœ˜>šœ)˜/Jšœ˜—Jšœ˜—Jšœœ˜J˜J˜—Jšœ™Jšœ(ž-˜UJ˜&J˜J˜&J˜&J˜Jšœ˜J˜J˜—…—hÎŒü