DFClosureImpl.mesa
Copyright Ó 1986, 1987, 1991 by Xerox Corporation. All rights reserved.
Created by Bertrand Serlet, October 20, 1986 9:25:11 pm PDT
Bertrand Serlet February 27, 1987 8:52:31 pm PST
Mike Spreitzer January 22, 1987 1:39:19 pm PST
Willie-s, September 27, 1991 2:25 pm PDT
DIRECTORY
DFClosure, DFUtilities, FS, Rope, RopeHash;
DFClosureImpl: CEDAR PROGRAM
IMPORTS DFUtilities, FS, Rope, RopeHash
EXPORTS DFClosure
~ BEGIN OPEN DFClosure;
ROPE: TYPE ~ Rope.ROPE;
ROPES: TYPE ~ LIST OF ROPE;
Operations
EnumerateClosure: PUBLIC PROC [dfName: ROPE, private: BOOL, file: FileProc, import: ImportProc, error: ErrorProc, message: MessageProc ¬ NIL, data: REF ¬ NIL] RETURNS [dfFiles: INT] ~ {
EnumerateClosureInternal: PROC [dfName: ROPE, private: BOOL] = {
ProcessItem: DFUtilities.ProcessItemProc = {
WITH item SELECT FROM
dirItem: REF DFUtilities.DirectoryItem  => lastDirectory ¬ dirItem;
fileItem: REF DFUtilities.FileItem  => {
IF (alreadyFetchedPublic AND NOT lastDirectory.exported) OR lastDirectory.exported OR private THEN file[data, fileItem.name, fileItem.date, lastDirectory.path1, lastDirectory.exported];
};
importsItem: REF DFUtilities.ImportsItem => SELECT import[data, importsItem.path1, importsItem.date, importsItem.exported, importsItem.form] FROM
public => EnumerateClosureInternal[importsItem.path1, FALSE];
all => EnumerateClosureInternal[importsItem.path1, TRUE];
same => EnumerateClosureInternal[importsItem.path1, private];
none => {};
ENDCASE => ERROR;
includeItem: REF DFUtilities.IncludeItem => EnumerateClosureInternal[includeItem.path1, private];
ENDCASE    => ERROR;
};
alreadyFetchedPublic: BOOL ¬ FALSE;
lastDirectory: REF DFUtilities.DirectoryItem ¬ NIL;
fullDFName: ROPE = ShortToFullMapping[shortToFull, dfName ! FS.Error => {errorMsg ¬ error.explanation; GOTO FSFailed}];
IF Member[IF private THEN fullWithAll ELSE fullWithPublic, fullDFName] THEN RETURN;
IF NOT private AND Member[fullWithAll, fullDFName] THEN RETURN;
dfFiles ¬ dfFiles + 1;
IF private
THEN fullWithAll ¬ CONS [fullDFName, fullWithAll]
ELSE fullWithPublic ¬ CONS [fullDFName, fullWithPublic];
alreadyFetchedPublic ¬ private AND Member[fullWithPublic, fullDFName];
IF message#NIL THEN message[data, Rope.Cat["Considering ", fullDFName, IF private THEN IF alreadyFetchedPublic THEN " (private)" ELSE " (all)" ELSE " (public)"]];
DFUtilities.ParseFromFile[
fullDFName, ProcessItem,
[comments: FALSE, filterA: $all, filterB: IF alreadyFetchedPublic THEN $private ELSE $all, filterC: $all, list: NIL]
! FS.Error => {errorMsg ¬ error.explanation; GOTO FSFailed};
DFUtilities.FileSyntaxError => {errorMsg ¬ reason; GOTO FileSyntaxError}];
EXITS
FSFailed => error[data, notFound, errorMsg];
FileSyntaxError => error[data, syntaxError, errorMsg];
};
errorMsg: ROPE;
shortToFull: REF = CreateShortToFullMapping[];
fullWithAll: LIST OF ROPE ¬ NIL; -- list of all the full df files fetched with recurse=all
fullWithPublic: LIST OF ROPE ¬ NIL; -- list of all the full df files fetched with recurse=public
dfFiles ¬ 0;
EnumerateClosureInternal[dfName: dfName, private: private ! ABORTED => {error[data, aborted, "ABORTED\n"]; CONTINUE}];
};
Utilities
Member: PROC [ropes: ROPES, rope: ROPE] RETURNS [BOOL] = {
WHILE ropes#NIL DO
IF Rope.Equal[ropes.first, rope, FALSE] THEN RETURN [TRUE]; ropes ¬ ropes.rest;
ENDLOOP;
RETURN [FALSE];
};
mappingSize: CARDINAL = 61;
MappingArray: TYPE = ARRAY [0 .. mappingSize) OF LIST OF MappingPair;
MappingPair: TYPE = RECORD [short, full: ROPE];
CreateShortToFullMapping: PUBLIC PROC RETURNS [mapping: REF] = {
mapping ¬ NEW [MappingArray ¬ ALL [NIL]];
};
ShortToFullMapping: PUBLIC PROC [mapping: REF, short: ROPE] RETURNS [full: ROPE] = {
map: REF MappingArray = NARROW [mapping];
hash: CARDINAL = RopeHash.FromRope[short, FALSE] MOD mappingSize;
FOR pairs: LIST OF MappingPair ¬ map[hash], pairs.rest WHILE pairs#NIL DO
IF Rope.Equal[pairs.first.short, short, FALSE] THEN RETURN [pairs.first.full];
ENDLOOP;
full ¬ FS.FileInfo[short].fullFName;
map[hash] ¬ CONS [[short: short, full: full], map[hash]];
};
END.