xref: /illumos-gate/usr/src/cmd/mandoc/tree.c (revision c3d26abc9ee97b4f60233556aadeb57e0bd30bb9)
1 /*	$Id: tree.c,v 1.62 2015/02/05 00:14:13 schwarze Exp $ */
2 /*
3  * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
4  * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #include "config.h"
19 
20 #include <sys/types.h>
21 
22 #include <assert.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <time.h>
27 
28 #include "mandoc.h"
29 #include "mdoc.h"
30 #include "man.h"
31 #include "main.h"
32 
33 static	void	print_box(const struct eqn_box *, int);
34 static	void	print_man(const struct man_node *, int);
35 static	void	print_mdoc(const struct mdoc_node *, int);
36 static	void	print_span(const struct tbl_span *, int);
37 
38 
39 void
40 tree_mdoc(void *arg, const struct mdoc *mdoc)
41 {
42 
43 	print_mdoc(mdoc_node(mdoc)->child, 0);
44 }
45 
46 void
47 tree_man(void *arg, const struct man *man)
48 {
49 
50 	print_man(man_node(man)->child, 0);
51 }
52 
53 static void
54 print_mdoc(const struct mdoc_node *n, int indent)
55 {
56 	const char	 *p, *t;
57 	int		  i, j;
58 	size_t		  argc;
59 	struct mdoc_argv *argv;
60 
61 	if (n == NULL)
62 		return;
63 
64 	argv = NULL;
65 	argc = 0;
66 	t = p = NULL;
67 
68 	switch (n->type) {
69 	case MDOC_ROOT:
70 		t = "root";
71 		break;
72 	case MDOC_BLOCK:
73 		t = "block";
74 		break;
75 	case MDOC_HEAD:
76 		t = "block-head";
77 		break;
78 	case MDOC_BODY:
79 		if (n->end)
80 			t = "body-end";
81 		else
82 			t = "block-body";
83 		break;
84 	case MDOC_TAIL:
85 		t = "block-tail";
86 		break;
87 	case MDOC_ELEM:
88 		t = "elem";
89 		break;
90 	case MDOC_TEXT:
91 		t = "text";
92 		break;
93 	case MDOC_TBL:
94 		break;
95 	case MDOC_EQN:
96 		t = "eqn";
97 		break;
98 	default:
99 		abort();
100 		/* NOTREACHED */
101 	}
102 
103 	switch (n->type) {
104 	case MDOC_TEXT:
105 		p = n->string;
106 		break;
107 	case MDOC_BODY:
108 		p = mdoc_macronames[n->tok];
109 		break;
110 	case MDOC_HEAD:
111 		p = mdoc_macronames[n->tok];
112 		break;
113 	case MDOC_TAIL:
114 		p = mdoc_macronames[n->tok];
115 		break;
116 	case MDOC_ELEM:
117 		p = mdoc_macronames[n->tok];
118 		if (n->args) {
119 			argv = n->args->argv;
120 			argc = n->args->argc;
121 		}
122 		break;
123 	case MDOC_BLOCK:
124 		p = mdoc_macronames[n->tok];
125 		if (n->args) {
126 			argv = n->args->argv;
127 			argc = n->args->argc;
128 		}
129 		break;
130 	case MDOC_TBL:
131 		break;
132 	case MDOC_EQN:
133 		p = "EQ";
134 		break;
135 	case MDOC_ROOT:
136 		p = "root";
137 		break;
138 	default:
139 		abort();
140 		/* NOTREACHED */
141 	}
142 
143 	if (n->span) {
144 		assert(NULL == p && NULL == t);
145 		print_span(n->span, indent);
146 	} else {
147 		for (i = 0; i < indent; i++)
148 			putchar(' ');
149 
150 		printf("%s (%s)", p, t);
151 
152 		for (i = 0; i < (int)argc; i++) {
153 			printf(" -%s", mdoc_argnames[argv[i].arg]);
154 			if (argv[i].sz > 0)
155 				printf(" [");
156 			for (j = 0; j < (int)argv[i].sz; j++)
157 				printf(" [%s]", argv[i].value[j]);
158 			if (argv[i].sz > 0)
159 				printf(" ]");
160 		}
161 
162 		putchar(' ');
163 		if (MDOC_LINE & n->flags)
164 			putchar('*');
165 		printf("%d:%d\n", n->line, n->pos + 1);
166 	}
167 
168 	if (n->eqn)
169 		print_box(n->eqn->root->first, indent + 4);
170 	if (n->child)
171 		print_mdoc(n->child, indent +
172 		    (n->type == MDOC_BLOCK ? 2 : 4));
173 	if (n->next)
174 		print_mdoc(n->next, indent);
175 }
176 
177 static void
178 print_man(const struct man_node *n, int indent)
179 {
180 	const char	 *p, *t;
181 	int		  i;
182 
183 	if (n == NULL)
184 		return;
185 
186 	t = p = NULL;
187 
188 	switch (n->type) {
189 	case MAN_ROOT:
190 		t = "root";
191 		break;
192 	case MAN_ELEM:
193 		t = "elem";
194 		break;
195 	case MAN_TEXT:
196 		t = "text";
197 		break;
198 	case MAN_BLOCK:
199 		t = "block";
200 		break;
201 	case MAN_HEAD:
202 		t = "block-head";
203 		break;
204 	case MAN_BODY:
205 		t = "block-body";
206 		break;
207 	case MAN_TBL:
208 		break;
209 	case MAN_EQN:
210 		t = "eqn";
211 		break;
212 	default:
213 		abort();
214 		/* NOTREACHED */
215 	}
216 
217 	switch (n->type) {
218 	case MAN_TEXT:
219 		p = n->string;
220 		break;
221 	case MAN_ELEM:
222 		/* FALLTHROUGH */
223 	case MAN_BLOCK:
224 		/* FALLTHROUGH */
225 	case MAN_HEAD:
226 		/* FALLTHROUGH */
227 	case MAN_BODY:
228 		p = man_macronames[n->tok];
229 		break;
230 	case MAN_ROOT:
231 		p = "root";
232 		break;
233 	case MAN_TBL:
234 		break;
235 	case MAN_EQN:
236 		p = "EQ";
237 		break;
238 	default:
239 		abort();
240 		/* NOTREACHED */
241 	}
242 
243 	if (n->span) {
244 		assert(NULL == p && NULL == t);
245 		print_span(n->span, indent);
246 	} else {
247 		for (i = 0; i < indent; i++)
248 			putchar(' ');
249 		printf("%s (%s) ", p, t);
250 		if (MAN_LINE & n->flags)
251 			putchar('*');
252 		printf("%d:%d\n", n->line, n->pos + 1);
253 	}
254 
255 	if (n->eqn)
256 		print_box(n->eqn->root->first, indent + 4);
257 	if (n->child)
258 		print_man(n->child, indent +
259 		    (n->type == MAN_BLOCK ? 2 : 4));
260 	if (n->next)
261 		print_man(n->next, indent);
262 }
263 
264 static void
265 print_box(const struct eqn_box *ep, int indent)
266 {
267 	int		 i;
268 	const char	*t;
269 
270 	static const char *posnames[] = {
271 	    NULL, "sup", "subsup", "sub",
272 	    "to", "from", "fromto",
273 	    "over", "sqrt", NULL };
274 
275 	if (NULL == ep)
276 		return;
277 	for (i = 0; i < indent; i++)
278 		putchar(' ');
279 
280 	t = NULL;
281 	switch (ep->type) {
282 	case EQN_ROOT:
283 		t = "eqn-root";
284 		break;
285 	case EQN_LISTONE:
286 	case EQN_LIST:
287 		t = "eqn-list";
288 		break;
289 	case EQN_SUBEXPR:
290 		t = "eqn-expr";
291 		break;
292 	case EQN_TEXT:
293 		t = "eqn-text";
294 		break;
295 	case EQN_PILE:
296 		t = "eqn-pile";
297 		break;
298 	case EQN_MATRIX:
299 		t = "eqn-matrix";
300 		break;
301 	}
302 
303 	fputs(t, stdout);
304 	if (ep->pos)
305 		printf(" pos=%s", posnames[ep->pos]);
306 	if (ep->left)
307 		printf(" left=\"%s\"", ep->left);
308 	if (ep->right)
309 		printf(" right=\"%s\"", ep->right);
310 	if (ep->top)
311 		printf(" top=\"%s\"", ep->top);
312 	if (ep->bottom)
313 		printf(" bottom=\"%s\"", ep->bottom);
314 	if (ep->text)
315 		printf(" text=\"%s\"", ep->text);
316 	if (ep->font)
317 		printf(" font=%d", ep->font);
318 	if (ep->size != EQN_DEFSIZE)
319 		printf(" size=%d", ep->size);
320 	if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
321 		printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
322 	else if (ep->args)
323 		printf(" args=%zu", ep->args);
324 	putchar('\n');
325 
326 	print_box(ep->first, indent + 4);
327 	print_box(ep->next, indent);
328 }
329 
330 static void
331 print_span(const struct tbl_span *sp, int indent)
332 {
333 	const struct tbl_dat *dp;
334 	int		 i;
335 
336 	for (i = 0; i < indent; i++)
337 		putchar(' ');
338 
339 	switch (sp->pos) {
340 	case TBL_SPAN_HORIZ:
341 		putchar('-');
342 		return;
343 	case TBL_SPAN_DHORIZ:
344 		putchar('=');
345 		return;
346 	default:
347 		break;
348 	}
349 
350 	for (dp = sp->first; dp; dp = dp->next) {
351 		switch (dp->pos) {
352 		case TBL_DATA_HORIZ:
353 			/* FALLTHROUGH */
354 		case TBL_DATA_NHORIZ:
355 			putchar('-');
356 			continue;
357 		case TBL_DATA_DHORIZ:
358 			/* FALLTHROUGH */
359 		case TBL_DATA_NDHORIZ:
360 			putchar('=');
361 			continue;
362 		default:
363 			break;
364 		}
365 		printf("[\"%s\"", dp->string ? dp->string : "");
366 		if (dp->spans)
367 			printf("(%d)", dp->spans);
368 		if (NULL == dp->layout)
369 			putchar('*');
370 		putchar(']');
371 		putchar(' ');
372 	}
373 
374 	printf("(tbl) %d:1\n", sp->line);
375 }
376