xref: /illumos-gate/usr/src/cmd/mandoc/tree.c (revision 4d131170e62381276a07ffc0aeb1b62e527d940c)
1*4d131170SRobert Mustacchi /* $Id: tree.c,v 1.91 2021/09/07 10:59:18 schwarze Exp $ */
295c635efSGarrett D'Amore /*
3260e9a87SYuri Pankov  * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
4*4d131170SRobert Mustacchi  * Copyright (c) 2013-2015, 2017-2021 Ingo Schwarze <schwarze@openbsd.org>
595c635efSGarrett D'Amore  *
695c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
795c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
895c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
995c635efSGarrett D'Amore  *
10371584c2SYuri Pankov  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1195c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12371584c2SYuri Pankov  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1395c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1495c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1595c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1695c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*4d131170SRobert Mustacchi  *
18*4d131170SRobert Mustacchi  * Formatting module to let mandoc(1) show
19*4d131170SRobert Mustacchi  * a human readable representation of the syntax tree.
2095c635efSGarrett D'Amore  */
2195c635efSGarrett D'Amore #include "config.h"
22260e9a87SYuri Pankov 
23260e9a87SYuri Pankov #include <sys/types.h>
2495c635efSGarrett D'Amore 
2595c635efSGarrett D'Amore #include <assert.h>
2695c635efSGarrett D'Amore #include <limits.h>
2795c635efSGarrett D'Amore #include <stdio.h>
2895c635efSGarrett D'Amore #include <stdlib.h>
2995c635efSGarrett D'Amore #include <time.h>
3095c635efSGarrett D'Amore 
3195c635efSGarrett D'Amore #include "mandoc.h"
32371584c2SYuri Pankov #include "roff.h"
3395c635efSGarrett D'Amore #include "mdoc.h"
3495c635efSGarrett D'Amore #include "man.h"
35cec8643bSMichal Nowak #include "tbl.h"
36cec8643bSMichal Nowak #include "eqn.h"
3795c635efSGarrett D'Amore #include "main.h"
3895c635efSGarrett D'Amore 
39*4d131170SRobert Mustacchi static	void	print_attr(const struct roff_node *);
4095c635efSGarrett D'Amore static	void	print_box(const struct eqn_box *, int);
41*4d131170SRobert Mustacchi static	void	print_cellt(enum tbl_cellt);
42371584c2SYuri Pankov static	void	print_man(const struct roff_node *, int);
43a40ea1a7SYuri Pankov static	void	print_meta(const struct roff_meta *);
44371584c2SYuri Pankov static	void	print_mdoc(const struct roff_node *, int);
4595c635efSGarrett D'Amore static	void	print_span(const struct tbl_span *, int);
4695c635efSGarrett D'Amore 
4795c635efSGarrett D'Amore 
4895c635efSGarrett D'Amore void
tree_mdoc(void * arg,const struct roff_meta * mdoc)49cec8643bSMichal Nowak tree_mdoc(void *arg, const struct roff_meta *mdoc)
5095c635efSGarrett D'Amore {
51cec8643bSMichal Nowak 	print_meta(mdoc);
52a40ea1a7SYuri Pankov 	putchar('\n');
53371584c2SYuri Pankov 	print_mdoc(mdoc->first->child, 0);
5495c635efSGarrett D'Amore }
5595c635efSGarrett D'Amore 
5695c635efSGarrett D'Amore void
tree_man(void * arg,const struct roff_meta * man)57cec8643bSMichal Nowak tree_man(void *arg, const struct roff_meta *man)
5895c635efSGarrett D'Amore {
59cec8643bSMichal Nowak 	print_meta(man);
60cec8643bSMichal Nowak 	if (man->hasbody == 0)
61a40ea1a7SYuri Pankov 		puts("body  = empty");
62a40ea1a7SYuri Pankov 	putchar('\n');
63371584c2SYuri Pankov 	print_man(man->first->child, 0);
6495c635efSGarrett D'Amore }
6595c635efSGarrett D'Amore 
6695c635efSGarrett D'Amore static void
print_meta(const struct roff_meta * meta)67a40ea1a7SYuri Pankov print_meta(const struct roff_meta *meta)
68a40ea1a7SYuri Pankov {
69a40ea1a7SYuri Pankov 	if (meta->title != NULL)
70a40ea1a7SYuri Pankov 		printf("title = \"%s\"\n", meta->title);
71a40ea1a7SYuri Pankov 	if (meta->name != NULL)
72a40ea1a7SYuri Pankov 		printf("name  = \"%s\"\n", meta->name);
73a40ea1a7SYuri Pankov 	if (meta->msec != NULL)
74a40ea1a7SYuri Pankov 		printf("sec   = \"%s\"\n", meta->msec);
75a40ea1a7SYuri Pankov 	if (meta->vol != NULL)
76a40ea1a7SYuri Pankov 		printf("vol   = \"%s\"\n", meta->vol);
77a40ea1a7SYuri Pankov 	if (meta->arch != NULL)
78a40ea1a7SYuri Pankov 		printf("arch  = \"%s\"\n", meta->arch);
79a40ea1a7SYuri Pankov 	if (meta->os != NULL)
80a40ea1a7SYuri Pankov 		printf("os    = \"%s\"\n", meta->os);
81a40ea1a7SYuri Pankov 	if (meta->date != NULL)
82a40ea1a7SYuri Pankov 		printf("date  = \"%s\"\n", meta->date);
83a40ea1a7SYuri Pankov }
84a40ea1a7SYuri Pankov 
85a40ea1a7SYuri Pankov static void
print_mdoc(const struct roff_node * n,int indent)86371584c2SYuri Pankov print_mdoc(const struct roff_node *n, int indent)
8795c635efSGarrett D'Amore {
8895c635efSGarrett D'Amore 	const char	 *p, *t;
8995c635efSGarrett D'Amore 	int		  i, j;
90698f87a4SGarrett D'Amore 	size_t		  argc;
9195c635efSGarrett D'Amore 	struct mdoc_argv *argv;
9295c635efSGarrett D'Amore 
93260e9a87SYuri Pankov 	if (n == NULL)
94260e9a87SYuri Pankov 		return;
95260e9a87SYuri Pankov 
9695c635efSGarrett D'Amore 	argv = NULL;
97698f87a4SGarrett D'Amore 	argc = 0;
9895c635efSGarrett D'Amore 	t = p = NULL;
9995c635efSGarrett D'Amore 
10095c635efSGarrett D'Amore 	switch (n->type) {
101371584c2SYuri Pankov 	case ROFFT_ROOT:
10295c635efSGarrett D'Amore 		t = "root";
10395c635efSGarrett D'Amore 		break;
104371584c2SYuri Pankov 	case ROFFT_BLOCK:
10595c635efSGarrett D'Amore 		t = "block";
10695c635efSGarrett D'Amore 		break;
107371584c2SYuri Pankov 	case ROFFT_HEAD:
108371584c2SYuri Pankov 		t = "head";
10995c635efSGarrett D'Amore 		break;
110371584c2SYuri Pankov 	case ROFFT_BODY:
11195c635efSGarrett D'Amore 		if (n->end)
11295c635efSGarrett D'Amore 			t = "body-end";
11395c635efSGarrett D'Amore 		else
114371584c2SYuri Pankov 			t = "body";
11595c635efSGarrett D'Amore 		break;
116371584c2SYuri Pankov 	case ROFFT_TAIL:
117371584c2SYuri Pankov 		t = "tail";
11895c635efSGarrett D'Amore 		break;
119371584c2SYuri Pankov 	case ROFFT_ELEM:
12095c635efSGarrett D'Amore 		t = "elem";
12195c635efSGarrett D'Amore 		break;
122371584c2SYuri Pankov 	case ROFFT_TEXT:
12395c635efSGarrett D'Amore 		t = "text";
12495c635efSGarrett D'Amore 		break;
1256640c13bSYuri Pankov 	case ROFFT_COMMENT:
1266640c13bSYuri Pankov 		t = "comment";
1276640c13bSYuri Pankov 		break;
128371584c2SYuri Pankov 	case ROFFT_TBL:
129260e9a87SYuri Pankov 		break;
130371584c2SYuri Pankov 	case ROFFT_EQN:
131260e9a87SYuri Pankov 		t = "eqn";
13295c635efSGarrett D'Amore 		break;
13395c635efSGarrett D'Amore 	default:
13495c635efSGarrett D'Amore 		abort();
13595c635efSGarrett D'Amore 	}
13695c635efSGarrett D'Amore 
13795c635efSGarrett D'Amore 	switch (n->type) {
138371584c2SYuri Pankov 	case ROFFT_TEXT:
1396640c13bSYuri Pankov 	case ROFFT_COMMENT:
14095c635efSGarrett D'Amore 		p = n->string;
14195c635efSGarrett D'Amore 		break;
142371584c2SYuri Pankov 	case ROFFT_BODY:
143c66b8046SYuri Pankov 		p = roff_name[n->tok];
14495c635efSGarrett D'Amore 		break;
145371584c2SYuri Pankov 	case ROFFT_HEAD:
146c66b8046SYuri Pankov 		p = roff_name[n->tok];
14795c635efSGarrett D'Amore 		break;
148371584c2SYuri Pankov 	case ROFFT_TAIL:
149c66b8046SYuri Pankov 		p = roff_name[n->tok];
15095c635efSGarrett D'Amore 		break;
151371584c2SYuri Pankov 	case ROFFT_ELEM:
152c66b8046SYuri Pankov 		p = roff_name[n->tok];
15395c635efSGarrett D'Amore 		if (n->args) {
15495c635efSGarrett D'Amore 			argv = n->args->argv;
15595c635efSGarrett D'Amore 			argc = n->args->argc;
15695c635efSGarrett D'Amore 		}
15795c635efSGarrett D'Amore 		break;
158371584c2SYuri Pankov 	case ROFFT_BLOCK:
159c66b8046SYuri Pankov 		p = roff_name[n->tok];
16095c635efSGarrett D'Amore 		if (n->args) {
16195c635efSGarrett D'Amore 			argv = n->args->argv;
16295c635efSGarrett D'Amore 			argc = n->args->argc;
16395c635efSGarrett D'Amore 		}
16495c635efSGarrett D'Amore 		break;
165371584c2SYuri Pankov 	case ROFFT_TBL:
16695c635efSGarrett D'Amore 		break;
167371584c2SYuri Pankov 	case ROFFT_EQN:
168260e9a87SYuri Pankov 		p = "EQ";
169260e9a87SYuri Pankov 		break;
170371584c2SYuri Pankov 	case ROFFT_ROOT:
17195c635efSGarrett D'Amore 		p = "root";
17295c635efSGarrett D'Amore 		break;
17395c635efSGarrett D'Amore 	default:
17495c635efSGarrett D'Amore 		abort();
17595c635efSGarrett D'Amore 	}
17695c635efSGarrett D'Amore 
17795c635efSGarrett D'Amore 	if (n->span) {
17895c635efSGarrett D'Amore 		assert(NULL == p && NULL == t);
17995c635efSGarrett D'Amore 		print_span(n->span, indent);
18095c635efSGarrett D'Amore 	} else {
18195c635efSGarrett D'Amore 		for (i = 0; i < indent; i++)
182260e9a87SYuri Pankov 			putchar(' ');
18395c635efSGarrett D'Amore 
18495c635efSGarrett D'Amore 		printf("%s (%s)", p, t);
18595c635efSGarrett D'Amore 
18695c635efSGarrett D'Amore 		for (i = 0; i < (int)argc; i++) {
18795c635efSGarrett D'Amore 			printf(" -%s", mdoc_argnames[argv[i].arg]);
18895c635efSGarrett D'Amore 			if (argv[i].sz > 0)
18995c635efSGarrett D'Amore 				printf(" [");
19095c635efSGarrett D'Amore 			for (j = 0; j < (int)argv[i].sz; j++)
19195c635efSGarrett D'Amore 				printf(" [%s]", argv[i].value[j]);
19295c635efSGarrett D'Amore 			if (argv[i].sz > 0)
19395c635efSGarrett D'Amore 				printf(" ]");
19495c635efSGarrett D'Amore 		}
195*4d131170SRobert Mustacchi 		print_attr(n);
19695c635efSGarrett D'Amore 	}
197260e9a87SYuri Pankov 	if (n->eqn)
198c66b8046SYuri Pankov 		print_box(n->eqn->first, indent + 4);
19995c635efSGarrett D'Amore 	if (n->child)
200260e9a87SYuri Pankov 		print_mdoc(n->child, indent +
201371584c2SYuri Pankov 		    (n->type == ROFFT_BLOCK ? 2 : 4));
20295c635efSGarrett D'Amore 	if (n->next)
20395c635efSGarrett D'Amore 		print_mdoc(n->next, indent);
20495c635efSGarrett D'Amore }
20595c635efSGarrett D'Amore 
20695c635efSGarrett D'Amore static void
print_man(const struct roff_node * n,int indent)207371584c2SYuri Pankov print_man(const struct roff_node *n, int indent)
20895c635efSGarrett D'Amore {
20995c635efSGarrett D'Amore 	const char	 *p, *t;
21095c635efSGarrett D'Amore 	int		  i;
21195c635efSGarrett D'Amore 
212260e9a87SYuri Pankov 	if (n == NULL)
213260e9a87SYuri Pankov 		return;
214260e9a87SYuri Pankov 
21595c635efSGarrett D'Amore 	t = p = NULL;
21695c635efSGarrett D'Amore 
21795c635efSGarrett D'Amore 	switch (n->type) {
218371584c2SYuri Pankov 	case ROFFT_ROOT:
21995c635efSGarrett D'Amore 		t = "root";
22095c635efSGarrett D'Amore 		break;
221371584c2SYuri Pankov 	case ROFFT_ELEM:
22295c635efSGarrett D'Amore 		t = "elem";
22395c635efSGarrett D'Amore 		break;
224371584c2SYuri Pankov 	case ROFFT_TEXT:
22595c635efSGarrett D'Amore 		t = "text";
22695c635efSGarrett D'Amore 		break;
2276640c13bSYuri Pankov 	case ROFFT_COMMENT:
2286640c13bSYuri Pankov 		t = "comment";
2296640c13bSYuri Pankov 		break;
230371584c2SYuri Pankov 	case ROFFT_BLOCK:
23195c635efSGarrett D'Amore 		t = "block";
23295c635efSGarrett D'Amore 		break;
233371584c2SYuri Pankov 	case ROFFT_HEAD:
234371584c2SYuri Pankov 		t = "head";
23595c635efSGarrett D'Amore 		break;
236371584c2SYuri Pankov 	case ROFFT_BODY:
237371584c2SYuri Pankov 		t = "body";
23895c635efSGarrett D'Amore 		break;
239371584c2SYuri Pankov 	case ROFFT_TBL:
24095c635efSGarrett D'Amore 		break;
241371584c2SYuri Pankov 	case ROFFT_EQN:
242260e9a87SYuri Pankov 		t = "eqn";
24395c635efSGarrett D'Amore 		break;
24495c635efSGarrett D'Amore 	default:
24595c635efSGarrett D'Amore 		abort();
24695c635efSGarrett D'Amore 	}
24795c635efSGarrett D'Amore 
24895c635efSGarrett D'Amore 	switch (n->type) {
249371584c2SYuri Pankov 	case ROFFT_TEXT:
2506640c13bSYuri Pankov 	case ROFFT_COMMENT:
25195c635efSGarrett D'Amore 		p = n->string;
25295c635efSGarrett D'Amore 		break;
253371584c2SYuri Pankov 	case ROFFT_ELEM:
254371584c2SYuri Pankov 	case ROFFT_BLOCK:
255371584c2SYuri Pankov 	case ROFFT_HEAD:
256371584c2SYuri Pankov 	case ROFFT_BODY:
257c66b8046SYuri Pankov 		p = roff_name[n->tok];
25895c635efSGarrett D'Amore 		break;
259371584c2SYuri Pankov 	case ROFFT_ROOT:
26095c635efSGarrett D'Amore 		p = "root";
26195c635efSGarrett D'Amore 		break;
262371584c2SYuri Pankov 	case ROFFT_TBL:
263260e9a87SYuri Pankov 		break;
264371584c2SYuri Pankov 	case ROFFT_EQN:
265260e9a87SYuri Pankov 		p = "EQ";
26695c635efSGarrett D'Amore 		break;
26795c635efSGarrett D'Amore 	default:
26895c635efSGarrett D'Amore 		abort();
26995c635efSGarrett D'Amore 	}
27095c635efSGarrett D'Amore 
27195c635efSGarrett D'Amore 	if (n->span) {
27295c635efSGarrett D'Amore 		assert(NULL == p && NULL == t);
27395c635efSGarrett D'Amore 		print_span(n->span, indent);
27495c635efSGarrett D'Amore 	} else {
27595c635efSGarrett D'Amore 		for (i = 0; i < indent; i++)
276260e9a87SYuri Pankov 			putchar(' ');
277260e9a87SYuri Pankov 		printf("%s (%s)", p, t);
278*4d131170SRobert Mustacchi 		print_attr(n);
27995c635efSGarrett D'Amore 	}
280260e9a87SYuri Pankov 	if (n->eqn)
281c66b8046SYuri Pankov 		print_box(n->eqn->first, indent + 4);
28295c635efSGarrett D'Amore 	if (n->child)
283260e9a87SYuri Pankov 		print_man(n->child, indent +
284371584c2SYuri Pankov 		    (n->type == ROFFT_BLOCK ? 2 : 4));
28595c635efSGarrett D'Amore 	if (n->next)
28695c635efSGarrett D'Amore 		print_man(n->next, indent);
28795c635efSGarrett D'Amore }
28895c635efSGarrett D'Amore 
28995c635efSGarrett D'Amore static void
print_attr(const struct roff_node * n)290*4d131170SRobert Mustacchi print_attr(const struct roff_node *n)
291*4d131170SRobert Mustacchi {
292*4d131170SRobert Mustacchi 	putchar(' ');
293*4d131170SRobert Mustacchi 	if (n->flags & NODE_DELIMO)
294*4d131170SRobert Mustacchi 		putchar('(');
295*4d131170SRobert Mustacchi 	if (n->flags & NODE_LINE)
296*4d131170SRobert Mustacchi 		putchar('*');
297*4d131170SRobert Mustacchi 	printf("%d:%d", n->line, n->pos + 1);
298*4d131170SRobert Mustacchi 	if (n->flags & NODE_DELIMC)
299*4d131170SRobert Mustacchi 		putchar(')');
300*4d131170SRobert Mustacchi 	if (n->flags & NODE_EOS)
301*4d131170SRobert Mustacchi 		putchar('.');
302*4d131170SRobert Mustacchi 	if (n->flags & NODE_ID) {
303*4d131170SRobert Mustacchi 		printf(" ID");
304*4d131170SRobert Mustacchi 		if (n->flags & NODE_HREF)
305*4d131170SRobert Mustacchi 			printf("=HREF");
306*4d131170SRobert Mustacchi 	} else if (n->flags & NODE_HREF)
307*4d131170SRobert Mustacchi 		printf(" HREF");
308*4d131170SRobert Mustacchi 	else if (n->tag != NULL)
309*4d131170SRobert Mustacchi 		printf(" STRAYTAG");
310*4d131170SRobert Mustacchi 	if (n->tag != NULL)
311*4d131170SRobert Mustacchi 		printf("=%s", n->tag);
312*4d131170SRobert Mustacchi 	if (n->flags & NODE_BROKEN)
313*4d131170SRobert Mustacchi 		printf(" BROKEN");
314*4d131170SRobert Mustacchi 	if (n->flags & NODE_NOFILL)
315*4d131170SRobert Mustacchi 		printf(" NOFILL");
316*4d131170SRobert Mustacchi 	if (n->flags & NODE_NOSRC)
317*4d131170SRobert Mustacchi 		printf(" NOSRC");
318*4d131170SRobert Mustacchi 	if (n->flags & NODE_NOPRT)
319*4d131170SRobert Mustacchi 		printf(" NOPRT");
320*4d131170SRobert Mustacchi 	putchar('\n');
321*4d131170SRobert Mustacchi }
322*4d131170SRobert Mustacchi 
323*4d131170SRobert Mustacchi static void
print_box(const struct eqn_box * ep,int indent)32495c635efSGarrett D'Amore print_box(const struct eqn_box *ep, int indent)
32595c635efSGarrett D'Amore {
32695c635efSGarrett D'Amore 	int		 i;
32795c635efSGarrett D'Amore 	const char	*t;
32895c635efSGarrett D'Amore 
329260e9a87SYuri Pankov 	static const char *posnames[] = {
330260e9a87SYuri Pankov 	    NULL, "sup", "subsup", "sub",
331260e9a87SYuri Pankov 	    "to", "from", "fromto",
332260e9a87SYuri Pankov 	    "over", "sqrt", NULL };
333260e9a87SYuri Pankov 
33495c635efSGarrett D'Amore 	if (NULL == ep)
33595c635efSGarrett D'Amore 		return;
33695c635efSGarrett D'Amore 	for (i = 0; i < indent; i++)
337260e9a87SYuri Pankov 		putchar(' ');
33895c635efSGarrett D'Amore 
33995c635efSGarrett D'Amore 	t = NULL;
34095c635efSGarrett D'Amore 	switch (ep->type) {
341260e9a87SYuri Pankov 	case EQN_LIST:
34295c635efSGarrett D'Amore 		t = "eqn-list";
34395c635efSGarrett D'Amore 		break;
344260e9a87SYuri Pankov 	case EQN_SUBEXPR:
34595c635efSGarrett D'Amore 		t = "eqn-expr";
34695c635efSGarrett D'Amore 		break;
347260e9a87SYuri Pankov 	case EQN_TEXT:
34895c635efSGarrett D'Amore 		t = "eqn-text";
34995c635efSGarrett D'Amore 		break;
350260e9a87SYuri Pankov 	case EQN_PILE:
351260e9a87SYuri Pankov 		t = "eqn-pile";
352260e9a87SYuri Pankov 		break;
353260e9a87SYuri Pankov 	case EQN_MATRIX:
35495c635efSGarrett D'Amore 		t = "eqn-matrix";
35595c635efSGarrett D'Amore 		break;
35695c635efSGarrett D'Amore 	}
35795c635efSGarrett D'Amore 
358260e9a87SYuri Pankov 	fputs(t, stdout);
359260e9a87SYuri Pankov 	if (ep->pos)
360260e9a87SYuri Pankov 		printf(" pos=%s", posnames[ep->pos]);
361260e9a87SYuri Pankov 	if (ep->left)
362260e9a87SYuri Pankov 		printf(" left=\"%s\"", ep->left);
363260e9a87SYuri Pankov 	if (ep->right)
364260e9a87SYuri Pankov 		printf(" right=\"%s\"", ep->right);
365260e9a87SYuri Pankov 	if (ep->top)
366260e9a87SYuri Pankov 		printf(" top=\"%s\"", ep->top);
367260e9a87SYuri Pankov 	if (ep->bottom)
368260e9a87SYuri Pankov 		printf(" bottom=\"%s\"", ep->bottom);
369260e9a87SYuri Pankov 	if (ep->text)
370260e9a87SYuri Pankov 		printf(" text=\"%s\"", ep->text);
371260e9a87SYuri Pankov 	if (ep->font)
372260e9a87SYuri Pankov 		printf(" font=%d", ep->font);
373260e9a87SYuri Pankov 	if (ep->size != EQN_DEFSIZE)
374260e9a87SYuri Pankov 		printf(" size=%d", ep->size);
375260e9a87SYuri Pankov 	if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
376260e9a87SYuri Pankov 		printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
377260e9a87SYuri Pankov 	else if (ep->args)
378260e9a87SYuri Pankov 		printf(" args=%zu", ep->args);
379260e9a87SYuri Pankov 	putchar('\n');
38095c635efSGarrett D'Amore 
381260e9a87SYuri Pankov 	print_box(ep->first, indent + 4);
38295c635efSGarrett D'Amore 	print_box(ep->next, indent);
38395c635efSGarrett D'Amore }
38495c635efSGarrett D'Amore 
38595c635efSGarrett D'Amore static void
print_cellt(enum tbl_cellt pos)386*4d131170SRobert Mustacchi print_cellt(enum tbl_cellt pos)
387*4d131170SRobert Mustacchi {
388*4d131170SRobert Mustacchi 	switch(pos) {
389*4d131170SRobert Mustacchi 	case TBL_CELL_LEFT:
390*4d131170SRobert Mustacchi 		putchar('L');
391*4d131170SRobert Mustacchi 		break;
392*4d131170SRobert Mustacchi 	case TBL_CELL_LONG:
393*4d131170SRobert Mustacchi 		putchar('a');
394*4d131170SRobert Mustacchi 		break;
395*4d131170SRobert Mustacchi 	case TBL_CELL_CENTRE:
396*4d131170SRobert Mustacchi 		putchar('c');
397*4d131170SRobert Mustacchi 		break;
398*4d131170SRobert Mustacchi 	case TBL_CELL_RIGHT:
399*4d131170SRobert Mustacchi 		putchar('r');
400*4d131170SRobert Mustacchi 		break;
401*4d131170SRobert Mustacchi 	case TBL_CELL_NUMBER:
402*4d131170SRobert Mustacchi 		putchar('n');
403*4d131170SRobert Mustacchi 		break;
404*4d131170SRobert Mustacchi 	case TBL_CELL_SPAN:
405*4d131170SRobert Mustacchi 		putchar('s');
406*4d131170SRobert Mustacchi 		break;
407*4d131170SRobert Mustacchi 	case TBL_CELL_DOWN:
408*4d131170SRobert Mustacchi 		putchar('^');
409*4d131170SRobert Mustacchi 		break;
410*4d131170SRobert Mustacchi 	case TBL_CELL_HORIZ:
411*4d131170SRobert Mustacchi 		putchar('-');
412*4d131170SRobert Mustacchi 		break;
413*4d131170SRobert Mustacchi 	case TBL_CELL_DHORIZ:
414*4d131170SRobert Mustacchi 		putchar('=');
415*4d131170SRobert Mustacchi 		break;
416*4d131170SRobert Mustacchi 	case TBL_CELL_MAX:
417*4d131170SRobert Mustacchi 		putchar('#');
418*4d131170SRobert Mustacchi 		break;
419*4d131170SRobert Mustacchi 	}
420*4d131170SRobert Mustacchi }
421*4d131170SRobert Mustacchi 
422*4d131170SRobert Mustacchi static void
print_span(const struct tbl_span * sp,int indent)42395c635efSGarrett D'Amore print_span(const struct tbl_span *sp, int indent)
42495c635efSGarrett D'Amore {
42595c635efSGarrett D'Amore 	const struct tbl_dat *dp;
426*4d131170SRobert Mustacchi 	const struct tbl_cell *cp;
42795c635efSGarrett D'Amore 	int		 i;
42895c635efSGarrett D'Amore 
429*4d131170SRobert Mustacchi 	if (sp->prev == NULL) {
430*4d131170SRobert Mustacchi 		for (i = 0; i < indent; i++)
431*4d131170SRobert Mustacchi 			putchar(' ');
432*4d131170SRobert Mustacchi 		printf("%d", sp->opts->cols);
433*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_CENTRE)
434*4d131170SRobert Mustacchi 			fputs(" center", stdout);
435*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_EXPAND)
436*4d131170SRobert Mustacchi 			fputs(" expand", stdout);
437*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_ALLBOX)
438*4d131170SRobert Mustacchi 			fputs(" allbox", stdout);
439*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_BOX)
440*4d131170SRobert Mustacchi 			fputs(" box", stdout);
441*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_DBOX)
442*4d131170SRobert Mustacchi 			fputs(" doublebox", stdout);
443*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_NOKEEP)
444*4d131170SRobert Mustacchi 			fputs(" nokeep", stdout);
445*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_NOSPACE)
446*4d131170SRobert Mustacchi 			fputs(" nospaces", stdout);
447*4d131170SRobert Mustacchi 		if (sp->opts->opts & TBL_OPT_NOWARN)
448*4d131170SRobert Mustacchi 			fputs(" nowarn", stdout);
449*4d131170SRobert Mustacchi 		printf(" (tbl options) %d:1\n", sp->line);
450*4d131170SRobert Mustacchi 	}
451*4d131170SRobert Mustacchi 
45295c635efSGarrett D'Amore 	for (i = 0; i < indent; i++)
453260e9a87SYuri Pankov 		putchar(' ');
45495c635efSGarrett D'Amore 
45595c635efSGarrett D'Amore 	switch (sp->pos) {
456260e9a87SYuri Pankov 	case TBL_SPAN_HORIZ:
45795c635efSGarrett D'Amore 		putchar('-');
458cec8643bSMichal Nowak 		putchar(' ');
459cec8643bSMichal Nowak 		break;
460260e9a87SYuri Pankov 	case TBL_SPAN_DHORIZ:
46195c635efSGarrett D'Amore 		putchar('=');
462cec8643bSMichal Nowak 		putchar(' ');
46395c635efSGarrett D'Amore 		break;
464cec8643bSMichal Nowak 	default:
465*4d131170SRobert Mustacchi 		for (cp = sp->layout->first; cp != NULL; cp = cp->next)
466*4d131170SRobert Mustacchi 			print_cellt(cp->pos);
467*4d131170SRobert Mustacchi 		putchar(' ');
46895c635efSGarrett D'Amore 		for (dp = sp->first; dp; dp = dp->next) {
469*4d131170SRobert Mustacchi 			if ((cp = dp->layout) == NULL)
470*4d131170SRobert Mustacchi 				putchar('*');
471*4d131170SRobert Mustacchi 			else {
472*4d131170SRobert Mustacchi 				printf("%d", cp->col);
473*4d131170SRobert Mustacchi 				print_cellt(dp->layout->pos);
474*4d131170SRobert Mustacchi 				switch (cp->font) {
475*4d131170SRobert Mustacchi 				case ESCAPE_FONTROMAN:
476*4d131170SRobert Mustacchi 					break;
477*4d131170SRobert Mustacchi 				case ESCAPE_FONTBOLD:
478*4d131170SRobert Mustacchi 					putchar('b');
479*4d131170SRobert Mustacchi 					break;
480*4d131170SRobert Mustacchi 				case ESCAPE_FONTITALIC:
481*4d131170SRobert Mustacchi 					putchar('i');
482*4d131170SRobert Mustacchi 					break;
483*4d131170SRobert Mustacchi 				case ESCAPE_FONTBI:
484*4d131170SRobert Mustacchi 					fputs("bi", stdout);
485*4d131170SRobert Mustacchi 					break;
486*4d131170SRobert Mustacchi 				case ESCAPE_FONTCR:
487*4d131170SRobert Mustacchi 					putchar('c');
488*4d131170SRobert Mustacchi 					break;
489*4d131170SRobert Mustacchi 				case ESCAPE_FONTCB:
490*4d131170SRobert Mustacchi 					fputs("cb", stdout);
491*4d131170SRobert Mustacchi 					break;
492*4d131170SRobert Mustacchi 				case ESCAPE_FONTCI:
493*4d131170SRobert Mustacchi 					fputs("ci", stdout);
494*4d131170SRobert Mustacchi 					break;
495*4d131170SRobert Mustacchi 				default:
496*4d131170SRobert Mustacchi 					abort();
497*4d131170SRobert Mustacchi 				}
498*4d131170SRobert Mustacchi 				if (cp->flags & TBL_CELL_TALIGN)
499*4d131170SRobert Mustacchi 					putchar('t');
500*4d131170SRobert Mustacchi 				if (cp->flags & TBL_CELL_UP)
501*4d131170SRobert Mustacchi 					putchar('u');
502*4d131170SRobert Mustacchi 				if (cp->flags & TBL_CELL_BALIGN)
503*4d131170SRobert Mustacchi 					putchar('d');
504*4d131170SRobert Mustacchi 				if (cp->flags & TBL_CELL_WIGN)
505*4d131170SRobert Mustacchi 					putchar('z');
506*4d131170SRobert Mustacchi 				if (cp->flags & TBL_CELL_EQUAL)
507*4d131170SRobert Mustacchi 					putchar('e');
508*4d131170SRobert Mustacchi 				if (cp->flags & TBL_CELL_WMAX)
509*4d131170SRobert Mustacchi 					putchar('x');
510*4d131170SRobert Mustacchi 			}
51195c635efSGarrett D'Amore 			switch (dp->pos) {
512260e9a87SYuri Pankov 			case TBL_DATA_HORIZ:
513260e9a87SYuri Pankov 			case TBL_DATA_NHORIZ:
51495c635efSGarrett D'Amore 				putchar('-');
515*4d131170SRobert Mustacchi 				break;
516260e9a87SYuri Pankov 			case TBL_DATA_DHORIZ:
517260e9a87SYuri Pankov 			case TBL_DATA_NDHORIZ:
51895c635efSGarrett D'Amore 				putchar('=');
519*4d131170SRobert Mustacchi 				break;
52095c635efSGarrett D'Amore 			default:
521*4d131170SRobert Mustacchi 				putchar(dp->block ? '{' : '[');
522*4d131170SRobert Mustacchi 				if (dp->string != NULL)
523*4d131170SRobert Mustacchi 					fputs(dp->string, stdout);
524*4d131170SRobert Mustacchi 				putchar(dp->block ? '}' : ']');
52595c635efSGarrett D'Amore 				break;
52695c635efSGarrett D'Amore 			}
527cec8643bSMichal Nowak 			if (dp->hspans)
528cec8643bSMichal Nowak 				printf(">%d", dp->hspans);
529cec8643bSMichal Nowak 			if (dp->vspans)
530cec8643bSMichal Nowak 				printf("v%d", dp->vspans);
53195c635efSGarrett D'Amore 			putchar(' ');
53295c635efSGarrett D'Amore 		}
533cec8643bSMichal Nowak 		break;
534cec8643bSMichal Nowak 	}
53595c635efSGarrett D'Amore 	printf("(tbl) %d:1\n", sp->line);
53695c635efSGarrett D'Amore }
537