<> <> DIRECTORY ConvertUnsafe, Directory, DirectoryList, Heap, MessageWindow, RefText, Rope, UnsafeSTP, UserCredentials; DirectoryListImpl: CEDAR PROGRAM IMPORTS ConvertUnsafe, Directory, Heap, MessageWindow, RefText, Rope, UnsafeSTP, UserCredentials EXPORTS DirectoryList ~ BEGIN ROPE: TYPE ~ Rope.ROPE; PastPattern: PROC [pattern: ROPE, text: REF TEXT, start: INT] RETURNS [BOOLEAN] ~ { FOR i: INT IN [0..MIN[pattern.Length, text.length - start]) DO c: CHAR _ Rope.Upper[pattern.Fetch[i]]; t: CHAR _ Rope.Upper[text[start+i]]; IF c = '* THEN RETURN [FALSE]; IF t # c THEN RETURN [t > c]; ENDLOOP; RETURN [FALSE]; }; NeverAbort: PUBLIC PROC RETURNS [BOOLEAN] ~ {RETURN [FALSE]}; Local: PUBLIC PROC [pattern: ROPE, abortProc: PROC RETURNS [BOOLEAN]] RETURNS [LIST OF ROPE] ~ { pathNameText: REF TEXT ~ RefText.ObtainScratch[200]; currentNameText: REF TEXT ~ RefText.ObtainScratch[200]; nextNameText: REF TEXT ~ RefText.ObtainScratch[200]; list: LIST OF ROPE _ NIL; TRUSTED { nextName: LONG STRING ~ LOOPHOLE[nextNameText]; [] _ Directory.GetNext[pathName: "WorkDir>", currentName: "", nextName: nextName]; }; FOR i: NAT DECREASING IN [0..nextNameText.length) DO IF nextNameText[i] = '> THEN {nextNameText.length _ i+1; EXIT} ENDLOOP; pathNameText.length _ 0; RefText.Append[pathNameText, nextNameText]; currentNameText.length _ 0; nextNameText.length _ 0; UNTIL abortProc[] DO TRUSTED { pathName: LONG STRING ~ LOOPHOLE[pathNameText]; currentName: LONG STRING ~ LOOPHOLE[currentNameText]; nextName: LONG STRING ~ LOOPHOLE[nextNameText]; [] _ Directory.GetNext[pathName: pathName, currentName: currentName, nextName: nextName]; }; IF nextNameText.length = 0 OR PastPattern[pattern, nextNameText, pathNameText.length] THEN EXIT; currentNameText.length _ 0; RefText.Append[currentNameText, nextNameText, pathNameText.length]; nextNameText.length _ 0; TRUSTED { object: Rope.Text ~ LOOPHOLE[currentNameText]; IF Rope.Match[pattern: pattern, object: object, case: FALSE] THEN list _ CONS[Rope.FromRefText[currentNameText], list]; }; ENDLOOP; RefText.ReleaseScratch[pathNameText]; RefText.ReleaseScratch[currentNameText]; RefText.ReleaseScratch[nextNameText]; RETURN[Reverse[list]]; }; Remote: PUBLIC PROC [host: ROPE, pattern: ROPE, abortProc: PROC RETURNS [BOOLEAN]] RETURNS [matchingFiles: LIST OF ROPE _ NIL, errorMsg: ROPE _ NIL] ~ TRUSTED { name, password: ROPE; [name, password] _ UserCredentials.GetUserCredentials[]; { nameText: REF TEXT ~ name.ToRefText; nameString: LONG STRING ~ LOOPHOLE[nameText]; passwordText: REF TEXT ~ password.ToRefText; passwordString: LONG STRING ~ LOOPHOLE[passwordText]; hostText: REF TEXT ~ host.ToRefText; hostString: LONG STRING ~ LOOPHOLE[hostText]; patternText: REF TEXT ~ pattern.ToRefText; patternString: LONG STRING ~ LOOPHOLE[patternText]; stp: UnsafeSTP.Handle _ UnsafeSTP.Create[]; aborted: BOOLEAN _ FALSE; herald: LONG STRING _ stp.Open[hostString]; MessageWindow.Append[ConvertUnsafe.ToRope[herald], TRUE]; Heap.systemZone.FREE[@herald]; herald _ NIL; MessageWindow.Append[" "]; stp.Login[nameString, passwordString]; { nMod10: NAT _ 0; Visit: PROCEDURE [file: LONG STRING] RETURNS [continue: UnsafeSTP.Continue] ~ TRUSTED { matchingFiles _ CONS[ConvertUnsafe.ToRope[file], matchingFiles]; IF nMod10 = 0 THEN MessageWindow.Append["."]; nMod10 _ nMod10 + 1; IF nMod10 = 10 THEN nMod10 _ 0; continue _ IF aborted _ abortProc[] THEN no ELSE yes; }; stp.SetDesiredProperties[desiredProperties]; stp.Enumerate[patternString, Visit ! UnsafeSTP.Error => {errorMsg _ ConvertUnsafe.ToRope[error]; CONTINUE}]; }; stp _ stp.Destroy; MessageWindow.Append[" Closed."]; IF aborted THEN errorMsg _ errorMsg.Concat[" (List aborted by user request)"]; matchingFiles _ Reverse[matchingFiles]; }; }; Reverse: PROC [list: LIST OF ROPE] RETURNS [reversed: LIST OF ROPE _ NIL] ~ { WHILE list # NIL DO t: LIST OF ROPE _ list; list _ t.rest; t.rest _ reversed; reversed _ t; ENDLOOP; }; desiredProperties: UnsafeSTP.DesiredProperties _ ALL[FALSE]; desiredProperties[directory] _ TRUE; desiredProperties[nameBody] _ TRUE; desiredProperties[version] _ TRUE; END.