DIRECTORY BasicTime USING [GetClockPulses, GMT, Pulses, PulsesToMicroseconds], FS USING [Close, ComponentPositions, Copy, Create, Delete, Error, ErrorDesc, EnumerateForInfo, EnumerateForNames, ExpandName, GetDefaultWDir, InfoProc, NameProc, nullOpenFile, Open, OpenFile, Position, Rename, SetKeep, SetDefaultWDir], FSBackdoor USING [EntryPtr, Enumerate, EnumerateCacheForNames, Flush, MakeFName, NameProc, ScavengeDirectoryAndCache, SetFreeboard, TextFromTextRep, VolumePages], IO USING [BreakProc, CharsAvail, CR, CreateEditedStream, Error, GetChar, GetInt, GetToken, LF, PutChar, PutF, PutFR, PutRope, Signal, SP, STREAM, TAB], List USING [PutAssoc], ProcessProps USING [AddPropList, GetPropList], Rope USING [Concat, Equal, Fetch, Find, Flatten, Length, ROPE, Substr, Text], SimpleTerminal USING [TurnOn]; FSTest: CEDAR PROGRAM IMPORTS BasicTime, FS, FSBackdoor, IO, List, ProcessProps, Rope, SimpleTerminal = BEGIN in, out: IO.STREAM; MyBreakProc: IO.BreakProc = BEGIN OPEN IO; SELECT char FROM SP, LF, TAB => RETURN[sepr]; CR => RETURN[break]; ENDCASE => RETURN[other]; END; Empty: PROC [] = BEGIN WHILE in.CharsAvail[] DO [] _ in.GetChar[] ENDLOOP; END; ProcessFSError: PROC [desc: FS.ErrorDesc] RETURNS [acceptIt: BOOLEAN] = BEGIN out.PutF[" ... FS.Error[%g]\n", [rope[desc.explanation]]]; acceptIt _ TRUE; END; DoIt: PROC = BEGIN uneditedIn: IO.STREAM; [uneditedIn, out] _ SimpleTerminal.TurnOn["FSTest"]; in _ IO.CreateEditedStream[in: uneditedIn, echoTo: out]; out.PutRope["\n\n"]; Commands[]; DO ENABLE BEGIN IO.Signal => { IF ec = Rubout THEN {out.PutRope["\n"]; RETRY} }; IO.Error => {IF ec = StreamClosed THEN EXIT ELSE {out.PutRope["\n"]; RETRY}}; END; cmd: Rope.ROPE; Empty[]; out.PutChar['>]; cmd _ in.GetToken[MyBreakProc]; BEGIN ENABLE FS.Error => IF ProcessFSError[error] THEN CONTINUE; SELECT TRUE FROM Rope.Equal["attach", cmd, FALSE] => Attach[]; Rope.Equal["bringover", cmd, FALSE] => BringOver[]; Rope.Equal["copy", cmd, FALSE] => Copy[]; Rope.Equal["create", cmd, FALSE] => Create[]; Rope.Equal["debug", cmd, FALSE] => Debug[]; Rope.Equal["delete", cmd, FALSE] => Delete[]; Rope.Equal["flush", cmd, FALSE] => Flush[]; Rope.Equal["getWDir", cmd, FALSE] => GetWDir[]; Rope.Equal["listCache", cmd, FALSE] => ListCache[]; Rope.Equal["listInfo", cmd, FALSE] => ListInfo[]; Rope.Equal["listNames", cmd, FALSE] => ListNames[]; Rope.Equal["load", cmd, FALSE] => Load[]; Rope.Equal["pages", cmd, FALSE] => Pages[]; Rope.Equal["parseName", cmd, FALSE] => ParseName[]; Rope.Equal["rename", cmd, FALSE] => Rename[]; Rope.Equal["scavenge", cmd, FALSE] => Scavenge[]; Rope.Equal["setFreeboard", cmd, FALSE] => SetFreeboard[]; Rope.Equal["setkeep", cmd, FALSE] => SetKeep[]; Rope.Equal["setPDir", cmd, FALSE] => SetPDir[]; Rope.Equal["setWDir", cmd, FALSE] => SetWDir[]; Rope.Equal["times", cmd, FALSE] => Times[]; Rope.Equal["?", cmd, FALSE] => Commands[]; Rope.Equal["\n", cmd, FALSE] => NULL; ENDCASE => out.PutRope[" ... ?\n"]; END; ENDLOOP; END; Commands: PROCEDURE = BEGIN out.PutRope["Commands are: attach, bringOver, copy, create, debug, delete, flush, getWDir, listCache, listInfo, listNames, load, pages, parseName, rename, scavenge, setFreeboard, setKeep, setPDir, setWDir and times\n"]; END; Attach: PROCEDURE = BEGIN from: Rope.ROPE = in.GetToken[MyBreakProc]; to: Rope.ROPE = in.GetToken[MyBreakProc]; FS.Copy[from: from, to: to, keep: createKeep, remoteCheck: FALSE, attach: TRUE]; END; BringOver: PROCEDURE = BEGIN attachIt: FS.InfoProc = BEGIN localName: Rope.ROPE; lastPoint, bangIndex: INT _ 0; FOR i: INT DECREASING IN [0 .. Rope.Length[fullFName]) DO SELECT Rope.Fetch[fullFName, i] FROM '! => bangIndex _ i; '> => {lastPoint _ i; EXIT}; ENDCASE; ENDLOOP; IF bangIndex = lastPoint + 1 THEN RETURN[TRUE]; -- skip [..]<..>!1 localName _ Rope.Substr[fullFName, lastPoint+1, bangIndex - lastPoint - 1]; out.PutF[" %g _ %g\n", [rope[localName]], [rope[fullFName]]]; FS.Copy[from: fullFName, to: localName, keep: createKeep, wantedCreatedTime: created, attach: TRUE]; RETURN[TRUE]; END; pattern: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Length[pattern] = 0 OR (Rope.Fetch[pattern, 0] = '[ AND Rope.Fetch[pattern,1] = ']) OR (Rope.Fetch[pattern, 0] = '/ AND Rope.Fetch[pattern, 1] = '/) THEN out.PutRope[" ... give a remote pattern\n"] ELSE FS.EnumerateForInfo[pattern, attachIt]; END; createKeep: CARDINAL _ 2; Copy: PROCEDURE = BEGIN fromName: Rope.ROPE = in.GetToken[MyBreakProc]; toName: Rope.ROPE = in.GetToken[MyBreakProc]; FS.Copy[from: fromName, to: toName, keep: createKeep]; END; Create: PROCEDURE = BEGIN name: Rope.ROPE = in.GetToken[MyBreakProc]; FS.Close[FS.Create[name: name, keep: createKeep]]; END; GoToDebugger: SIGNAL = CODE; Debug: PROCEDURE = { SIGNAL GoToDebugger }; Delete: PROCEDURE = BEGIN deleteIt: FS.NameProc = BEGIN out.PutF[" deleting %g\n", [rope[fullFName]]]; FS.Delete[fullFName]; RETURN[TRUE]; END; pattern: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Find[pattern, "*"] = -1 THEN FS.Delete[pattern] ELSE BEGIN IF Rope.Find[pattern, "!"] = -1 THEN pattern _ Rope.Concat[pattern, "!L"]; FS.EnumerateForNames[pattern, deleteIt]; END END; Flush: PROCEDURE = BEGIN flushIt: FSBackdoor.NameProc = BEGIN out.PutF[" flushing %g", [rope[fullGName]]]; FSBackdoor.Flush[fullGName ! FS.Error => {out.PutF[ " ... FS.Error[%g]", [rope[error.explanation]] ]; CONTINUE}]; out.PutRope["\n"]; RETURN[TRUE]; END; pattern: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Find[pattern, "*"] = -1 THEN FSBackdoor.Flush[pattern] ELSE FSBackdoor.EnumerateCacheForNames[flushIt, NIL, pattern]; END; GetWDir: PROCEDURE = BEGIN out.PutF[" ... default working directory is %g\n", [rope[FS.GetDefaultWDir[]]] ]; END; ListInfo: PROCEDURE = BEGIN print: FS.InfoProc = BEGIN IF attachedTo = NIL THEN out.PutF[" %g -- keep = %g, %g bytes, %g\n", [rope[fullFName]], [cardinal[keep]], [integer[bytes]], [time[created]]] ELSE out.PutF[" %g -- keep = %g\n attached to %g -- %g bytes, %g\n", [rope[fullFName]], [cardinal[keep]], [rope[attachedTo]], [integer[bytes]], [time[created]]]; RETURN[TRUE]; END; pattern: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Equal[pattern, "\n"] THEN pattern _ "*"; FS.EnumerateForInfo[pattern, print]; END; ListCache: PROCEDURE = BEGIN print: UNSAFE PROC [entry: FSBackdoor.EntryPtr] RETURNS [accept, stop: BOOLEAN] = UNCHECKED BEGIN fullGName: Rope.ROPE = FSBackdoor.MakeFName[ FSBackdoor.TextFromTextRep[@entry[entry.nameBody]], entry.version ]; WITH e: entry^ SELECT FROM cached => out.PutF[" %g -- used at %g\n", [rope[fullGName]], [time[e.used]]]; ENDCASE => ERROR; RETURN[FALSE, FALSE]; END; pattern: Rope.Text _ Rope.Flatten[in.GetToken[MyBreakProc]]; IF Rope.Equal[pattern, "\n"] THEN pattern _ "[*"; FSBackdoor.Enumerate[volName: NIL, nameBodyPattern: pattern, localOnly: FALSE, allVersions: TRUE, version: [0], matchProc: print, acceptProc: NIL]; END; ListNames: PROCEDURE = BEGIN print: FS.NameProc = BEGIN out.PutF[" %g\n", [rope[fullFName]] ]; RETURN[TRUE]; END; pattern: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Equal[pattern, "\n"] THEN pattern _ "*"; FS.EnumerateForNames[pattern, print]; END; Load: PROCEDURE = BEGIN fetch: FS.NameProc = BEGIN file: FS.OpenFile _ FS.nullOpenFile; out.PutF[" loading %g\n", [rope[fullFName]] ]; file _ FS.Open[fullFName, read ! FS.Error => {out.PutF[ " ... FS.Error[%g] on opening %g\n", [rope[error.explanation]], [rope[fullFName]] ]; CONTINUE}]; IF file # FS.nullOpenFile THEN FS.Close[file]; RETURN[TRUE]; END; pattern: Rope.ROPE _ in.GetToken[MyBreakProc]; FS.EnumerateForNames[pattern, fetch]; END; Pages: PROCEDURE = BEGIN volName: Rope.ROPE _ in.GetToken[MyBreakProc]; size, free, freeboard: INT; IF Rope.Equal[volName, "\n"] THEN volName _ NIL; [size, free, freeboard] _ FSBackdoor.VolumePages[volName]; out.PutF[" size = %g, free = %g, freeboard = %g\n", [integer[size]], [integer[free]], [integer[freeboard]] ]; END; ParseName: PROCEDURE = BEGIN MakePrintRope: PROC [p: FS.Position] RETURNS [r: Rope.ROPE] = BEGIN IF p.length = 0 THEN r _ IO.PutFR["[%g, 0]", [cardinal[p.start]]] ELSE r _ Rope.Substr[fullName, p.start, p.length]; END; cp: FS.ComponentPositions; fullName: Rope.ROPE; name: Rope.ROPE _ in.GetToken[MyBreakProc]; wDir: Rope.ROPE _ NIL; IF Rope.Equal[name, "\n"] THEN name _ NIL ELSE BEGIN wDir _ in.GetToken[MyBreakProc]; IF Rope.Equal[wDir, "\n"] THEN wDir _ NIL; END; [fullName, cp, ] _ FS.ExpandName[name, wDir]; out.PutF[" %g\n", [rope[fullName]]]; out.PutF[" \"%g\", \"%g\", \"%g\", ", [rope[MakePrintRope[cp.server]]], [rope[MakePrintRope[cp.dir]]], [rope[MakePrintRope[cp.subDirs]]] ]; out.PutF["\"%g\", \"%g\", \"%g\"\n", [rope[MakePrintRope[cp.base]]], [rope[MakePrintRope[cp.ext]]], [rope[MakePrintRope[cp.ver]]] ]; END; Rename: PROCEDURE = BEGIN fromName: Rope.ROPE = in.GetToken[MyBreakProc]; toName: Rope.ROPE = in.GetToken[MyBreakProc]; FS.Rename[from: fromName, to: toName]; END; Scavenge: PROCEDURE = BEGIN volName: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Equal[volName, "\n"] THEN volName _ NIL; FSBackdoor.ScavengeDirectoryAndCache[volName]; END; SetFreeboard: PROCEDURE = BEGIN FSBackdoor.SetFreeboard[in.GetInt[]]; END; SetKeep: PROCEDURE = BEGIN name: Rope.ROPE = in.GetToken[MyBreakProc]; FS.SetKeep[name, in.GetInt[]]; END; SetPDir: PROCEDURE = BEGIN name: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Length[name] <= 1 THEN name _ NIL; [] _ List.PutAssoc[key: $WorkingDirectory, val: name, aList: ProcessProps.GetPropList[]]; END; SetWDir: PROCEDURE = BEGIN name: Rope.ROPE _ in.GetToken[MyBreakProc]; IF Rope.Length[name] <= 1 THEN name _ NIL; FS.SetDefaultWDir[name]; GetWDir[]; END; Times: PROCEDURE = BEGIN start: BasicTime.Pulses; period, count: INT; entryProc: UNSAFE PROC [entry: FSBackdoor.EntryPtr] RETURNS [accept, stop: BOOLEAN] = UNCHECKED { count _ count + 1; RETURN[FALSE, FALSE] }; nameProc: FS.NameProc = { count _ count + 1; RETURN[TRUE] }; infoProc: FS.InfoProc = { count _ count + 1; RETURN[TRUE] }; openProc: FS.NameProc = BEGIN file: FS.OpenFile _ FS.nullOpenFile; count _ count + 1; file _ FS.Open[fullFName, read ! FS.Error => CONTINUE ]; IF file # FS.nullOpenFile THEN FS.Close[file]; RETURN[TRUE]; END; pattern: Rope.Text _ Rope.Flatten[in.GetToken[MyBreakProc]]; IF Rope.Equal[pattern, "\n"] THEN pattern _ "*"; count _ 0; start _ BasicTime.GetClockPulses[]; FSBackdoor.Enumerate[NIL, pattern, TRUE, TRUE, [0], entryProc, NIL]; period _ BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[] - start] / 1000; out.PutF[" enumerated %g entries in %g milliseconds\n", [integer[count]], [integer[period]]]; count _ 0; start _ BasicTime.GetClockPulses[]; FS.EnumerateForNames[pattern, nameProc]; period _ BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[] - start] / 1000; out.PutF[" enumerated %g names in %g milliseconds\n", [integer[count]], [integer[period]]]; count _ 0; start _ BasicTime.GetClockPulses[]; FS.EnumerateForInfo[pattern, infoProc]; period _ BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[] - start] / 1000; out.PutF[" enumerated %g infos in %g milliseconds\n", [integer[count]], [integer[period]]]; count _ 0; start _ BasicTime.GetClockPulses[]; FS.EnumerateForNames[pattern, openProc]; period _ BasicTime.PulsesToMicroseconds[BasicTime.GetClockPulses[] - start] / 1000; out.PutF[" opened %g different files in %g milliseconds\n", [integer[count]], [integer[period]]]; END; p: PROCESS = FORK ProcessProps.AddPropList [ List.PutAssoc[key: $WorkingDirectory, val: NIL, aList: NIL], DoIt ]; END. HFSTest.mesa Last Edited by: Schroeder, September 14, 1983 4:54 pm Κ τ– "Cedar" style˜J™ J™5unitšΟk ˜ Icodešœ œœ ˜DLšœœγ˜λLšœ œ’˜’Lšœœœ8œ)œœœ˜—Lšœœ ˜Lšœ œ˜.Lšœœ/œ˜MLšœœ ˜—šœœ˜Lšœ œœ*˜OLšœ˜L˜Lšœ œœ˜šœ œ ˜Lš˜šœ˜Lšœœœœ˜Lšœœ˜Lšœœ˜—Lšœ˜—šΟnœœ˜Lš˜Lšœœœ˜3Lšœ˜—šžœœœ œ˜GLš˜Lšœ:˜:Lšœ œ˜Lšœ˜—šžœœ˜ Lš˜Lšœ œœ˜Lšœ4˜4Lšœ8˜8L˜L˜ š˜šœ˜ Lšœ œ œœ˜@Lš œ œœœœœ˜MLšœ˜—Lšœ œ˜Lšœ˜L˜Lšœ˜š œœœ œœœ˜@šœœ˜Lšœœ˜-Lšœœ˜3Lšœœ ˜)Lšœœ˜-Lšœœ ˜+Lšœœ˜-Lšœœ ˜+Lšœœ˜/Lšœœ˜3Lšœœ˜1Lšœœ˜3Lšœœ ˜)Lšœœ ˜+Lšœœ˜3Lšœœ˜-Lšœœ˜1Lšœ œ˜9Lšœœ˜/Lšœœ˜/Lšœœ˜/Lšœœ ˜+Lšœœ˜*Lšœœœ˜%Lšœ˜#—Lšœ˜—Lšœ˜—Lšœ˜—šžœ œ˜Lš˜LšœΫ˜ΫLšœ˜—šžœ œ˜Lš˜Lšœ œ˜+Lšœ œ˜)Jšœ9œ œ˜PLšœ˜—šž œ œ˜Lš˜šœ œ ˜Lš˜Lšœœ˜Lšœœ˜š œœ œœ˜9šœ˜$Lšœ˜Lšœœ˜Lšœ˜—Lšœ˜—Lš œœœœΟc˜BLšœL˜LLšœ>˜>Lšœ\œ˜dLšœœ˜ Lšœ˜—Lšœœ˜.šœ˜Lšœœ˜?Lšœœ˜=—Lšœ.˜2Lšœœ%˜,Lšœ˜—Kšœ œ˜šžœ œ˜Lš˜Lšœœ˜/Lšœ œ˜-Lšœ4˜6Lšœ˜—šžœ œ˜Lš˜Lšœ œ˜+Lšœœ'˜2Lšœ˜—Kšœœœ˜šžœ œ˜Lš œ œ˜—šžœ œ˜Lš˜šœ œ ˜Lš˜Lšœ/˜/Lšœ˜Lšœœ˜ Lšœ˜—Lšœœ˜.Lšœ˜Lšœœ˜šœœ˜ Lšœ˜Lšœ'˜+Lšœ&˜(Lš˜—Lšœ˜—šžœ œ˜Lš˜šœ˜Lš˜Lšœ-˜-šœ˜LšœKœ˜V—Lšœ˜Lšœœ˜ Lšœ˜—Lšœœ˜.Lšœ˜Lšœ˜Lšœ,œ ˜>Lšœ˜—šžœ œ˜Lš˜Lšœ9œ˜QLšœ˜—šžœ œ˜Lš˜šœœ ˜Lš˜Lšœ˜Lšœv˜zLšœ‘˜₯Lšœœ˜ Lšœ˜—Lšœœ˜.Lšœœ˜0Lšœ"˜$Lšœ˜—šž œ œ˜Lš˜š œœœœœ ˜[Lš˜Lšœœ]˜qšœ  ˜LšœN˜NLšœœ˜—Lšœœœ˜Lšœ˜—Lšœ<˜