<<>> <> <> <> <> DIRECTORY Alloc USING [Handle, Notifier, AddNotify, DropNotify, Top, Units], ConvertUnsafe USING [SubString, SubStringToRope], FileParms USING [ActualId, BindingProc, Ops, Name, nullActual, nullName, SymbolSpace], MimosaCopier USING [], MimZones USING [RegisterForReset, tempZone], MobDefs USING [VersionStamp], Rope USING [Flatten, Length, ROPE], SymbolOps USING [EnterString, own, SubStringForName], Symbols USING [Base, CTXNull, FileIndex, IncludedCTXNull, MDIndex, MDFirst, MDNull, MDRecord, mdType, Name, nullFileIndex, nullName, OwnMdi], SymbolSegment USING [VersionID], SymbolTable USING [Base, Handle, AcquireSTB, ForgetSTB, LockedSTB, ReleaseSTB], SymbolTablePrivate USING [SymbolTableBaseRep]; MimFilesImpl: PROGRAM IMPORTS Alloc, ConvertUnsafe, MimZones, Rope, SymbolTable, SymbolOps EXPORTS MimosaCopier, SymbolTable = { OPEN Symbols; STB: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; table: Alloc.Handle ¬ NIL; <> mdb: Symbols.Base; -- module directory base FilePackNotify: Alloc.Notifier = {mdb ¬ base[mdType]}; <> VersionStamp: TYPE = MobDefs.VersionStamp; FileProblem: PUBLIC SIGNAL [Name] RETURNS [BOOL] = CODE; FileVersion: PUBLIC SIGNAL [Name] RETURNS [BOOL] = CODE; FileVersionMix: PUBLIC SIGNAL [Name] = CODE; EnterFile: PUBLIC PROC [formalId, typeId: Name, defaultFile: Rope.ROPE] RETURNS [mdi: MDIndex ¬ MDNull] = { BindItem: FileParms.BindingProc = { IF actual # FileParms.nullActual THEN mdi ¬ FindMdEntry[formalId, typeId, actual.version, EnterRope[actual.locator]] ELSE [] ¬ SIGNAL FileProblem[formalId]; }; fd: FileParms.Name ¬ (SymbolOps.SubStringForName[ SymbolOps.own, formalId]).SubStringToRope; td: FileParms.Name ¬ (SymbolOps.SubStringForName[ SymbolOps.own, typeId]).SubStringToRope; fileParms.Binding[fd, td, defaultFile, BindItem]; }; FindMdEntry: PUBLIC PROC [formalId, typeId: Name, version: VersionStamp, file: Name] RETURNS [mdi: MDIndex] = { limit: MDIndex = table.Top[mdType]; duplicate: BOOL ¬ FALSE; FOR mdi ¬ MDFirst, mdi + MDRecord.SIZE UNTIL mdi = limit DO IF mdb[mdi].moduleId = typeId THEN { IF formalId # typeId THEN <> <> IF mdb[mdi].fileId # file THEN LOOP; IF mdb[mdi].stamp = version THEN RETURN; duplicate ¬ TRUE; }; ENDLOOP; IF duplicate THEN SIGNAL FileVersionMix[typeId]; mdi ¬ table.Units[mdType, MDRecord.SIZE]; mdb[mdi] ¬ MDRecord[ stamp: version, moduleId: typeId, fileId: file, ctx: IncludedCTXNull, shared: FALSE, exported: FALSE, defaultImport: CTXNull, file: nullFileIndex]; { stb: STB ¬ SymbolOps.own; stb.mdLimit ¬ stb.mdLimit + MDRecord.SIZE; }; }; GetSymbolTable: PUBLIC PROC [mdi: MDIndex] RETURNS [base: STB] = { index: FileIndex; OpenSymbols[mdi]; index ¬ mdb[mdi].file; IF fileTable[index].space = NIL THEN base ¬ NIL ELSE { base ¬ SymbolTable.AcquireSTB[FileHandleToSymbolHandle[fileTable[index]]]; SELECT TRUE FROM base.stHandle.versionIdent # SymbolSegment.VersionID => { SymbolTable.ReleaseSTB[base]; base ¬ NIL; IF SIGNAL FileProblem[mdb[mdi].fileId] THEN GO TO flush; }; base.stHandle.version # mdb[mdi].stamp => { SymbolTable.ReleaseSTB[base]; base ¬ NIL; IF SIGNAL FileProblem[mdb[mdi].fileId] THEN GO TO flush; }; ENDCASE; EXITS flush => { SymbolTable.ForgetSTB[FileHandleToSymbolHandle[fileTable[index]] ! SymbolTable.LockedSTB => {CONTINUE}]; fileParms.Release[fileTable[index].space]; fileTable[index] ¬ voidHandle; }; }; }; FreeSymbolTable: PUBLIC PROC [base: SymbolTable.Base] = { SymbolTable.ReleaseSTB[base]; }; EnterRope: PROC [rope: Rope.ROPE] RETURNS [Symbols.Name] = INLINE { flat: Rope.ROPE ¬ Rope.Flatten[rope]; <> ss: ConvertUnsafe.SubString ¬ [ base: LOOPHOLE[flat], offset: 0, length: Rope.Length[flat]]; RETURN [SymbolOps.EnterString[ss]]; }; <> FileHandle: TYPE = RECORD [space: FileParms.SymbolSpace, void: BOOL]; FileTable: TYPE = RECORD [SEQUENCE length: NAT OF FileHandle]; FileHandleToSymbolHandle: PROC [fh: FileHandle] RETURNS [SymbolTable.Handle] = INLINE { RETURN [[fh.space, FALSE]]; }; nullHandle: FileHandle = [NIL, FALSE]; voidHandle: FileHandle = [NIL, TRUE]; fileTable: REF FileTable ¬ NIL; lastFile: INTEGER; <> fileParms: FileParms.Ops ¬ [NIL, NIL, NIL, NIL]; FileInit: PUBLIC PROC [self: FileParms.ActualId, ownTable: Alloc.Handle, ops: FileParms.Ops] = { file: Symbols.Name = EnterRope[self.locator]; table ¬ ownTable; table.AddNotify[FilePackNotify]; IF FindMdEntry[nullName, nullName, self.version, file] # Symbols.OwnMdi THEN ERROR; fileParms ¬ ops; fileTable ¬ NIL; lastFile ¬ -1; }; CreateFileTable: PUBLIC PROC [size: CARDINAL] = { n: CARDINAL = size+1; -- allow for ownMdi fileTable ¬ MimZones.tempZone.NEW[FileTable[n]]; FOR i: FileIndex IN [0..n) DO fileTable[i] ¬ nullHandle ENDLOOP; lastFile ¬ -1; }; ExpandFileTable: PROC = { size: CARDINAL = fileTable.length + 2; newTable: REF FileTable ¬ MimZones.tempZone.NEW[FileTable[size]]; FOR i: FileIndex IN [0..fileTable.length) DO newTable[i] ¬ fileTable[i] ENDLOOP; FOR i: FileIndex IN [fileTable.length..size) DO newTable[i] ¬ nullHandle ENDLOOP; MimZones.tempZone.FREE[@fileTable]; fileTable ¬ newTable; }; FileReset: PUBLIC PROC = { IF fileTable # NIL THEN { FOR i: INTEGER IN [0..lastFile] DO IF fileTable[i] # nullHandle THEN fileParms.Release[fileTable[i].space]; fileTable[i] ¬ nullHandle; ENDLOOP; MimZones.tempZone.FREE[@fileTable]; }; IF table # NIL THEN {table.DropNotify[FilePackNotify]; table ¬ NIL}; }; <> MdiToFile: PROC [mdi: MDIndex] RETURNS [FileIndex] = { IF mdb[mdi].file = nullFileIndex THEN { newFile: FileIndex = lastFile + 1; UNTIL newFile < fileTable.length DO ExpandFileTable[] ENDLOOP; fileTable[newFile] ¬ nullHandle; lastFile ¬ newFile; mdb[mdi].file ¬ newFile; }; RETURN [mdb[mdi].file]; }; OpenSymbols: PROC [mdi: MDIndex] = { index: FileIndex = MdiToFile[mdi]; IF fileTable[index] = nullHandle THEN { d1: FileParms.Name ¬ ConvertUnsafe.SubStringToRope[ SymbolOps.SubStringForName[SymbolOps.own, mdb[mdi].moduleId]]; d2: FileParms.Name ¬ ConvertUnsafe.SubStringToRope[ SymbolOps.SubStringForName[SymbolOps.own, mdb[mdi].fileId]]; space: FileParms.SymbolSpace ¬ fileParms.Acquire[d1, [mdb[mdi].stamp, d2]]; IF space = NIL AND (SIGNAL FileProblem[mdb[mdi].moduleId]) THEN { fileTable[index] ¬ voidHandle; RETURN; }; fileTable[index] ¬ [space, FALSE]; }; }; TableForModule: PUBLIC PROC [mdi: MDIndex] RETURNS [SymbolTable.Handle] = { RETURN [FileHandleToSymbolHandle[fileTable[mdb[mdi].file]]]; }; <> MapSymbols: PUBLIC PROC [id: FileParms.ActualId] RETURNS [base: STB ¬ NIL] = { IF id # FileParms.nullActual THEN { space: FileParms.SymbolSpace = fileParms.Acquire[FileParms.nullName, id]; IF space # NIL THEN { handle: SymbolTable.Handle ¬ [space, FALSE]; base ¬ SymbolTable.AcquireSTB[handle]; IF base.stHandle.versionIdent # SymbolSegment.VersionID THEN { SymbolTable.ReleaseSTB[base]; fileParms.Release[space]; base ¬ NIL; }; }; }; }; UnmapSymbols: PUBLIC PROC [SymbolTable.Base] = FreeSymbolTable; MimZones.RegisterForReset[FileReset]; }.