-- File: [Thyme]<Thyme>System>CSIM01>spMain.mesa
-- Last editted:
-- by Barth, July 11, 1983  12:46 PM
-- SChen April 19, 1983  6:45 PM.
-- Wilhelm April 27, 1982  4:07 PM, reformated by Barth and stored under
--   [Cherry]<Barth>Thyme>1.97> .
-- Details at end of file.
DIRECTORY spGlobals, AltoDefs, MiscDefs, AltoFileDefs,
          ProcessDefs, KeyDefs, FrameDefs, Real, AltoHardware,
          InlineDefs, plotDefs, ComLineDefs, AbsAllocDefs, CWF, SegmentDefs,
          TrapDefs, LoaderOps;
spMain:  MONITOR
  IMPORTS spGlobals, ProcessDefs, FrameDefs, R:  Real, InlineDefs, plotDefs,
          ComLineDefs, A:  AbsAllocDefs, CWF, SegmentDefs, TrapDefs,
          LoaderOps
  EXPORTS spGlobals =
  BEGIN
    OPEN spGlobals;

    buffer:      STRING = [100];
    memorySize,
    allocation:  LONG CARDINAL;

    key:       keys;
    lastTime:  REAL;
    checkPointInterval:  REAL ← 60.0;
    holdDisplay:  BOOLEAN ← FALSE;
    displayOn:    BOOLEAN ← TRUE;

    cursors:  ARRAY[0..3] OF ARRAY[0..15] OF CARDINAL =
              [[  3700B,  14060B,  20410B,  41604B,
                 40404B, 100402B, 100402B, 100402B,
                100002B, 100002B,  40004B,  40004B,
                 20010B,  14060B,   3700B,      0B],
               [  3700B,  14060B,  20010B,  40004B,
                 40004B, 100002B, 100022B, 100772B,
                100022B, 100002B,  40004B,  40004B,
                 20010B,  14060B,   3700B,      0B],
               [  3700B,  14060B,  20010B,  40004B,
                 40004B, 100002B, 100002B, 100402B,
                100402B, 100402B,  40404B,  41604B,
                 20410B,  14060B,   3700B,      0B],
               [  3700B,  14060B,  20010B,  40004B,
                 40004B, 100002B, 110002B, 137402B,
                110002B, 100002B,  40004B,  40004B,
                 20010B,  14060B,   3700B,      0B]];

    thymeCursor:  ARRAY[0..15] OF CARDINAL =
                  [177740B, 102040B,   2400B,   2400B,
                      2751B,   2451B,   2451B,   2447B,
                      2001B,   2007B,   2000B,   2242B,
                      2525B,   2527B,   2524B,   7523B];

    bombCursor:  ARRAY[0..15] OF CARDINAL =
                 [    30B,    140B,    200B,    700B,
                      600B,    700B,   3060B,   4010B,
                     4010B,  10004B,  10004B,  10004B,
                     4010B,   4010B,   3060B,    700B];

    analCursor:  ARRAY[0..15] OF CARDINAL =
                 [     0B,    400B,      0B,  20410B,
                    10020B,   4440B,   2100B,      0B,
                   124052B,      0B,   2100B,   4440B,
                    10020B,  20410B,      0B,    400B];

    setCursor:  PROCEDURE[c:  ARRAY[0..15] OF CARDINAL,
                          inv:  BOOLEAN ← FALSE] =
      BEGIN
          FOR i:  CARDINAL IN [0..15] DO
            AltoHardware.Cursor[i] ← IF ~inv THEN c[i]
                                     ELSE InlineDefs.BITNOT[c[i]]
          ENDLOOP;
      END;

    advanceCursor:  PUBLIC PROCEDURE =
      BEGIN
        setCursor[cursors[cursorState], holdDisplay];
        cursorState ← (cursorState + 1) MOD 4
      END;



    forkedProcedure:  TYPE = PROCEDURE[cv:  POINTER TO CONDITION];

    keyboardProcess:  PROCESS;
    keyboardCV:       CONDITION;
    forcedDump:       BOOLEAN ← FALSE;
    cursorState:      CARDINAL ← 0;

    keyboardWatcher:  ENTRY forkedProcedure =
      BEGIN
        OPEN KeyDefs;

        DO
          WAIT cv;
          IF Keys↑.Ctrl = down AND Keys↑.LeftShift = down THEN
            IF Keys↑.Q = down THEN
              BEGIN
                forcedDump ← TRUE;
                holdDisplay ← FALSE;
                canIt[]
              END
            ELSE
              IF Keys↑.T = down THEN
                BEGIN
                  holdDisplay ← FALSE;
                  canIt[]
                END
              ELSE
                IF Keys↑.H = down THEN holdDisplay ← ~holdDisplay
                ELSE
                  IF Keys↑.D = down THEN
                    BEGIN
                      displayOn ← ~displayOn;
                      plotDefs.DisplayControl[displayOn]
                    END;
          setCursor[cursors[cursorState], holdDisplay]
        ENDLOOP
      END;

    checkPointProcess:  PROCESS;
    checkPointCV:       CONDITION;

    checkPointTimer:  ENTRY forkedProcedure =
      BEGIN
        DO
          WAIT cv;
          checkIt[]
        ENDLOOP;
      END;

    forkIt: PROCEDURE[seconds:  CARDINAL, p:  forkedProcedure,
                      cv:  POINTER TO CONDITION]
              RETURNS[ph:  PROCESS] =
      BEGIN 
        enterPri:     ProcessDefs.Priority ← ProcessDefs.GetPriority[]; 
        newPriority:  ProcessDefs.Priority ← SUCC[enterPri]; 
        newTicks:     ProcessDefs.Ticks ←
                                  ProcessDefs.SecondsToTicks[seconds];
     
        ProcessDefs.SetTimeout[cv, newTicks]; 
        FrameDefs.SwapInCode[FrameDefs.GlobalFrame[p]]; 
        ProcessDefs.SetPriority[newPriority]; 
        ph ← FORK p[cv]; 
        ProcessDefs.SetPriority[enterPri]; 
        ProcessDefs.Detach[ph] 
      END;
    

    switches:  ComLineDefs.SwitchVector ← ALL[TRUE];
    color:     CARDINAL = 2;

    setCursor[thymeCursor];

    ComLineDefs.OpenComLine[];
    ComLineDefs.GetFromLine[inputFileName, @switches];
    ComLineDefs.CloseComLine[];
    openInputFile[];
    openSysWindow["Thyme - CSIM02 - July 1983"];
    [memorySize,] ← A.AllocateStats[];
    memorySize    ← memorySize/1024;
    IF A.Machine[] THEN CWF.SWF1[buffer, "%luk Dorado.", @memorySize]
    ELSE CWF.SWF1[buffer, "%luk Dolphin.", @memorySize];
    printSysWindow[buffer];
    next[];

    WHILE item = name DO
      IF searchKey[] # libraryKey THEN EXIT;
      next[];
      IF item = leftB THEN next[] ELSE error[801, TRUE];
      IF item = name THEN
        BEGIN
          ENABLE
            BEGIN
              SegmentDefs.FileNameError =>
                BEGIN
                  error[890, FALSE];
                  GO TO eatIt
                END;
              TrapDefs.StartFault =>
                BEGIN
                  error[891, FALSE];
                  GO TO eatIt
                END;
              TrapDefs.UnboundProcedure =>
                BEGIN
                  error[892, FALSE];
                  GO TO eatIt
                END;
              TrapDefs.ControlFault =>
                BEGIN
                  error[893, FALSE];
                  GO TO eatIt
                END;
              LoaderOps.VersionMismatch =>
                BEGIN
                  error[894, FALSE];
                  GO TO eatIt
                END
            END;
          CWF.SWF1[buffer, "%s.thybcd", newString];
          FrameDefs.RunConfig[buffer];
          next[]
        EXITS
          eatIt => next[]
        END
      ELSE error[804, TRUE];
      IF item = rightB THEN next[] ELSE error[802, FALSE];
      IF item = semi THEN next[] ELSE error[800, FALSE]
    ENDLOOP;
    IF item = name AND searchKey[] = circuitKey THEN input[]
    ELSE error[820, TRUE];
    IF item = slash AND ~AnyErrors[] THEN
      BEGIN
        next[];
        output[cktRoot, 0]
      END;
    IF item = semi THEN next[] ELSE error[800,, FALSE];
    IF ~AnyErrors[] THEN
      BEGIN
        setCursor[bombCursor];
        bomb[];
        IF item = plus THEN
          BEGIN
            next[];
            printHole[]
          END
      END;
    [, allocation] ← A.AllocateStats[];
    CWF.SWF1[buffer, "%lu words allocated.", @allocation];
    printSysWindow[buffer];
    IF ~AnyErrors[] THEN
      BEGIN
        setCursor[analCursor];
        topoAnalysis[]
      END;

    keyboardProcess ← forkIt[1, keyboardWatcher, @keyboardCV];
    IF ~AnyErrors[] THEN
      WHILE item = name DO
        key ← searchKey[];
        next[];
        SELECT key FROM
          runKey =>
            BEGIN
              checkPointProcess ← forkIt[R.FixC[60.0*checkPointInterval], 
                                         checkPointTimer, @checkPointCV];
              lastTime ← runIt[];
              printSysWindow["Done."];
              WHILE holdDisplay DO ProcessDefs.Yield[] ENDLOOP
            END;
          printKey => makePrintList[];
          plotKey  => makePlotList[~switches[color]];
          icKey    => setICs[];
          dumpKey  => IF ~forcedDump THEN dumpAll[lastTime];
          checkPointKey =>
            BEGIN
              IF item=leftB THEN next[] ELSE error[801];
              IF item = number THEN
                BEGIN
                  checkPointInterval ← value;
                  next[]
                END
              ELSE error[809, FALSE];
              IF item=rightB THEN next[] ELSE error[802];
            END
        ENDCASE => GOTO err1;
        IF item = eof THEN EXIT;
        IF item = semi THEN next[] ELSE error[800,, FALSE]
      REPEAT
        err1 => error[821, TRUE]
      ENDLOOP;

    IF forcedDump THEN dumpAll[lastTime];
    killPlot[]
  END.
4/19/83:- 
  original: [Cherry]<Barth>Thyme>1.97>spMain.mesa
  changed the argument of PROCEDURE openSysWindow to a new version name/number.