blob: e32be5dde8937b83348b3aa907ae6706ccce1e8d [file] [log] [blame]
/*@z25.c:Object Echo:aprint(), cprint(), printnum()@**************************/
/* */
/* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.24) */
/* COPYRIGHT (C) 1991, 2000 Jeffrey H. Kingston */
/* */
/* Jeffrey H. Kingston (jeff@cs.usyd.edu.au) */
/* Basser Department of Computer Science */
/* The University of Sydney 2006 */
/* AUSTRALIA */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either Version 2, or (at your option) */
/* any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */
/* */
/* FILE: z25.c */
/* MODULE: Object Echo */
/* EXTERNS: EchoObject(), DebugObject() */
/* */
/*****************************************************************************/
#include "externs.h"
#if DEBUG_ON
static int limit; /* column where newline is needed */
static int indent; /* current indent */
static int col; /* current output column */
static FILE *fp; /* current output file */
#define moveright() (indent += 3)
#define moveleft() (indent -= 3)
/*****************************************************************************/
/* */
/* static aprint(x) */
/* static cprint(x) */
/* */
/* Print the ASCII or FULL_CHAR string x onto the appropriate output. */
/* */
/*****************************************************************************/
static void cprint(FULL_CHAR *x)
{ col += StringLength(x);
if( fp == null ) AppendString(x);
else StringFPuts(x, fp);
} /* end print */
static void aprint(char *x)
{ cprint(AsciiToFull(x));
} /* end aprint */
/*****************************************************************************/
/* */
/* static printnum(x) */
/* */
/* Print the number x onto the appropriate output. */
/* */
/*****************************************************************************/
static void printnum(int x)
{ cprint(StringInt(x));
} /* end printnum */
/*@::tab(), newline(), space()@***********************************************/
/* */
/* static tab(x) */
/* */
/* Tab to column x, or anyway insert at least one space. */
/* */
/*****************************************************************************/
static void tab(int x)
{ do
aprint(" ");
while( col < x );
} /* end tab */
/*****************************************************************************/
/* */
/* static newline() */
/* */
/* Echo a newline to the appropriate output (unless output is a string). */
/* Correct indenting and right limits are maintained, if possible. */
/* */
/*****************************************************************************/
static void newline(void)
{ if( fp == null ) AppendString(STR_SPACE);
else
{ fputs("\n", fp);
fflush(fp);
for( col = 0; col < indent; col++ ) fputs(" ", fp);
}
} /* end newline */
/*@::echo()@******************************************************************/
/* */
/* static echo(x, outer_prec, count) */
/* */
/* Echo x. The result will be enclosed in braces only if its precedence */
/* is less than or equal to outer_prec (words and parameterless closures */
/* are taken to have infinite precedence, i.e. never enclosed in braces). */
/* */
/* x is child number count of its parent. Used by COL_THR and ROW_THR */
/* only. */
/* */
/*****************************************************************************/
static void echo(OBJECT x, unsigned outer_prec, int count)
{ OBJECT link, y, tmp, sym, z;
char *op; int prec, i, childcount, ycount;
BOOLEAN npar_seen, name_printed, lbr_printed, braces_needed;
switch( type(x) )
{
case DEAD:
aprint("#dead");
break;
case UNDER_REC:
aprint("#under_rec");
break;
case UNATTACHED:
aprint( "#unattached " );
moveright();
if( Down(x) != x )
{ CountChild(y, Down(x), count);
if( y != x ) echo(y, NO_PREC, count);
else aprint("<child is self!>");
}
else aprint("<no child!>");
moveleft();
break;
case SCALE_IND:
case COVER_IND:
case EXPAND_IND:
case GALL_PREC:
case GALL_FOLL:
case GALL_FOLL_OR_PREC:
case GALL_TARG:
case CROSS_PREC:
case CROSS_FOLL:
case CROSS_FOLL_OR_PREC:
case CROSS_TARG:
case RECURSIVE:
case PAGE_LABEL_IND:
/* aprint("#"); cprint(Image(type(x))); aprint(" "); */
echo(actual(x), NO_PREC, 1);
break;
case RECEPTIVE:
case RECEIVING:
aprint(type(x) == RECEIVING ? "#receiving " : "#receptive ");
if( external_ver(actual(x)) ) aprint("(external_ver) ");
if( external_hor(actual(x)) ) aprint("(external_hor) ");
if( threaded(actual(x)) ) aprint("(threaded) ");
if( blocked(x) ) aprint("(blocked) " );
if( trigger_externs(x) ) aprint("(trigger_externs) " );
if( non_blocking(x) ) aprint("(non_blocking) " );
cprint( type(actual(x)) == CLOSURE ?
SymName(actual(actual(x))) : Image(type(actual(x))) );
aprint(" ");
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
moveright();
echo(y, NO_PREC, count);
moveleft();
}
break;
case PRECEDES:
aprint("#precedes");
break;
case FOLLOWS:
aprint("#follows");
if( blocked(x) ) aprint(" (blocked)");
CountChild(y, Down(x), count);
if( Up(y) == LastUp(y) ) aprint(" (no precedes!)");
break;
case HEAD:
aprint("Galley "); cprint(SymName(actual(x)));
aprint(" into "); cprint(SymName(whereto(x)));
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
newline();
echo(y, type(y) == GAP_OBJ ? VCAT : VCAT_PREC, count);
}
break;
case ROW_THR:
aprint("{R ");
for( i=0, link = Down(x); link != x && i < count ; link = NextDown(link), i++ );
if( link != x )
{ CountChild(y, link, count);
echo(y, VCAT_PREC, count);
/* newline(); */
}
aprint(" R}");
break;
/* ***
case COL_THR:
aprint("{C ");
for( i=0, link = Down(x); link != x && i < count ; link = NextDown(link), i++ );
if( link != x )
{ CountChild(y, link, count);
echo(y, HCAT_PREC, count);
}
aprint(" C}");
break;
*** */
case COL_THR:
aprint("{C ");
newline();
for( i=1, link = Down(x); link != x; link = NextDown(link), i++ )
{
if( i == count )
aprint("C@ ");
else
aprint("C: ");
CountChild(y, link, ycount);
echo(y, HCAT_PREC, ycount);
newline();
}
aprint(" C}");
break;
case HSPANNER:
aprint("{HS ");
CountChild(y, Down(x), count);
echo(y, NO_PREC, count);
aprint(" HS}");
break;
case VSPANNER:
aprint("{VS ");
CountChild(y, Down(x), count);
echo(y, NO_PREC, count);
aprint(" VS}");
break;
case THREAD:
aprint("<thread>");
break;
case VCAT: op = "/", prec = VCAT_PREC; goto ETC;
case HCAT: op = "|", prec = HCAT_PREC; goto ETC;
ETC:
if( Down(x) == x )
{ aprint(op);
aprint("<empty>");
break;
}
if( prec <= outer_prec ) aprint("{ ");
/* *** if( Down(x) == LastDown(x) ) aprint(op); must be manifested */
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
if( is_index(type(y)) )
newline();
else if( (type(y) == GAP_OBJ && type(x) != ACAT) )
newline();
if( type(y) == GAP_OBJ ) echo(y, type(x), count);
else echo(y, prec, count);
}
if( prec <= outer_prec ) aprint(" }");
break;
case ACAT: op = "&", prec = ACAT_PREC;
childcount = 0;
aprint("[[ ");
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
if( type(y) == GAP_OBJ )
{
echo(y, ACAT, count);
continue;
}
childcount++;
aprint("[");
echo(y, prec, count);
aprint("]");
/* ***
if( link == Down(x) || link == LastDown(x) )
echo(y, prec, count);
else if( NextDown(NextDown(link)) == LastDown(x) )
{ sprintf(buff, " ++%d++ ", childcount+1);
aprint(buff);
}
*** */
}
aprint(" ]]");
break;
case GAP_OBJ:
/* in this case the outer_prec argument is VCAT, HCAT or ACAT */
if( Down(x) != x )
{ if( outer_prec == ACAT ) aprint(" ");
cprint( EchoCatOp(outer_prec, mark(gap(x)), join(gap(x))) );
CountChild(y, Down(x), count);
echo(y, FORCE_PREC, count);
aprint(" ");
}
/* ***
else if( outer_prec == ACAT )
{ for( i = 1; i <= vspace(x); i++ ) newline();
for( i = 1; i <= hspace(x); i++ ) aprint(" ");
}
*** */
else
{ cprint( EchoCatOp(outer_prec, mark(gap(x)), join(gap(x))) );
cprint( EchoGap(&gap(x)) );
aprint(" ");
}
break;
case WORD:
if( StringLength(string(x)) == 0 )
aprint("{}");
else
{ aprint("\"");
cprint( string(x) );
aprint("\"");
}
break;
case QWORD:
cprint( StringQuotedWord(x) );
break;
case ENV:
/* debug only */
aprint("<");
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
if( type(y) == CLOSURE )
{ cprint( SymName(actual(y)) );
if( LastDown(y) != y ) echo(GetEnv(y), NO_PREC, count);
}
else if( type(y) == ENV ) echo(y, NO_PREC, count);
else cprint(Image(type(y)));
if( NextDown(link) != x ) aprint(" ");
}
aprint(">");
break;
case CROSS:
case FORCE_CROSS:
assert( Down(x) != x, "echo: CROSS Down(x)!" );
CountChild(y, Down(x), count);
if( type(y) == CLOSURE ) cprint(SymName(actual(y)));
else
{ cprint(KW_LBR);
echo(y, NO_PREC, count);
cprint(KW_RBR);
}
cprint(Image(type(x)));
/* ***
cprint(KW_CROSS);
aprint("<");
cprint(Image(cross_type(x)));
aprint(">");
*** */
aprint(" ");
if( NextDown(Down(x)) != x )
{ CountChild(y, NextDown(Down(x)), count);
echo(y, NO_PREC, count);
}
else aprint("??");
break;
case CLOSURE:
sym = actual(x);
braces_needed =
precedence(sym) <= outer_prec && (has_lpar(sym) || has_rpar(sym));
/* print brace if needed */
if( braces_needed ) aprint("{ ");
npar_seen = FALSE; name_printed = FALSE;
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
if( type(y) == PAR )
{ assert( Down(y) != y, "EchoObject: Down(PAR)!" );
switch( type(actual(y)) )
{
case LPAR: Child(tmp, Down(y));
echo(tmp, (unsigned) precedence(sym), 1);
aprint(" ");
break;
case NPAR: if( !name_printed )
{ cprint(SymName(sym));
aprint("%");
cprint(SymName(enclosing(sym)));
if( external_ver(x) || external_hor(x) || threaded(x) )
{ aprint(" #");
if( external_ver(x) ) aprint(" external_ver");
if( external_hor(x) ) aprint(" external_hor");
if( threaded(x) ) aprint(" threaded");
newline();
}
name_printed = TRUE;
}
newline(); aprint(" ");
cprint( SymName(actual(y)) );
aprint(" { ");
Child(tmp, Down(y));
echo(tmp, NO_PREC, 1);
aprint(" }");
npar_seen = TRUE;
break;
case RPAR: if( !name_printed )
{ cprint(SymName(sym));
aprint("%");
cprint(SymName(enclosing(sym)));
if( external_ver(x) || external_hor(x) || threaded(x) )
{ aprint(" #");
if( external_ver(x) ) aprint(" external_ver");
if( external_hor(x) ) aprint(" external_hor");
if( threaded(x) ) aprint(" threaded");
newline();
}
name_printed = TRUE;
}
if( npar_seen ) newline();
else aprint(" ");
Child(tmp, Down(y));
if( has_body(sym) )
{ aprint("{ ");
echo(tmp, NO_PREC, 1);
aprint(" }");
}
else echo(tmp, (unsigned) precedence(sym), 1);
break;
default: assert1(FALSE, "echo:", Image(type(actual(y))));
break;
}
}
}
if( !name_printed )
{ cprint( SymName(sym) );
aprint("%");
cprint(SymName(enclosing(sym)));
if( external_ver(x) || external_hor(x) || threaded(x) )
{ aprint(" #");
if( external_ver(x) ) aprint(" external_ver");
if( external_hor(x) ) aprint(" external_hor");
if( threaded(x) ) aprint(" threaded");
newline();
}
}
/* print closing brace if needed */
if( braces_needed ) aprint(" }");
break;
case SPLIT:
/* this should occur only in debug output case */
cprint(KW_SPLIT); moveright();
CountChild(y, DownDim(x, COLM), count);
aprint(" COLM:");
echo(y, FORCE_PREC, count);
newline();
/* ***
Child(y, DownDim(x, ROWM));
aprint(" ROWM:");
echo(y, FORCE_PREC);
*** */
moveleft();
break;
case PAR:
/* this should occur only in debug output case */
aprint("par "); cprint(SymName(actual(x)));
break;
case CR_LIST:
aprint("(");
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
echo(y, NO_PREC, count);
if( NextDown(link) != x ) aprint(", ");
}
aprint(")");
break;
case MACRO:
newline(); cprint(KW_MACRO);
aprint(" "); cprint(SymName(x));
if( sym_body(x) != nilobj )
{ newline(); cprint(KW_LBR);
y = sym_body(x);
do
{ for( i = 1; i <= vspace(y); i++ ) newline();
for( i = 1; i <= hspace(y); i++ ) aprint(" ");
cprint(EchoToken(y));
y = succ(y, PARENT);
} while( y != sym_body(x) );
newline(); cprint(KW_RBR);
}
else aprint(" {}");
if( visible(x) ) aprint(" # (visible)");
break;
case NPAR:
case LOCAL:
/* print predefined operators in abbreviated form */
if( sym_body(x) == nilobj && enclosing(x) != nilobj )
{ tab(3); aprint("# sys ");
cprint(SymName(x));
break;
}
/* print def line and miscellaneous debug info */
if( type(x) == LOCAL ) newline();
cprint(type(x) == NPAR ? KW_NAMED : KW_DEF);
aprint(" "); cprint( SymName(x) );
if( recursive(x) || indefinite(x) || visible(x) ||
is_extern_target(x) || uses_extern_target(x) || uses_galley(x) )
{ tab(25); aprint("#");
if( visible(x) ) aprint(" visible");
if( recursive(x) ) aprint(" recursive");
if( indefinite(x) ) aprint(" indefinite");
if( is_extern_target(x) ) aprint(" is_extern_target");
if( uses_extern_target(x) ) aprint(" uses_extern_target");
if( uses_galley(x) ) aprint(" uses_galley");
}
/* print uses list, if necessary */
if( uses(x) != nilobj || dirty(x) )
{ newline(); aprint(" # ");
if( dirty(x) ) aprint("dirty, ");
aprint("uses");
if( uses(x) != nilobj )
{ tmp = next(uses(x));
do
{ aprint(" "), cprint( SymName(item(tmp)) );
tmp = next(tmp);
} while( tmp != next(uses(x)) );
}
/* ***
for( tmp = uses(x); tmp != nilobj; tmp = next(tmp) )
{ aprint(" "), cprint( SymName(item(tmp)) );
}
*** */
}
/* print precedence, if necessary */
if( precedence(x) != DEFAULT_PREC )
{ newline(); aprint(" "); cprint(KW_PRECEDENCE);
aprint(" "); printnum(precedence(x));
}
/* print associativity, if necessary */
if( !right_assoc(x) )
{ newline(); aprint(" ");
cprint(KW_ASSOC); aprint(" "); cprint(KW_LEFT);
}
/* print named parameters and local objects */
lbr_printed = FALSE;
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
assert( enclosing(y) == x, "echo: enclosing(y) != x!" );
switch( type(y) )
{
case LPAR:
case RPAR: newline(); aprint(" ");
cprint( type(y) == LPAR ? KW_LEFT :
has_body(x) ? KW_BODY : KW_RIGHT);
aprint(" ");
cprint( SymName(y) );
aprint(" # uses_count = ");
printnum(uses_count(y));
if( visible(y) ) aprint(" (visible)");
break;
case NPAR: moveright(); newline();
echo(y, NO_PREC, count);
aprint(" # uses_count = ");
printnum(uses_count(y));
moveleft();
break;
case MACRO:
case LOCAL: if( !lbr_printed )
{ newline();
cprint(KW_LBR);
lbr_printed = TRUE;
}
moveright();
echo(y, NO_PREC, count);
moveleft(); newline();
break;
default: assert1(FALSE, "echo:", Image(type(y)));
break;
}
}
if( type(x) == NPAR && Down(x) == x ) aprint(" ");
else newline();
if( !lbr_printed )
{ cprint(KW_LBR); aprint(" ");
lbr_printed = TRUE;
}
else aprint(" ");
/* print body */
moveright();
if( sym_body(x) != nilobj ) echo(sym_body(x), NO_PREC, 1);
moveleft(); if( type(x) == LOCAL ) newline();
cprint(KW_RBR);
break;
case BEGIN_HEADER:
case SET_HEADER:
case ONE_COL:
case ONE_ROW:
case HCONTRACT:
case VCONTRACT:
case HLIMITED:
case VLIMITED:
case HEXPAND:
case VEXPAND:
case START_HVSPAN:
case START_HSPAN:
case START_VSPAN:
case PADJUST:
case HADJUST:
case VADJUST:
case HSCALE:
case VSCALE:
case HCOVER:
case VCOVER:
case COMMON:
case RUMP:
case MELD:
case INSERT:
case ONE_OF:
case NEXT:
case PLUS:
case MINUS:
case WIDE:
case HIGH:
case HSHIFT:
case VSHIFT:
case INCGRAPHIC:
case SINCGRAPHIC:
case PLAIN_GRAPHIC:
case GRAPHIC:
case LINK_SOURCE:
case LINK_DEST:
case ROTATE:
case BACKGROUND:
case SCALE:
case KERN_SHRINK:
case CASE:
case YIELD:
case XCHAR:
case FONT:
case SPACE:
case YUNIT:
case ZUNIT:
case BREAK:
case UNDERLINE:
case COLOUR:
case OUTLINE:
case LANGUAGE:
case OPEN:
case TAGGED:
case ENV_OBJ:
/* print enclosing left brace if needed */
braces_needed = (DEFAULT_PREC <= outer_prec);
if( braces_needed ) cprint(KW_LBR), aprint(" ");
/* print left parameter */
if( Down(x) != LastDown(x) )
{ CountChild(y, Down(x), count);
echo(y, find_max(outer_prec, DEFAULT_PREC), count);
aprint(" ");
}
cprint(Image(type(x)));
/* print right parameter */
assert( LastDown(x) != x, "echo: right parameter of predefined!" );
aprint(" ");
CountChild(y, LastDown(x), count);
echo(y, type(x)==OPEN ? FORCE_PREC : find_max(outer_prec,DEFAULT_PREC),
count);
if( braces_needed ) aprint(" "), cprint(KW_RBR);
break;
case RAW_VERBATIM:
case VERBATIM:
cprint(type(x) == VERBATIM ? KW_VERBATIM : KW_RAWVERBATIM);
aprint(" ");
cprint(KW_LBR);
CountChild(y, Down(x), count);
if( type(y) == WORD )
{ cprint(string(y));
}
else
{ newline();
for( link = Down(y); link != y; link = NextDown(link) )
{ Child(z, link)
cprint(string(z));
newline();
}
}
cprint(KW_RBR);
break;
case CURR_LANG:
case CURR_FAMILY:
case CURR_FACE:
case CURR_YUNIT:
case CURR_ZUNIT:
case BACKEND:
case PAGE_LABEL:
case HSPAN:
case VSPAN:
case END_HEADER:
case CLEAR_HEADER:
/* predefined symbols that have (or may have) no parameters */
cprint(Image(type(x)));
break;
case FILTERED:
aprint("[filtered ");
if( Down(x) != x )
{ Child(y, Down(x));
if( type(y) != WORD ) cprint(Image(type(y)));
else cprint(string(y));
}
else aprint("?");
aprint("]");
break;
case NULL_CLOS:
cprint(Image(type(x)));
break;
case CR_ROOT:
for( link = Down(x); link != x; link = NextDown(link) )
{ CountChild(y, link, count);
echo(y, NO_PREC, count); newline();
}
break;
case CROSS_SYM:
aprint("Cross-references for ");
cprint(SymName(symb(x))); newline();
switch( target_state(x) )
{
case 0: aprint("NO_TARGET");
break;
case 1: aprint("SEEN_TARGET ");
printnum(target_seq(x));
aprint(": ");
echo(target_val(x), NO_PREC, 1);
break;
case 2: aprint("WRITTEN_TARGET ");
printnum(target_seq(x));
aprint(": to file ");
cprint(FileName(target_file(x)));
aprint(" at ");
printnum(target_pos(x));
break;
default: aprint("ILLEGAL!");
break;
}
newline();
for( link = Down(x); link != x; link = NextDown(link) )
{ Child(y, link);
aprint(" ");
cprint(Image(cs_type(y)));
aprint(": ");
cprint(string(y));
newline();
}
break;
default:
assert1(FALSE, "echo:", Image(type(x)));
break;
} /* end switch */
} /* end echo */
/*@::EchoObject(), DebugObject()@*********************************************/
/* */
/* FULL_CHAR *EchoObject(x) */
/* */
/* Return an image of unsized object x in result. */
/* */
/*****************************************************************************/
FULL_CHAR *EchoObject(OBJECT x)
{ debug0(DOE, D, "EchoObject()");
fp = null;
col = 0;
indent = 0;
limit = 60;
if( fp == null )
BeginString();
if( x == nilobj ) AppendString(AsciiToFull("<nilobj>"));
else echo(x, type(x) == GAP_OBJ ? VCAT : 0, 1);
debug0(DOE, D, "EchoObject returning");
return EndString();
} /* end EchoObject */
/*****************************************************************************/
/* */
/* DebugObject(x) */
/* */
/* Send an image of unsized object x to result. */
/* */
/*****************************************************************************/
void DebugObject(OBJECT x)
{ debug0(DOE, D, "DebugObject()");
fp = stderr;
col = 0;
indent = 0;
limit = 60;
if( x == nilobj ) fprintf(stderr, "<nilobj>");
else echo(x, type(x) == GAP_OBJ ? VCAT : 0, 1);
fprintf(stderr, "\n");
debug0(DOE, D, "DebugObject returning");
} /* end DebugObject */
/*@::EchoIndex()@*************************************************************/
/* */
/* FULL_CHAR *EchoIndex() */
/* */
/* Echo a component of a galley, briefly. */
/* */
/*****************************************************************************/
FULL_CHAR *EchoIndex(OBJECT index)
{ static char buff[MAX_BUFF]; OBJECT z;
if( index == nilobj )
{ sprintf(buff, "<nilobj>");
}
else switch( type(index) )
{
case RECEIVING:
sprintf(buff, "receiving %s%s", type(actual(index)) == CLOSURE ?
SymName(actual(actual(index))) : Image(type(actual(index))),
non_blocking(index) ? " (non_blocking)" : "");
break;
case RECEPTIVE:
sprintf(buff, "receptive %s%s", type(actual(index)) == CLOSURE ?
SymName(actual(actual(index))) : Image(type(actual(index))),
non_blocking(index) ? " (non_blocking)" : "");
break;
case UNATTACHED:
if( Down(index) != index )
{ Child(z, Down(index));
}
else z = nilobj;
sprintf(buff, "unattached %s",
z == nilobj ? AsciiToFull("<nilobj>") : SymName(actual(z)));
break;
case WORD:
case QWORD:
sprintf(buff, "\"%s\"", string(index));
break;
default:
sprintf(buff, "%s", Image(type(index)));
break;
}
return AsciiToFull(buff);
} /* end EchoIndex */
/*@::DebugGalley()@***********************************************************/
/* */
/* DebugGalley(hd, pinpt, indent) */
/* */
/* Print overview of galley hd on stderr; mark pinpoint if found */
/* */
/*****************************************************************************/
#define eprint(x, a, b, c) fprintf(stderr, "| %d %-7s %20s %s\n", x, a, b, c)
void DebugGalley(OBJECT hd, OBJECT pinpt, int indent)
{ OBJECT link, y; char istr[30]; int i;
for( i = 0; i < indent; i++ ) istr[i] = ' ';
istr[i] = '\0';
if( type(hd) != HEAD )
{ fprintf(stderr, "%shd is %s\n", istr, Image(type(hd)));
return;
}
fprintf(stderr, "%sgalley %s into %s\n", istr,
SymName(actual(hd)), SymName(whereto(hd)));
for( link = Down(hd); link != hd; link = NextDown(link) )
{ Child(y, link);
if( y == pinpt || link == pinpt )
{ fprintf(stderr, "++ %d %s ", (int) y, Image(type(y)));
DebugObject(y);
}
else
if( type(y) == GAP_OBJ )
eprint((int) y, "gap_obj", Image(type(y)), EchoGap(&gap(y)));
else if( is_index(type(y)) )
eprint((int) y, "index", Image(type(y)), "");
else if( is_definite(type(y)) )
eprint((int) y, "def_obj", Image(type(y)), is_word(type(y)) ? string(y):STR_EMPTY);
else if( is_indefinite(type(y)) )
eprint((int) y, "indefin", Image(type(y)),
type(y) == CLOSURE ? SymName(actual(y)) : STR_EMPTY);
else
eprint((int) y, "unknown", Image(type(y)), "");
}
} /* end DebugGalley */
#endif