1 /*@z25.c:Object Echo:aprint(), cprint(), printnum()@**************************/
2 /*                                                                           */
3 /*  THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.39)                       */
4 /*  COPYRIGHT (C) 1991, 2008 Jeffrey H. Kingston                             */
5 /*                                                                           */
6 /*  Jeffrey H. Kingston (jeff@it.usyd.edu.au)                                */
7 /*  School of Information Technologies                                       */
8 /*  The University of Sydney 2006                                            */
9 /*  AUSTRALIA                                                                */
10 /*                                                                           */
11 /*  This program is free software; you can redistribute it and/or modify     */
12 /*  it under the terms of the GNU General Public License as published by     */
13 /*  the Free Software Foundation; either Version 3, or (at your option)      */
14 /*  any later version.                                                       */
15 /*                                                                           */
16 /*  This program is distributed in the hope that it will be useful,          */
17 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
18 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
19 /*  GNU General Public License for more details.                             */
20 /*                                                                           */
21 /*  You should have received a copy of the GNU General Public License        */
22 /*  along with this program; if not, write to the Free Software              */
23 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA   */
24 /*                                                                           */
25 /*  FILE:         z25.c                                                      */
26 /*  MODULE:       Object Echo                                                */
27 /*  EXTERNS:      EchoObject(), DebugObject()                                */
28 /*                                                                           */
29 /*****************************************************************************/
30 #include "externs.h"
31 #if DEBUG_ON
32 
33 static	int	limit;			/* column where newline is needed    */
34 static	int	indent;			/* current indent                    */
35 static	int	col;			/* current output column             */
36 static	FILE	*fp;			/* current output file               */
37 
38 #define	moveright()	(indent += 3)
39 #define	moveleft()	(indent -= 3)
40 
41 
42 /*****************************************************************************/
43 /*                                                                           */
44 /*  static aprint(x)                                                         */
45 /*  static cprint(x)                                                         */
46 /*                                                                           */
47 /*  Print the ASCII or FULL_CHAR string x onto the appropriate output.       */
48 /*                                                                           */
49 /*****************************************************************************/
50 
cprint(FULL_CHAR * x)51 static void cprint(FULL_CHAR *x)
52 { col += StringLength(x);
53   if( fp == null ) AppendString(x);
54   else StringFPuts(x, fp);
55 } /* end print */
56 
aprint(char * x)57 static void aprint(char *x)
58 { cprint(AsciiToFull(x));
59 } /* end aprint */
60 
61 
62 /*****************************************************************************/
63 /*                                                                           */
64 /*  static printnum(x)                                                       */
65 /*                                                                           */
66 /*  Print the number x onto the appropriate output.                          */
67 /*                                                                           */
68 /*****************************************************************************/
69 
printnum(int x)70 static void printnum(int x)
71 { cprint(StringInt(x));
72 } /* end printnum */
73 
74 
75 /*@::tab(), newline(), space()@***********************************************/
76 /*                                                                           */
77 /*  static tab(x)                                                            */
78 /*                                                                           */
79 /*  Tab to column x, or anyway insert at least one space.                    */
80 /*                                                                           */
81 /*****************************************************************************/
82 
tab(int x)83 static void tab(int x)
84 {  do
85      aprint(" ");
86    while( col < x );
87 } /* end tab */
88 
89 
90 /*****************************************************************************/
91 /*                                                                           */
92 /*  static newline()                                                         */
93 /*                                                                           */
94 /*  Echo a newline to the appropriate output (unless output is a string).    */
95 /*  Correct indenting and right limits are maintained, if possible.          */
96 /*                                                                           */
97 /*****************************************************************************/
98 
newline(void)99 static void newline(void)
100 { if( fp == null )  AppendString(STR_SPACE);
101   else
102   { StringFPuts(STR_NEWLINE, fp);
103     fflush(fp);
104     for( col = 0;  col < indent;  col++ )  fputs(" ", fp);
105   }
106 } /* end newline */
107 
108 /*****************************************************************************/
109 /*                                                                           */
110 /*  static int DiffChildrenParents(OBJECT x)                                 */
111 /*                                                                           */
112 /*  Return the number of children minus the number of parents.  For          */
113 /*  the COL_THR and ROW_THR objects we are interested in, this difference    */
114 /*  should be 0.                                                             */
115 /*                                                                           */
116 /*****************************************************************************/
117 
DiffChildrenParents(OBJECT x)118 static int DiffChildrenParents(OBJECT x)
119 {
120   int pcount, ccount;
121   OBJECT link;
122   pcount = 0;
123   for( link = Up(x);  link != x;  link = NextUp(link) )
124     pcount++;
125   ccount = 0;
126   for( link = Down(x);  link != x;  link = NextDown(link) )
127     ccount++;
128   return ccount - pcount;
129 }
130 
131 
132 /*@::echo()@******************************************************************/
133 /*                                                                           */
134 /*  static echo(x, outer_prec, count)                                        */
135 /*                                                                           */
136 /*  Echo x.  The result will be enclosed in braces only if its precedence    */
137 /*  is less than or equal to outer_prec (words and parameterless closures    */
138 /*  are taken to have infinite precedence, i.e. never enclosed in braces).   */
139 /*                                                                           */
140 /*  x is child number count of its parent.  Used by COL_THR and ROW_THR      */
141 /*  only.                                                                    */
142 /*                                                                           */
143 /*****************************************************************************/
144 
echo(OBJECT x,unsigned outer_prec,int count)145 static void echo(OBJECT x, unsigned outer_prec, int count)
146 { OBJECT link, y, tmp, sym, z;
147   char *op;  int prec, i, childcount, ycount;
148   BOOLEAN npar_seen, name_printed, lbr_printed, braces_needed;
149   int cpcount;
150 
151   switch( type(x) )
152   {
153 
154     case DEAD:
155 
156 	aprint("#dead");
157 	break;
158 
159 
160     case UNDER_REC:
161 
162 	aprint("#under_rec");
163 	break;
164 
165 
166     case UNATTACHED:
167 
168 	aprint( "#unattached " );
169 	moveright();
170 	if( Down(x) != x )
171 	{ CountChild(y, Down(x), count);
172 	  if( y != x ) echo(y, NO_PREC, count);
173 	  else aprint("<child is self!>");
174 	}
175 	else aprint("<no child!>");
176 	moveleft();
177 	break;
178 
179 
180     case SCALE_IND:
181     case COVER_IND:
182     case EXPAND_IND:
183     case GALL_PREC:
184     case GALL_FOLL:
185     case GALL_FOLL_OR_PREC:
186     case GALL_TARG:
187     case CROSS_PREC:
188     case CROSS_FOLL:
189     case CROSS_FOLL_OR_PREC:
190     case CROSS_TARG:
191     case RECURSIVE:
192     case PAGE_LABEL_IND:
193 
194 	/* aprint("#"); cprint(Image(type(x))); aprint(" "); */
195 	echo(actual(x), NO_PREC, 1);
196 	break;
197 
198 
199     case RECEPTIVE:
200     case RECEIVING:
201 
202 	aprint(type(x) == RECEIVING ? "#receiving " : "#receptive ");
203 	if( external_ver(actual(x)) )  aprint("(external_ver) ");
204 	if( external_hor(actual(x)) )  aprint("(external_hor) ");
205 	if( threaded(actual(x)) )  aprint("(threaded) ");
206 	if( blocked(x) )           aprint("(blocked) " );
207 	if( trigger_externs(x) )   aprint("(trigger_externs) " );
208 	if( non_blocking(x) )      aprint("(non_blocking) " );
209 	cprint( type(actual(x)) == CLOSURE ?
210 		SymName(actual(actual(x))) : Image(type(actual(x))) );
211 	aprint(" ");
212 	for( link = Down(x);  link != x;  link = NextDown(link) )
213 	{ CountChild(y, link, count);
214 	  moveright();
215 	  echo(y, NO_PREC, count);
216 	  moveleft();
217 	}
218 	break;
219 
220 
221     case PRECEDES:
222 
223 	aprint("#precedes");
224 	break;
225 
226 
227     case FOLLOWS:
228 
229 	aprint("#follows");
230 	if( blocked(x) )  aprint(" (blocked)");
231 	CountChild(y, Down(x), count);
232 	if( Up(y) == LastUp(y) )  aprint(" (no precedes!)");
233 	break;
234 
235 
236     case HEAD:
237 
238 	aprint("Galley ");  cprint(SymName(actual(x)));
239 	aprint(" into ");   cprint(SymName(whereto(x)));
240 	for( link = Down(x);  link != x;  link = NextDown(link) )
241 	{ CountChild(y, link, count);
242 	  newline();
243 	  echo(y, type(y) == GAP_OBJ ? VCAT : VCAT_PREC, count);
244 	}
245 	break;
246 
247 
248     case ROW_THR:
249 
250 	aprint("{R ");
251 	cpcount = DiffChildrenParents(x);
252 	printnum(cpcount);
253 	aprint(" ");
254 	for( i=0, link = Down(x);  link != x && i < count ;  link = NextDown(link), i++ );
255 	if( link != x )
256 	{ CountChild(y, link, count);
257 	  echo(y, VCAT_PREC, count);
258 	  /* newline(); */
259 	}
260 	aprint(" R}");
261 	break;
262 
263 
264     case COL_THR:
265 
266 	aprint("{C ");
267 	cpcount = DiffChildrenParents(x);
268 	printnum(cpcount);
269 	aprint(" ");
270 	newline();
271 	for( i=1, link = Down(x);  link != x;  link = NextDown(link), i++ )
272 	{
273 	  if( i == count )
274 	    aprint("C@ ");
275 	  else
276 	    aprint("C: ");
277 	  CountChild(y, link, ycount);
278 	  echo(y, HCAT_PREC, ycount);
279 	  newline();
280 	}
281 	aprint(" C}");
282 	break;
283 
284 
285     case HSPANNER:
286 
287 	aprint("{HS ");
288 	CountChild(y, Down(x), count);
289 	echo(y, NO_PREC, count);
290 	aprint(" HS}");
291 	break;
292 
293 
294     case VSPANNER:
295 
296 	aprint("{VS ");
297 	CountChild(y, Down(x), count);
298 	echo(y, NO_PREC, count);
299 	aprint(" VS}");
300 	break;
301 
302 
303     case THREAD:
304 
305 	aprint("<thread>");
306 	break;
307 
308 
309     case VCAT: op = "/", prec = VCAT_PREC;  goto ETC;
310     case HCAT: op = "|", prec = HCAT_PREC;  goto ETC;
311 
312 	ETC:
313 	if( Down(x) == x )
314 	{ aprint(op);
315 	  aprint("<empty>");
316 	  break;
317 	}
318 	if( prec <= outer_prec ) aprint("{ ");
319 	/* *** if( Down(x) == LastDown(x) )  aprint(op);  must be manifested */
320 	for( link = Down(x);  link != x;  link = NextDown(link) )
321 	{ CountChild(y, link, count);
322 	  if( is_index(type(y)) )
323 	    newline();
324 	  else if( (type(y) == GAP_OBJ && type(x) != ACAT) )
325 	    newline();
326 	  if( type(y) == GAP_OBJ )  echo(y, type(x), count);
327 	  else echo(y, prec, count);
328 	}
329 	if( prec <= outer_prec )  aprint(" }");
330 	break;
331 
332 
333     case ACAT: op = "&", prec = ACAT_PREC;
334 
335 	childcount = 0;
336 	aprint("[[ ");
337 	for( link = Down(x);  link != x;  link = NextDown(link) )
338 	{ CountChild(y, link, count);
339 	  if( type(y) == GAP_OBJ )
340 	  {
341 	    echo(y, ACAT, count);
342 	    continue;
343 	  }
344 	  childcount++;
345 	  aprint("[");
346 	  echo(y, prec, count);
347 	  aprint("]");
348 	  /* ***
349 	  if( link == Down(x) || link == LastDown(x) )
350 	    echo(y, prec, count);
351 	  else if( NextDown(NextDown(link)) == LastDown(x) )
352 	  { sprintf(buff, " ++%d++ ", childcount+1);
353 	    aprint(buff);
354 	  }
355 	  *** */
356 	}
357 	aprint(" ]]");
358 	break;
359 
360 
361     case GAP_OBJ:
362 
363 	/* in this case the outer_prec argument is VCAT, HCAT or ACAT */
364 	if( outer_prec == ACAT )  aprint(" ");
365 	if( Down(x) != x )
366 	{
367 	  cprint( EchoCatOp(outer_prec, mark(gap(x)), join(gap(x))) );
368 	  CountChild(y, Down(x), count);
369 	  echo(y, FORCE_PREC, count);
370 	}
371 	/* ***
372 	else if( outer_prec == ACAT )
373 	{ for( i = 1;  i <= vspace(x);  i++ )  newline();
374 	  for( i = 1;  i <= hspace(x);  i++ )  aprint(" ");
375 	}
376 	*** */
377 	else
378 	{ cprint( EchoCatOp(outer_prec, mark(gap(x)), join(gap(x))) );
379 	  cprint( EchoGap(&gap(x)) );
380 	}
381 	aprint(" ");
382 	break;
383 
384 
385     case WORD:
386 
387 	if( StringLength(string(x)) == 0 )
388 	  aprint("{}");
389 	else
390 	{ aprint("\"");
391 	  cprint( string(x) );
392 	  aprint("\"");
393 	}
394 	break;
395 
396 
397     case QWORD:
398 
399 	cprint( StringQuotedWord(x) );
400 	break;
401 
402 
403     case ENV:
404 
405 	/* debug only */
406 	aprint("<");
407 	for( link = Down(x);  link != x;  link = NextDown(link) )
408 	{ CountChild(y, link, count);
409 	  if( type(y) == CLOSURE )
410 	  { cprint( SymName(actual(y)) );
411 	    if( LastDown(y) != y )  echo(GetEnv(y), NO_PREC, count);
412 	  }
413 	  else if( type(y) == ENV )  echo(y, NO_PREC, count);
414 	  else cprint(Image(type(y)));
415 	  if( NextDown(link) != x )  aprint(" ");
416 	}
417 	aprint(">");
418 	break;
419 
420 
421     case CROSS:
422     case FORCE_CROSS:
423 
424 	assert( Down(x) != x, "echo: CROSS Down(x)!" );
425 	CountChild(y, Down(x), count);
426 	if( type(y) == CLOSURE )  cprint(SymName(actual(y)));
427 	else
428 	{ cprint(KW_LBR);
429 	  echo(y, NO_PREC, count);
430 	  cprint(KW_RBR);
431 	}
432 	cprint(Image(type(x)));
433 	/* ***
434 	cprint(KW_CROSS);
435 	aprint("<");
436 	cprint(Image(cross_type(x)));
437 	aprint(">");
438 	*** */
439 	aprint(" ");
440 	if( NextDown(Down(x)) != x )
441 	{ CountChild(y, NextDown(Down(x)), count);
442 	  echo(y, NO_PREC, count);
443 	}
444 	else aprint("??");
445 	break;
446 
447 
448     case CLOSURE:
449 
450 	sym = actual(x);
451 	braces_needed =
452 	    precedence(sym) <= outer_prec && (has_lpar(sym) || has_rpar(sym));
453 
454 	/* print brace if needed */
455 	if( braces_needed )  aprint("{ ");
456 
457 	npar_seen = FALSE;  name_printed = FALSE;
458 	for( link = Down(x); link != x;  link = NextDown(link) )
459 	{ CountChild(y, link, count);
460 	  if( type(y) == PAR )
461 	  { assert( Down(y) != y, "EchoObject: Down(PAR)!" );
462 	    switch( type(actual(y)) )
463 	    {
464 	     case LPAR:	Child(tmp, Down(y));
465 			echo(tmp, (unsigned) precedence(sym), 1);
466 			aprint(" ");
467 			break;
468 
469 	     case NPAR:	if( !name_printed )
470 			{ cprint(SymName(sym));
471 			  aprint("%");
472 			  cprint(SymName(enclosing(sym)));
473 			  if( external_ver(x) || external_hor(x) || threaded(x) )
474 			  { aprint(" #");
475 			    if( external_ver(x) )  aprint(" external_ver");
476 			    if( external_hor(x) )  aprint(" external_hor");
477 			    if( threaded(x) )  aprint(" threaded");
478 			    newline();
479 			  }
480 			  name_printed = TRUE;
481 			}
482 			newline();  aprint("  ");
483 			cprint( SymName(actual(y)) );
484 			aprint(" { ");
485 			Child(tmp, Down(y));
486 			echo(tmp, NO_PREC, 1);
487 			aprint(" }");
488 			npar_seen = TRUE;
489 			break;
490 
491 	     case RPAR:	if( !name_printed )
492 			{ cprint(SymName(sym));
493 			  aprint("%");
494 			  cprint(SymName(enclosing(sym)));
495 			  if( external_ver(x) || external_hor(x) || threaded(x) )
496 			  { aprint(" #");
497 			    if( external_ver(x) )  aprint(" external_ver");
498 			    if( external_hor(x) )  aprint(" external_hor");
499 			    if( threaded(x) )  aprint(" threaded");
500 			    newline();
501 			  }
502 			  name_printed = TRUE;
503 			}
504 			if( npar_seen ) newline();
505 			else aprint(" ");
506 			Child(tmp, Down(y));
507 			if( has_body(sym) )
508 			{ aprint("{ ");
509 			  echo(tmp, NO_PREC, 1);
510 			  aprint(" }");
511 			}
512 			else echo(tmp, (unsigned) precedence(sym), 1);
513 			break;
514 
515 	     default:	assert1(FALSE, "echo:", Image(type(actual(y))));
516 			break;
517 
518 	    }
519 	  }
520 	}
521 	if( !name_printed )
522 	{ cprint( SymName(sym) );
523 	  aprint("%");
524 	  cprint(SymName(enclosing(sym)));
525 	  if( external_ver(x) || external_hor(x) || threaded(x) )
526 	  { aprint(" #");
527 	    if( external_ver(x) )  aprint(" external_ver");
528 	    if( external_hor(x) )  aprint(" external_hor");
529 	    if( threaded(x) )  aprint(" threaded");
530 	    newline();
531 	  }
532 	}
533 
534 	/* print closing brace if needed */
535 	if( braces_needed ) aprint(" }");
536 	break;
537 
538 
539     case SPLIT:
540 
541 	/* this should occur only in debug output case */
542 	cprint(KW_SPLIT);  moveright();
543 	CountChild(y, DownDim(x, COLM), count);
544 	aprint(" COLM:");
545 	echo(y, FORCE_PREC, count);
546 	newline();
547 	Child(y, DownDim(x, ROWM));
548 	aprint(" ROWM:");
549 	echo(y, FORCE_PREC, count);
550 	moveleft();
551 	break;
552 
553 
554     case PAR:
555 
556 	/* this should occur only in debug output case */
557 	aprint("par ");  cprint(SymName(actual(x)));
558 	break;
559 
560 
561     case CR_LIST:
562 
563 	aprint("(");
564 	for( link = Down(x);  link != x;  link = NextDown(link) )
565 	{ CountChild(y, link, count);
566 	  echo(y, NO_PREC, count);
567 	  if( NextDown(link) != x )  aprint(", ");
568 	}
569 	aprint(")");
570 	break;
571 
572 
573     case MACRO:
574 
575 	newline();  cprint(KW_MACRO);
576 	aprint(" ");  cprint(SymName(x));
577 	if( sym_body(x) != nilobj )
578 	{ newline();  cprint(KW_LBR);
579 	  y = sym_body(x);
580 	  do
581 	  { for( i = 1;  i <= vspace(y);  i++ )  newline();
582 	    for( i = 1;  i <= hspace(y);  i++ )  aprint(" ");
583 	    cprint(EchoToken(y));
584 	    y = succ(y, PARENT);
585 	  } while( y != sym_body(x) );
586 	  newline();  cprint(KW_RBR);
587 	}
588 	else aprint(" {}");
589 	if( visible(x) )  aprint(" # (visible)");
590 	break;
591 
592 
593     case NPAR:
594     case LOCAL:
595 
596 	/* print predefined operators in abbreviated form */
597 	if( sym_body(x) == nilobj && enclosing(x) != nilobj )
598 	{ tab(3); aprint("# sys ");
599 	  cprint(SymName(x));
600 	  break;
601 	}
602 
603 	/* print def line and miscellaneous debug info */
604 	if( type(x) == LOCAL ) newline();
605 	cprint(type(x) == NPAR ? KW_NAMED : KW_DEF);
606 	aprint(" ");  cprint( SymName(x) );
607 	if( recursive(x) || indefinite(x) || visible(x) ||
608 	    is_extern_target(x) || uses_extern_target(x) || uses_galley(x) )
609 	{ tab(25);  aprint("#");
610 	  if( visible(x)  )  aprint(" visible");
611 	  if( recursive(x)  )  aprint(" recursive");
612 	  if( indefinite(x) )  aprint(" indefinite");
613 	  if( is_extern_target(x) )  aprint(" is_extern_target");
614 	  if( uses_extern_target(x) )  aprint(" uses_extern_target");
615 	  if( uses_galley(x) )  aprint(" uses_galley");
616 	}
617 
618 	/* print uses list, if necessary */
619 	if( uses(x) != nilobj || dirty(x) )
620 	{ newline();  aprint("   # ");
621 	  if( dirty(x) ) aprint("dirty, ");
622 	  aprint("uses");
623 	  if( uses(x) != nilobj )
624 	  { tmp = next(uses(x));
625 	    do
626 	    { aprint(" "), cprint( SymName(item(tmp)) );
627 	      tmp = next(tmp);
628 	    } while( tmp != next(uses(x)) );
629 	  }
630 	  /* ***
631 	  for( tmp = uses(x);  tmp != nilobj;  tmp = next(tmp) )
632 	  { aprint(" "), cprint( SymName(item(tmp)) );
633 	  }
634 	  *** */
635 	}
636 
637 	/* print precedence, if necessary */
638 	if( precedence(x) != DEFAULT_PREC )
639 	{ newline();  aprint("   ");  cprint(KW_PRECEDENCE);
640 	  aprint(" ");  printnum(precedence(x));
641 	}
642 
643 	/* print associativity, if necessary */
644 	if( !right_assoc(x) )
645 	{ newline();  aprint("   ");
646 	  cprint(KW_ASSOC);  aprint(" ");  cprint(KW_LEFT);
647 	}
648 
649 	/* print named parameters and local objects */
650 	lbr_printed = FALSE;
651 	for( link = Down(x);  link != x;  link = NextDown(link) )
652 	{ CountChild(y, link, count);
653 	  assert( enclosing(y) == x, "echo: enclosing(y) != x!" );
654 	  switch( type(y) )
655 	  {
656 	    case LPAR:
657 	    case RPAR:	newline();  aprint("   ");
658 			cprint( type(y) == LPAR ? KW_LEFT :
659 			    has_body(x) ? KW_BODY : KW_RIGHT);
660 			aprint(" ");
661 			cprint( SymName(y) );
662 			aprint("   # uses_count = ");
663 			printnum(uses_count(y));
664 			if( visible(y) )  aprint(" (visible)");
665 			break;
666 
667 	    case NPAR:	moveright();  newline();
668 			echo(y, NO_PREC, count);
669 			aprint("   # uses_count = ");
670 			printnum(uses_count(y));
671 			moveleft();
672 			break;
673 
674 	    case MACRO:
675 	    case LOCAL:	if( !lbr_printed )
676 			{ newline();
677 			  cprint(KW_LBR);
678 			  lbr_printed = TRUE;
679 			}
680 			moveright();
681 			echo(y, NO_PREC, count);
682 			moveleft();  newline();
683 			break;
684 
685 	    default:	assert1(FALSE, "echo:", Image(type(y)));
686 			break;
687 	  }
688 	}
689 	if( type(x) == NPAR && Down(x) == x )  aprint(" ");
690 	else newline();
691 	if( !lbr_printed )
692 	{ cprint(KW_LBR);  aprint("  ");
693 	  lbr_printed = TRUE;
694 	}
695 	else aprint("   ");
696 
697 	/* print body */
698 	moveright();
699 	if( sym_body(x) != nilobj )  echo(sym_body(x), NO_PREC, 1);
700 	moveleft();  if( type(x) == LOCAL ) newline();
701 	cprint(KW_RBR);
702 	break;
703 
704 
705     case ONE_COL:
706     case ONE_ROW:
707     case HCONTRACT:
708     case VCONTRACT:
709     case HLIMITED:
710     case VLIMITED:
711     case HEXPAND:
712     case VEXPAND:
713     case START_HVSPAN:
714     case START_HSPAN:
715     case START_VSPAN:
716     case PADJUST:
717     case HADJUST:
718     case VADJUST:
719     case HMIRROR:
720     case VMIRROR:
721     case HSCALE:
722     case VSCALE:
723     case HCOVER:
724     case VCOVER:
725     case COMMON:
726     case RUMP:
727     case MELD:
728     case INSERT:
729     case ONE_OF:
730     case NEXT:
731     case PLUS:
732     case MINUS:
733     case WIDE:
734     case HIGH:
735     case HSHIFT:
736     case VSHIFT:
737     case INCGRAPHIC:
738     case SINCGRAPHIC:
739     case PLAIN_GRAPHIC:
740     case GRAPHIC:
741     case LINK_SOURCE:
742     case LINK_DEST:
743     case LINK_DEST_NULL:
744     case LINK_URL:
745     case ROTATE:
746     case BACKGROUND:
747     case SCALE:
748     case KERN_SHRINK:
749     case CASE:
750     case YIELD:
751     case XCHAR:
752     case FONT:
753     case SPACE:
754     case YUNIT:
755     case ZUNIT:
756     case SET_CONTEXT:
757     case GET_CONTEXT:
758     case BREAK:
759     case UNDERLINE:
760     case UNDERLINE_COLOUR:
761     case COLOUR:
762     case TEXTURE:
763     case OUTLINE:
764     case LANGUAGE:
765     case OPEN:
766     case TAGGED:
767     case ENV_OBJ:
768 
769 
770 	/* print enclosing left brace if needed */
771 	braces_needed = (DEFAULT_PREC <= outer_prec);
772 	if( braces_needed )  cprint(KW_LBR), aprint(" ");
773 
774 	/* print left parameter, if any */
775 	if( Down(x) != LastDown(x) )
776 	{ CountChild(y, Down(x), count);
777 	  echo(y, find_max(outer_prec, DEFAULT_PREC), count);
778 	  aprint(" ");
779 	}
780 
781 	cprint(Image(type(x)));
782 
783 	/* print right parameter */
784 	assert( LastDown(x) != x, "echo: right parameter of predefined!" );
785 	aprint(" ");
786 	CountChild(y, LastDown(x), count);
787 	echo(y, type(x)==OPEN ? FORCE_PREC : find_max(outer_prec,DEFAULT_PREC),
788 	  count);
789 	if( braces_needed )  aprint(" "), cprint(KW_RBR);
790 	break;
791 
792 
793     case BEGIN_HEADER:
794     case SET_HEADER:
795 
796 	/* print enclosing left brace if needed */
797 	braces_needed = (DEFAULT_PREC <= outer_prec);
798 	if( braces_needed )  cprint(KW_LBR), aprint(" ");
799 
800 	/* print left parameter */
801 	if( Down(x) != LastDown(x) )
802 	{ CountChild(y, Down(x), count);
803 	  echo(y, find_max(outer_prec, DEFAULT_PREC), count);
804 	  aprint(" ");
805 	}
806 
807 	cprint(Image(type(x)));
808 
809 	/* print right parameter copies */
810 	for( link = NextDown(Down(x)), i=1; link != x; link = NextDown(link), i++ )
811 	{
812 	  newline();
813 	  printnum(i);
814 	  aprint(": ");
815 	  CountChild(y, link, count);
816 	  echo(y, find_max(outer_prec,DEFAULT_PREC), count);
817 	}
818 	if( braces_needed )  aprint(" "), cprint(KW_RBR);
819 	break;
820 
821 
822     case RAW_VERBATIM:
823     case VERBATIM:
824 
825 	cprint(type(x) == VERBATIM ? KW_VERBATIM : KW_RAWVERBATIM);
826 	aprint(" ");
827 	cprint(KW_LBR);
828 	CountChild(y, Down(x), count);
829 	if( type(y) == WORD )
830 	{ cprint(string(y));
831 	}
832 	else
833 	{ newline();
834 	  for( link = Down(y);  link != y;  link = NextDown(link) )
835 	  { Child(z, link)
836 	    cprint(string(z));
837 	    newline();
838 	  }
839 	}
840 	cprint(KW_RBR);
841 	break;
842 
843 
844     case CURR_LANG:
845     case CURR_FAMILY:
846     case CURR_FACE:
847     case CURR_YUNIT:
848     case CURR_ZUNIT:
849     case BACKEND:
850     case PAGE_LABEL:
851     case HSPAN:
852     case VSPAN:
853     case END_HEADER:
854     case CLEAR_HEADER:
855 
856 	/* predefined symbols that have (or may have) no parameters */
857 	cprint(Image(type(x)));
858 	break;
859 
860 
861     case FILTERED:
862 
863 	aprint("[filtered ");
864 	if( Down(x) != x )
865 	{ Child(y, Down(x));
866 	  if( type(y) != WORD ) cprint(Image(type(y)));
867 	  else cprint(string(y));
868 	}
869 	else aprint("?");
870 	aprint("]");
871 	break;
872 
873 
874     case NULL_CLOS:
875 
876 	cprint(Image(type(x)));
877 	break;
878 
879 
880     case CR_ROOT:
881 
882 	for( link = Down(x);  link != x;  link = NextDown(link) )
883 	{ CountChild(y, link, count);
884 	  echo(y, NO_PREC, count);  newline();
885 	}
886 	break;
887 
888 
889     case CROSS_SYM:
890 
891 	aprint("Cross-references for ");
892 	cprint(SymName(symb(x)));  newline();
893 	switch( target_state(x) )
894 	{
895 	  case 0:	aprint("NO_TARGET");
896 			break;
897 
898 	  case 1:	aprint("SEEN_TARGET ");
899 			printnum(target_seq(x));
900 			aprint(": ");
901 			echo(target_val(x), NO_PREC, 1);
902 			break;
903 
904 	  case 2:	aprint("WRITTEN_TARGET ");
905 			printnum(target_seq(x));
906 			aprint(": to file ");
907 			cprint(FileName(target_file(x)));
908 			aprint(" at ");
909 			printnum(target_pos(x));
910 			break;
911 
912 	  default:	aprint("ILLEGAL!");
913 			break;
914 	}
915 	newline();
916 	for( link = Down(x);  link != x;  link = NextDown(link) )
917 	{ Child(y, link);
918 	  aprint("   ");
919 	  cprint(Image(cs_type(y)));
920 	  aprint(": ");
921 	  cprint(string(y));
922 	  newline();
923 	}
924 	break;
925 
926 
927     default:
928 
929 	assert1(FALSE, "echo:", Image(type(x)));
930 	break;
931 
932   } /* end switch */
933 } /* end echo */
934 
935 
936 /*@::EchoObject(), DebugObject()@*********************************************/
937 /*                                                                           */
938 /*  FULL_CHAR *EchoObject(x)                                                 */
939 /*                                                                           */
940 /*  Return an image of unsized object x in result.                           */
941 /*                                                                           */
942 /*****************************************************************************/
943 
EchoObject(OBJECT x)944 FULL_CHAR *EchoObject(OBJECT x)
945 { debug0(DOE, D, "EchoObject()");
946   fp = null;
947   col = 0;
948   indent = 0;
949   limit  = 60;
950   if( fp == null )
951   BeginString();
952   if( x == nilobj )  AppendString(AsciiToFull("<nilobj>"));
953   else echo(x, type(x) == GAP_OBJ ? VCAT : 0, 1);
954   debug0(DOE, D, "EchoObject returning");
955   return EndString();
956 } /* end EchoObject */
957 
958 
959 /*****************************************************************************/
960 /*                                                                           */
961 /*  DebugObject(x)                                                           */
962 /*                                                                           */
963 /*  Send an image of unsized object x to stderr.                             */
964 /*                                                                           */
965 /*****************************************************************************/
966 
DebugObject(OBJECT x)967 void DebugObject(OBJECT x)
968 { debug0(DOE, D, "DebugObject()");
969   fp = stderr;
970   col = 0;
971   indent = 0;
972   limit  = 60;
973   if( x == nilobj )  fprintf(stderr, "<nilobj>");
974   else echo(x, type(x) == GAP_OBJ ? VCAT : 0, 1);
975   fprintf(stderr, "%s", STR_NEWLINE);
976   debug0(DOE, D, "DebugObject returning");
977 } /* end DebugObject */
978 
979 
980 /*@::EchoIndex()@*************************************************************/
981 /*                                                                           */
982 /*  FULL_CHAR *EchoIndex()                                                   */
983 /*                                                                           */
984 /*  Echo a component of a galley, briefly.                                   */
985 /*                                                                           */
986 /*****************************************************************************/
987 
EchoIndex(OBJECT index)988 FULL_CHAR *EchoIndex(OBJECT index)
989 { static char buff[MAX_BUFF];  OBJECT z;
990   if( index == nilobj )
991   { sprintf(buff, "<nilobj>");
992   }
993   else switch( type(index) )
994   {
995     case RECEIVING:
996 
997       sprintf(buff, "receiving %s%s", type(actual(index)) == CLOSURE ?
998 	SymName(actual(actual(index))) : Image(type(actual(index))),
999 	non_blocking(index) ? " (non_blocking)" : "");
1000       break;
1001 
1002 
1003     case RECEPTIVE:
1004 
1005       sprintf(buff, "receptive %s%s", type(actual(index)) == CLOSURE ?
1006 	SymName(actual(actual(index))) : Image(type(actual(index))),
1007 	non_blocking(index) ? " (non_blocking)" : "");
1008       break;
1009 
1010 
1011     case UNATTACHED:
1012 
1013       if( Down(index) != index )
1014       { Child(z, Down(index));
1015       }
1016       else z = nilobj;
1017       sprintf(buff, "unattached %s",
1018 	z == nilobj ? AsciiToFull("<nilobj>") : SymName(actual(z)));
1019       break;
1020 
1021 
1022     case WORD:
1023     case QWORD:
1024 
1025       sprintf(buff, "\"%s\"", string(index));
1026       break;
1027 
1028 
1029     default:
1030 
1031       sprintf(buff, "%s", Image(type(index)));
1032       break;
1033   }
1034   return AsciiToFull(buff);
1035 } /* end EchoIndex */
1036 
1037 
1038 /*@::DebugGalley()@***********************************************************/
1039 /*                                                                           */
1040 /*  DebugGalley(hd, pinpt, indent)                                           */
1041 /*                                                                           */
1042 /*  Print overview of galley hd on stderr; mark pinpoint if found            */
1043 /*                                                                           */
1044 /*****************************************************************************/
1045 
DebugGalley(OBJECT hd,OBJECT pinpt,int indent)1046 void DebugGalley(OBJECT hd, OBJECT pinpt, int indent)
1047 { OBJECT link, y;  char istr[30];  int i;
1048   for( i = 0;  i < indent;  i++ )  istr[i] = ' ';
1049   istr[i] = '\0';
1050   if( type(hd) != HEAD )
1051   {
1052     debug2(ANY, D, "%shd is %s", istr, Image(type(hd)));
1053     return;
1054   }
1055   debug3(ANY, D, "%sgalley %s into %s", istr,
1056     SymName(actual(hd)), SymName(whereto(hd)));
1057   for( link = Down(hd);  link != hd;  link = NextDown(link) )
1058   { Child(y, link);
1059     if( y == pinpt || link == pinpt )
1060     {
1061       debug2(ANY, D, "++ %d %s ", (int) y, Image(type(y)));
1062       DebugObject(y);
1063     }
1064     else if( type(y) == GAP_OBJ )
1065     {
1066       debug4(ANY, D, "| %d %-7s %20s %s", (int) y, "gap_obj",
1067 	Image(type(y)), EchoGap(&gap(y)));
1068     }
1069     else if( type(y) == EXPAND_IND )
1070     { OBJECT z = nilobj;
1071       if( type(actual(y)) == VEXPAND || type(actual(y)) == HEXPAND )
1072       {
1073 	Child(z, Down(actual(y)));
1074 	if( !is_word(type(z)) )
1075 	  z = nilobj;
1076       }
1077       if( z == nilobj )
1078       {
1079         debug4(ANY, D, "| %d %-7s %20s %s", (int) y, "index",
1080 	  Image(type(y)), Image(type(actual(y))));
1081       }
1082       else
1083       {
1084         debug5(ANY, D, "| %d %-7s %20s %s \"%s\"", (int) y, "index",
1085 	  Image(type(y)), Image(type(actual(y))), string(z));
1086       }
1087       assert( type(actual(y)) == VEXPAND || type(actual(y)) == HEXPAND,
1088 	"DebugGalley: type(actual(EXPAND_IND))!");
1089     }
1090     else if( is_index(type(y)) )
1091     {
1092       debug4(ANY, D, "| %d %-7s %20s %s", (int) y, "index",
1093 	Image(type(y)), "");
1094     }
1095     else if( is_definite(type(y)) )
1096     {
1097       debug5(ANY, D, "| %d %-7s %20s %s width %s", (int) y, "def_obj",
1098 	Image(type(y)), is_word(type(y)) ? string(y):STR_EMPTY,
1099 	EchoLength(size(y, COLM)));
1100       if( size(y, COLM) > 25 * CM )
1101       {
1102 	debug0(ANY, D, "wide object: {");
1103 	DebugObject(y);
1104 	debug0(ANY, D, "}");
1105       }
1106     }
1107     else if( is_indefinite(type(y)) )
1108     {
1109       debug4(ANY, D, "| %d %-7s %20s %s", (int) y, "indefin",
1110 	Image(type(y)), type(y) == CLOSURE ? SymName(actual(y)) : STR_EMPTY);
1111     }
1112     else
1113     {
1114       debug4(ANY, D, "| %d %-7s %20s %s", (int) y, "unknown",
1115 	Image(type(y)), "");
1116     }
1117   }
1118 } /* end DebugGalley */
1119 #endif
1120