-- file FileTableImpl.mesa -- last edited by Lewis on 6-Jan-82 17:56:02 -- last edited by Satterthwaite, December 27, 1982 9:43 am DIRECTORY BcdDefs USING [BCD, FTIndex, FTRecord, FTSelf, NameRecord, VersionStamp], CIFS: TYPE USING [OpenFile, Close, Error, GetFC, Open, read], ConvertUnsafe: TYPE USING [ToRope], Error USING [ErrorFile, WrongFileVersion], FileTable: TYPE USING [], PackagerDefs USING [globalData, nullSourceIndex], SourceBcd USING [bcdBases, bcdLimits, SubStringForName], Space: TYPE USING [ Handle, nullHandle, virtualMemory, CopyIn, Create, Delete, Error, LongPointer, Map], String USING [AppendString, AppendSubString, SubString, SubStringDescriptor]; FileTableImpl: PROGRAM IMPORTS CIFS, ConvertUnsafe, Error, PackagerDefs, SourceBcd, Space, String EXPORTS FileTable = BEGIN FTIndex: TYPE = BcdDefs.FTIndex; SubStringDescriptor: TYPE = String.SubStringDescriptor; SubString: TYPE = String.SubString; UnknownFile: PUBLIC ERROR [fti: FTIndex] = CODE; maxFiles: NAT = (FTIndex.LAST-FTIndex.FIRST)/BcdDefs.FTRecord.SIZE + 1; FileSequence: TYPE = RECORD [SEQUENCE length: [0..maxFiles] OF CIFS.OpenFile]; BitSequence: TYPE = RECORD [PACKED SEQUENCE length: [0..maxFiles] OF BOOL]; nullFile: CIFS.OpenFile = NIL; fileArray: REF FileSequence ← NIL; -- REF so GC can find OpenFile objects fileStampChecked: LONG POINTER TO BitSequence ← NIL; headerSeg: Space.Handle ← Space.nullHandle; header: LONG POINTER TO BcdDefs.BCD ← NIL; Build: PUBLIC PROC = { OPEN BcdDefs; numFiles: NAT; fileNameString: STRING ← [100]; 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 ← --PackagerDefs.globalData.zone.--NEW[FileSequence[numFiles]]; fileStampChecked ← PackagerDefs.globalData.zone.NEW[BitSequence[numFiles]]; FOR i IN [0..numFiles) DO fileArray[i] ← nullFile; fileStampChecked[i] ← FALSE; ENDLOOP; -- enter file names into symtab (if not already there) to speed file lookup i ← 0; FOR fti: FTIndex ← FIRST[FTIndex], fti+SIZE[FTRecord] UNTIL fti = SourceBcd.bcdLimits.ft DO SourceBcd.SubStringForName[ftiName, SourceBcd.bcdBases.ftb[fti].name]; fileNameString.length ← 0; String.AppendSubString[fileNameString, ftiName]; FOR j: CARDINAL IN [0..fileNameString.length) DO IF fileNameString[j] = '. THEN EXIT; REPEAT FINISHED => String.AppendString[fileNameString, ".bcd"L]; ENDLOOP; fileArray[i] ← CIFS.Open[ConvertUnsafe.ToRope[fileNameString], CIFS.read ! CIFS.Error => TRUSTED {CONTINUE}]; i ← i + 1; ENDLOOP; headerSeg ← Space.Create[size: 1, parent: Space.virtualMemory]; headerSeg.Map[]; header ← headerSeg.LongPointer[]; PackagerDefs.globalData.textIndex ← saveIndex}; IndexForFti: PROC [fti: FTIndex] RETURNS [CARDINAL] = INLINE { RETURN[ LOOPHOLE[fti,CARDINAL]/SIZE[BcdDefs.FTRecord] ]}; Destroy: PUBLIC PROC = { IF headerSeg # Space.nullHandle THEN { Space.Delete[headerSeg]; headerSeg ← Space.nullHandle}; IF fileArray # NIL THEN { FOR i: CARDINAL IN [0..fileArray.length) DO IF fileArray[i] # nullFile THEN{ CIFS.Close[fileArray[i]]; fileArray[i] ← nullFile}; ENDLOOP; --PackagerDefs.globalData.zone.--FREE[@fileArray]}}; HandleForFile: PUBLIC PROC [fti: FTIndex] RETURNS [file: CIFS.OpenFile←nullFile] = { -- copies into non-GC storage are ok index: CARDINAL; IF fti = BcdDefs.FTSelf THEN file ← PackagerDefs.globalData.sourceBcdFile ELSE { index ← IndexForFti[fti]; IF index >= fileArray.length OR (file ← fileArray[index]) = nullFile THEN ERROR UnknownFile[fti]; IF ~fileStampChecked[index] THEN { BEGIN headerSeg.CopyIn[window: [file: file.GetFC, base: 1] ! Space.Error => {GO TO fail}]; IF header.version # SourceBcd.bcdBases.ftb[fti].version THEN Error.WrongFileVersion[ class: error, fti: fti, requiredVersion: SourceBcd.bcdBases.ftb[fti].version, actualVersion: header.version]; EXITS fail => { Error.ErrorFile[class: error, fti: fti, s: "cannot be opened"L]; ERROR UnknownFile[fti]}; END; fileStampChecked[index] ← TRUE}}; RETURN}; END.