DIRECTORY BasicTime USING [GMT, minutesPerHour, MonthOfYear, nullGMT, OutOfRange, Period, TimeParametersNotKnown, Unpack, Unpacked, unspecifiedZone, Zone], Commander USING [CommandProc, Register], CommanderOps USING [NextArgument], IO, List USING [AList, PutAssoc], PFS USING [EnumerateForInfo, Error, ErrorGroup, FileType, InfoProc, PathFromRope, RopeFromPath], PFSNames USING [Compare, ComponentCount, Equal, Parent, PATH, SubName], PriorityQueue USING [Create, Insert, Item, Ref, Remove, Size, SortPred], Process USING [CheckForAbort], ProcessProps USING [AddPropList, GetProp], Rope; DListImpl: CEDAR PROGRAM IMPORTS BasicTime, Commander, CommanderOps, IO, List, PFS, PFSNames, PriorityQueue, Process, ProcessProps, Rope = BEGIN GMT: TYPE = BasicTime.GMT; LORA: TYPE = LIST OF REF ANY; ROPE: TYPE = Rope.ROPE; PATH: TYPE = PFSNames.PATH; STREAM: TYPE = IO.STREAM; DListCommandProc: Commander.CommandProc = { EachFileInfo: PFS.InfoProc = { item: FileItem ฌ NIL; continue ฌ TRUE; Process.CheckForAbort[]; item ฌ NEW[FileItemRep ฌ [fullFName, attachedTo, uniqueID.egmt.gmt, bytes, fileType]]; filesSeen ฌ filesSeen + 1; IF bytes > 0 THEN bytesTotal ฌ bytesTotal + bytes; PriorityQueue.Insert[pq, item]; }; PrintOneFile: PROC [item: FileItem] = { oldLag: PATH ฌ lagPrefix; printName: ROPE ฌ PFS.RopeFromPath[item.fullUName]; Process.CheckForAbort[]; SetLagPrefix[item.fullUName]; IF oldLag # lagPrefix THEN { IO.PutRope[out, PFS.RopeFromPath[lagPrefix]]; IO.PutChar[out, '\n]; }; printName ฌ PFS.RopeFromPath[PFSNames.SubName[item.fullUName, lagPrefixLen]]; IO.PutRope[out, " "]; IO.PutF1[out, "%-24g ", [rope[printName]] ]; IF item.created = BasicTime.nullGMT THEN IO.PutRope[out, "??"] ELSE DateToStream[out, [explicit, item.created] ]; IO.PutChar[out, '\n]; }; AddFile: PROC [pattern: PATH, allVersions: BOOL] = { Do: PROC [] ~ { ENABLE PFS.Error => IF error.group # $bug THEN { IO.PutRope[cmd.err, " -- "]; IO.PutRope[cmd.err, error.explanation]; IO.PutRope[cmd.err, "\n"]; GO TO err}; patternsTried ฌ patternsTried + 1; PFS.EnumerateForInfo[pattern, EachFileInfo]; EXITS err => {IO.PutRope[cmd.err, "\n"]; RETURN}; }; wDir: ROPE ~ NARROW[ProcessProps.GetProp[$WorkingDirectory]]; newProp: List.AList ~ List.PutAssoc[$WDir, PFS.PathFromRope[wDir], NIL]; ProcessProps.AddPropList[newProp, Do]; }; SetLagPrefix: PROC [fileName: PATH] = { newPrefix: PATH ฌ IF fileName# NIL THEN PFSNames.Parent[fileName] ELSE NIL; IF lagPrefix # NIL THEN { IF PFSNames.Equal[lagPrefix, newPrefix] THEN RETURN; }; lagPrefix ฌ newPrefix; lagPrefixLen ฌ PFSNames.ComponentCount[newPrefix]; }; AddSortOption: PROC [option: ATOM] = { new: LORA ฌ LIST[option]; IF sortDataTail = NIL THEN sortData ฌ new ELSE sortDataTail.rest ฌ new; sortDataTail ฌ new; }; out: STREAM = cmd.out; lagPrefix: PATH ฌ NIL; lagPrefixLen: INT ฌ 0; patternsTried, filesSeen, bytesTotal: INT ฌ 0; complexSorting: BOOL ฌ TRUE; sortData: LORA ฌ NIL; sortDataTail: LORA ฌ NIL; pq: PriorityQueue.Ref; AddSortOption[$MoreRecent]; pq ฌ PriorityQueue.Create[SortPred, sortData]; DO arg: ROPE = CommanderOps.NextArgument[cmd]; IF arg = NIL THEN EXIT; AddFile[PFS.PathFromRope[arg ! PFS.Error => IF error.group # $bug THEN { IO.PutRope[cmd.err, " -- "]; IO.PutRope[cmd.err, error.explanation]; IO.PutRope[cmd.err, "\n"]; GO TO failed}], FALSE]; ENDLOOP; IF filesSeen > 0 THEN { out: IO.STREAM ~ IO.ROS[]; IF pq # NIL THEN { lagName: PATH ฌ NIL; THROUGH [0..PriorityQueue.Size[pq]) DO item: FileItem = NARROW[PriorityQueue.Remove[pq]]; PrintOneFile[item]; ENDLOOP; }; IO.PutF1[out, "-- %g files", [integer[filesSeen]] ]; IF bytesTotal > 0 THEN IO.PutF1[out, ", %g total bytes", [integer[bytesTotal]] ]; IO.PutChar[out, '\n]; msg ฌ IO.RopeFromROS[out]; }; EXITS failed => {result ฌ $Failure}; }; FileItem: TYPE = REF FileItemRep; FileItemRep: TYPE = RECORD [fullUName, attachedTo: PATH, created: GMT, bytes: INT, fileType: PFS.FileType]; SortPred: PriorityQueue.SortPred = { xx: FileItem = NARROW[x]; yy: FileItem = NARROW[y]; options: LORA = NARROW[data]; FOR each: LORA ฌ options, each.rest WHILE each # NIL DO SELECT each.first FROM $MoreRecent => { IF xx.created = yy.created THEN LOOP; RETURN [BasicTime.Period[xx.created, yy.created] < 0]; }; $LessRecent => { IF xx.created = yy.created THEN LOOP; RETURN [BasicTime.Period[xx.created, yy.created] > 0]; }; $Larger => { IF xx.bytes = yy.bytes THEN LOOP; RETURN [xx.bytes > yy.bytes]; }; $Smaller => { IF xx.bytes = yy.bytes THEN LOOP; RETURN [xx.bytes < yy.bytes]; }; ENDCASE; ENDLOOP; RETURN [PFSNames.Compare[xx.fullUName, yy.fullUName, FALSE] = less]; }; -- Stolen from DFUtilitiesImpl DateFormat: TYPE = {explicit, omitted, greaterThan, notEqual}; Date: TYPE = RECORD [ format: DateFormat ฌ $omitted, gmt: GMT ฌ BasicTime.nullGMT ]; DateToStream: PROC [s: STREAM, date: Date] = { SELECT date.format FROM $explicit => { months: ROPE = "JanFebMarAprMayJunJulAugSepOctNovDec"; up: BasicTime.Unpacked = BasicTime.Unpack[date.gmt ! BasicTime.OutOfRange, BasicTime.TimeParametersNotKnown => GO TO noDate]; ConvertZone: PROC = { dst: BOOL = up.dst = yes; SELECT up.zone FROM 0 => IF ~dst THEN s.PutRope["GMT"]; NAT[5*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "EDT" ELSE "EST"]; NAT[6*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "CDT" ELSE "CST"]; NAT[7*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "MDT" ELSE "MST"]; NAT[8*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "PDT" ELSE "PST"]; ENDCASE => s.PutF["%g%02d%02d", [character[IF up.zone < 0 THEN '- ELSE '+]], [cardinal[up.zone.ABS/BasicTime.minutesPerHour]], [cardinal[up.zone.ABS MOD BasicTime.minutesPerHour]] ] }; s.PutF["%02d-%g-%02d ", [cardinal[up.day]], [rope[months.Substr[start: up.month.ORD*3, len: 3]]], [cardinal[up.year MOD 100]] ]; s.PutF["%02d:%02d:%02d ", [cardinal[up.hour]], [cardinal[up.minute]], [cardinal[up.second]]]; ConvertZone[]; }; $notEqual => s.PutRope["~="]; $greaterThan => s.PutChar['>]; ENDCASE; EXITS noDate => NULL; }; Commander.Register["DList", DListCommandProc, "sort a list of file names (not a pattern) by date"]; END. ธ DListImpl.mesa Copyright ำ 1989, 1990, 1991, 1993 by Xerox Corporation. All rights reserved. Carl Hauser, August 24, 1989 4:43:16 pm PDT Michael Plass, November 25, 1991 1:19 pm PST Doug Wyatt, April 15, 1992 12:28 pm PDT Last tweaked by Mike Spreitzer on February 7, 1990 12:12:30 pm PST Chauser, September 28, 1990 11:16 am PDT Willie-s, March 18, 1993 7:45 pm PST taken from PFSCommandsImpl.ListCommandProc DList Command [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...] item: REF [fullUName, attachedTo: PATH, created: GMT, bytes: INT, keep: CARDINAL, PFS.FileType] Factor out the directories In these cases it is better to enumerate for info, to reduce server traffic ... sets the lagging prefix from the given file name, which is presumed to be syntactically correct, although it need not be complete. A file name without a prefix will set the lagPrefix to NIL. We also enforce lagPrefixLen = Rope.Length[lagPrefix] at exit, assuming that no other routine sets lagPrefix. do we have a new prefix? We have a new lagging prefix, so scan backwards for the LAST directory the argument is assumed to be a file name. [x: Item, y: Item, data: REF] RETURNS [BOOL] Utilities 'gmt' is valid only if dateFormat = $explicit. (We don't use a variant record because it complicates the client's life too much (i.e., the compiler is unnecessarily picky about assignments involving variant records that aren't REF-containing).) Note: Dates returned by ParseFromStream are guaranteed to have `gmt' = nullGMT if `format' ~= $explicit. The other procedures of this interface ignore the 'gmt' field if 'format' ~= $explicit. Initialization ส •NewlineDelimiter –(cedarcode) style™code™Kšœ ฯeœC™NK™+K™,K™'K™BK™(K™$K™*K˜šฯk ˜ Kšœ žœžœ}˜‘Kšœ žœ˜(Kšœ žœ˜"Kšžœ˜Kšœžœ˜KšžœžœW˜`Kšœ žœ*žœ ˜GKšœžœ5˜HKšœžœ˜Kšœ žœ˜*K˜K˜——šะln œžœž˜Kšžœ%žœžœ6˜oKšœž˜K˜Kšžœžœ žœ˜Kš žœžœžœžœžœžœ˜Kšžœžœžœ˜Kšžœžœ žœ˜Kšžœžœžœžœ˜—head™ šฯn œ˜+š œžœ žœžœžœžœ™:Kšœžœžœ™G—š  œžœ ˜Kšœžœ˜Kšœ žœ˜Kšœ˜KšœžœL˜VK˜Kšžœ žœ!˜2K˜K˜K˜—š  œžœ˜'Kš œžœžœ žœ žœžœžœ ™_Kšœžœ ˜Kšœ žœžœ˜3Kšœ˜K˜Kšœ™Kšœ˜šžœžœ˜Kšžœžœ˜-Kšžœœ˜K˜—Kšœ žœ>˜MKšžœ˜K˜Kšžœ0˜2šžœ!˜#Kšžœžœ˜Kšžœ.˜2—Kšžœ˜K˜—š   œžœ žœžœ˜4š œžœ˜šžœžœ žœžœ˜0Kšžœ˜Kšžœ%˜'K˜Kšžœžœ˜ —K˜"šžœ)˜,K™K—šž˜Kšœžœžœ˜+—K˜—Kšœžœžœ*˜=Kšœ+žœžœ˜HKšœ&˜&K˜—š  œžœ žœ˜'Kšœฟžœp™ฒKš œ žœžœ žœžœžœžœ˜Kšžœ žœžœ˜Kšœ™Kšžœ&žœžœ˜4K˜—Kšœ8žœ ™FKšœ˜Kšœ2˜2Kšœ˜—š  œžœ žœ˜&Kšœžœžœ ˜Kšžœžœžœžœ˜GKšœ˜K˜—Kšœžœ ˜Kšœ žœžœ˜Kšœžœ˜Kšœ&žœ˜.Kšœžœžœ˜Kšœ žœžœ˜Kšœžœžœ˜K˜K˜˜.K˜—šž˜Kšœžœ"˜+Kšžœžœžœžœ˜K™*š œžœžœ žœžœ˜HKšžœ˜Kšžœ%˜'K˜Kšžœžœ žœ˜—Kšžœ˜—šžœžœ˜Kš œžœžœžœžœ˜šžœžœžœ˜Kšœ žœžœ˜šžœž˜&Kšœžœ˜2Kšœ˜Kšžœ˜—K˜—Kšžœ2˜4Kšžœžœžœ8˜QKšžœ˜Kšœžœ˜K˜—šž˜Kšœ˜—K˜K˜Kšœ žœžœ ˜!š œ žœžœžœ žœ žœ žœ ˜kK˜—š œ˜$Kšœžœžœžœ™,Kšœžœ˜Kšœžœ˜Kšœ žœžœ˜š žœžœžœžœž˜7šžœ ž˜˜Kšžœžœžœ˜%Kšžœ0˜6K˜—˜Kšžœžœžœ˜%Kšžœ0˜6K˜—˜ Kšžœžœžœ˜!Kšžœ˜K˜—˜ Kšžœžœžœ˜!Kšžœ˜K˜—Kšžœ˜—Kšžœ˜—Kšžœ/žœ ˜DK˜K˜———™ ™K˜K˜Kšœ žœ.˜>šœžœžœ˜Kšœ˜Kšœžœ˜Kšœ๕™๕Kšœ˜K™ยK˜—š  œžœžœ˜.šžœ ž˜šœ˜Kšœžœ*˜6˜2Kšœ<žœžœ ˜J—š  œžœ˜Kšœžœ˜šžœ ž˜Kšœžœžœ˜#Kšžœ*žœžœžœ˜KKšžœ*žœžœžœ˜KKšžœ*žœžœžœ˜KKšžœ*žœžœžœ˜Kšžœ˜ šœ˜Kšœ žœ žœžœ˜,Kšœžœ˜1Kšœžœžœ˜4K˜———K˜—šœ˜Kšœ˜Kšœ$žœ˜5Kšœžœ˜K˜—šœ˜KšœC˜C—Kšœ˜K˜—Kšœ˜Kšœ˜Kšžœ˜—šž˜Kšœ žœ˜—K˜———™K˜cK˜—Kšžœ˜—…—ฎ'„