-- file P5Debug.mesa
-- last modified by Sweet, July 27, 1979  1:46 PM

DIRECTORY
  CharIO: FROM "chario" USING [CR, NumberFormat, PutChar, PutDecimal, PutNumber, PutOctal, PutString],
  CodeDefs: FROM "codedefs" USING [CCIndex, CCInfoType, CCNull, JumpCCIndex, JumpCCNull, JumpType],
  ComData: FROM "comdata" USING [errorStream],
  CompilerUtil: FROM "compilerutil" USING [PrintTree, PrintBodies, PrintSymbols],
  ErrorTable: FROM "errortable" USING [CompStrDesc],
  P5: FROM "p5" USING [CCInfoMeaning],
  P5U: FROM "p5u" USING [ParamCount],
  SegmentDefs: FROM "segmentdefs" USING [DefaultPages, DefaultVersion, FileSegmentAddress, FileSegmentHandle, NewFile, NewFileSegment, Read, SwapIn, SwapOut, Unlock],
  StringDefs: FROM "stringdefs" USING [SubString, SubStringDescriptor],
  Table: FROM "table" USING [AddNotify, Base, DropNotify, Notifier],
  Tree: FROM "tree" USING [treeType, Link];

P5Debug: PROGRAM
    IMPORTS MPtr: ComData, CharIO, CompilerUtil, P5, P5U, SegmentDefs, Table =
  BEGIN OPEN CodeDefs;

  cb: Table.Base;		-- code base (local copy)

  WriteChar: PROCEDURE [c: CHARACTER] = INLINE
    BEGIN
    CharIO.PutChar[MPtr.errorStream, c];
    END;

  WriteString: PROCEDURE [s: STRING] = INLINE
    BEGIN
    CharIO.PutString[MPtr.errorStream, s];
    END;

  WriteDecimal: PROCEDURE [n: INTEGER] = INLINE
    BEGIN
    CharIO.PutDecimal[MPtr.errorStream, n];
    END;

  WriteOctal: PROCEDURE [n: CARDINAL] = INLINE
    BEGIN
    CharIO.PutOctal[MPtr.errorStream, n];
    END;

  WriteNumber: PROCEDURE [n: UNSPECIFIED, f: CharIO.NumberFormat] = INLINE
    BEGIN
    CharIO.PutNumber[MPtr.errorStream, n, f];
    END;

  P5DebugNotify: Table.Notifier =
    BEGIN  -- called by allocator whenever table area is repacked
    cb ← base[Tree.treeType];
    RETURN
    END;

  SubString: TYPE = StringDefs.SubString;
  fopnameSH: SegmentDefs.FileSegmentHandle ← NIL;
  mopnameSH: SegmentDefs.FileSegmentHandle ← NIL;
  fopbase, mopbase: STRING;

  fopnames: POINTER TO ARRAY [0..256) OF ErrorTable.CompStrDesc;
  mopnames: POINTER TO ARRAY [0..256) OF ErrorTable.CompStrDesc;

  PrintTree: PROCEDURE [t: UNSPECIFIED] =
    BEGIN
    CompilerUtil.PrintTree[t];
    END;

  PrintSei: PROCEDURE [sei: UNSPECIFIED] =
    BEGIN
    t: Tree.Link = [symbol[sei]];
    CompilerUtil.PrintTree[t];
    END;

  PrintBodies: PROCEDURE =
    BEGIN
    CompilerUtil.PrintBodies[];
    END;

  PrintSymbols: PROCEDURE =
    BEGIN
    CompilerUtil.PrintSymbols[];
    END;
    

  SwapInOpTab: PROCEDURE =
    BEGIN OPEN SegmentDefs;
    fopbase ← mopbase ← NIL;
    BEGIN
      IF fopnameSH = NIL THEN fopnameSH ← NewFileSegment[
        NewFile["FOpNames.binary",Read,DefaultVersion !ANY => GOTO notfound],
        1, DefaultPages, Read];
      SwapIn[fopnameSH];
      fopnames ← FileSegmentAddress[fopnameSH]+1;
      fopbase ← LOOPHOLE[fopnames + 256*SIZE[ErrorTable.CompStrDesc], STRING];
    EXITS notfound => NULL;
    END;
    BEGIN
      IF mopnameSH = NIL THEN mopnameSH ← NewFileSegment[
        NewFile["OpNames.binary",Read,DefaultVersion !ANY => GOTO notfound],
        1, DefaultPages, Read];
      SwapIn[mopnameSH];
      mopnames ← FileSegmentAddress[mopnameSH]+1;
      mopbase ← LOOPHOLE[mopnames + 256*SIZE[ErrorTable.CompStrDesc], STRING];
    EXITS notfound => NULL;
    END;
    RETURN
    END;

  CloseOpTable: PROCEDURE =
    BEGIN
    IF fopnameSH # NIL THEN
      BEGIN
      SegmentDefs.Unlock[fopnameSH];
      SegmentDefs.SwapOut[fopnameSH];
      END;
    IF mopnameSH # NIL THEN
      BEGIN
      SegmentDefs.Unlock[mopnameSH];
      SegmentDefs.SwapOut[mopnameSH];
      END;
    RETURN
    END;


  WriteSubString: PROCEDURE [ss: SubString] =
    BEGIN
    i: CARDINAL;
    FOR i IN [ss.offset..ss.offset+ss.length)
      DO
      WriteChar[ss.base[i]]
      ENDLOOP;
    RETURN
    END;

  PrintChunks: PUBLIC PROCEDURE [v: CodeDefs.CCIndex] =
    BEGIN
    PrintChunksWithInfo[v, P5.CCInfoMeaning[]];
    END;

  PrintChunksWithInfo: PUBLIC PROCEDURE [v: CodeDefs.CCIndex, ccInfo: CCInfoType] =
    BEGIN
    c: CCIndex;
    jc: JumpCCIndex;
    i: CARDINAL;

    Table.AddNotify[P5DebugNotify];
    SwapInOpTab[];
    WriteChar[CharIO.CR];
    FOR c ← v, cb[c].flink UNTIL c = CCNull DO
      WriteNumber[c, [10,FALSE,TRUE,6]];
      WITH cc:cb[c] SELECT FROM
	label =>
	  BEGIN
	  WriteString[": Label "L];
	  WITH cc SELECT ccInfo FROM 
	    generating => 
	      FOR jc ← cc.jumplist, cb[jc].thread UNTIL jc = JumpCCNull DO
		WriteChar[' ];
		WriteNumber[jc, [10,FALSE,TRUE,6]];
		ENDLOOP;
	    binding =>
	      BEGIN
	      WriteString[", minPC: "L]; WriteDecimal[minPC];
	      WriteString[", maxPC: "L]; WriteDecimal[maxPC];
	      END;
	    coding =>
	      BEGIN
	      WriteString[", pc: "L]; WriteDecimal[pc];
	      END;
	    ENDCASE;
	  END;
	jump =>
	  BEGIN
	  WriteString[": "L]; WriteJumpName[cc.jtype]; WriteChar[' ];
	  WriteDecimal[LOOPHOLE[cc.destlabel]];
	  WITH cc SELECT ccInfo FROM 
	    binding =>
	      BEGIN
	      WriteString[", minPC: "L]; WriteDecimal[minPC];
	      WriteString[", maxPC: "L]; WriteDecimal[maxPC];
	      END;
	    coding =>
	      BEGIN
	      WriteString[", pc: "L]; WriteDecimal[pc];
	      END;
	    ENDCASE;
	  END;
	code =>
	  BEGIN
	  WriteString[": Code "L];
	  IF cc.realinst THEN WriteMOpName[cc.inst] 
	  ELSE WriteFOpName[cc.inst];
	  FOR i IN [1..P5U.ParamCount[LOOPHOLE[c]]] DO
	    WriteNumber[cc.parameters[i], [8,FALSE,TRUE,7]];
	    WriteChar['B];
	    ENDLOOP;
	  WriteString[", source "L]; WriteOctal[cc.sourcefileindex];
	  END;
	other => WITH cc SELECT FROM
	  table => WriteString[": Table"L];
	  startbody, endbody =>
	    BEGIN
	    WriteString[IF cc.otag = startbody THEN ": Start"L ELSE ": End"L];
	    WriteString["Body, bti: "L];
	    WriteDecimal[LOOPHOLE[index]];
	    END;
	  ENDCASE;
	ENDCASE;
      IF cb[c].pad # 0 THEN WriteString[" pad=1"L];
      WriteChar[CharIO.CR];
      ENDLOOP;
    CloseOpTable[];
    Table.DropNotify[P5DebugNotify];
    RETURN
    END;

  WriteFOpName: PROCEDURE [n: CARDINAL] =
    BEGIN
    opss: StringDefs.SubStringDescriptor;
    WriteChar['q];
    IF fopbase = NIL THEN WriteNumber[n,[8,TRUE,TRUE,3]]
    ELSE
      BEGIN
      opss.base ← fopbase;
      opss.offset ← fopnames[n].offset;
      opss.length ← fopnames[n].length;
      IF opss.length = 0 THEN WriteNumber[n,[8,TRUE,TRUE,3]]
      ELSE WriteSubString[@opss];
      END;
    RETURN
    END;

  WriteMOpName: PROCEDURE [n: CARDINAL] =
    BEGIN
    opss: StringDefs.SubStringDescriptor;
    WriteChar['z];
    IF mopbase = NIL THEN WriteNumber[n,[8,TRUE,TRUE,3]]
    ELSE
      BEGIN
      opss.base ← mopbase;
      opss.offset ← mopnames[n].offset;
      opss.length ← mopnames[n].length;
      IF opss.length = 0 THEN WriteNumber[n,[8,TRUE,TRUE,3]]
      ELSE WriteSubString[@opss];
      END;
    RETURN
    END;

  WriteJumpName: PROCEDURE[n: CodeDefs.JumpType] =
    BEGIN
    JumpName: ARRAY CodeDefs.JumpType OF STRING =
	["JumpE"L, "JumpN"L, "JumpL"L, "JumpGE"L, "JumpG"L, "JumpLE"L,
	 "UJumpL"L, "UJumpGE"L, "UJumpG"L, "UJumpLE"L, "ZJumpE"L, "ZJumpN"L, 
	 "Jump"L, "JumpA"L, "JumpC"L, "JumpCA"L, "JumpRet"L,
	 "NILJumpE"L, "NILJumpN"L,
	 "PAIRJumpL"L, "PAIRJumpG"L, "BYTEJumpE"L, "BYTEJumpN"L, "BITJumpE"L, "BITJumpN"L];

    IF n > LAST[JumpType] THEN
      BEGIN WriteChar['j]; WriteDecimal[LOOPHOLE[n]] END
    ELSE WriteString[JumpName[n]];  RETURN
    END;

  END...