<<>> <> <> <> <> <> DIRECTORY IO, Atom, Convert, ConvertUnsafe, MobConnection, File, MobDefs, MobListerUtils, OSMiscOps, RefText, Rope, SymbolOps, Symbols, SymbolSegment, SymbolTable, SymbolTablePrivate, Table; MobConnectionImpl: PROGRAM IMPORTS IO, Atom, Convert, RefText, Rope, SymbolOps, MobListerUtils EXPORTS MobConnection, SymbolTable, SymbolOps = { FormIdentifier: TYPE = ATOM; ModuleID: TYPE = MobConnection.ModuleID; FilterItem: TYPE = MobConnection.FilterItem; Filter: TYPE = MobConnection.Filter; bytesPerUnit: NAT = BYTES[WORD]; unitsPerFilePage: NAT = File.wordsPerPage; bytesPerFilePage: NAT = unitsPerFilePage*bytesPerUnit; bitsPerByte: CARD = 8; bitsPerUnit: CARD = OSMiscOps.bytesPerUnit*bitsPerByte; UnitsToFilePages: PROC[units: INT] RETURNS[INT] = { RETURN[(units+unitsPerFilePage-1)/unitsPerFilePage]}; BytesToFilePages: PROC[bytes: INT] RETURNS[INT] = { RETURN[(bytes+bytesPerFilePage-1)/bytesPerFilePage]}; Base: TYPE = MobDefs.Base; Mob: TYPE = MobDefs.Mob; BitAddress: TYPE = Symbols.BitAddress; BodyRecord: TYPE = Symbols.BodyRecord; BTIndex: TYPE = Symbols.BTIndex; RootBti: BTIndex = Symbols.RootBti; CBTIndex: TYPE = Symbols.CBTIndex; ContextLevel: TYPE = Symbols.ContextLevel; lG: ContextLevel = Symbols.lG; CSEIndex: TYPE = Symbols.CSEIndex; CSENull: CSEIndex = Symbols.CSENull; typeTYPE: CSEIndex = Symbols.typeTYPE; CTIndex: TYPE = MobDefs.CTIndex; CTNull: CTIndex = MobDefs.CTNull; CTRecord: TYPE = MobDefs.CTRecord; CTXIndex: TYPE = Symbols.CTXIndex; CTXNull: CTXIndex = Symbols.CTXNull; CTXRecord: TYPE = Symbols.CTXRecord; EVIndex: TYPE = MobDefs.EVIndex; EVNull: EVIndex = MobDefs.EVNull; EVRecord: TYPE = MobDefs.EVRecord; EXPIndex: TYPE = MobDefs.EXPIndex; EXPLink: TYPE = MobDefs.EXPLink; EXPRecord: TYPE = MobDefs.EXPRecord; FPIndex: TYPE = MobDefs.FPIndex; FPRecord: TYPE = MobDefs.FPRecord; FTIndex: TYPE = MobDefs.FTIndex; FTNull: FTIndex = MobDefs.FTNull; FTSelf: FTIndex = MobDefs.FTSelf; FTRecord: TYPE = MobDefs.FTRecord; HTIndex: TYPE = Symbols.HTIndex; ISEIndex: TYPE = Symbols.ISEIndex; ISENull: ISEIndex = Symbols.ISENull; ISERecord: TYPE = SERecord.id; LFIndex: TYPE = MobDefs.LFIndex; LFNull: LFIndex = MobDefs.LFNull; LFRecord: TYPE = MobDefs.LinkFrag; Link: TYPE = MobDefs.Link; nullLink: Link = MobDefs.nullLink; Namee: TYPE = MobDefs.Namee; NameRecord: TYPE = MobDefs.NameRecord; NameString: TYPE = MobDefs.NameString; NTIndex: TYPE = MobDefs.NTIndex; NTNull: NTIndex = MobDefs.NTNull; NTRecord: TYPE = MobDefs.NTRecord; IMPIndex: TYPE = MobDefs.IMPIndex; IMPRecord: TYPE = MobDefs.IMPRecord; MTIndex: TYPE = MobDefs.MTIndex; MTRecord: TYPE = MobDefs.MTRecord; RefMob: TYPE = REF Mob; RefMTRecord: TYPE = REF MTRecord; RefSGRecord: TYPE = REF SGRecord; RFIndex: TYPE = MobDefs.RFIndex; RFNull: RFIndex = MobDefs.RFNull; RFRecord: TYPE = MobDefs.RefLitFrag; ROPE: TYPE = Rope.ROPE; Name: TYPE = Symbols.Name; nullName: Name = Symbols.nullName; SEIndex: TYPE = Symbols.SEIndex; SENull: SEIndex = Symbols.SENull; SERecord: TYPE = Symbols.SERecord; SGIndex: TYPE = MobDefs.SGIndex; SGNull: SGIndex = MobDefs.SGNull; SGRecord: TYPE = MobDefs.SGRecord; SpaceID: TYPE = MobDefs.SpaceID; SPIndex: TYPE = MobDefs.SPIndex; SPRecord: TYPE = MobDefs.SPRecord; SymbolTableBase: TYPE = REF SymbolTableBaseRep; STB: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; TFIndex: TYPE = MobDefs.TFIndex; TFNull: TFIndex = MobDefs.TFNull; TFRecord: TYPE = MobDefs.TypeFrag; TYPIndex: TYPE = MobDefs.TYPIndex; TYPNull: TYPIndex = MobDefs.TYPNull; TYPRecord: TYPE = MobDefs.TYPRecord; VersionStamp: TYPE = MobDefs.VersionStamp; Error: PUBLIC ERROR [culprit: REF, msg: ROPE] = CODE; Appender: TYPE = RECORD [head, last: LIST OF REF ANY]; LORAFromMob: PUBLIC SAFE PROC [fileName: Rope.ROPE, filter: Filter ¬ ALL[TRUE]] RETURNS [result: LIST OF REF ANY ¬ NIL] = CHECKED { stack: LIST OF Appender ¬ NIL; Begin: SAFE PROC [id: FormIdentifier] = { head: LIST OF REF ANY = LIST[id]; stack ¬ CONS[[head, head], stack]; }; End: SAFE PROC = { a: LIST OF REF ANY ¬ stack.first.head; stack ¬ stack.rest; IF stack = NIL THEN result ¬ a ELSE Put[a]; }; Put: SAFE PROC [a: REF] = {stack.first.last ¬ stack.first.last.rest ¬ LIST[a]}; PutATOM: SAFE PROC [a: ATOM] = {Put[a]}; PutROPE: SAFE PROC [a: ROPE] = {Put[a]}; PutINT: SAFE PROC [a: INT] = {Put[NEW[INT ¬ a]]}; PutBOOL: SAFE PROC [a: BOOL] = {Put[IF a THEN $TRUE ELSE $FALSE]}; PutModuleID: SAFE PROC [a: ModuleID] = {Put[NEW[ModuleID ¬ a]]}; DecodeMob[fileName: fileName, begin: Begin, end: End, putATOM: PutATOM, putROPE: PutROPE, putINT: PutINT, putBOOL: PutBOOL, putModuleID: PutModuleID, filter: filter]; IF stack # NIL THEN ERROR; }; DecodeMob: PUBLIC SAFE PROC [fileName: Rope.ROPE, begin: SAFE PROC [FormIdentifier], end: SAFE PROC, putATOM: SAFE PROC[ATOM], putROPE: SAFE PROC[ROPE], putINT: SAFE PROC[INT], putBOOL: SAFE PROC[BOOL], putModuleID: SAFE PROC[ModuleID], filter: Filter] = TRUSTED { Inner: PROC [mob: MobDefs.MobBase] = { Start: PROC [FormIdentifier] = begin; End: PROC = end; PutRope: PROC [ROPE] = putROPE; PutINT: PROC [int: INT] = putINT; PutLabeledINT: PROC [symbol: ATOM, int: INT] = {Start[symbol]; PutINT[int]; End[]}; PutLabeledBOOL: PROC [symbol: ATOM, bool: BOOL] = {Start[symbol]; putBOOL[bool]; End[]}; PrintStamps: PROC = { IF filter[imports] THEN {Start[$imports]; FOR iti: IMPIndex ¬ IMPIndex.FIRST, iti + IMPRecord.SIZE UNTIL iti = mob.impLimit DO ip: LONG POINTER TO IMPRecord = @itb[iti]; IF LOOPHOLE[iti, CARD] > LOOPHOLE[mob.impLimit, CARD] THEN GO TO Bogus; <> <> <> PutFileStamp[ip.file, ip.name]; REPEAT Bogus => PrintGarbage[]; ENDLOOP; End[]}; IF filter[exports] THEN {Start[$exports]; FOR eti: EXPIndex ¬ EXPIndex.FIRST, eti + etb[eti].nLinks*EXPLink.SIZE + EXPRecord.SIZE UNTIL eti = mob.expLimit DO ee: LONG POINTER TO EXPRecord = @etb[eti]; OnlyTypes: PROC RETURNS [BOOL] = { FOR i: CARD16 IN [0..ee.nLinks) DO IF ee[i].from = [tag: var, modIndex: 0, offset: 0] THEN EXIT; IF ee[i].from.tag # type THEN RETURN [FALSE] ENDLOOP; RETURN [TRUE] }; IF LOOPHOLE[eti, CARD] > LOOPHOLE[mob.expLimit, CARD] THEN GO TO Bogus; IF NOT filter[typeExports] AND OnlyTypes[] THEN LOOP; IF filter[exportedItems] THEN {Start[$export]; PutFileStamp[ee.file, ee.name]; FOR i: CARD16 IN [0..ee.nLinks) DO IF ee[i].from = [tag: var, modIndex: 0, offset: 0] THEN EXIT; Start[SELECT ee[i].from.tag FROM var => $var, proc => $proc, type => $type, ENDCASE => $other]; PutINT[ee[i].to]; End[]; ENDLOOP; End[]} ELSE PutFileStamp[ee.file, ee.name]; <> <> <> REPEAT Bogus => PrintGarbage[]; ENDLOOP; End[]}; IF filter[modules] THEN {Start[$modules]; FOR mti: MTIndex ¬ MTIndex.FIRST, mti + MTSize[mti] UNTIL mti = mob.mtLimit DO mm: LONG POINTER TO MTRecord = @mtb[mti]; IF LOOPHOLE[mti, CARD] > LOOPHOLE[mob.mtLimit, CARD] THEN GO TO Bogus; <> <> <> PutFileStamp[mm.file, mm.name]; REPEAT Bogus => PrintGarbage[]; ENDLOOP; End[]}; }; PutFileStamp: PROC[fti: FTIndex, mName: NameRecord] = { SELECT fti FROM FTNull => PutName[mName]; FTSelf => PutName[mName]; ENDCASE => { ftr: LONG POINTER TO FTRecord = @ftb[fti]; PutStampedName[n: ftr.name, stamp: ftr.version]; }; }; PutMobName: PROC[] = { name: NameRecord = IF mob.nModules=1 AND mob.nConfigs = 0 THEN (@mtb[MTIndex.FIRST]).name ELSE mob.source; PutStampedName[n: name, stamp: mob.version]; }; PrintHeader: PROC = { {Start[$header]; PutLabeledINT[$configurations, mob.nConfigs]; PutLabeledINT[$modules, mob.nModules]; PutLabeledINT[$imports, mob.nImports]; PutLabeledINT[$exports, mob.nExports]; PutLabeledINT[$firstdummy, mob.firstdummy]; PutLabeledINT[$dummies, mob.nDummies]; PutLabeledBOOL[$definitions, mob.definitions]; PutLabeledBOOL[$repackaged, mob.repackaged]; PutLabeledBOOL[$typeexported, mob.typeExported]; PutLabeledBOOL[$inlinefloat, mob.inlineFloat]; PutLabeledBOOL[$mappingstarted, mob.mappingStarted]; PutLabeledBOOL[$mappingfinished, mob.mappingFinished]; PutLabeledBOOL[$versions, mob.versions]; PutLabeledBOOL[$extended, mob.extended]; End[]}; }; PrintConfigs: PROC = { cti: CTIndex ¬ CTIndex.FIRST; IF cti = mob.ctLimit THEN RETURN; {Start[$configurations]; <> UNTIL cti = mob.ctLimit DO PrintConfig[cti]; cti ¬ cti + CTRecord.SIZE + ctb[cti].nControls*Namee.SIZE; IF LOOPHOLE[cti, CARD] > LOOPHOLE[mob.ctLimit, CARD] THEN GO TO Bogus; REPEAT Bogus => PrintGarbage[]; ENDLOOP; End[]}; }; PrintConfig: PROC[cti: CTIndex] = { ctp: LONG POINTER TO CTRecord = @ctb[cti]; Start[$configuration]; PutName[ctp.name]; <> <> <> IF ctp.nControls # 0 THEN {Start[$control]; FOR i: CARDINAL IN [0..ctp.nControls) DO WITH c~~ctp.controls[i] SELECT FROM module => {PutName[mtb[c.mti].name]}; config => {Start[$config]; PutName[ctb[c.cti].name]; End[]}; ENDCASE => ERROR; ENDLOOP; End[]}; End[]}; <> <> <> <> <> <> < LOOPHOLE[mob.impLimit, CARD] THEN GO TO Bogus;>> <> < PrintGarbage[];>> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < maxSpan _ DoContext[t.fieldCtx];>> <> <<};>> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> < {>> <> <> <> < {>> <> <> <> <> <> <> <> <> <<};>> < {>> <> <<};>> < CONTINUE];>> <> <<};>> <<};>> <<>> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<>> <> <> <> <> <> <> < LOOPHOLE[mob.mtLimit, CARD] THEN GO TO Bogus;>> <> < PrintGarbage[];>> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<"exported variables: [%g]", [cardinal[LOOPHOLE[mth.variables, CARD]]]];>> <<};>> <> <> <> <> <> <> <> <> <> <> <> <> <<>> MTSize: PROC[mti: MTIndex] RETURNS[NAT] = { RETURN[MTRecord.SIZE] }; <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<};>> <<};>> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<};>> <<};>> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<};>> <<};>> <<>> <> <> <> <> <> <> < LOOPHOLE[mob.ftLimit, CARD] THEN {>> <> <> <> <<};>> <<>> <> <> <> <<~sep.mark4 OR SymbolOps.LinkMode[exstb, sei] = $manifest => {};>> < {>> <> <> <> <