-- File: PerfCommon.mesa   last edited by
-- Sandman on September 15, 1980  4:14 PM
-- Karlton on Jun 23, 1980 3:19 PM

DIRECTORY
  BP USING [BBHandle, Conditionalize, EnumerateBBs, Fail],
  Inline USING [COPY],
  PerfCommonOps USING [logSW, Number],
  Put USING [Char, Line],
  String USING [AppendChar, AppendLongNumber],
  Window USING [Handle];

PerfCommon: PROGRAM
  IMPORTS BP, Inline, Put, String, PerfCommonOps EXPORTS PerfCommonOps =PUBLIC

  BEGIN

  Zero: PROC [p: POINTER, l: CARDINAL] = {
    IF l # 0 THEN {p↑ ← 0; Inline.COPY[from: p, to: p + 1, nwords: l - 1]}};

  handle: Window.Handle ← PerfCommonOps.logSW;
  Number: TYPE = PerfCommonOps.Number;

  ConditionBreaks: PROCEDURE =
    BEGIN
    gotThemAll: BOOLEAN ← TRUE;
    Proc: PROCEDURE [bb: BP.BBHandle] RETURNS [done: BOOLEAN] = {
      BP.Conditionalize[bb, "1"L]; RETURN[FALSE]};
    [] ← BP.EnumerateBBs[Proc ! BP.Fail => {gotThemAll ← FALSE; CONTINUE}];
    IF gotThemAll THEN Put.Line[handle, "Conditionalized breaks"L];
    RETURN
    END;

  AverageTime: PROCEDURE [time, count: Number, conversion: LONG CARDINAL] RETURNS [Number] =
    BEGIN
    PreventOverflow: LONG CARDINAL = LAST[LONG CARDINAL]/conversion;
    WHILE time > PreventOverflow DO count ← count/4; time ← time/4; ENDLOOP;
    time ← IF count = 0 THEN 0 ELSE ((time*conversion)/100)/count;
    RETURN[time];
    END;


  WriteConvertedTicksToMs: PROCEDURE [
    ticks: Number, conversion: LONG CARDINAL, columns: CARDINAL ← 0] =
    BEGIN
    s: STRING ← [24];
    PreventOverflow: LONG CARDINAL = LAST[LONG CARDINAL]/conversion;
    IF ticks < PreventOverflow THEN WriteTime[(ticks*conversion)/100, columns]
    ELSE {
      i: CARDINAL ← 1;
      DO ticks ← ticks / 10; IF ticks < PreventOverflow THEN EXIT; i ← i + 1; ENDLOOP;
      String.AppendLongNumber[s, (ticks*conversion)/100, 10];
      THROUGH [0..i) DO String.AppendChar[s, '0]; ENDLOOP;
      WriteTimeString[s, columns]};
    RETURN
    END;

  MaxPercent: LONG CARDINAL = LAST[LONG CARDINAL]/10000;

  WritePercent: PROCEDURE [count, total: Number, columns: CARDINAL ← 0] =
    BEGIN
    s: STRING ← [20];
    whole: LONG INTEGER;
    l, i: CARDINAL;
    WHILE count > MaxPercent DO count ← count/4; total ← total/4; ENDLOOP;
    whole ← IF total = 0 THEN 0 ELSE (count*10000)/total;
    String.AppendLongNumber[s, whole, 10];
    IF (l ← s.length) = 1 THEN BEGIN s[1] ← s[0]; s[0] ← '0; l ← 2; END;
    FOR i IN (l..columns - 1] DO Put.Char[handle, ' ]; ENDLOOP;
    FOR i IN [0..l - 2) DO Put.Char[handle, s[i]]; ENDLOOP;
    Put.Char[handle, '.];
    FOR i IN [l - 2..l) DO Put.Char[handle, s[i]]; ENDLOOP;
    END;

  WriteTime: PROCEDURE [time: Number, columns: CARDINAL ← 0] =
    BEGIN
    s: STRING ← [20];
    String.AppendLongNumber[s, time, 10];
    WriteTimeString[s, columns];
    RETURN
    END;

  WriteTimeString: PROCEDURE [s: STRING, columns: CARDINAL ← 0] =
    BEGIN
    i, nPuncuation: CARDINAL;
    nPuncuation ← MIN[(s.length - 1)/3, 3];
    FOR i IN (s.length + nPuncuation..columns] DO Put.Char[handle, ' ]; ENDLOOP;
    FOR i IN [0..s.length) DO
      Put.Char[handle, s[i]];
      SELECT s.length - i FROM
	10 => Put.Char[handle, ',];
	7 => Put.Char[handle, '.];
	4 => Put.Char[handle, ':];
	ENDCASE;
      ENDLOOP;
    RETURN
    END;

  WriteLongNumber: PROCEDURE [number: Number, columns: CARDINAL ← 0] =
    BEGIN
    s: STRING ← [20];
    i, nPuncuation: CARDINAL;
    String.AppendLongNumber[s, number, 10];
    nPuncuation ← MIN[(s.length - 1)/3, 3];
    FOR i IN (s.length + nPuncuation..columns] DO Put.Char[handle, ' ]; ENDLOOP;
    FOR i IN [0..s.length) DO
      Put.Char[handle, s[i]];
      SELECT s.length - i FROM 10, 7, 4 => Put.Char[handle, ',]; ENDCASE;
      ENDLOOP;
    RETURN
    END;

  END.