in CTMark/consumer-typeset/z25.c [122:884]
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 */