1*d2672555Sschwarze /* $OpenBSD: tree.c,v 1.59 2022/01/12 04:53:57 schwarze Exp $ */
2f73abda9Skristaps /*
30ac7e6ecSschwarze * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
4*d2672555Sschwarze * Copyright (c) 2013-2015, 2017-2022 Ingo Schwarze <schwarze@openbsd.org>
5f73abda9Skristaps *
6f73abda9Skristaps * Permission to use, copy, modify, and distribute this software for any
7a6464425Sschwarze * purpose with or without fee is hereby granted, provided that the above
8a6464425Sschwarze * copyright notice and this permission notice appear in all copies.
9f73abda9Skristaps *
10d1982c71Sschwarze * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11a6464425Sschwarze * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12d1982c71Sschwarze * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13a6464425Sschwarze * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14a6464425Sschwarze * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a6464425Sschwarze * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16a6464425Sschwarze * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
170ac7e6ecSschwarze *
180ac7e6ecSschwarze * Formatting module to let mandoc(1) show
190ac7e6ecSschwarze * a human readable representation of the syntax tree.
20f73abda9Skristaps */
21f8617809Sschwarze #include <sys/types.h>
22f8617809Sschwarze
23f73abda9Skristaps #include <assert.h>
24f8618d99Sschwarze #include <limits.h>
25f73abda9Skristaps #include <stdio.h>
26f73abda9Skristaps #include <stdlib.h>
27a66b65d0Sschwarze #include <time.h>
28f73abda9Skristaps
296e03d529Sschwarze #include "mandoc.h"
30d1982c71Sschwarze #include "roff.h"
31f73abda9Skristaps #include "mdoc.h"
32f73abda9Skristaps #include "man.h"
33fae2491eSschwarze #include "tbl.h"
34d4c8d4a3Sschwarze #include "eqn.h"
354175bdabSschwarze #include "main.h"
36f73abda9Skristaps
37c220f9cfSschwarze static void print_attr(const struct roff_node *);
38f8618d99Sschwarze static void print_box(const struct eqn_box *, int);
39e5c2e3c9Sschwarze static void print_cellt(enum tbl_cellt);
403a0d07afSschwarze static void print_man(const struct roff_node *, int);
41d5fe3964Sschwarze static void print_meta(const struct roff_meta *);
423a0d07afSschwarze static void print_mdoc(const struct roff_node *, int);
432791bd1cSschwarze static void print_span(const struct tbl_span *, int);
44f73abda9Skristaps
45f73abda9Skristaps
466ae2e8acSschwarze void
tree_mdoc(void * arg,const struct roff_meta * mdoc)476b86842eSschwarze tree_mdoc(void *arg, const struct roff_meta *mdoc)
48f73abda9Skristaps {
496b86842eSschwarze print_meta(mdoc);
50d5fe3964Sschwarze putchar('\n');
516d0e9b63Sschwarze print_mdoc(mdoc->first->child, 0);
52f73abda9Skristaps }
53f73abda9Skristaps
546ae2e8acSschwarze void
tree_man(void * arg,const struct roff_meta * man)556b86842eSschwarze tree_man(void *arg, const struct roff_meta *man)
56f73abda9Skristaps {
576b86842eSschwarze print_meta(man);
586b86842eSschwarze if (man->hasbody == 0)
59d5fe3964Sschwarze puts("body = empty");
60d5fe3964Sschwarze putchar('\n');
616d0e9b63Sschwarze print_man(man->first->child, 0);
62f73abda9Skristaps }
63f73abda9Skristaps
64f73abda9Skristaps static void
print_meta(const struct roff_meta * meta)65d5fe3964Sschwarze print_meta(const struct roff_meta *meta)
66d5fe3964Sschwarze {
67d5fe3964Sschwarze if (meta->title != NULL)
68d5fe3964Sschwarze printf("title = \"%s\"\n", meta->title);
69d5fe3964Sschwarze if (meta->name != NULL)
70d5fe3964Sschwarze printf("name = \"%s\"\n", meta->name);
71d5fe3964Sschwarze if (meta->msec != NULL)
72d5fe3964Sschwarze printf("sec = \"%s\"\n", meta->msec);
73d5fe3964Sschwarze if (meta->vol != NULL)
74d5fe3964Sschwarze printf("vol = \"%s\"\n", meta->vol);
75d5fe3964Sschwarze if (meta->arch != NULL)
76d5fe3964Sschwarze printf("arch = \"%s\"\n", meta->arch);
77d5fe3964Sschwarze if (meta->os != NULL)
78d5fe3964Sschwarze printf("os = \"%s\"\n", meta->os);
79d5fe3964Sschwarze if (meta->date != NULL)
80d5fe3964Sschwarze printf("date = \"%s\"\n", meta->date);
81d5fe3964Sschwarze }
82d5fe3964Sschwarze
83d5fe3964Sschwarze static void
print_mdoc(const struct roff_node * n,int indent)843a0d07afSschwarze print_mdoc(const struct roff_node *n, int indent)
85f73abda9Skristaps {
86f73abda9Skristaps const char *p, *t;
87f73abda9Skristaps int i, j;
8856d07b44Sschwarze size_t argc;
89f73abda9Skristaps struct mdoc_argv *argv;
90f73abda9Skristaps
910a42f588Sschwarze if (n == NULL)
920a42f588Sschwarze return;
930a42f588Sschwarze
94f73abda9Skristaps argv = NULL;
9556d07b44Sschwarze argc = 0;
96f8618d99Sschwarze t = p = NULL;
97f73abda9Skristaps
98f73abda9Skristaps switch (n->type) {
99d1982c71Sschwarze case ROFFT_ROOT:
100f73abda9Skristaps t = "root";
101f73abda9Skristaps break;
102d1982c71Sschwarze case ROFFT_BLOCK:
103f73abda9Skristaps t = "block";
104f73abda9Skristaps break;
105d1982c71Sschwarze case ROFFT_HEAD:
10631a38b0eSschwarze t = "head";
107f73abda9Skristaps break;
108d1982c71Sschwarze case ROFFT_BODY:
10932dadbacSschwarze if (n->end)
11032dadbacSschwarze t = "body-end";
11132dadbacSschwarze else
11231a38b0eSschwarze t = "body";
113f73abda9Skristaps break;
114d1982c71Sschwarze case ROFFT_TAIL:
11531a38b0eSschwarze t = "tail";
116f73abda9Skristaps break;
117d1982c71Sschwarze case ROFFT_ELEM:
118f73abda9Skristaps t = "elem";
119f73abda9Skristaps break;
120d1982c71Sschwarze case ROFFT_TEXT:
121f73abda9Skristaps t = "text";
122f73abda9Skristaps break;
1234c293873Sschwarze case ROFFT_COMMENT:
1244c293873Sschwarze t = "comment";
1254c293873Sschwarze break;
126d1982c71Sschwarze case ROFFT_TBL:
12725fe02efSschwarze break;
128d1982c71Sschwarze case ROFFT_EQN:
12925fe02efSschwarze t = "eqn";
1308d973ab1Sschwarze break;
131f73abda9Skristaps default:
132f73abda9Skristaps abort();
133f73abda9Skristaps }
134f73abda9Skristaps
135f73abda9Skristaps switch (n->type) {
136d1982c71Sschwarze case ROFFT_TEXT:
1374c293873Sschwarze case ROFFT_COMMENT:
138f73abda9Skristaps p = n->string;
139f73abda9Skristaps break;
140d1982c71Sschwarze case ROFFT_BODY:
14114a309e3Sschwarze p = roff_name[n->tok];
142f73abda9Skristaps break;
143d1982c71Sschwarze case ROFFT_HEAD:
14414a309e3Sschwarze p = roff_name[n->tok];
145f73abda9Skristaps break;
146d1982c71Sschwarze case ROFFT_TAIL:
14714a309e3Sschwarze p = roff_name[n->tok];
148f73abda9Skristaps break;
149d1982c71Sschwarze case ROFFT_ELEM:
15014a309e3Sschwarze p = roff_name[n->tok];
151f73abda9Skristaps if (n->args) {
152f73abda9Skristaps argv = n->args->argv;
153f73abda9Skristaps argc = n->args->argc;
154f73abda9Skristaps }
155f73abda9Skristaps break;
156d1982c71Sschwarze case ROFFT_BLOCK:
15714a309e3Sschwarze p = roff_name[n->tok];
158f73abda9Skristaps if (n->args) {
159f73abda9Skristaps argv = n->args->argv;
160f73abda9Skristaps argc = n->args->argc;
161f73abda9Skristaps }
162f73abda9Skristaps break;
163d1982c71Sschwarze case ROFFT_TBL:
16425fe02efSschwarze break;
165d1982c71Sschwarze case ROFFT_EQN:
16625fe02efSschwarze p = "EQ";
1678d973ab1Sschwarze break;
168d1982c71Sschwarze case ROFFT_ROOT:
169f73abda9Skristaps p = "root";
170f73abda9Skristaps break;
171f73abda9Skristaps default:
172f73abda9Skristaps abort();
173f73abda9Skristaps }
174f73abda9Skristaps
1752791bd1cSschwarze if (n->span) {
176f8618d99Sschwarze assert(NULL == p && NULL == t);
1772791bd1cSschwarze print_span(n->span, indent);
1782791bd1cSschwarze } else {
179f73abda9Skristaps for (i = 0; i < indent; i++)
1800a42f588Sschwarze putchar(' ');
1812791bd1cSschwarze
1822791bd1cSschwarze printf("%s (%s)", p, t);
183f73abda9Skristaps
184f73abda9Skristaps for (i = 0; i < (int)argc; i++) {
1852791bd1cSschwarze printf(" -%s", mdoc_argnames[argv[i].arg]);
186f73abda9Skristaps if (argv[i].sz > 0)
1872791bd1cSschwarze printf(" [");
188f73abda9Skristaps for (j = 0; j < (int)argv[i].sz; j++)
1892791bd1cSschwarze printf(" [%s]", argv[i].value[j]);
190f73abda9Skristaps if (argv[i].sz > 0)
1912791bd1cSschwarze printf(" ]");
192f73abda9Skristaps }
193c220f9cfSschwarze print_attr(n);
1949a542ed3Sschwarze }
19525fe02efSschwarze if (n->eqn)
196bf9acac6Sschwarze print_box(n->eqn->first, indent + 4);
197f73abda9Skristaps if (n->child)
1980a42f588Sschwarze print_mdoc(n->child, indent +
199d1982c71Sschwarze (n->type == ROFFT_BLOCK ? 2 : 4));
200f73abda9Skristaps if (n->next)
201f73abda9Skristaps print_mdoc(n->next, indent);
202f73abda9Skristaps }
203f73abda9Skristaps
204f73abda9Skristaps static void
print_man(const struct roff_node * n,int indent)2053a0d07afSschwarze print_man(const struct roff_node *n, int indent)
206f73abda9Skristaps {
207f73abda9Skristaps const char *p, *t;
208f73abda9Skristaps int i;
209f73abda9Skristaps
2100a42f588Sschwarze if (n == NULL)
2110a42f588Sschwarze return;
2120a42f588Sschwarze
213f8618d99Sschwarze t = p = NULL;
214f8618d99Sschwarze
215f73abda9Skristaps switch (n->type) {
216d1982c71Sschwarze case ROFFT_ROOT:
217f73abda9Skristaps t = "root";
218f73abda9Skristaps break;
219d1982c71Sschwarze case ROFFT_ELEM:
220f73abda9Skristaps t = "elem";
221f73abda9Skristaps break;
222d1982c71Sschwarze case ROFFT_TEXT:
223f73abda9Skristaps t = "text";
224f73abda9Skristaps break;
2254c293873Sschwarze case ROFFT_COMMENT:
2264c293873Sschwarze t = "comment";
2274c293873Sschwarze break;
228d1982c71Sschwarze case ROFFT_BLOCK:
229e35cb253Sschwarze t = "block";
230e35cb253Sschwarze break;
231d1982c71Sschwarze case ROFFT_HEAD:
23231a38b0eSschwarze t = "head";
233e35cb253Sschwarze break;
234d1982c71Sschwarze case ROFFT_BODY:
23531a38b0eSschwarze t = "body";
236e35cb253Sschwarze break;
237d1982c71Sschwarze case ROFFT_TBL:
23825fe02efSschwarze break;
239d1982c71Sschwarze case ROFFT_EQN:
24025fe02efSschwarze t = "eqn";
2418d973ab1Sschwarze break;
242f73abda9Skristaps default:
243f73abda9Skristaps abort();
244f73abda9Skristaps }
245f73abda9Skristaps
246f73abda9Skristaps switch (n->type) {
247d1982c71Sschwarze case ROFFT_TEXT:
2484c293873Sschwarze case ROFFT_COMMENT:
249f73abda9Skristaps p = n->string;
250f73abda9Skristaps break;
251d1982c71Sschwarze case ROFFT_ELEM:
252d1982c71Sschwarze case ROFFT_BLOCK:
253d1982c71Sschwarze case ROFFT_HEAD:
254d1982c71Sschwarze case ROFFT_BODY:
25514a309e3Sschwarze p = roff_name[n->tok];
256f73abda9Skristaps break;
257d1982c71Sschwarze case ROFFT_ROOT:
258f73abda9Skristaps p = "root";
259f73abda9Skristaps break;
260d1982c71Sschwarze case ROFFT_TBL:
26125fe02efSschwarze break;
262d1982c71Sschwarze case ROFFT_EQN:
26325fe02efSschwarze p = "EQ";
2648d973ab1Sschwarze break;
265f73abda9Skristaps default:
266f73abda9Skristaps abort();
267f73abda9Skristaps }
268f73abda9Skristaps
2692791bd1cSschwarze if (n->span) {
270f8618d99Sschwarze assert(NULL == p && NULL == t);
2712791bd1cSschwarze print_span(n->span, indent);
2722791bd1cSschwarze } else {
273f73abda9Skristaps for (i = 0; i < indent; i++)
2740a42f588Sschwarze putchar(' ');
275074125cbSschwarze printf("%s (%s)", p, t);
276c220f9cfSschwarze print_attr(n);
277c220f9cfSschwarze }
278c220f9cfSschwarze if (n->eqn)
279c220f9cfSschwarze print_box(n->eqn->first, indent + 4);
280c220f9cfSschwarze if (n->child)
281c220f9cfSschwarze print_man(n->child, indent +
282c220f9cfSschwarze (n->type == ROFFT_BLOCK ? 2 : 4));
283c220f9cfSschwarze if (n->next)
284c220f9cfSschwarze print_man(n->next, indent);
285c220f9cfSschwarze }
286c220f9cfSschwarze
287c220f9cfSschwarze static void
print_attr(const struct roff_node * n)288c220f9cfSschwarze print_attr(const struct roff_node *n)
289c220f9cfSschwarze {
290c220f9cfSschwarze putchar(' ');
291c220f9cfSschwarze if (n->flags & NODE_DELIMO)
292c220f9cfSschwarze putchar('(');
293b6438c31Sschwarze if (n->flags & NODE_LINE)
294074125cbSschwarze putchar('*');
29531a38b0eSschwarze printf("%d:%d", n->line, n->pos + 1);
296b6438c31Sschwarze if (n->flags & NODE_DELIMC)
297252b7e4aSschwarze putchar(')');
298b6438c31Sschwarze if (n->flags & NODE_EOS)
29931a38b0eSschwarze putchar('.');
3000ac7e6ecSschwarze if (n->flags & NODE_ID) {
3010ac7e6ecSschwarze printf(" ID");
302c220f9cfSschwarze if (n->flags & NODE_HREF)
303c220f9cfSschwarze printf("=HREF");
304c220f9cfSschwarze } else if (n->flags & NODE_HREF)
305c220f9cfSschwarze printf(" HREF");
306c220f9cfSschwarze else if (n->tag != NULL)
307c220f9cfSschwarze printf(" STRAYTAG");
308c220f9cfSschwarze if (n->tag != NULL)
309c220f9cfSschwarze printf("=%s", n->tag);
310c220f9cfSschwarze if (n->flags & NODE_BROKEN)
311c220f9cfSschwarze printf(" BROKEN");
312b6438c31Sschwarze if (n->flags & NODE_NOFILL)
313b6438c31Sschwarze printf(" NOFILL");
314c220f9cfSschwarze if (n->flags & NODE_NOSRC)
315c220f9cfSschwarze printf(" NOSRC");
316c220f9cfSschwarze if (n->flags & NODE_NOPRT)
317c220f9cfSschwarze printf(" NOPRT");
31831a38b0eSschwarze putchar('\n');
3192791bd1cSschwarze }
3202791bd1cSschwarze
3212791bd1cSschwarze static void
print_box(const struct eqn_box * ep,int indent)322f8618d99Sschwarze print_box(const struct eqn_box *ep, int indent)
323f8618d99Sschwarze {
324f8618d99Sschwarze int i;
325f8618d99Sschwarze const char *t;
326f8618d99Sschwarze
327f8617809Sschwarze static const char *posnames[] = {
328f8617809Sschwarze NULL, "sup", "subsup", "sub",
329f8617809Sschwarze "to", "from", "fromto",
330f8617809Sschwarze "over", "sqrt", NULL };
331f8617809Sschwarze
332f8618d99Sschwarze if (NULL == ep)
333f8618d99Sschwarze return;
334f8618d99Sschwarze for (i = 0; i < indent; i++)
3350a42f588Sschwarze putchar(' ');
336f8618d99Sschwarze
337f8618d99Sschwarze t = NULL;
338f8618d99Sschwarze switch (ep->type) {
33949aff9f8Sschwarze case EQN_LIST:
340f8618d99Sschwarze t = "eqn-list";
341f8618d99Sschwarze break;
34249aff9f8Sschwarze case EQN_SUBEXPR:
343f8618d99Sschwarze t = "eqn-expr";
344f8618d99Sschwarze break;
34549aff9f8Sschwarze case EQN_TEXT:
346f8618d99Sschwarze t = "eqn-text";
347f8618d99Sschwarze break;
348f8617809Sschwarze case EQN_PILE:
349f8617809Sschwarze t = "eqn-pile";
350f8617809Sschwarze break;
35149aff9f8Sschwarze case EQN_MATRIX:
352f8618d99Sschwarze t = "eqn-matrix";
353f8618d99Sschwarze break;
354f8618d99Sschwarze }
355f8618d99Sschwarze
356f8617809Sschwarze fputs(t, stdout);
357f8617809Sschwarze if (ep->pos)
358f8617809Sschwarze printf(" pos=%s", posnames[ep->pos]);
359f8617809Sschwarze if (ep->left)
360f8617809Sschwarze printf(" left=\"%s\"", ep->left);
361f8617809Sschwarze if (ep->right)
362f8617809Sschwarze printf(" right=\"%s\"", ep->right);
363f8617809Sschwarze if (ep->top)
364f8617809Sschwarze printf(" top=\"%s\"", ep->top);
365f8617809Sschwarze if (ep->bottom)
366f8617809Sschwarze printf(" bottom=\"%s\"", ep->bottom);
367f8617809Sschwarze if (ep->text)
368f8617809Sschwarze printf(" text=\"%s\"", ep->text);
369f8617809Sschwarze if (ep->font)
370f8617809Sschwarze printf(" font=%d", ep->font);
371f8617809Sschwarze if (ep->size != EQN_DEFSIZE)
372f8617809Sschwarze printf(" size=%d", ep->size);
373f8617809Sschwarze if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
374f8617809Sschwarze printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
375f8617809Sschwarze else if (ep->args)
376f8617809Sschwarze printf(" args=%zu", ep->args);
377f8617809Sschwarze putchar('\n');
378f8618d99Sschwarze
3790a42f588Sschwarze print_box(ep->first, indent + 4);
380f8618d99Sschwarze print_box(ep->next, indent);
381f8618d99Sschwarze }
382f8618d99Sschwarze
383f8618d99Sschwarze static void
print_cellt(enum tbl_cellt pos)384e5c2e3c9Sschwarze print_cellt(enum tbl_cellt pos)
385e5c2e3c9Sschwarze {
386e5c2e3c9Sschwarze switch(pos) {
387e5c2e3c9Sschwarze case TBL_CELL_LEFT:
388e5c2e3c9Sschwarze putchar('L');
389e5c2e3c9Sschwarze break;
390e5c2e3c9Sschwarze case TBL_CELL_LONG:
391e5c2e3c9Sschwarze putchar('a');
392e5c2e3c9Sschwarze break;
393e5c2e3c9Sschwarze case TBL_CELL_CENTRE:
394e5c2e3c9Sschwarze putchar('c');
395e5c2e3c9Sschwarze break;
396e5c2e3c9Sschwarze case TBL_CELL_RIGHT:
397e5c2e3c9Sschwarze putchar('r');
398e5c2e3c9Sschwarze break;
399e5c2e3c9Sschwarze case TBL_CELL_NUMBER:
400e5c2e3c9Sschwarze putchar('n');
401e5c2e3c9Sschwarze break;
402e5c2e3c9Sschwarze case TBL_CELL_SPAN:
403e5c2e3c9Sschwarze putchar('s');
404e5c2e3c9Sschwarze break;
405e5c2e3c9Sschwarze case TBL_CELL_DOWN:
406e5c2e3c9Sschwarze putchar('^');
407e5c2e3c9Sschwarze break;
408e5c2e3c9Sschwarze case TBL_CELL_HORIZ:
409e5c2e3c9Sschwarze putchar('-');
410e5c2e3c9Sschwarze break;
411e5c2e3c9Sschwarze case TBL_CELL_DHORIZ:
412e5c2e3c9Sschwarze putchar('=');
413e5c2e3c9Sschwarze break;
414e5c2e3c9Sschwarze case TBL_CELL_MAX:
415e5c2e3c9Sschwarze putchar('#');
416e5c2e3c9Sschwarze break;
417e5c2e3c9Sschwarze }
418e5c2e3c9Sschwarze }
419e5c2e3c9Sschwarze
420e5c2e3c9Sschwarze static void
print_span(const struct tbl_span * sp,int indent)4212791bd1cSschwarze print_span(const struct tbl_span *sp, int indent)
4222791bd1cSschwarze {
4232791bd1cSschwarze const struct tbl_dat *dp;
424e5c2e3c9Sschwarze const struct tbl_cell *cp;
4252791bd1cSschwarze int i;
4262791bd1cSschwarze
427e5c2e3c9Sschwarze if (sp->prev == NULL) {
428e5c2e3c9Sschwarze for (i = 0; i < indent; i++)
429e5c2e3c9Sschwarze putchar(' ');
430e5c2e3c9Sschwarze printf("%d", sp->opts->cols);
431e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_CENTRE)
432e5c2e3c9Sschwarze fputs(" center", stdout);
433e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_EXPAND)
434e5c2e3c9Sschwarze fputs(" expand", stdout);
435e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_ALLBOX)
436e5c2e3c9Sschwarze fputs(" allbox", stdout);
437e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_BOX)
438e5c2e3c9Sschwarze fputs(" box", stdout);
439e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_DBOX)
440e5c2e3c9Sschwarze fputs(" doublebox", stdout);
441e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_NOKEEP)
442e5c2e3c9Sschwarze fputs(" nokeep", stdout);
443e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_NOSPACE)
444e5c2e3c9Sschwarze fputs(" nospaces", stdout);
445e5c2e3c9Sschwarze if (sp->opts->opts & TBL_OPT_NOWARN)
446e5c2e3c9Sschwarze fputs(" nowarn", stdout);
447e5c2e3c9Sschwarze printf(" (tbl options) %d:1\n", sp->line);
448e5c2e3c9Sschwarze }
449e5c2e3c9Sschwarze
4502791bd1cSschwarze for (i = 0; i < indent; i++)
4510a42f588Sschwarze putchar(' ');
4522791bd1cSschwarze
4532791bd1cSschwarze switch (sp->pos) {
45449aff9f8Sschwarze case TBL_SPAN_HORIZ:
4552791bd1cSschwarze putchar('-');
456a93944b2Sschwarze putchar(' ');
457a93944b2Sschwarze break;
45849aff9f8Sschwarze case TBL_SPAN_DHORIZ:
4592791bd1cSschwarze putchar('=');
460a93944b2Sschwarze putchar(' ');
4612791bd1cSschwarze break;
462a93944b2Sschwarze default:
463e5c2e3c9Sschwarze for (cp = sp->layout->first; cp != NULL; cp = cp->next)
464e5c2e3c9Sschwarze print_cellt(cp->pos);
465e5c2e3c9Sschwarze putchar(' ');
4662791bd1cSschwarze for (dp = sp->first; dp; dp = dp->next) {
467e5c2e3c9Sschwarze if ((cp = dp->layout) == NULL)
468e5c2e3c9Sschwarze putchar('*');
469e5c2e3c9Sschwarze else {
470e5c2e3c9Sschwarze printf("%d", cp->col);
471e5c2e3c9Sschwarze print_cellt(dp->layout->pos);
4727d063611Sschwarze switch (cp->font) {
473f8e2f34eSschwarze case ESCAPE_FONTROMAN:
474f8e2f34eSschwarze break;
4757d063611Sschwarze case ESCAPE_FONTBOLD:
476e5c2e3c9Sschwarze putchar('b');
4777d063611Sschwarze break;
4787d063611Sschwarze case ESCAPE_FONTITALIC:
479e5c2e3c9Sschwarze putchar('i');
4807d063611Sschwarze break;
4817d063611Sschwarze case ESCAPE_FONTBI:
4827d063611Sschwarze fputs("bi", stdout);
4837d063611Sschwarze break;
4847d063611Sschwarze case ESCAPE_FONTCR:
4857d063611Sschwarze putchar('c');
4867d063611Sschwarze break;
4877d063611Sschwarze case ESCAPE_FONTCB:
4887d063611Sschwarze fputs("cb", stdout);
4897d063611Sschwarze break;
4907d063611Sschwarze case ESCAPE_FONTCI:
4917d063611Sschwarze fputs("ci", stdout);
4927d063611Sschwarze break;
4937d063611Sschwarze default:
4947d063611Sschwarze abort();
4957d063611Sschwarze }
496e5c2e3c9Sschwarze if (cp->flags & TBL_CELL_TALIGN)
497e5c2e3c9Sschwarze putchar('t');
498e5c2e3c9Sschwarze if (cp->flags & TBL_CELL_UP)
499e5c2e3c9Sschwarze putchar('u');
500e5c2e3c9Sschwarze if (cp->flags & TBL_CELL_BALIGN)
501e5c2e3c9Sschwarze putchar('d');
502e5c2e3c9Sschwarze if (cp->flags & TBL_CELL_WIGN)
503e5c2e3c9Sschwarze putchar('z');
504e5c2e3c9Sschwarze if (cp->flags & TBL_CELL_EQUAL)
505e5c2e3c9Sschwarze putchar('e');
506e5c2e3c9Sschwarze if (cp->flags & TBL_CELL_WMAX)
507e5c2e3c9Sschwarze putchar('x');
508e5c2e3c9Sschwarze }
5092791bd1cSschwarze switch (dp->pos) {
51049aff9f8Sschwarze case TBL_DATA_NHORIZ:
511*d2672555Sschwarze putchar('\\');
512*d2672555Sschwarze /* FALLTHROUGH */
513*d2672555Sschwarze case TBL_DATA_HORIZ:
514*d2672555Sschwarze putchar('_');
515e5c2e3c9Sschwarze break;
51649aff9f8Sschwarze case TBL_DATA_NDHORIZ:
517*d2672555Sschwarze putchar('\\');
518*d2672555Sschwarze /* FALLTHROUGH */
519*d2672555Sschwarze case TBL_DATA_DHORIZ:
5202791bd1cSschwarze putchar('=');
521e5c2e3c9Sschwarze break;
5222791bd1cSschwarze default:
523e5c2e3c9Sschwarze putchar(dp->block ? '{' : '[');
524e5c2e3c9Sschwarze if (dp->string != NULL)
525e5c2e3c9Sschwarze fputs(dp->string, stdout);
526e5c2e3c9Sschwarze putchar(dp->block ? '}' : ']');
5272791bd1cSschwarze break;
5282791bd1cSschwarze }
529a93944b2Sschwarze if (dp->hspans)
530a93944b2Sschwarze printf(">%d", dp->hspans);
531a93944b2Sschwarze if (dp->vspans)
532a93944b2Sschwarze printf("v%d", dp->vspans);
5332791bd1cSschwarze putchar(' ');
5342791bd1cSschwarze }
535a93944b2Sschwarze break;
536a93944b2Sschwarze }
537f8618d99Sschwarze printf("(tbl) %d:1\n", sp->line);
5382791bd1cSschwarze }
539