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