MimFilesImpl.mesa
Copyright Ó 1985, 1986, 1987, 1988, 1991 by Xerox Corporation. All rights reserved.
Satterthwaite, June 10, 1986 9:58:21 am PDT
Russ Atkinson (RRA) June 21, 1989 11:43:50 am PDT
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;
tables defining the current symbol table
mdb: Symbols.Base;  -- module directory base
FilePackNotify: Alloc.Notifier = {mdb ¬ base[mdType]};
included module accounting
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
Insist on different file names as well (a kludge, we should be storing the formalId as well). This takes care of entries like:
Target: TYPE MachineParms USING [bitsPerLongWord, bitsPerWord]
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];
Don't let this be collected too soon!
ss: ConvertUnsafe.SubString ¬ [
base: LOOPHOLE[flat],
offset: 0,
length: Rope.Length[flat]];
RETURN [SymbolOps.EnterString[ss]];
};
low-level file manipulation
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;
file table management
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};
};
file setup
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]]];
};
mdi bypass
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];
}.