<> <> <> <> <> <> <> <> <> <<>> DIRECTORY Alloc USING [AddNotify, Base, DropNotify, Handle, InstanceData, Notifier], CinderSysOps USING [Close, Open, OpenKind], ConvertUnsafe USING [LS, SubString, SubStringToRope], IO USING [STREAM], MobComData USING [Data, data], MobDefs USING [Base, FTIndex, FTNull, fttype, IMPIndex, IMPRecord, LFIndex, lftype, Link, LinkOffset, LinkTag, Mob, MobBase, MobOffset, ModuleIndex, MTIndex, MTNull, mttype, NameRecord, Selector, SGIndex, SGNull, sgtype, sstype, VersionStamp], MobErrorDefs USING [InterfaceId], MobOps USING [Configuration, Cookie, CookieObj, DoMobStream, DoSymbols, FileError, NoSymbols, WrongMobdefsVersion, WrongSymbolsVersion], OSMiscOps USING [], Rope USING [ActionType, Concat, FetchType, Find, MapType, MoveType, ROPE], SymbolOps USING [DecodeBitAddr, DecodeCard, DecodeLink, FirstCtxSe, LinkMode, NextSe, STB, SubStringForName, UnderType], Symbols USING [Base, BitAddress, BitCount, CSEIndex, CTXIndex, HashVector, ISEIndex, ISENull, Linkage, MDIndex, Name, nullName, nullType, nullUNSPEC, Type, TypeClass, UNSPEC], SymbolTable USING [SymbolTableBaseRep], SymbolTablePrivate USING [FGTEntryArray, FGTEntryArrayDesc, HashVectorPtr, STHeaderPtr, SymbolTableBase, SymbolTableBaseRep]; MobSymbolPack: PROGRAM IMPORTS Alloc, CinderSysOps, ConvertUnsafe, Rope, MobComData, SymbolOps, MobOps EXPORTS MobErrorDefs, SymbolTable = { OPEN MobDefs, MobComData; mtb, lfb, sgb, ftb: MobDefs.Base; ssb: LONG STRING; Base: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; Notifier: Alloc.Notifier ~ { mtb ¬ base[mttype]; lfb ¬ base[lftype]; sgb ¬ base[sgtype]; ftb ¬ base[fttype]; ssb ¬ base[sstype]}; Initialize: PUBLIC PROC ~ {}; Finalize: PUBLIC PROC ~ {}; ExportItemName: PUBLIC PROC[export: MobErrorDefs.InterfaceId, ep: CARDINAL, userProc: PROC[ConvertUnsafe.SubString]] ~ { (data.table).AddNotify[Notifier]; PrintNameFromInterface[export, ep, userProc]; (data.table).DropNotify[Notifier]}; ImportItemName: PUBLIC PROC[import: MobErrorDefs.InterfaceId, ep: CARDINAL, clientMti: MobDefs.MTIndex, linkOffset: CARDINAL, link: MobDefs.Link, userProc: PROC[ConvertUnsafe.SubString]] ~ { (data.table).AddNotify[Notifier]; IF clientMti = MobDefs.MTNull THEN RETURN; IF mtb[clientMti].sseg # MobDefs.SGNull THEN PrintNameFromModule[import, clientMti, linkOffset, link, userProc] ELSE PrintNameFromInterface[import, ep, userProc]; (data.table).DropNotify[Notifier]}; VersionForModuleIndex: PROC[impb, ftb: MobDefs.Base, modIndex: MobDefs.ModuleIndex] RETURNS[MobDefs.VersionStamp] = { FOR impi: MobDefs.IMPIndex ¬ MobDefs.IMPIndex.FIRST, impi + MobDefs.IMPRecord.SIZE DO IF impb[impi].modIndex = modIndex THEN RETURN[ftb[impb[impi].file].version]; ENDLOOP }; PrintNameFromModule: PROC[ import: MobErrorDefs.InterfaceId, importerMti: MobDefs.MTIndex, linkOffset: CARDINAL, link: MobDefs.Link, userProc: PROC[ConvertUnsafe.SubString]] ~ { key: Symbols.BitAddress ~ ComputeAddress[importerMti, linkOffset]; mobimpb, mobftb: MobDefs.Base ¬ NIL; DoSymbols: PROC[sym: Base] = { OPEN Symbols; Imported: PROC[sei: Symbols.ISEIndex] RETURNS[BOOL] ~ INLINE { RETURN[sym.seb[sei].linkSpace AND ~sym.seb[sei].extended]}; LinksMatch: PROC[link, linkInSym: MobDefs.Link] RETURNS[BOOL] ~ { RETURN[ linkInSym.tag = link.tag AND linkInSym.offset = link.offset AND ftb[import.fti].version = -- link.version VersionForModuleIndex[mobimpb, mobftb, linkInSym.modIndex]]}; importCtx: CTXIndex; sei: ISEIndex; type: CSEIndex; IF sym = NIL THEN RETURN; importCtx ¬ sym.stHandle.importCtx; FOR iSei: ISEIndex ¬ SymbolOps.FirstCtxSe[sym, importCtx], SymbolOps.NextSe[sym, iSei] UNTIL iSei = ISENull DO type ¬ SymbolOps.UnderType[sym, sym.seb[iSei].idType]; WITH t~~sym.seb[type] SELECT FROM definition => FOR sei ¬ SymbolOps.FirstCtxSe[sym, t.defCtx], SymbolOps.NextSe[sym, sei] UNTIL sei = ISENull DO IF Imported[sei] AND LinksMatch[link, SymbolOps.DecodeLink[sym.seb[sei].idValue]] THEN GO TO Found; ENDLOOP; ref => IF Imported[iSei] AND SymbolOps.DecodeBitAddr[sym.seb[iSei].idValue] = key THEN {sei ¬ iSei; GO TO Found}; ENDCASE => NULL; REPEAT Found => { d: ConvertUnsafe.SubString; d ¬ SymbolOps.SubStringForName[sym, sym.seb[sei].hash]; userProc[d ! UNWIND => {(data.table).DropNotify[Notifier]}]}; ENDLOOP}; DoMob: PROC[mob: MobDefs.MobBase, cookie: MobOps.Cookie] = { IF mob = NIL THEN RETURN; mobimpb ¬ LOOPHOLE[mob + mob.impOffset.units]; mobftb ¬ LOOPHOLE[mob + mob.ftOffset.units]; MobOps.DoSymbols[cookie, DoSymbols ! MobOps.Configuration => CONTINUE; MobOps.NoSymbols => CONTINUE; MobOps.WrongSymbolsVersion => CONTINUE]}; sgi: MobDefs.SGIndex = mtb[importerMti].sseg; IF sgb[sgi].file # FTNull THEN { name: Rope.ROPE ¬ GetMobName[ftb[sgb[sgi].file].name]; openFile: IO.STREAM ¬ CinderSysOps.Open[name, $read].stream; Cleanup: PROC[] = {[] ¬ CinderSysOps.Close[openFile, FALSE]}; IF openFile # NIL THEN { MobOps.DoMobStream[openFile, DoMob ! MobOps.FileError => {Cleanup[]; CONTINUE}; MobOps.WrongMobdefsVersion => {Cleanup[]; CONTINUE}]; Cleanup[]; }; }; }; ComputeAddress: PROC[mti: MobDefs.MTIndex, linkOffset: CARDINAL] RETURNS[Symbols.BitAddress] ~ { linkLength: CARDINAL ~ lfb[mtb[mti].links].length; RETURN[[bd~((linkLength-1)-linkOffset)*BITS[MobDefs.Link]]]}; PrintNameFromInterface: PROC[ id: MobErrorDefs.InterfaceId, ep: CARDINAL, userProc: PROC[ConvertUnsafe.SubString]] ~ { DoSymbols: PROC[sym: Base] = { OPEN Symbols; outerCtx: CTXIndex; d: ConvertUnsafe.SubString; IF sym = NIL THEN RETURN; outerCtx ¬ sym.stHandle.outerCtx; FOR sei: ISEIndex ¬ SymbolOps.FirstCtxSe[sym, outerCtx], SymbolOps.NextSe[sym, sei] UNTIL sei = ISENull DO SELECT SymbolOps.LinkMode[sym, sei] FROM $val, $ref, $type => IF SymbolOps.DecodeCard[sym.seb[sei].idValue] = ep THEN { d ¬ SymbolOps.SubStringForName[sym, sym.seb[sei].hash]; userProc[d ! UNWIND => {(data.table).DropNotify[Notifier]}]}; ENDCASE; ENDLOOP}; DoMob: PROC[mob: MobDefs.MobBase, cookie: MobOps.Cookie] = { IF mob = NIL OR ~mob.definitions THEN RETURN; MobOps.DoSymbols[cookie, DoSymbols ! MobOps.Configuration => CONTINUE; MobOps.NoSymbols => CONTINUE; MobOps.WrongSymbolsVersion => CONTINUE]}; IF id.fti # FTNull THEN { name: Rope.ROPE ¬ GetMobName[ftb[id.fti].name]; openFile: IO.STREAM ¬ CinderSysOps.Open[name, $read].stream; LocalCleanup: PROC[] = {[] ¬ CinderSysOps.Close[openFile, FALSE]}; IF openFile # NIL THEN { MobOps.DoMobStream[openFile, DoMob ! MobOps.FileError => {LocalCleanup[]; CONTINUE}; MobOps.WrongMobdefsVersion => {LocalCleanup[]; CONTINUE}]; LocalCleanup[]; }; }; }; GetMobName: PROC[name: NameRecord] RETURNS[rope: Rope.ROPE] ~ { dotIndex: INT; d: ConvertUnsafe.SubString ¬ [base~ssb, offset~name+1, length~MIN[ssb.text[name].ORD, 40]]; rope ¬ d.SubStringToRope; dotIndex ¬ Rope.Find[rope, "."]; IF dotIndex < 0 THEN rope ¬ Rope.Concat[rope, ".mob"]}; }.