DIRECTORY IO USING [GetLength, SetIndex, STREAM, UnsafeGetBlock], MobDefs USING [Base, FTSelf, MobBase, MTIndex, SGHandle, SGNull, VersionStamp], MobMapper USING [AlterMob], MobOps USING [], Rope USING [ROPE], Symbols USING [Base, MDFirst], SymbolSegment USING [Base, biases, bodyType, ctxType, ExtFirst, extType, FGHeader, htType, ltType, mdType, seType, ssType, STHeader, stType, treeType, VersionID], SymbolTable USING [], SymbolTablePrivate USING [SymbolTableBaseRep], VM USING [AddressForPageNumber, Free, Interval, nullInterval, PagesForBytes, SimpleAllocate]; MobOpsImpl: PROGRAM IMPORTS IO, MobMapper, VM EXPORTS MobOps, SymbolTable ~ { Cookie: TYPE = REF CookieObj; CookieObj: PUBLIC TYPE = RECORD [ mob: MobDefs.MobBase, openFile: IO.STREAM ]; bytesPerUnit: NAT = BYTES[UNIT]; FileError: PUBLIC ERROR[err: Rope.ROPE] = CODE; WrongMobdefsVersion: PUBLIC ERROR = CODE; Configuration: PUBLIC ERROR = CODE; NoSymbols: PUBLIC ERROR = CODE; WrongSymbolsVersion: PUBLIC ERROR = CODE; DoMobStream: PUBLIC PROC [file: IO.STREAM, proc: PROC[mob: MobDefs.MobBase, cookie: Cookie]] = { mob: MobDefs.MobBase; interval: VM.Interval ¬ VM.nullInterval; openFile: IO.STREAM; allocedBytes: INT ¬ IO.GetLength[file]; err: Rope.ROPE ¬ NIL; Cleanup: PROC[] = {VM.Free[interval]}; openFile ¬ file; IF err # NIL THEN ERROR FileError[err]; interval ¬ VM.SimpleAllocate[VM.PagesForBytes[allocedBytes]]; mob ¬ VM.AddressForPageNumber[interval.page]; IO.SetIndex[openFile, 0]; [] ¬ IO.UnsafeGetBlock[openFile, [LOOPHOLE[mob], 0, allocedBytes]]; IF MobMapper.AlterMob[mob, LOOPHOLE[mob], allocedBytes/BYTES[UNIT]] = badVersion THEN { Cleanup[]; ERROR WrongMobdefsVersion; }; proc[mob, NEW[CookieObj ¬ [mob, openFile]] ! UNWIND => Cleanup[]; ]; Cleanup[]; }; STB: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; DoSymbols: PUBLIC PROC [cookie: Cookie, proc: PROC[sym: STB]] = { sym: STB ¬ NIL; sgb: MobDefs.Base = LOOPHOLE[cookie.mob+cookie.mob.sgOffset.units]; mtb: MobDefs.Base = LOOPHOLE[cookie.mob+cookie.mob.mtOffset.units]; sgh: MobDefs.SGHandle = IF mtb[FIRST[MobDefs.MTIndex]].sseg = MobDefs.SGNull THEN ERROR NoSymbols ELSE @sgb[mtb[FIRST[MobDefs.MTIndex]].sseg]; stb: LONG POINTER TO SymbolSegment.STHeader = LOOPHOLE[cookie.mob+sgh.base.units]; IF cookie.mob.nConfigs # 0 THEN ERROR Configuration; IF sgh.file # MobDefs.FTSelf OR sgh.units.units = 0 THEN ERROR NoSymbols; IF stb.versionIdent # SymbolSegment.VersionID THEN ERROR WrongSymbolsVersion; sym ¬ InstallTable[stb]; proc[sym]; }; InstallTable: PROC [node: LONG POINTER] RETURNS [STB] = { b: LONG POINTER = node; tB: SymbolSegment.Base = LOOPHOLE[b]; p: LONG POINTER TO SymbolSegment.STHeader = b; base: STB ¬ NEW[SymbolTableBaseRep]; base.cacheInfo ¬ LOOPHOLE[node]; base.hashVec ¬ b+p.hvBlock.offset; base.htb ¬ tB + p.htBlock.offset - SymbolSegment.biases[SymbolSegment.htType]; base.ssb ¬ b + p.ssBlock.offset - SymbolSegment.biases[SymbolSegment.ssType]; base.seb ¬ tB + p.seBlock.offset - SymbolSegment.biases[SymbolSegment.seType]; base.ctxb ¬ tB + p.ctxBlock.offset - SymbolSegment.biases[SymbolSegment.ctxType]; base.mdb ¬ tB + p.mdBlock.offset - SymbolSegment.biases[SymbolSegment.mdType]; base.bb ¬ tB + p.bodyBlock.offset - SymbolSegment.biases[SymbolSegment.bodyType]; base.tb ¬ tB + p.treeBlock.offset - SymbolSegment.biases[SymbolSegment.treeType]; base.ltb ¬ tB + p.litBlock.offset - SymbolSegment.biases[SymbolSegment.ltType]; base.stb ¬ tB + p.sLitBlock.offset - SymbolSegment.biases[SymbolSegment.stType]; base.extb ¬ tB + p.extBlock.offset - SymbolSegment.biases[SymbolSegment.extType]; base.mdLimit ¬ Symbols.MDFirst + p.mdBlock.size; base.extLimit ¬ SymbolSegment.ExtFirst + p.extBlock.size; base.mainCtx ¬ p.outerCtx; base.stHandle ¬ p; IF p.fgRelBase = 0 THEN { base.sourceFile ¬ NIL; base.fgTable ¬ NIL; } ELSE { bytesPerAU: NAT = BYTES[UNIT]; q: LONG POINTER TO SymbolSegment.FGHeader = LOOPHOLE[b + p.fgRelBase/bytesPerAU]; source: LONG STRING = LOOPHOLE[q + SIZE[SymbolSegment.FGHeader[0]] - SIZE[StringBody[0]]]; base.sourceFile ¬ source; base.fgTable ¬ DESCRIPTOR[q + q.offset, q.length]; }; IF base.ssb.length = 0 OR base.ssb.length > base.ssb.maxlength THEN ERROR; RETURN [base]; }; Cache: TYPE ~ REF CacheList ¬ NIL; CacheRep: PUBLIC TYPE = CacheList; CacheList: TYPE = REF CacheListRep; CacheListRep: TYPE ~ RECORD [ rest: CacheList, version: MobDefs.VersionStamp, stb: STB, interval: VM.Interval]; DoCachedSymbols: PUBLIC PROC [cookie: Cookie, proc: PROC[sym: STB], cache: Cache] = { interval: VM.Interval; sym: STB ¬ NIL; sgb: MobDefs.Base = LOOPHOLE[cookie.mob+cookie.mob.sgOffset.units]; mtb: MobDefs.Base = LOOPHOLE[cookie.mob+cookie.mob.mtOffset.units]; sgh: MobDefs.SGHandle ¬ IF mtb[FIRST[MobDefs.MTIndex]].sseg = MobDefs.SGNull THEN ERROR NoSymbols ELSE @sgb[mtb[FIRST[MobDefs.MTIndex]].sseg]; bytes: INT = (sgh.units.units+sgh.extraUnits.units)*BYTES[UNIT]; stb: LONG POINTER TO SymbolSegment.STHeader ¬ LOOPHOLE[cookie.mob+sgh.base.units]; symbolSegment: LONG POINTER TO SymbolSegment.STHeader ¬ NIL; IF cookie.mob.nConfigs # 0 THEN ERROR Configuration; IF sgh.file # MobDefs.FTSelf OR sgh.units.units = 0 THEN ERROR NoSymbols; IF stb.versionIdent # SymbolSegment.VersionID THEN ERROR WrongSymbolsVersion; IF cache = NIL THEN { sym ¬ InstallTable[stb]; proc[sym]; RETURN; }; FOR each: CacheList ¬ cache­, each.rest WHILE each # NIL DO IF each.version = stb.version THEN { proc[each.stb]; RETURN; }; ENDLOOP; interval ¬ VM.SimpleAllocate[VM.PagesForBytes[bytes]]; symbolSegment ¬ VM.AddressForPageNumber[interval.page]; CopyWords[ dst: LOOPHOLE[symbolSegment], src: LOOPHOLE[stb], nwords: bytes/BYTES[WORD]]; sym ¬ InstallTable[symbolSegment]; cache­ ¬ NEW[CacheListRep ¬ [cache­, symbolSegment.version, sym, interval]]; proc[sym]; }; NewCache: PUBLIC PROC RETURNS [Cache] ~ { cache: Cache ~ NEW[CacheList ¬ NIL]; RETURN [cache]; }; FlushCache: PUBLIC PROC [cache: Cache] ~ { IF cache # NIL THEN { list: CacheList = cache­; cache­ ¬ NIL; FOR left: CacheList ¬ list, left.rest UNTIL left = NIL DO VM.Free[left.interval]; ENDLOOP; cache­ ¬ NIL; }; }; CopyWords: PROC [dst, src: LONG POINTER TO WORD, nwords: CARD] = { BlockPtr: TYPE = LONG POINTER TO Block; Block: TYPE = ARRAY [0..16) OF WORD; WHILE nwords >= WORDS[Block] DO LOOPHOLE[dst, BlockPtr]­ ¬ LOOPHOLE[src, BlockPtr]­; src ¬ src + SIZE[Block]; dst ¬ dst + SIZE[Block]; nwords ¬ nwords - WORDS[Block]; ENDLOOP; WHILE nwords # 0 DO dst­ ¬ src­; src ¬ src + SIZE[WORD]; dst ¬ dst + SIZE[WORD]; nwords ¬ nwords - 1; ENDLOOP; }; }. ϊ MobOpsImpl.mesa Copyright Σ 1988, 1991 by Xerox Corporation. All rights reserved. Andy Litman August 24, 1988 8:52:52 pm PDT JKF January 11, 1989 9:18:59 pm PST Peter B. Kessler October 18, 1988 4:57:32 pm PDT Russ Atkinson (RRA) December 19, 1988 5:02:37 pm PST Cookies avoid having any global state Consistency check failed! Something is NOT kosher with the string table! No caching, so no copying Search the cache for the desired version Found it! Copy from the src into the dst (dumb, really) Κ •NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ7™BKšΟy*™*K™#K™0™4K™—šΟk ˜ KšŸœŸœŸœ˜7KšœŸœB˜OKšœ Ÿœ ˜KšœŸœ˜KšœŸœŸœ˜KšœŸœ˜KšœŸœ˜’Kšœ Ÿœ˜KšœŸœ˜.KšŸœŸœU˜]——K˜šΟn œŸ˜KšŸœŸœ Ÿ˜KšŸœ˜Kšœ˜K™%KšœŸœŸœ ˜šœ ŸœŸœŸœ˜!Kšœ˜Kšœ ŸœŸ˜Kšœ˜—K˜KšœŸœŸœŸœ˜!Kš   œŸœŸœ ŸœŸœ˜/Kš œŸœŸœŸœ˜)Kš  œŸœŸœŸœ˜#Kš  œŸœŸœŸœ˜Kš œŸœŸœŸœ˜*š   œŸœŸœŸœŸœŸœ+˜`Kšœ˜Kšœ Ÿœ Ÿœ˜(Kšœ ŸœŸœ˜KšœŸœŸœ˜'Kšœ ŸœŸœ˜Kš œŸœŸœ˜&Kšœ˜KšŸœŸœŸœŸœ˜'Kšœ ŸœŸœ˜=KšœŸœ%˜-KšŸœ˜KšœŸœŸœ˜Cš ŸœŸœŸœŸœŸœ˜WKšœ ˜ KšŸœ˜K˜—šœ Ÿœ˜*KšœŸœ˜Kšœ˜—K˜ Kšœ˜K˜—KšŸœŸœŸœ˜#šœŸœŸœ)˜HK˜—š   œŸœŸœŸœŸœ˜AKšœŸœŸœ˜KšœŸœ'˜CKšœŸœ'˜CKš œŸœŸœ)ŸœŸœ Ÿœ Ÿœ˜ŽKš œŸœŸœŸœŸœ˜RKšŸœŸœŸœ˜4KšŸœŸœŸœŸœ ˜IšŸœ,Ÿ˜2K™KšŸœ˜—Kšœ˜K˜ Kšœ˜K˜—š   œŸœŸœŸœŸœŸœ˜9KšœŸœŸœ˜KšœŸœ˜%KšœŸœŸœŸœ˜.KšœŸœŸœ˜$KšœŸœ˜ K˜"KšœN˜NKšœM˜MKšœN˜NKšœQ˜QKšœN˜NKšœQ˜QKšœQ˜QKšœO˜OKšœP˜PKšœQ˜QKšœ0˜0Kšœ9˜9K˜.šŸœ˜šŸœ˜KšœŸœ˜KšœŸœ˜Kšœ˜—šŸœ˜Kšœ ŸœŸœŸœ˜Kš œŸœŸœŸœŸœ˜QKš œŸœŸœŸœŸœŸœ˜ZKšœ˜KšœŸ œ˜2Kšœ˜——šŸœŸœ&ŸœŸœ˜JK™.—KšŸœ˜K˜K˜—šœŸœŸœ Ÿœ˜"Kšœ ŸœŸœ ˜"Kšœ ŸœŸœ˜#šœŸœŸœ˜Kšœ˜Kšœ˜KšœŸœ˜ Kšœ Ÿœ ˜—K˜—š  œŸœŸœŸœŸœ˜UKšœ Ÿœ ˜KšœŸœŸœ˜KšœŸœ'˜CKšœŸœ'˜CKš œŸœŸœ)ŸœŸœ Ÿœ Ÿœ˜ŽKšœŸœ*ŸœŸœ˜@Kš œŸœŸœŸœŸœ˜RKš œŸœŸœŸœŸœ˜