-- FileTableImpl.Mesa
-- Last edited by Lewis on 3-Jan-81 16:04:40
-- Last edited by Sweet on 6-Feb-81 14:56:24
DIRECTORY
BcdDefs USING [FTIndex, FTRecord, FTSelf, NameRecord],
FileTable,
PackagerDefs USING [globalData, NullSourceIndex],
PackEnviron USING [SetBlock],
PackHeap USING [GetSpace, FreeSpace],
Segments USING [
FHandle, LockFile, NewFile, Read,
ReleasableFile, ReleaseFile, UnlockFile],
SourceBcd USING [bcdBases, bcdLimits, SubStringForName],
Strings USING [AppendString, AppendSubString, SubString, SubStringDescriptor],
SymTabDefs USING [HTIndex],
SymTabOps USING [EnterString];
FileTableImpl: PROGRAM
IMPORTS PackagerDefs, PackEnviron, PackHeap, Segments, SourceBcd, Strings,
SymTabOps
EXPORTS FileTable =
BEGIN
FTIndex: TYPE = BcdDefs.FTIndex;
SubStringDescriptor: TYPE = Strings.SubStringDescriptor;
SubString: TYPE = Strings.SubString;
UnknownFile: PUBLIC ERROR [fti: FTIndex] = CODE;
fileArray: LONG DESCRIPTOR FOR ARRAY OF Segments.FHandle;
numFiles: CARDINAL;
Build: PUBLIC PROC =
BEGIN OPEN BcdDefs;
fileNameString: STRING ← [50];
fti: FTIndex;
ftiNameDesc: SubStringDescriptor;
ftiName: SubString ← @ftiNameDesc;
saveIndex: CARDINAL = PackagerDefs.globalData.textIndex;
i: CARDINAL;
PackagerDefs.globalData.textIndex ← PackagerDefs.NullSourceIndex;
-- allocate file handle array
numFiles ← IndexForFti[SourceBcd.bcdLimits.ft];
fileArray ← DESCRIPTOR[PackHeap.GetSpace[numFiles], numFiles];
PackEnviron.SetBlock[BASE[fileArray], NIL, numFiles];
-- enter file names into symtab (if not already there) to speed file lookup
i ← 0;
FOR fti ← FIRST[FTIndex], fti+SIZE[FTRecord]
UNTIL fti = SourceBcd.bcdLimits.ft DO
SourceBcd.SubStringForName[ftiName, SourceBcd.bcdBases.ftb[fti].name];
[] ← SymTabOps.EnterString[ftiName];
fileNameString.length ← 0;
Strings.AppendSubString[fileNameString, ftiName];
FOR j: CARDINAL IN [0..fileNameString.length) DO
IF fileNameString[j] = '. THEN EXIT;
REPEAT
FINISHED => Strings.AppendString[fileNameString, ".bcd"L];
ENDLOOP;
fileArray[i] ← Segments.NewFile[fileNameString, Segments.Read ! ANY => CONTINUE];
IF fileArray[i] # NIL THEN Segments.LockFile[fileArray[i]];
i ← i + 1;
ENDLOOP;
PackagerDefs.globalData.textIndex ← saveIndex;
END;
IndexForFti: PROC [fti: FTIndex] RETURNS [CARDINAL] = INLINE
{RETURN[ LOOPHOLE[fti, CARDINAL] / SIZE[BcdDefs.FTRecord] ]};
Destroy: PUBLIC PROC =
BEGIN
f: Segments.FHandle;
FOR i: CARDINAL IN [0..numFiles) DO
IF (f ← fileArray[i]) # NIL THEN
BEGIN
Segments.UnlockFile[f];
IF Segments.ReleasableFile[f] THEN Segments.ReleaseFile[f];
END;
ENDLOOP;
PackHeap.FreeSpace[BASE[fileArray]];
numFiles ← 0;
END;
HandleForFile: PUBLIC PROC [fti: FTIndex] RETURNS [file: Segments.FHandle] =
BEGIN
index: CARDINAL;
IF fti = BcdDefs.FTSelf THEN
RETURN [PackagerDefs.globalData.sourceBcdFile];
index ← IndexForFti[fti];
IF index >= numFiles OR fileArray[index] = NIL THEN
ERROR UnknownFile[fti];
RETURN[fileArray[index]];
END;
END.