DIRECTORY Commander USING [CommandProc, Register], CommandTool USING [ArgumentVector, Failed, Parse], FS, GenerateDFClosure, IO, PriorityQueue, Rope; GenSortedClosure: CEDAR PROGRAM IMPORTS Commander, CommandTool, FS, GenerateDFClosure, IO, PriorityQueue, Rope = BEGIN LORA: TYPE = LIST OF REF ANY; ROPE: TYPE = Rope.ROPE; RopeList: TYPE = LIST OF ROPE; STREAM: TYPE = IO.STREAM; Wombat: Commander.CommandProc = { err: STREAM = cmd.err; outName: ROPE _ "[]<>Temp>GenSortedClosure.$"; out: STREAM _ NIL; fx: NAT _ 1; lag: ROPE _ NIL; argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO failed}]; GenerateDir: PROC [dirName: ROPE] RETURNS [head: RopeList _ NIL] = { tail: RopeList _ NIL; eachName: FS.NameProc = { new: RopeList _ LIST[fullFName]; continue _ TRUE; IF tail = NIL THEN head _ new ELSE tail.rest _ new; tail _ new; }; IF Rope.SkipTo[dirName, 0, "*"] = Rope.Length[dirName] THEN dirName _ Rope.Concat[dirName, "*"]; FS.EnumerateForNames[dirName, eachName]; }; GenSortedClosure: PROC [dfName: ROPE] RETURNS [head: RopeList _ NIL] = { tail: RopeList _ NIL; pq: PriorityQueue.Ref _ PriorityQueue.Predict[100, SortPred, NIL]; eachData: EachData _ NEW[EachDataRep _ [pq, err]]; [] _ GenerateDFClosure.GenerateClosureToProc[dfName, err, EachFile, eachData, [messages: TRUE, toFork: IF switches['m] THEN 2 ELSE 0, followImports: NOT switches['s]]]; WHILE NOT PriorityQueue.Empty[pq] DO name: ROPE _ NARROW[PriorityQueue.Remove[pq]]; new: RopeList _ LIST[name]; IF tail = NIL THEN head _ new ELSE tail.rest _ new; tail _ new; ENDLOOP; }; DumpList: PROC [list: RopeList, out: STREAM] = { WHILE list # NIL DO IO.PutRope[out, list.first]; IO.PutChar[out, '\n]; list _ list.rest; ENDLOOP; }; RemoveNames: PROC [list: RopeList, subList: RopeList] RETURNS [RopeList] = { lag: RopeList _ NIL; current: RopeList _ list; WHILE current # NIL AND subList # NIL DO top: ROPE = subList.first; SELECT Rope.Compare[top, current.first, FALSE] FROM less => { subList _ subList.rest; }; equal => { subList _ subList.rest; current _ current.rest; lag.rest _ current; }; greater => { lag _ current; current _ lag.rest; }; ENDCASE; ENDLOOP; RETURN [list]; }; ProcessSwitches: PROC [arg: ROPE] = { sense: BOOL _ TRUE; FOR index: INT IN [0..Rope.Length[arg]) DO char: CHAR _ Rope.Fetch[arg, index]; SELECT char FROM '- => LOOP; '~ => {sense _ NOT sense; LOOP}; IN ['a..'z] => switches[char] _ sense; IN ['A..'Z] => switches[char + ('a-'A)] _ sense; ENDCASE; sense _ TRUE; ENDLOOP; }; switches: PACKED ARRAY CHAR['a..'z] OF BOOL _ ALL[FALSE]; dfName: ROPE _ NIL; directory: ROPE _ NIL; FOR i: NAT IN [1..argv.argc) DO arg: ROPE = argv[i]; IF Rope.Length[arg] = 0 THEN LOOP; IF Rope.Fetch[arg, 0] = '- THEN { ProcessSwitches[arg]; LOOP; }; SELECT TRUE FROM Rope.Equal[arg, "_"] => {}; i+1 < argv.argc AND Rope.Equal[argv[i+1], "_"] => outName _ arg; dfName = NIL => dfName _ arg; directory = NIL => directory _ arg; ENDCASE => GO TO usage; ENDLOOP; out _ FS.StreamOpen[outName, create ! FS.Error => IF error.group # bug THEN {msg _ error.explanation; GO TO failed} ]; IO.PutRope[err, "Output to "]; IO.PutRope[err, outName]; DumpList[RemoveNames[GenerateDir[directory], GenSortedClosure[dfName]], out]; IO.PutChar[err, '\n]; IO.Close[out]; EXITS usage => { result _ $Failure; msg _ "Usage: GenSortedClosure (output _) dfName dirName\n"}; failed => {result _ $Failure}; }; EachData: TYPE = REF EachDataRep; EachDataRep: TYPE = RECORD [pq: PriorityQueue.Ref, err: STREAM]; EachFile: GenerateDFClosure.ActionProc = TRUSTED { eachData: EachData = NARROW[data]; pq: PriorityQueue.Ref = eachData.pq; IF date.format # explicit OR Rope.SkipTo[name, 0, "!"] = Rope.Length[name] THEN { name _ FS.FileInfo[name ! FS.Error => IF error.group # bug THEN { IO.PutRope[eachData.err, "\n"]; IO.PutRope[eachData.err, error.explanation]; GO TO bogus; } ].fullFName; }; PriorityQueue.Insert[pq, name]; EXITS bogus => {}; }; SortPred: PriorityQueue.SortPred = { xx: ROPE = NARROW[x]; yy: ROPE = NARROW[y]; RETURN [Rope.Compare[xx, yy, FALSE] = less]; }; Commander.Register[key: "///Commands/GenSortedClosure", proc: Wombat, doc: "GenSortedClosure (output _) dfName dirName\n -m: multiple processes (2 helpers)\n -s: shallow (don't follow imports)"]; END. .GenSortedClosure.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Russ Atkinson, July 9, 1984 11:21:52 pm PDT Russ Atkinson (RRA) June 25, 1985 2:43:01 pm PDT [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...] ... returns a list of names provided by the enumeration of the given pattern (no error handling if the pattern is illegal). [fullFName: ROPE] RETURNS [continue: BOOL] ... destructively removes names from the list that are in the subList. No alteration is made to the subList. The name from the subList is less than the current name from the list, so just remove the name from the subList. The list should not be touched. The name from the subList is equal to the name from the list, so splice out the current element from the list. Also advance to the next element in the subList. The name from the subList is greater than the name from the list, so just leave the name from the list as it is, and advance to the next list element. Each argument can either be a switch specification or a genuine argument to be processed. The first argument (argv[0]) is not examined, because by convention it is the name of the command as given by the user. Ignore null arguments (it is not easy to generate them, even). This argument sets switches for the remaining patterns. By convention, switches are normally "sticky", in that they stay set until explicitly changed. Full name not present so get it from the server (if possible) [x: Item, y: Item, data: REF] RETURNS [BOOL] Ê=˜codešœ™Kšœ Ïmœ1™™>—šžœžœ˜!Kšœ—™—Kšœ˜Kšžœ˜Kšœ˜—šžœžœž˜Kšœ˜Kšœžœ-˜@Kšœ žœ˜Kšœ žœ˜#Kšžœžœžœ˜—Kšžœ˜K˜—šœžœ˜#Kš œžœ žœžœžœžœ˜OK˜—Kšžœ˜Kšžœ˜KšœM˜MKšžœ˜Kšžœ ˜šž˜šœ ˜ Kšœ˜Kšœ=˜=—Kšœ˜—K˜K˜—Kšœ žœžœ ˜!šœ žœžœžœ˜@K˜—šœ)žœ˜2Kšœžœ˜"Kšœ$˜$šžœžœ/žœ˜QKšœ=™=šœžœ˜šœžœ žœžœ˜)Kšžœ˜Kšžœ*˜,Kšžœžœ˜ K˜—Kšœ ˜ —K˜—Kšœ˜Kšžœ ˜K˜K˜—šœ$˜$Kšœžœžœžœ™,Kšœžœžœ˜Kšœžœžœ˜Kšžœžœ ˜,K˜K˜—KšœÅ˜ÅK˜K˜Kšžœ˜K˜šœ˜K™——…—À+