-- PPDebug.Mesa
-- Satterthwaite, January 13, 1981 9:28 AM
-- Russ Atkinson, August 17, 1982 5:13 pm

DIRECTORY
Ascii USING [TAB],
PPCommentTable USING [Explode, FindNextComment, Ref],
PPUtil: TYPE USING
[AcquireTable, ReleaseTable, SetOutput,
ShowChar, ShowCR, ShowDecimal, ShowRope],
PPDebugTable USING [CSRptr],
PPLeaves USING [HTIndex, ISEIndex, HTNull, LTIndex],
PPTree USING [AttrId, Handle, Link, NodeName, Scan, Null],
PPTreeOps USING [ScanSons],
PrintTV USING [NullPutClosure, PutClosure],
Rope USING [Map, ROPE, Text];

PPDebug: PROGRAM
IMPORTS PPUtil, PPTreeOps, CT: PPCommentTable, Rope
EXPORTS PPUtil
SHARES Rope
= BEGIN OPEN Ascii, Tree: PPTree, PPLeaves, PrintTV, Rope;

-- basic io

WriteChar: PROC [c: CHAR] = INLINE {PPUtil.ShowChar[c]};

WriteString: PROC [s: ROPE] = INLINE {PPUtil.ShowRope[s]};

WriteQuotedText: SAFE PROC [s: ROPE] = TRUSTED {
OPEN PPUtil;
EachChar: SAFE PROC [c: CHAR] RETURNS [BOOL] = TRUSTED {
IF c = '" THEN ShowChar['"];
ShowChar[c]; RETURN [FALSE]};
IF s # NIL THEN {
ShowChar['"];
[] ← Rope.Map[base: s, action: EachChar];
ShowChar['"]}};

WriteDecimal: PROC [n: INT] = INLINE {PPUtil.ShowDecimal[n]};

NewLine: PROC = INLINE {PPUtil.ShowCR[]};

Indent: PROC [n: NAT] = {
NewLine[];
THROUGH [1..n/8] DO WriteChar[TAB] ENDLOOP;
THROUGH [1..n MOD 8] DO WriteChar[' ] ENDLOOP};

-- csrP and desc.base are set by Enter

csrP: PPDebugTable.CSRptr;
ss: LONG STRINGNIL;

Enter: PROC = {
csrP ← PPUtil.AcquireTable[debug];
ss ← @csrP[csrP.stringOffset]};

Exit: PROC =
{PPUtil.ReleaseTable[debug]; csrP ← NIL; ss ← NIL};

WriteSubString: PROC [offset,length: CARDINAL] = {
FOR i: CARDINAL IN [offset..offset+length)
DO WriteChar[ss[i]] ENDLOOP};

-- tree printing

PrintTree: PUBLIC SAFE PROC
[t: Tree.Link, put: PutClosure ← NullPutClosure] = TRUSTED {
IF put # NullPutClosure THEN
IF NOT PPUtil.SetOutput[put] THEN ERROR;
Enter[]; PrintSubTree[t, 0]; NewLine[]; NewLine[];
{index: INT ← 0;
DO
ref: CT.Ref ← CT.FindNextComment[index];
IF ref = NIL THEN EXIT;
NewLine[];
index ← CT.Explode[ref].start+1;
ENDLOOP};
NewLine[]; NewLine[];
Exit[];
IF put # NullPutClosure THEN
IF NOT PPUtil.SetOutput[] THEN ERROR
};

PrintSubTree: PROC [t: Tree.Link, nBlanks: NAT] = TRUSTED {
OPEN Tree;

Printer: Tree.Scan = TRUSTED {
Indent[nBlanks];
IF t = Tree.Null
THEN WriteString["<empty>"]
ELSE
WITH t SELECT FROM
  hti: HTIndex => PrintHti[hti];
  sei: ISEIndex => PrintSei[sei];
  node: Tree.Handle => {
  WriteNodeName[node.name];
IF node.info # 0 THEN {
WriteString[" info="];
WriteDecimal[node.info]};
IF node.attr # ALL[FALSE]
  THEN {
   IF node.info = 0 THEN WriteChar[' ];
   WriteChar['(];
   FOR i: Tree.AttrId IN Tree.AttrId
   DO IF node.attr[i] THEN WriteChar[i+'0] ENDLOOP;
   WriteChar[')]};
  nBlanks ← nBlanks + 2;
  PPTreeOps.ScanSons[t, Printer];
  nBlanks ← nBlanks - 2};
lti: LTIndex => PrintLti[lti];
ENDCASE => PrintLiteral[t]};

Printer[t]};

WriteNodeName: PROC [n: Tree.NodeName] = {
WriteSubString[csrP.NodePrintName[n].offset,
csrP.NodePrintName[n].length]};

PrintLiteral: PROC [t: Tree.Link] = {
WITH t SELECT FROM
s: Rope.Text => {
 WriteChar['"];
FOR i: NAT IN [0..s.length) DO WriteChar[s[i]] ENDLOOP;
 WriteChar['"]};
n: REF CARDINAL => WriteDecimal[n^];
ENDCASE => WriteChar['?]};

PrintLti: PROC [lti: LTIndex] = {
val: REF ← lti.value;
WITH val SELECT FROM
txt: ROPE => WriteQuotedText[txt];
ENDCASE => WriteString[lti.literal];
PrintIndex[lti.index];
};

PrintIndex: PROC [index: INT] = {
IF index # LAST[INT] THEN {
WriteString[" {index: "];
WriteDecimal[index];
WriteString["}"]}};

PrintHti: PROC [hti: HTIndex] = {
IF hti = HTNull
THEN WriteString["(anon)"]
ELSE {
 WriteString[hti.name];
PrintIndex[hti.index]}};

PrintSei: PROC [sei: ISEIndex] = {
IF sei = NIL
THEN WriteString["(anon)"]
ELSE {WriteString[sei]}};

END.