-- Debugger.Mesa  Edited by: Bruce  September 22, 1980  3:58 PM

DIRECTORY
  Actions USING [ReadProc, WriteProc],
  Ascii USING [SP],
  DebugFormat USING [OctalFormat],
  DebugOps USING [LongREAD, LongWRITE, ShortCopyREAD, StringExpToDecimal, StringExpToLOctal, StringExpToOctal],
  DOutput USING [Char, EOL, LongOctal, Number, Octal, Text],
  Dump USING [Char],
  PrincOps USING [StateVector, SVPointer],
  State USING [GetGS, GSHandle],
  UserInput USING [ResetUserAbort, userAbort];

Debugger: PROGRAM
  IMPORTS DebugOps, DOutput, Dump, State, UserInput
  EXPORTS Actions, DebugOps, Dump =
  BEGIN

  data: State.GSHandle ← State.GetGS[];
  Abort: PUBLIC SIGNAL = CODE;
  CommandNotAllowed: PUBLIC SIGNAL = CODE;
  Proceed: PUBLIC SIGNAL = CODE;
  Quit: PUBLIC SIGNAL = CODE;
  Kill: PUBLIC SIGNAL = CODE;

  AsciiDisplay: PUBLIC PROC [start, chars: STRING] = {AsciiDump[start,chars,TRUE]};
  AsciiRead: PUBLIC PROC [start, chars: STRING] = {AsciiDump[start,chars,FALSE]};

  AsciiDump: PROCEDURE [start, chars: STRING, interpret: BOOLEAN] =
    BEGIN
    i: CARDINAL;
    s: PACKED ARRAY [0..1] OF CHARACTER;
    p: POINTER = @s;
    lp: LONG POINTER ← LOOPHOLE[DebugOps.StringExpToLOctal[start]];
    cnt: CARDINAL ← DebugOps.StringExpToDecimal[chars];
    DOutput.EOL[];
    FOR i IN [0..cnt) DO
      IF i MOD 2 = 0 THEN p↑ ← DebugOps.LongREAD[lp+i/2];
      IF ~interpret THEN DOutput.Char[s[i MOD 2]]
      ELSE {Dump.Char[s[i MOD 2]]; DOutput.Text[IF i MOD 2 = 0 THEN ","L ELSE "; "L]};
      IF UserInput.userAbort THEN {ControlDel[]; RETURN};
      ENDLOOP;
    RETURN
    END;

  ControlDel: PROC = {UserInput.ResetUserAbort[]; DOutput.Text[" ... aborted"L]};

  Read: PUBLIC PROC [start, cnt: STRING, proc: Actions.ReadProc ← ReadUser] =
    BEGIN
    lp: LONG POINTER ← LOOPHOLE[DebugOps.StringExpToLOctal[start]];
    num: CARDINAL ← DebugOps.StringExpToDecimal[cnt];
    DoRead[lp,num,proc];
    END;

  OctalRead: PUBLIC PROCEDURE [start, cnt: STRING] = {Read[start,cnt]};
  ReadUser: PUBLIC PROC [loc: LONG POINTER] RETURNS [UNSPECIFIED] =
    BEGIN RETURN[DebugOps.LongREAD[loc]] END;

  DoRead: PUBLIC PROC [
      start: LONG POINTER, cnt: CARDINAL, proc: Actions.ReadProc] =
    BEGIN
    j,n: CARDINAL;
    i: INTEGER ← -1;
    FOR j IN [0..cnt) DO
      IF UserInput.userAbort THEN RETURN;
      IF (i ← i+1) MOD 8 = 0 THEN
	BEGIN
	DOutput.EOL[];
	DOutput.LongOctal[start + j];
	DOutput.Char['/]
	END; 
      DOutput.Char[' ];
      DOutput.Number[n ← proc[start+j], DebugFormat.OctalFormat];
      DOutput.Char[IF n ~IN[0..7] THEN 'B ELSE Ascii.SP];
      ENDLOOP;
    END;

  Write: PUBLIC PROC [loc, val: STRING, proc: Actions.WriteProc ← WriteUser] =
    BEGIN
    lp: LONG POINTER ← LOOPHOLE[DebugOps.StringExpToLOctal[loc]];
    v: UNSPECIFIED ← DebugOps.StringExpToOctal[val];
    DoWrite[lp,v,proc];
    END;

  OctalWrite: PUBLIC PROCEDURE [loc, val: STRING] = {Write[loc,val]};
  WriteUser: PUBLIC PROC [loc: LONG POINTER, val: UNSPECIFIED] =
    BEGIN DebugOps.LongWRITE[loc,val] END;
  DoWrite: PUBLIC PROC [
      loc: LONG POINTER,val: UNSPECIFIED, proc: Actions.WriteProc] =
    BEGIN proc[loc,val] END;

EvalStack: PUBLIC PROCEDURE =
  BEGIN OPEN DOutput;
  i: CARDINAL;
  sp: PrincOps.SVPointer ← data.StatePtr;
  state: PrincOps.StateVector;
  IF sp = NIL THEN GOTO empty;
  Text[" ("L]; Octal[sp]; Text[") "L];
  DebugOps.ShortCopyREAD[
    from: sp, to: @state, nwords: SIZE[PrincOps.StateVector]];
  IF state.stkptr = 0 THEN GOTO empty;
  FOR i IN [0..state.stkptr)
    DO Char[' ]; Octal[state.stk[i]] ENDLOOP;
  RETURN
  EXITS empty => DOutput.Text["empty!"L];
  END;

  END.