-- STDebugMisc.mesa  Edited by Bruce,  October 14, 1980  10:50 AM

DIRECTORY
  Ascii USING [CR, DEL, ESC, FF, LF, SP, TAB],
  DebugFormat USING [LongSubString, LongSubStringDescriptor],
  DebugTable USING [CompStrDesc, CSRptr],
  DebugUsefulDefs USING [ShortREAD],
  ErrorTable USING [CompStrDesc],
  RESOut USING [Log8, Log10, MakeRoom, PChar, PCr, PDecimal, PNumber, PString],
  STDebugDefs USING [
    AppendLongSubString, LockTableSegment, PLongSubString, STCopyRead, STRead,
    TableBase, TableId, UnlockTableSegment],
  String USING [AppendOctal, SubString, SubStringDescriptor],
  Symbols USING [
    HTIndex, HTNull, HTRecord, htType, ISEIndex, SERecord, seType, ssType,
    TransferMode, TypeClass],
  Table USING [Base];

STDebugMisc: PROGRAM 
  IMPORTS DebugUsefulDefs, RESOut, STDebugDefs, String
  EXPORTS STDebugDefs =
  BEGIN OPEN STDebugDefs, RESOut;

  showLinks: PUBLIC BOOLEAN ← FALSE;
  csrP: DebugTable.CSRptr;
  desc: DebugFormat.LongSubStringDescriptor;
  ss: DebugFormat.LongSubString = @desc;
  opnames: LONG POINTER TO ARRAY [0..256) OF ErrorTable.CompStrDesc;
  mopdesc: DebugFormat.LongSubStringDescriptor;

  PutAsMopcode: PUBLIC PROCEDURE [n: CARDINAL] = {
    PCr[]; PDecimal[n]; PString[" = z"L]; WriteOpName[n, mopcodes]};

  WriteMOpName: PUBLIC PROCEDURE [n: CARDINAL] = {PChar['z]; WriteOpName[n, mopcodes]};

  AppendMopcodeName: PUBLIC PROCEDURE [s: STRING, n: CARDINAL] = {
    AppendOpcodeName[s, n, mopcodes]};

  AppendOpcodeName: PROCEDURE [s: STRING, n: CARDINAL, id: TableId] =
    BEGIN
    LockMopcodes[id];
    [offset: mopdesc.offset, length: mopdesc.length] ← opnames[n];
    IF mopdesc.length = 0 THEN String.AppendOctal[s, n]
    ELSE AppendLongSubString[s, @mopdesc];
    UnlockMopcodes[id];
    RETURN
    END;

  WriteOpName: PUBLIC PROCEDURE [n: CARDINAL, id: TableId] =
    BEGIN
    LockMopcodes[id];
    [offset: mopdesc.offset, length: mopdesc.length] ← opnames[n];
    IF desc.length = 0 THEN PNumber[n,[8,TRUE,TRUE,3]]
    ELSE PLongSubString[@mopdesc];
    UnlockMopcodes[id];
    RETURN
    END;

  LockMopcodes: PROC [id: TableId] = {
    opnames ← LockTableSegment[id];
    mopdesc.base ← LOOPHOLE[opnames + 256*SIZE[ErrorTable.CompStrDesc], LONG STRING]};

  UnlockMopcodes: PROC [id: TableId] = {UnlockTableSegment[id]};

  LockDebugTab: PROC = {
    csrP ← LockTableSegment[debugtab];
    ss.base ← @csrP[csrP.stringOffset]};

  UnlockDebugTab: PROC = {UnlockTableSegment[debugtab]};

  PutNodeName: PUBLIC PROCEDURE [n: UNSPECIFIED] =
    BEGIN
    LockDebugTab[];
    [offset: desc.offset, length: desc.length] ← csrP.NodePrintName[n];
    PLongSubString[ss];
    UnlockDebugTab[];
    RETURN
    END;

  PutTypeName: PUBLIC PROCEDURE [n: Symbols.TypeClass] =
    BEGIN
    LockDebugTab[];
    [offset: desc.offset, length: desc.length] ← csrP.TypePrintName[n];
    PLongSubString[ss];
    UnlockDebugTab[];
    END;

  PutModeName: PUBLIC PROCEDURE [n: Symbols.TransferMode] =
    BEGIN
    LockDebugTab[];
    [offset: desc.offset, length: desc.length] ← csrP.ModePrintName[n];
    PLongSubString[ss];
    UnlockDebugTab[];
    END;

  PRemoteSubString: PUBLIC PROCEDURE [ss: String.SubString] =
    BEGIN
    i: CARDINAL;
    s: PACKED ARRAY [0..1] OF CHARACTER;
    p: POINTER ← @s;
    len: CARDINAL ← MIN[ss.length, 50];

    IF ss.offset MOD 2 # 0 THEN
      p↑ ← DebugUsefulDefs.ShortREAD[@ss.base.text+ss.offset/2];
    FOR i IN [ss.offset..ss.offset+len) DO
      IF i MOD 2 = 0 THEN p↑ ← DebugUsefulDefs.ShortREAD[@ss.base.text+i/2];
      PChar[s[i MOD 2]];
      ENDLOOP;
    IF ss.length > len THEN PString["..."L];
    END;

  PRemoteString: PUBLIC PROCEDURE [s: STRING] =
    BEGIN
    desc: String.SubStringDescriptor ← [base: s, offset: 0, length: NULL];
    IF s = NIL THEN {PString["NIL"L]; RETURN};
    desc.length ← DebugUsefulDefs.ShortREAD[@s.length];
    PRemoteSubString[@desc];
    END;

  HashForSei: PUBLIC PROCEDURE [sei: Symbols.ISEIndex]
      RETURNS [hti: Symbols.HTIndex] =
    BEGIN OPEN Symbols;
    ise: id SERecord;
    seb: Table.Base;

    seb ← TableBase[seType];
    STCopyRead[to: @ise, from: @seb[sei],
      nwords: SIZE[id SERecord]];
    RETURN[ise.hash];
    END;

  PutAsChar: PROCEDURE [c: [0..128)] =
    BEGIN
    SELECT LOOPHOLE [c, CHARACTER] FROM
      Ascii.CR => PString["CR"L];
      Ascii.DEL => PString["DEL"L];
      Ascii.ESC => PString["ESC"L];
      Ascii.FF => PString["FF"L];
      Ascii.LF => PString["LF"L];
      Ascii.SP => PString["SP"L];
      Ascii.TAB => PString["TAB"L];
      < 40C => BEGIN PString["'↑"L]; PChar['@+c]; END;
      ENDCASE => BEGIN PChar['']; PChar[LOOPHOLE[c]]; END;
    END;

  LengthAsChar: PROCEDURE [c: [0..128)] RETURNS [CARDINAL] =
    BEGIN
    SELECT LOOPHOLE [c, CHARACTER] FROM
      Ascii.CR => RETURN [2];
      Ascii.DEL => RETURN [3];
      Ascii.ESC => RETURN [3];
      Ascii.FF => RETURN [2];
      Ascii.LF => RETURN [2];
      Ascii.SP => RETURN [2];
      Ascii.TAB => RETURN [3];
      < 40C => BEGIN RETURN [3]; END;
      ENDCASE => BEGIN RETURN [2]; END;
    END;

  PutAsVariousRep: PUBLIC PROCEDURE [n: UNSPECIFIED] =
    BEGIN
    r: RECORD [ SELECT OVERLAID * FROM
      int => [i: INTEGER],
      card => [c: CARDINAL],
      bytes => [b1, b2: [0..256)],
      nibbles => [n1, n2, n3, n4: [0..16)],
      bitaddr => [wd: [0..7777B], bd: [0..17B]],
      pdesc => [gfi: [0..1777B], entry: [0..37B], tag: BOOLEAN],
      ENDCASE] = n;
    AnotherVal: PROCEDURE [len: CARDINAL] =
      BEGIN
      PString[" ="L];
      IF MakeRoom[len+1, 2] THEN PChar[Ascii.SP];
      END;
    PCr[];
    BEGIN OPEN r;
    PNumber[c, [base: 8, zerofill: FALSE, unsigned: TRUE, columns: 0]];
    PString["B = "L];
    PNumber[c, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
    IF i < 0 THEN
      BEGIN
      AnotherVal[1+Log10[-i]];
      PNumber[c, [base: 10, zerofill: FALSE, unsigned: FALSE, columns: 0]];
      END;
    IF b1 # 0 THEN
      BEGIN
      AnotherVal[Log10[b1]+Log10[b2]+2];
      PNumber[b1, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
      PString[",,"L];
      PNumber[b2, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
      IF b1 > 15 OR b2 > 15 THEN
	BEGIN
        chars: CARDINAL ← Log8[b1]+Log8[b2]+2;
        IF b1 > 7 THEN chars ← chars+1;
        IF b2 > 7 THEN chars ← chars+1;
	AnotherVal[chars];
	PNumber[b1, [base: 8, zerofill: FALSE, unsigned: TRUE, columns: 0]];
	IF b1 > 7 THEN PChar['B];
	PString[",,"L];
	PNumber[b2, [base: 8, zerofill: FALSE, unsigned: TRUE, columns: 0]];
	IF b2 > 7 THEN PChar['B];
	END;
      IF b1 < 128 AND b2 < 128 THEN
        BEGIN
	AnotherVal[LengthAsChar[b1]+ LengthAsChar[b2] + 2];
	PutAsChar[b1]; PString[",,"L]; PutAsChar[b2];
	END;
      END
    ELSE IF b2 IN [1..127] THEN 
      BEGIN AnotherVal[LengthAsChar[b2]]; PutAsChar[b2]; END;
    IF n1 # 0 OR n3 # 0 THEN
      BEGIN
      chars: CARDINAL ← Log10[n4];
      IF b1 # 0 THEN
        BEGIN
        IF n1 # 0 THEN chars ← chars + Log10[n1]+1;
        chars ← chars + Log10[n2]+2;
        END;
      IF n3 # 0 THEN chars ← chars + Log10[n3]+1;
      AnotherVal[chars];
      IF b1 # 0 THEN
        BEGIN
        IF n1 # 0 THEN
	  BEGIN
	  PNumber[n1, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
	  PChar[':];
	  END;
        PNumber[n2, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
        PString[",,"L];
        END;
      IF n3 # 0 THEN
	BEGIN
	PNumber[n3, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
	PChar[':];
	END;
      PNumber[n4, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
      END;
    IF gfi # 0 AND tag THEN
      BEGIN
      AnotherVal[7 + Log10[gfi] + Log10[entry]];
      PString["pd["L];
      PNumber[gfi, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
      PChar[',];
      PNumber[entry, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
      PString[",1]"];
      END;
    IF b1 # 0 THEN
      BEGIN
      AnotherVal[5 + Log10[wd] + Log10[bd]];
      PString["ba["L];
      PNumber[wd, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
      PChar[',];
      PNumber[bd, [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 0]];
      PChar[']];
      END;
    END;
    END;

  SubStringForHash: PUBLIC PROCEDURE [
      ss: String.SubString, hti: Symbols.HTIndex] =
    BEGIN OPEN Symbols;
    ht: POINTER TO ARRAY HTIndex OF HTRecord;
    this, next: HTRecord;
    ht ← TableBase[htType];
    ss.base ← TableBase[ssType];
    STCopyRead[to: @this, from: @ht[hti-1], 
      nwords: SIZE[HTRecord]];
    STCopyRead[to: @next, from: @ht[hti], 
      nwords: SIZE[HTRecord]];
    ss.offset ← this.ssIndex;
    ss.length ← next.ssIndex - this.ssIndex;
    END;

  PutHashString: PUBLIC PROCEDURE [hti: Symbols.HTIndex] =
    BEGIN OPEN Symbols;
    desc: String.SubStringDescriptor;

    IF hti = HTNull THEN 
      BEGIN PString["Anon"L]; RETURN END;
    SubStringForHash[@desc, hti];
    PSTSubString[@desc];
    END;

  PSTSubString: PUBLIC PROCEDURE [ss: String.SubString] =
    BEGIN
    i: CARDINAL;
    s: PACKED ARRAY [0..1] OF CHARACTER;
    p: POINTER ← @s;
    len: CARDINAL ← MIN[ss.length, 50];

    IF ss.offset MOD 2 # 0 THEN
      p↑ ← STRead[@ss.base.text+ss.offset/2];
    FOR i IN [ss.offset..ss.offset+len) DO
      IF i MOD 2 = 0 THEN p↑ ← STRead[@ss.base.text+i/2];
      PChar[s[i MOD 2]];
      ENDLOOP;
    IF ss.length > len THEN PString["..."L];
    END;

  PSTString: PUBLIC PROCEDURE [s: STRING] =
    BEGIN
    desc: String.SubStringDescriptor ← [base: s, offset: 0, length: NULL];
    desc.length ← STRead[@s.length];
    PSTSubString[@desc];
    END;

  END.