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