-- File BcdSymbolPack.mesa -- Last edited by Satterthwaite on May 10, 1983 10:23 am -- Last edited by Lewis on 27-Mar-81 10:04:27 DIRECTORY Alloc: TYPE USING [AddNotify, DropNotify, Handle, Notifier], BcdComData: TYPE USING [table], BcdDefs: TYPE USING [ Base, fttype, FTIndex, FTNull, FTSelf, lftype, Link, mttype, MTIndex, MTNull, MTRecord, NameRecord, sgtype, SGIndex, SGNull, sstype, VersionID, VersionStamp], BcdErrorDefs: TYPE USING [InterfaceId], BcdFileDefs: TYPE USING [CapabilityForFile, UnknownFile], BcdOps: TYPE USING [BcdBase, NameString], File: TYPE USING [Capability, nullCapability], FileSegment: TYPE USING [Pages], OSMiscOps: TYPE USING [FindFile, FileError], Space: TYPE USING [ Handle, nullHandle, virtualMemory, Create, Delete, LongPointer, Map], Strings: TYPE USING [ AppendString, AppendSubString, EqualSubStrings, String, SubString, SubStringDescriptor], Symbols: TYPE USING [ ISEIndex, CSEIndex, CTXIndex, BitAddress, ISENull], SymbolTable: TYPE USING [ Base, Handle, nullHandle, Acquire, Missing, Release]; BcdSymbolPack: PROGRAM IMPORTS Alloc, BcdFileDefs, data: BcdComData, OSMiscOps, Space, Strings, SymbolTable EXPORTS BcdErrorDefs = { OPEN BcdDefs; InterfaceId: TYPE ~ BcdErrorDefs.InterfaceId; mtb, lfb, sgb, ftb: BcdDefs.Base; ssb: BcdOps.NameString; Notifier: Alloc.Notifier ~ { mtb ← base[mttype]; lfb ← base[lftype]; sgb ← base[sgtype]; ftb ← base[fttype]; ssb ← base[sstype]}; nullPages: SymbolTable.Handle ~ SymbolTable.nullHandle; initialized: BOOL ← FALSE; Initialize: PUBLIC PROC ~ { IF initialized THEN Finalize[]; initialized ← TRUE}; Finalize: PUBLIC PROC ~ {initialized ← FALSE}; ExportItemName: PUBLIC PROC [ export: InterfaceId, ep: CARDINAL, userProc: PROC [Strings.SubString]] ~ { symbolPages: SymbolTable.Handle; (data.table).AddNotify[Notifier]; symbolPages ← InterfaceSymbols[export]; IF symbolPages # nullPages THEN PrintNameFromInterface[symbolPages, ep, userProc]; (data.table).DropNotify[Notifier]}; ImportItemName: PUBLIC PROC [ import: InterfaceId, ep: CARDINAL, clientMti: BcdDefs.MTIndex, linkOffset: CARDINAL, userProc: PROC [Strings.SubString]] ~ { symbolPages: SymbolTable.Handle; (data.table).AddNotify[Notifier]; IF clientMti = BcdDefs.MTNull THEN RETURN; symbolPages ← ModuleSymbols[clientMti]; IF symbolPages # nullPages THEN PrintNameFromModule[symbolPages, clientMti, linkOffset, userProc] ELSE { symbolPages ← InterfaceSymbols[import]; IF symbolPages # nullPages THEN PrintNameFromInterface[symbolPages, ep, userProc]}; (data.table).DropNotify[Notifier]}; ModuleSymbols: PROC [mti: BcdDefs.MTIndex] RETURNS [symbolPages: SymbolTable.Handle] ~ { sgi: BcdDefs.SGIndex ~ mtb[mti].sseg; IF sgi = BcdDefs.SGNull THEN symbolPages ← nullPages ELSE { symbolPages.file ← BcdFileDefs.CapabilityForFile[sgb[sgi].file ! BcdFileDefs.UnknownFile => {GO TO notFound}]; symbolPages.span ← [base~sgb[sgi].base, pages~sgb[sgi].pages]}; EXITS notFound => RETURN [nullPages]}; PrintNameFromModule: PROC [ symbolPages: SymbolTable.Handle, importerMti: BcdDefs.MTIndex, linkOffset: CARDINAL, userProc: PROC [Strings.SubString]] ~ { symbols: SymbolTable.Base ← NIL; symbols ← SymbolTable.Acquire[symbolPages ! SymbolTable.Missing => {CONTINUE}]; IF symbols # NIL THEN { OPEN Symbols; key: Symbols.BitAddress ~ ComputeAddress[importerMti, linkOffset]; iCtx: CTXIndex ~ symbols.stHandle.importCtx; sei: ISEIndex; type: CSEIndex; Imported: PROC [sei: Symbols.ISEIndex] RETURNS [BOOL] ~ INLINE { RETURN [symbols.seb[sei].linkSpace AND ~symbols.seb[sei].extended]}; FOR iSei: ISEIndex ← symbols.FirstCtxSe[iCtx], symbols.NextSe[iSei] UNTIL iSei = ISENull DO type ← symbols.UnderType[symbols.seb[iSei].idType]; WITH t~~symbols.seb[type] SELECT FROM definition => FOR sei ← symbols.FirstCtxSe[t.defCtx], symbols.NextSe[sei] UNTIL sei = ISENull DO IF Imported[sei] AND symbols.seb[sei].idValue = key THEN GO TO Found; ENDLOOP; ref => IF Imported[iSei] AND symbols.seb[iSei].idValue = key THEN { sei ← iSei; GO TO Found}; ENDCASE => NULL; REPEAT Found => { d: Strings.SubStringDescriptor; symbols.SubStringForName[@d, symbols.seb[sei].hash]; userProc[@d ! UNWIND => { SymbolTable.Release[symbols]; (data.table).DropNotify[Notifier]}]}; ENDLOOP; SymbolTable.Release[symbols]}}; ComputeAddress: PROC [mti: BcdDefs.MTIndex, linkOffset: CARDINAL] RETURNS [Symbols.BitAddress] ~ { linkLength: CARDINAL ~ (WITH m~~mtb[mti] SELECT FROM direct => m.length, indirect => lfb[m.links].length, multiple => lfb[m.links].length, ENDCASE => ERROR); RETURN [[wd~(linkLength-1)-linkOffset, bd~0]]}; InterfaceSymbols: PROC [id: InterfaceId] RETURNS [symbolPages: SymbolTable.Handle] ~ { s: STRING ← [100]; file: File.Capability ← File.nullCapability; headerSpace: Space.Handle ← Space.nullHandle; DeleteHeader: PROC ~ { IF headerSpace # Space.nullHandle THEN { Space.Delete[headerSpace]; headerSpace ← Space.nullHandle}}; IF id.fti # FTNull THEN { s: STRING ← [100]; GetBcdName[s, ftb[id.fti].name]; file ← OSMiscOps.FindFile[s, $read ! OSMiscOps.FileError => {CONTINUE}]}; IF file = File.nullCapability THEN symbolPages ← nullPages ELSE { ENABLE { UNWIND => {NULL}; ANY => {GO TO badFile}}; BcdBase: PROC [p: LONG POINTER] RETURNS [BcdDefs.Base] ~ INLINE { RETURN [LOOPHOLE[p, BcdDefs.Base]]}; bcd: BcdOps.BcdBase; bcdPages: CARDINAL ← 8; iMtb, iFtb, iSgb: BcdDefs.Base; iSsb: BcdOps.NameString; iMti: BcdDefs.MTIndex; iSgi: BcdDefs.SGIndex; d1, d2: Strings.SubStringDescriptor; DO headerSpace ← Space.Create[size~bcdPages, parent~Space.virtualMemory]; headerSpace.Map[window~[file~file, base~1]]; bcd ← headerSpace.LongPointer[]; IF bcd.versionIdent # BcdDefs.VersionID THEN GO TO badFile; IF bcdPages >= bcd.nPages THEN EXIT; bcdPages ← bcd.nPages; Space.Delete[headerSpace]; headerSpace ← Space.nullHandle ENDLOOP; IF bcd.nConfigs # 0 OR ~bcd.definitions THEN GO TO badFile; -- no packaged bcd's (for now) iSsb ← LOOPHOLE[bcd + bcd.ssOffset]; iMtb ← BcdBase[bcd + bcd.mtOffset]; iFtb ← BcdBase[bcd + bcd.ftOffset]; iSgb ← BcdBase[bcd + bcd.sgOffset]; d1 ← [base~@ssb.string, offset~id.name, length~ssb.size[id.name]]; d2.base ← @iSsb.string; iMti ← BcdDefs.MTIndex.FIRST; UNTIL iMti = bcd.mtLimit DO d2.offset ← iMtb[iMti].name; d2.length ← iSsb.size[iMtb[iMti].name]; IF Strings.EqualSubStrings[@d1, @d2] THEN EXIT; iMti ← iMti + (WITH m~~iMtb[iMti] SELECT FROM direct => BcdDefs.MTRecord.direct.SIZE + m.length*BcdDefs.Link.SIZE, indirect => BcdDefs.MTRecord.indirect.SIZE, multiple => BcdDefs.MTRecord.multiple.SIZE, ENDCASE => ERROR); REPEAT FINISHED => IF bcd.nModules = 1 THEN iMti ← BcdDefs.MTIndex.FIRST ELSE GOTO badFile; ENDLOOP; iSgi ← iMtb[iMti].sseg; IF iSgi = BcdDefs.SGNull OR iSgb[iSgi].pages = 0 OR iSgb[iSgi].file # BcdDefs.FTSelf OR bcd.version # ftb[id.fti].version THEN GO TO badFile; symbolPages ← [ file~file, span~[base~iSgb[iSgi].base, pages~iSgb[iSgi].pages]]; DeleteHeader[]; EXITS badFile => {DeleteHeader[]; symbolPages ← nullPages}}; RETURN}; GetBcdName: PROC [s: Strings.String, n: NameRecord] ~ { d: Strings.SubStringDescriptor ← [base~@ssb.string, offset~n, length~MIN[ssb.size[n], 40]]; s.length ← 0; Strings.AppendSubString[s, @d]; FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN RETURN ENDLOOP; Strings.AppendString[s, ".bcd"L]}; PrintNameFromInterface: PROC [ symbolPages: SymbolTable.Handle, ep: CARDINAL, userProc: PROC [Strings.SubString]] ~ { symbols: SymbolTable.Base ← NIL; symbols ← SymbolTable.Acquire[symbolPages ! SymbolTable.Missing => {CONTINUE}]; IF symbols # NIL THEN { OPEN Symbols; outerCtx: CTXIndex ~ symbols.stHandle.outerCtx; d: Strings.SubStringDescriptor; FOR sei: ISEIndex ← symbols.FirstCtxSe[outerCtx], symbols.NextSe[sei] UNTIL sei = ISENull DO SELECT symbols.LinkMode[sei] FROM $val, $ref, $type => IF symbols.seb[sei].idValue = ep THEN { symbols.SubStringForName[@d, symbols.seb[sei].hash]; userProc[@d ! UNWIND => { SymbolTable.Release[symbols]; (data.table).DropNotify[Notifier]}]}; ENDCASE; ENDLOOP; SymbolTable.Release[symbols]}}; }.