-- FastDir.mesa edited: Sandman July 15, 1980 4:18 PM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AltoFileDefs USING [FP], DirectoryDefs USING [EnumerateDirectory], FastDirDefs USING [ Item, ItemHandle, HashVal, NilFileSwitches, FileSwitches, StringItem, FileType, LocalDir, Hash], String USING [AppendChar, EquivalentString], Storage USING [Node, CopyString]; FastDir: PROGRAM IMPORTS DirectoryDefs, FastDirDefs, String, Storage EXPORTS FastDirDefs = BEGIN OPEN FastDirDefs; StringHead: POINTER TO StringItem; ItemHead: ARRAY FileType OF ItemHandle; extensions: ARRAY FileType OF STRING = ["mesa", "bcd", "config", "symbols", "code", "image"]; fileSwitches: FileSwitches; NewString: PROCEDURE [s: STRING] RETURNS [STRING] = BEGIN p: POINTER TO StringItem; hash: HashVal = Hash[s]; FOR p ← StringHead, p.link UNTIL p = NIL DO IF p.hash = hash AND String.EquivalentString[s, p.s] THEN RETURN[p.s]; ENDLOOP; p ← Storage.Node[SIZE[Item]]; p.link ← StringHead; StringHead ← p; p.hash ← hash; RETURN[p.s ← Storage.CopyString[s]] END; EnterItem: PROCEDURE [s: STRING, t: FileType] RETURNS [p: ItemHandle] = INLINE BEGIN IF (p ← LookupItem[s, t]) = NIL THEN BEGIN p ← NewItem[s]; p.link ← ItemHead[t]; ItemHead[t] ← p; END; RETURN END; EnumerateList: PUBLIC PROCEDURE [ ft: FileType, proc: PROCEDURE [ItemHandle] RETURNS [BOOLEAN]] RETURNS [ih: ItemHandle] = BEGIN FOR ih ← ItemHead[ft], ih.link UNTIL ih = NIL OR proc[ih] DO ENDLOOP; END; GetExtension: PUBLIC PROCEDURE [ft: FileType] RETURNS [ext: STRING] = BEGIN RETURN[extensions[ft]] END; GetFiles: PROCEDURE [fp: POINTER TO AltoFileDefs.FP, fn: STRING] RETURNS [BOOLEAN] = BEGIN i: FileType; p: ItemHandle; ext: STRING ← [40]; StripExtension[fn, ext]; FOR i IN FileType DO IF fileSwitches[i] AND String.EquivalentString[ext, extensions[i]] THEN BEGIN p ← EnterItem[fn, i]; p.fp ← fp↑; EXIT; END; ENDLOOP; RETURN[FALSE] END; Init: PROCEDURE = BEGIN i: FileType; StringHead ← NIL; fileSwitches ← NilFileSwitches; FOR i IN FileType DO ItemHead[i] ← NIL ENDLOOP; END; LookupItem: PUBLIC PROCEDURE [s: STRING, t: FileType] RETURNS [p: ItemHandle] = BEGIN hash: HashVal = Hash[s]; FOR p ← ItemHead[t], p.link UNTIL p = NIL DO IF p.hash = hash AND String.EquivalentString[s, p.name] THEN EXIT; ENDLOOP; RETURN END; NewItem: PROCEDURE [s: STRING] RETURNS [p: ItemHandle] = INLINE BEGIN p ← Storage.Node[SIZE[Item]]; p.hash ← Hash[s]; p.name ← NewString[s]; RETURN END; ScanDir: PUBLIC PROCEDURE [ files: FileSwitches, proc: PROCEDURE [ PROCEDURE [POINTER TO AltoFileDefs.FP, STRING] RETURNS [BOOLEAN]]] = BEGIN fileSwitches ← files; IF proc = LocalDir THEN DirectoryDefs.EnumerateDirectory[GetFiles] ELSE proc[GetFiles]; END; StripExtension: PUBLIC PROCEDURE [name, ext: STRING] = BEGIN i, j: CARDINAL; i ← (j ← name.length) - 1; IF name[i] = '. THEN i ← (j ← i) - 1; FOR i ← i, i - 1 UNTIL name[i] = '. DO IF name[i] = '! THEN j ← i; IF i = 0 THEN RETURN; ENDLOOP; name.length ← i; IF ext = NIL THEN RETURN; ext.length ← 0; UNTIL (i ← i + 1) = j DO String.AppendChar[ext, name[i]]; ENDLOOP; RETURN END; StripSwitches: PUBLIC PROCEDURE [name, switches: STRING] = BEGIN OPEN String; i, j: CARDINAL; FOR i ← 0, i + 1 UNTIL i = name.length DO IF name[i] = '/ THEN EXIT; REPEAT FINISHED => RETURN; ENDLOOP; IF switches = NIL THEN BEGIN name.length ← i; RETURN END; FOR j IN (i..name.length) DO AppendChar[switches, name[j]] ENDLOOP; name.length ← i; RETURN; END; Init[]; END.