-- FileLookup.Mesa; edited by Sandman on July 10, 1980 8:30 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AltoFileDefs, DirectoryDefs, FileLookupDefs, InlineDefs, IODefs, Storage, String, SegmentDefs; FileLookup: PROGRAM IMPORTS DirectoryDefs, InlineDefs, IODefs, SegmentDefs, String, Storage EXPORTS FileLookupDefs, SegmentDefs SHARES SegmentDefs = BEGIN OPEN SegmentDefs; FP: TYPE = AltoFileDefs.FP; Entry: TYPE = RECORD [link: POINTER TO Entry, name: STRING, fp: FP]; HashSize: CARDINAL = 19; HashIndex: TYPE = [0..HashSize); HashVector: ARRAY HashIndex OF POINTER TO Entry; HashValue: PROCEDURE [s: STRING] RETURNS [HashIndex] = BEGIN OPEN InlineDefs; i: CARDINAL; i _ BITAND[s[0], 137B] + BITAND[s[s.length/2], 137B]; RETURN[BITXOR[i, s.length*17B] MOD HashSize]; END; InsertEntry: PROCEDURE [name: STRING, fp: POINTER TO FP] = BEGIN hv: HashIndex = HashValue[name]; entry: POINTER TO Entry; entry _ Storage.Node[SIZE[Entry]]; entry.name _ name; entry.fp _ fp^; entry.link _ HashVector[hv]; HashVector[hv] _ entry; END; FindEntry: PROCEDURE [name: STRING, fp: POINTER TO FP] RETURNS [BOOLEAN] = BEGIN hv: HashIndex = HashValue[name]; entry: POINTER TO Entry; FOR entry _ HashVector[hv], entry.link UNTIL entry = NIL DO IF String.EquivalentString[name, entry.name] THEN BEGIN fp^ _ entry.fp; RETURN[TRUE]; END; ENDLOOP; RETURN[FALSE]; END; GetFileName: PUBLIC PROCEDURE [file: FileHandle] RETURNS [STRING] = BEGIN hv: HashIndex; entry: POINTER TO Entry; localname: STRING _ [40]; heapname: STRING; FOR hv IN HashIndex DO FOR entry _ HashVector[hv], entry.link UNTIL entry = NIL DO IF entry.fp.serial = file.fp.serial THEN RETURN[entry.name]; ENDLOOP; ENDLOOP; IF ~DirectoryDefs.DirectoryLookupFP[@file.fp, localname] THEN SIGNAL InvalidFP[@file.fp]; heapname _ Storage.CopyString[localname]; InsertEntry[heapname, @file.fp]; RETURN[heapname]; END; NewFile: PUBLIC PROCEDURE [ name: STRING, access: AccessOptions, version: VersionOptions] RETURNS [FileHandle] = BEGIN OPEN InlineDefs; fp: FP; old, create: BOOLEAN; [access, version] _ ValidateOptions[access, version]; create _ BITAND[version, OldFileOnly] = 0; old _ FindEntry[name, @fp]; IF ~old THEN old _ DirectoryDefs.DirectoryLookup[@fp, name, create]; IF (old AND BITAND[version, NewFileOnly] # 0) OR (~old AND ~create) THEN ERROR FileNameError[name]; RETURN[InsertFile[@fp, access]]; END; ValidateOptions: PROCEDURE [access: AccessOptions, version: VersionOptions] RETURNS [AccessOptions, VersionOptions] = BEGIN OPEN InlineDefs; IF access = DefaultAccess THEN access _ Read; -- IF version = DefaultVersion THEN version _ 0; IF BITAND[version, NewFileOnly + OldFileOnly] = NewFileOnly + OldFileOnly OR (BITAND[version, NewFileOnly] # 0 AND BITAND[access, Append] = 0) THEN ERROR FileAccessError[NIL]; IF BITAND[access, Append] = 0 THEN version _ BITOR[version, OldFileOnly]; RETURN[access, version] END; -- FileRequests FileRequest: TYPE = RECORD [link: POINTER TO FileRequest, name: STRING]; RequestHead: POINTER TO FileRequest _ NIL; AddFileRequest: PUBLIC PROCEDURE [name: STRING] = BEGIN r: POINTER TO FileRequest = Storage.Node[SIZE[FileRequest]]; r.name _ name; r.link _ RequestHead; RequestHead _ r; END; FilesMissing: PUBLIC ERROR = CODE; ProcessFileRequests: PUBLIC PROCEDURE = BEGIN r, next: POINTER TO FileRequest; checkone: PROCEDURE [fp: POINTER TO AltoFileDefs.FP, name: STRING] RETURNS [BOOLEAN] = BEGIN r, next: POINTER TO FileRequest; prev: POINTER TO FileRequest _ NIL; FOR r _ RequestHead, next UNTIL r = NIL DO next _ r.link; IF String.EquivalentString[r.name, name] THEN BEGIN InsertEntry[r.name, fp]; IF prev = NIL THEN RequestHead _ next ELSE prev.link _ next; Storage.Free[r]; EXIT; END; prev _ r; ENDLOOP; RETURN[RequestHead = NIL] END; DirectoryDefs.EnumerateDirectory[checkone]; IF RequestHead # NIL THEN BEGIN OPEN IODefs; WriteLine["Files not found:"]; FOR r _ RequestHead, next UNTIL r = NIL DO next _ r.link; WriteChar[' ]; WriteLine[r.name]; Storage.Free[r]; ENDLOOP; RequestHead _ NIL; ERROR FilesMissing; END; END; -- Main body i: HashIndex; FOR i IN HashIndex DO HashVector[i] _ NIL ENDLOOP; END...