-- 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.