-- ShowTimeImpl.Mesa
-- Russ Atkinson, June 7, 1982 5:52 pm

DIRECTORY
  ShowTime,
  System USING [GetClockPulses, Microseconds, PulsesToMicroseconds];

ShowTimeImpl: CEDAR PROGRAM
    IMPORTS System
    EXPORTS ShowTime
    = BEGIN OPEN System;

  Microseconds: TYPE = LONG CARDINAL;

  GetMark: PUBLIC PROC RETURNS [Microseconds] = TRUSTED {
    RETURN [System.PulsesToMicroseconds[System.GetClockPulses[]]]};

  SinceMark: PUBLIC PROC [from: Microseconds] RETURNS [Microseconds] = {
    now: Microseconds ← GetMark[];
    RETURN [LOOPHOLE[now - from, Microseconds]]};

  ShowDecimal: PUBLIC PROC
      [number: Microseconds, p: PROC [CHAR] RETURNS [BOOL],
       field: CARDINAL ← 0, fill: CHAR ← ' ]
      RETURNS [BOOL] = TRUSTED {
    chars: STRING ← [12];
    size: CARDINAL ← 0;
    IF LOOPHOLE[number, INT] < 0 THEN RETURN[p['?]];
    DO
       next: Microseconds ← number / 10;
       chars[size] ← '0 + (number - (next * 10));
       size ← size + 1;
       IF (number ← next) = 0 THEN EXIT;
       ENDLOOP;
    WHILE field > size DO
        IF p[fill] THEN RETURN [TRUE]; field ← field - 1 ENDLOOP;
    WHILE size > 0 DO
        size ← size - 1;
        IF p[chars[size]] THEN RETURN [TRUE]
        ENDLOOP;
    RETURN [FALSE]; 
    };

  Show: PUBLIC PROC
     [from: Microseconds, p: PROC [CHAR] RETURNS [BOOL],
      places: CARDINAL ← 6] = {
    ShowDelta[SinceMark[from], p, places]};

  ShowDelta: PUBLIC PROC
     [delta: Microseconds, p: PROC [CHAR] RETURNS [BOOL],
      places: CARDINAL ← 6] = {
    adjust: Microseconds;
    IF places >= 6
       THEN {places ← 6; adjust ← 0}
       ELSE {delta ← delta + (adjust ← Adjust[places])};
    IF ShowDecimal[delta / 1000000, p, 0, '0] THEN RETURN;
    IF p['.] THEN RETURN;
    delta ← delta MOD 1000000;
    IF places < 6 THEN delta ← delta / (adjust+adjust);
    IF ShowDecimal[delta, p, places, '0] THEN RETURN;
    };

Adjust: ARRAY [0..6] OF Microseconds =
    [500000, 50000, 5000, 500, 50, 5, 0];

  END.