xref: /dragonfly/contrib/mdocml/tree.c (revision e8c03636)
1 /*	$Id: tree.c,v 1.47 2011/09/18 14:14:15 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 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include <assert.h>
22 #include <limits.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <time.h>
26 
27 #include "mandoc.h"
28 #include "mdoc.h"
29 #include "man.h"
30 #include "main.h"
31 
32 static	void	print_box(const struct eqn_box *, int);
33 static	void	print_man(const struct man_node *, int);
34 static	void	print_mdoc(const struct mdoc_node *, int);
35 static	void	print_span(const struct tbl_span *, int);
36 
37 
38 /* ARGSUSED */
39 void
40 tree_mdoc(void *arg, const struct mdoc *mdoc)
41 {
42 
43 	print_mdoc(mdoc_node(mdoc), 0);
44 }
45 
46 
47 /* ARGSUSED */
48 void
49 tree_man(void *arg, const struct man *man)
50 {
51 
52 	print_man(man_node(man), 0);
53 }
54 
55 
56 static void
57 print_mdoc(const struct mdoc_node *n, int indent)
58 {
59 	const char	 *p, *t;
60 	int		  i, j;
61 	size_t		  argc, sz;
62 	char		**params;
63 	struct mdoc_argv *argv;
64 
65 	argv = NULL;
66 	argc = sz = 0;
67 	params = NULL;
68 	t = p = NULL;
69 
70 	switch (n->type) {
71 	case (MDOC_ROOT):
72 		t = "root";
73 		break;
74 	case (MDOC_BLOCK):
75 		t = "block";
76 		break;
77 	case (MDOC_HEAD):
78 		t = "block-head";
79 		break;
80 	case (MDOC_BODY):
81 		if (n->end)
82 			t = "body-end";
83 		else
84 			t = "block-body";
85 		break;
86 	case (MDOC_TAIL):
87 		t = "block-tail";
88 		break;
89 	case (MDOC_ELEM):
90 		t = "elem";
91 		break;
92 	case (MDOC_TEXT):
93 		t = "text";
94 		break;
95 	case (MDOC_TBL):
96 		/* FALLTHROUGH */
97 	case (MDOC_EQN):
98 		break;
99 	default:
100 		abort();
101 		/* NOTREACHED */
102 	}
103 
104 	switch (n->type) {
105 	case (MDOC_TEXT):
106 		p = n->string;
107 		break;
108 	case (MDOC_BODY):
109 		p = mdoc_macronames[n->tok];
110 		break;
111 	case (MDOC_HEAD):
112 		p = mdoc_macronames[n->tok];
113 		break;
114 	case (MDOC_TAIL):
115 		p = mdoc_macronames[n->tok];
116 		break;
117 	case (MDOC_ELEM):
118 		p = mdoc_macronames[n->tok];
119 		if (n->args) {
120 			argv = n->args->argv;
121 			argc = n->args->argc;
122 		}
123 		break;
124 	case (MDOC_BLOCK):
125 		p = mdoc_macronames[n->tok];
126 		if (n->args) {
127 			argv = n->args->argv;
128 			argc = n->args->argc;
129 		}
130 		break;
131 	case (MDOC_TBL):
132 		/* FALLTHROUGH */
133 	case (MDOC_EQN):
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 if (n->eqn) {
147 		assert(NULL == p && NULL == t);
148 		print_box(n->eqn->root, indent);
149 	} else {
150 		for (i = 0; i < indent; i++)
151 			putchar('\t');
152 
153 		printf("%s (%s)", p, t);
154 
155 		for (i = 0; i < (int)argc; i++) {
156 			printf(" -%s", mdoc_argnames[argv[i].arg]);
157 			if (argv[i].sz > 0)
158 				printf(" [");
159 			for (j = 0; j < (int)argv[i].sz; j++)
160 				printf(" [%s]", argv[i].value[j]);
161 			if (argv[i].sz > 0)
162 				printf(" ]");
163 		}
164 
165 		for (i = 0; i < (int)sz; i++)
166 			printf(" [%s]", params[i]);
167 
168 		printf(" %d:%d\n", n->line, n->pos);
169 	}
170 
171 	if (n->child)
172 		print_mdoc(n->child, indent + 1);
173 	if (n->next)
174 		print_mdoc(n->next, indent);
175 }
176 
177 
178 static void
179 print_man(const struct man_node *n, int indent)
180 {
181 	const char	 *p, *t;
182 	int		  i;
183 
184 	t = p = NULL;
185 
186 	switch (n->type) {
187 	case (MAN_ROOT):
188 		t = "root";
189 		break;
190 	case (MAN_ELEM):
191 		t = "elem";
192 		break;
193 	case (MAN_TEXT):
194 		t = "text";
195 		break;
196 	case (MAN_BLOCK):
197 		t = "block";
198 		break;
199 	case (MAN_HEAD):
200 		t = "block-head";
201 		break;
202 	case (MAN_BODY):
203 		t = "block-body";
204 		break;
205 	case (MAN_TAIL):
206 		t = "block-tail";
207 		break;
208 	case (MAN_TBL):
209 		/* FALLTHROUGH */
210 	case (MAN_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_TAIL):
228 		/* FALLTHROUGH */
229 	case (MAN_BODY):
230 		p = man_macronames[n->tok];
231 		break;
232 	case (MAN_ROOT):
233 		p = "root";
234 		break;
235 	case (MAN_TBL):
236 		/* FALLTHROUGH */
237 	case (MAN_EQN):
238 		break;
239 	default:
240 		abort();
241 		/* NOTREACHED */
242 	}
243 
244 	if (n->span) {
245 		assert(NULL == p && NULL == t);
246 		print_span(n->span, indent);
247 	} else if (n->eqn) {
248 		assert(NULL == p && NULL == t);
249 		print_box(n->eqn->root, indent);
250 	} else {
251 		for (i = 0; i < indent; i++)
252 			putchar('\t');
253 		printf("%s (%s) %d:%d\n", p, t, n->line, n->pos);
254 	}
255 
256 	if (n->child)
257 		print_man(n->child, indent + 1);
258 	if (n->next)
259 		print_man(n->next, indent);
260 }
261 
262 static void
263 print_box(const struct eqn_box *ep, int indent)
264 {
265 	int		 i;
266 	const char	*t;
267 
268 	if (NULL == ep)
269 		return;
270 	for (i = 0; i < indent; i++)
271 		putchar('\t');
272 
273 	t = NULL;
274 	switch (ep->type) {
275 	case (EQN_ROOT):
276 		t = "eqn-root";
277 		break;
278 	case (EQN_LIST):
279 		t = "eqn-list";
280 		break;
281 	case (EQN_SUBEXPR):
282 		t = "eqn-expr";
283 		break;
284 	case (EQN_TEXT):
285 		t = "eqn-text";
286 		break;
287 	case (EQN_MATRIX):
288 		t = "eqn-matrix";
289 		break;
290 	}
291 
292 	assert(t);
293 	printf("%s(%d, %d, %d, %d, %d, \"%s\", \"%s\") %s\n",
294 		t, EQN_DEFSIZE == ep->size ? 0 : ep->size,
295 		ep->pos, ep->font, ep->mark, ep->pile,
296 		ep->left ? ep->left : "",
297 		ep->right ? ep->right : "",
298 		ep->text ? ep->text : "");
299 
300 	print_box(ep->first, indent + 1);
301 	print_box(ep->next, indent);
302 }
303 
304 static void
305 print_span(const struct tbl_span *sp, int indent)
306 {
307 	const struct tbl_dat *dp;
308 	int		 i;
309 
310 	for (i = 0; i < indent; i++)
311 		putchar('\t');
312 
313 	switch (sp->pos) {
314 	case (TBL_SPAN_HORIZ):
315 		putchar('-');
316 		return;
317 	case (TBL_SPAN_DHORIZ):
318 		putchar('=');
319 		return;
320 	default:
321 		break;
322 	}
323 
324 	for (dp = sp->first; dp; dp = dp->next) {
325 		switch (dp->pos) {
326 		case (TBL_DATA_HORIZ):
327 			/* FALLTHROUGH */
328 		case (TBL_DATA_NHORIZ):
329 			putchar('-');
330 			continue;
331 		case (TBL_DATA_DHORIZ):
332 			/* FALLTHROUGH */
333 		case (TBL_DATA_NDHORIZ):
334 			putchar('=');
335 			continue;
336 		default:
337 			break;
338 		}
339 		printf("[\"%s\"", dp->string ? dp->string : "");
340 		if (dp->spans)
341 			printf("(%d)", dp->spans);
342 		if (NULL == dp->layout)
343 			putchar('*');
344 		putchar(']');
345 		putchar(' ');
346 	}
347 
348 	printf("(tbl) %d:1\n", sp->line);
349 }
350