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