-- MungeStats.mesa -- Edited by Sweet, February 3, 1981 11:06 AM DIRECTORY AltoFileDefs, InlineDefs, IODefs, ImageDefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs; Munge: PROGRAM IMPORTS ImageDefs, InlineDefs, IODefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs = BEGIN OPEN IODefs, StringDefs, StreamDefs; in1, in2: StreamHandle; line1: STRING ← [200]; line2: STRING ← [200]; token1: STRING ← [40]; token2: STRING ← [40]; beforeFile: STRING ← [40]; afterFile: STRING ← [40]; n1, n2: CARDINAL; commandStream: StreamHandle; SetUpCommands: PROCEDURE = BEGIN cfa: POINTER TO AltoFileDefs.CFA ← MiscDefs.CommandLineCFA[]; cfile: SegmentDefs.FileHandle ← SegmentDefs.InsertFile[@cfa.fp,Read]; commandStream ← NIL; commandStream ← CreateByteStream[cfile,Read ! SegmentDefs.InvalidFP => CONTINUE]; IF commandStream # NIL THEN BEGIN JumpToFA[commandStream,@cfa.fa]; WHILE commandStream.get[commandStream ! StreamError => GOTO nocommands] <= SP DO NULL ENDLOOP; SetIndex[commandStream,ModifyIndex[GetIndex[commandStream],-1]]; EXITS nocommands => BEGIN commandStream.destroy[commandStream]; commandStream ← NIL END; END; END; ReadName: PROCEDURE [s: STRING] = BEGIN c: CHARACTER; IF commandStream = NIL THEN ReadID[s] ELSE BEGIN s.length ← 0; DO IF (c←commandStream.get[commandStream ! StreamError => GOTO endoffile]) <= SP THEN BEGIN IF s.length # 0 THEN RETURN END ELSE BEGIN StringDefs.AppendChar[s,c]; WriteChar[c] END; REPEAT endoffile => BEGIN commandStream.destroy[commandStream]; commandStream ← NIL END; ENDLOOP; END; END; ReadLines: PROC RETURNS [BOOLEAN] = BEGIN line1.length ← n1 ← 0; line2.length ← n2 ← 0; DO line1[n1] ← in1.get[in1 ! StreamError => EXIT]; IF line1[n1] = CR THEN IF n1 = 0 THEN LOOP ELSE EXIT; n1 ← n1 + 1; ENDLOOP; line1.length ← n1; DO line2[n2] ← in2.get[in2 ! StreamError => EXIT]; IF line2[n2] = CR THEN IF n2 = 0 THEN LOOP ELSE EXIT; n2 ← n2 + 1; ENDLOOP; line2.length ← n2; RETURN [n1*n2 # 0]; END; Scan: PROC = BEGIN token1.length ← 0; WHILE n1 < line1.length AND (line1[n1] = SP OR line1[n1] = TAB) DO n1 ← n1 + 1; ENDLOOP; WHILE n1 < line1.length AND ~(line1[n1] = SP OR line1[n1] = TAB) DO AppendChar[token1, line1[n1]]; n1 ← n1 + 1; ENDLOOP; token2.length ← 0; WHILE n2 < line2.length AND (line2[n2] = SP OR line2[n2] = TAB) DO n2 ← n2 + 1; ENDLOOP; WHILE n2 < line2.length AND ~(line2[n2] = SP OR line2[n2] = TAB) DO AppendChar[token2, line2[n2]]; n2 ← n2 + 1; ENDLOOP; END; sourceChars, obj1, obj2: LONG INTEGER; tSource, tObj1, tObj2, dSource, dObj1, dObj2: LONG INTEGER ← 0; Decimal7: NumberFormat = [base: 10, unsigned: FALSE, zerofill: FALSE, columns: 7]; Decimal8: NumberFormat = [base: 10, unsigned: FALSE, zerofill: FALSE, columns: 8]; Decimal5: NumberFormat = [base: 10, unsigned: FALSE, zerofill: FALSE, columns: 5]; Decimal2Z: NumberFormat = [base: 10, unsigned: TRUE, zerofill: TRUE, columns: 2]; RJ: PROC [s: STRING, cols: CARDINAL] = BEGIN THROUGH (s.length..cols] DO WriteChar[SP] ENDLOOP; WriteString[s]; END; LJ: PROC [s: STRING, cols: CARDINAL] = BEGIN WriteString[s]; THROUGH (s.length..cols] DO WriteChar[SP] ENDLOOP; END; WriteLongNumber: PROC [n: LONG INTEGER, fmt: NumberFormat] = BEGIN s: STRING = [20]; c: CARDINAL; f: CHARACTER = IF fmt.zerofill THEN '0 ELSE SP; AppendLongNumber[s, (IF fmt.unsigned THEN n ELSE ABS[n]), fmt.base]; c ← s.length; IF ~fmt.unsigned AND n < 0 THEN BEGIN c ← c + 1; IF fmt.zerofill THEN WriteChar['-]; END; THROUGH (c..fmt.columns] DO WriteChar[SP] ENDLOOP; IF ~fmt.unsigned AND n < 0 AND ~fmt.zerofill THEN WriteChar['-]; WriteString[s]; END; Results: PROC [sou, c1, c2: LONG INTEGER] = BEGIN delta, t: LONG INTEGER; it: INTEGER; WriteLongNumber[sou, Decimal8]; WriteLongNumber[c1, Decimal8]; WriteLongNumber[c2, Decimal8]; delta ← c2 - c1; WriteLongNumber[delta, Decimal7]; t ← (delta * 10000) / c1; it ← InlineDefs.LowHalf[t]; IF it = 0 THEN RJ["0", 5] ELSE BEGIN IF it IN (-100..0) THEN RJ["-", 5] ELSE WriteNumber[it / 100, Decimal5]; WriteChar['.]; WriteNumber[ABS[it] MOD 100, Decimal2Z]; END; IF c1 / 512 # c2 / 512 THEN WriteChar['*]; WriteChar[CR]; END; Dashes: PROC [s: STRING] RETURNS [BOOLEAN] = BEGIN d: CARDINAL ← 0; FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '- THEN d ← d + 1 ELSE d ← 0; IF d = 3 THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; DoIt: PROC = BEGIN DO BEGIN tSource ← 0; tObj1 ← 0; tObj2 ← 0; dSource ← 0; dObj1 ← 0; dObj2 ← 0; WriteChar[CR]; WriteChar[CR]; WriteChar[CR]; WriteString["file 1: "L]; ReadName[beforeFile]; IF beforeFile.length = 0 THEN ImageDefs.StopMesa[]; in1 ← NewByteStream[beforeFile, Read ! SegmentDefs.FileNameError => GO TO cantFind]; WriteChar[CR]; WriteString["file 2: "L]; ReadName[afterFile]; in2 ← NewByteStream[afterFile, Read ! SegmentDefs.FileNameError => { in1.destroy[in1]; GO TO cantFind}]; WriteChar[CR]; WriteChar[CR]; LJ["MODULE", 35]; RJ["source", 8]; RJ["obj/1", 8]; RJ["obj/2", 8]; RJ["diff", 7]; RJ["%", 5]; WriteChar[CR]; WriteChar[CR]; DO IF ~ReadLines[] THEN GO TO badFormat; IF Dashes[line1] THEN EXIT; ENDLOOP; WHILE ReadLines[] DO IF Dashes[line1] OR Dashes[line2] THEN EXIT; n1 ← n2 ← 0; Scan[]; IF ~EqualStrings[token1, token2] THEN GO TO unequalNames; LJ[token1, 35]; Scan[]; sourceChars ← StringToLongNumber[token1, 10]; Scan[]; Scan[]; obj1 ← StringToLongNumber[token1, 10]; obj2 ← StringToLongNumber[token2, 10]; Results[sourceChars, obj1, obj2]; tSource ← tSource + sourceChars; tObj1 ← tObj1 + obj1; tObj2 ← tObj2 + obj2; IF obj1 # obj2 THEN BEGIN dSource ← dSource + sourceChars; dObj1 ← dObj1 + obj1; dObj2 ← dObj2 + obj2; END; REPEAT unequalNames => { WriteChar[CR]; WriteString[token1]; WriteString[" (from 1) and "]; WriteString[token2]; WriteLine[" (from 2) should be equal"]}; ENDLOOP; in1.destroy[in1]; in2.destroy[in2]; LJ["<total modules>", 35]; Results[tSource, tObj1, tObj2]; LJ["<modules with change>", 35]; Results[dSource, dObj1, dObj2]; beforeFile.length ← 0; StringDefs.AppendString[beforeFile, afterFile]; EXITS badFormat => WriteLine[" can't find start of stats"]; cantFind => WriteLine[" file not found"]; END; ENDLOOP; END; SetUpCommands[]; DoIt[]; END.