-- 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.