<> <> <> DIRECTORY Basics, Commander, CommandTool, CountedVM, FS, FSBackdoor, IO, MessageWindow USING [Append], Process, Rope, VersionMap; CountReleaseSize: CEDAR PROGRAM IMPORTS Basics, Commander, CommandTool, CountedVM, FS, FSBackdoor, IO, MessageWindow, Process, Rope, VersionMap = BEGIN CARD: TYPE = Basics.CARD; Map: TYPE = VersionMap.Map; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; CountCommand: Commander.CommandProc = { InnerCount: PROC [name: ROPE, match: ROPE _ NIL] = { files: INT _ 0; pages: INT _ 0; ifsPages: INT _ 0; totalBytes: INT _ 0; map: Map _ VersionMap.RestoreMapFromFile[name]; IF match = NIL THEN IO.PutF[cmd.out, " Processing: %g\n", [rope[name]]] ELSE IO.PutF[cmd.out, " Processing: %g (%g)\n", [rope[name]], [rope[match]] ]; FOR i: INT IN [0..VersionMap.Length[map]) DO eachName: ROPE _ VersionMap.FetchName[map, i]; IF match = NIL OR Rope.Match[match, eachName, FALSE] THEN { bytes: INT _ FS.FileInfo[name: eachName, remoteCheck: FALSE ! FS.Error => IF error.group # bug THEN { IO.PutF[cmd.out, "File not found: %g\n", [rope[eachName]]]; LOOP; }].bytes; totalBytes _ totalBytes + bytes; pages _ pages + (bytes+511) / 512; ifsPages _ ifsPages + (bytes+2047) / 2048; files _ files + 1; MessageWindow.Append[ msg _ IO.PutFR[ " files: %g, bytes: %g, pages: %g, ifsPages: %g", [integer[files]], [integer[totalBytes]], [integer[pages]], [integer[ifsPages]]], TRUE]; }; ENDLOOP; IO.PutF[cmd.out, " cmd.out: %g, bytes: %g, pages: %g, ifsPages: %g\n", [integer[files]], [integer[totalBytes]], [integer[pages]], [integer[ifsPages]] ]; }; InnerCount["CedarSource.VersionMap", "*.mesa*"]; InnerCount["CedarSource.VersionMap"]; InnerCount["CedarSymbols.VersionMap"]; }; CountLinesCommand: Commander.CommandProc = { <<[cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL]>> <> out: STREAM = cmd.out; switches: PACKED ARRAY CHAR['a..'z] OF BOOL _ ALL[FALSE]; 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; }; ProcessArgument: PROC [arg: ROPE] = { bytes, pos, lines, empties, charsPerLine: CARD _ 0; Process.CheckForAbort[]; [bytes, pos, lines, empties] _ CountThingsInFile[arg]; argsProcessed _ argsProcessed + 1; totalChars _ totalChars + pos; totalLines _ totalLines + lines; IF lines # 0 THEN charsPerLine _ (pos + lines/2) / lines; IO.PutF1[cmd.out, "%g\n", [rope[arg]] ]; IO.PutF[cmd.out, " chars: %g, lines: %g, lineLen: %g", [integer[pos]], [integer[lines]], [integer[charsPerLine]] ]; IO.PutF[cmd.out, ", bytes: %g, empties: %g\n", [integer[bytes]], [integer[empties]] ]; }; totalChars: CARD _ 0; totalLines: CARD _ 0; argsProcessed: NAT _ 0; <<# of arguments processed>> argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd, starExpand: TRUE ! CommandTool.Failed => {msg _ errorMsg; GO TO failed}]; <> FOR i: NAT IN [1..argv.argc) DO <> arg: ROPE = CommandTool.FileWithSearchRules[argv[i], ".mesa", cmd]; Process.CheckForAbort[]; <> IF Rope.Length[arg] = 0 THEN LOOP; <> IF Rope.Fetch[arg, 0] = '- THEN { <> ProcessSwitches[arg]; LOOP; }; ProcessArgument[arg]; <> ENDLOOP; IO.PutF[cmd.out, "Total - files: %g, chars: %g, lines: %g, lineLen: %g\n", [integer[argsProcessed]], [integer[totalChars]], [integer[totalLines]], [integer[(totalChars+totalLines/2) / totalLines]] ]; EXITS failed => {result _ $Failure}; }; CountReleaseLinesCommand: Commander.CommandProc = { <<[cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL]>> <> out: STREAM = cmd.out; switches: PACKED ARRAY CHAR['a..'z] OF BOOL _ ALL[FALSE]; 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; }; ProcessArgument: PROC [arg: ROPE] = { bytes, pos, lines, empties, charsPerLine: CARD _ 0; Process.CheckForAbort[]; [bytes, pos, lines, empties] _ CountThingsInFile[arg]; argsProcessed _ argsProcessed + 1; totalChars _ totalChars + pos; totalLines _ totalLines + lines; IF lines # 0 THEN charsPerLine _ (pos + lines/2) / lines; IO.PutF1[cmd.out, "%g\n", [rope[arg]] ]; IO.PutF[cmd.out, " chars: %g, lines: %g, lineLen: %g", [integer[pos]], [integer[lines]], [integer[charsPerLine]] ]; IO.PutF[cmd.out, ", bytes: %g, empties: %g\n", [integer[bytes]], [integer[empties]] ]; }; totalChars: CARD _ 0; totalLines: CARD _ 0; argsProcessed: NAT _ 0; <<# of arguments processed>> argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd, starExpand: TRUE ! CommandTool.Failed => {msg _ errorMsg; GO TO failed}]; <> FOR i: NAT IN [1..argv.argc) DO <> arg: ROPE = CommandTool.FileWithSearchRules[argv[i], ".mesa", cmd]; Process.CheckForAbort[]; <> IF Rope.Length[arg] = 0 THEN LOOP; <> IF Rope.Fetch[arg, 0] = '- THEN { <> ProcessSwitches[arg]; LOOP; }; ProcessArgument[arg]; <> ENDLOOP; IO.PutF[cmd.out, "Total - files: %g, chars: %g, lines: %g, lineLen: %g\n", [integer[argsProcessed]], [integer[totalChars]], [integer[totalLines]], [integer[(totalChars+totalLines/2) / totalLines]] ]; EXITS failed => {result _ $Failure}; }; CountThingsInFile: PROC [name: ROPE] RETURNS [bytes, pos, lines, empties: CARD _ 0] = TRUSTED { vm: CountedVM.Handle _ NIL; file: FS.OpenFile _ FS.Open[name: name, remoteCheck: FALSE ! FS.Error => GO TO fail]; tempName: ROPE _ NIL; noteFound: FSBackdoor.NameProc = TRUSTED { <<[fullGName: ROPE] RETURNS [continue: BOOLEAN]>> tempName _ fullGName; continue _ TRUE; }; FSBackdoor.EnumerateCacheForNames[noteFound, NIL, name]; IF tempName = NIL THEN { tempName _ FS.Copy[from: name, to: "///Temp/Count.temp$" ! FS.Error => CONTINUE; ]; }; file _ FS.Open[name: tempName, remoteCheck: FALSE ! FS.Error => GO TO fail]; { ENABLE UNWIND => { IF vm # NIL THEN CountedVM.Free[vm]; FS.Close[file]; }; Buffer: TYPE = PACKED ARRAY [0..charsPerBuffer) OF CHAR; charsPerBuffer: NAT = 16; ptr: LONG POINTER TO Buffer _ NIL; lag: CHAR _ '\n; GetChar: PROC [peek: BOOL _ FALSE] RETURNS [c: CHAR] = TRUSTED INLINE { mod: [0..charsPerBuffer) _ Basics.LowHalf[pos] MOD charsPerBuffer; IF pos >= bytes THEN RETURN [0C]; c _ ptr[mod]; IF peek THEN RETURN; pos _ pos + 1; IF mod = charsPerBuffer - 1 THEN { ptr _ ptr + SIZE[Buffer]; pos _ pos + 1; }; }; bytes _ FS.GetInfo[file].bytes; vm _ CountedVM.SimpleAllocate[(bytes + Basics.bytesPerWord-1)/Basics.bytesPerWord]; ptr _ vm.pointer; FS.Read[file, 0, vm.interval.count, ptr]; DO c: CHAR _ GetChar[]; SELECT c FROM '\n => IF lag = '\n THEN empties _ empties + 1 ELSE lines _ lines + 1; 0C => IF lag = 0C THEN EXIT; ENDCASE; lag _ c; ENDLOOP; CountedVM.Free[vm]; FS.Close[file]; }; EXITS fail => RETURN; }; Commander.Register["CountReleaseSize", CountCommand]; Commander.Register["CountLines", CountLinesCommand]; END.