xref: /dragonfly/contrib/mdocml/tree.c (revision 3851e4b8)
1 /*	$Id: tree.c,v 1.53 2014/07/02 07:10:38 schwarze Exp $ */
2 /*
3  * Copyright (c) 2008, 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4  * Copyright (c) 2013, 2014 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 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
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), 0);
44 }
45 
46 void
47 tree_man(void *arg, const struct man *man)
48 {
49 
50 	print_man(man_node(man), 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 	argv = NULL;
62 	argc = 0;
63 	t = p = NULL;
64 
65 	switch (n->type) {
66 	case MDOC_ROOT:
67 		t = "root";
68 		break;
69 	case MDOC_BLOCK:
70 		t = "block";
71 		break;
72 	case MDOC_HEAD:
73 		t = "block-head";
74 		break;
75 	case MDOC_BODY:
76 		if (n->end)
77 			t = "body-end";
78 		else
79 			t = "block-body";
80 		break;
81 	case MDOC_TAIL:
82 		t = "block-tail";
83 		break;
84 	case MDOC_ELEM:
85 		t = "elem";
86 		break;
87 	case MDOC_TEXT:
88 		t = "text";
89 		break;
90 	case MDOC_TBL:
91 		/* FALLTHROUGH */
92 	case MDOC_EQN:
93 		break;
94 	default:
95 		abort();
96 		/* NOTREACHED */
97 	}
98 
99 	switch (n->type) {
100 	case MDOC_TEXT:
101 		p = n->string;
102 		break;
103 	case MDOC_BODY:
104 		p = mdoc_macronames[n->tok];
105 		break;
106 	case MDOC_HEAD:
107 		p = mdoc_macronames[n->tok];
108 		break;
109 	case MDOC_TAIL:
110 		p = mdoc_macronames[n->tok];
111 		break;
112 	case MDOC_ELEM:
113 		p = mdoc_macronames[n->tok];
114 		if (n->args) {
115 			argv = n->args->argv;
116 			argc = n->args->argc;
117 		}
118 		break;
119 	case MDOC_BLOCK:
120 		p = mdoc_macronames[n->tok];
121 		if (n->args) {
122 			argv = n->args->argv;
123 			argc = n->args->argc;
124 		}
125 		break;
126 	case MDOC_TBL:
127 		/* FALLTHROUGH */
128 	case MDOC_EQN:
129 		break;
130 	case MDOC_ROOT:
131 		p = "root";
132 		break;
133 	default:
134 		abort();
135 		/* NOTREACHED */
136 	}
137 
138 	if (n->span) {
139 		assert(NULL == p && NULL == t);
140 		print_span(n->span, indent);
141 	} else if (n->eqn) {
142 		assert(NULL == p && NULL == t);
143 		print_box(n->eqn->root, indent);
144 	} else {
145 		for (i = 0; i < indent; i++)
146 			putchar('\t');
147 
148 		printf("%s (%s)", p, t);
149 
150 		for (i = 0; i < (int)argc; i++) {
151 			printf(" -%s", mdoc_argnames[argv[i].arg]);
152 			if (argv[i].sz > 0)
153 				printf(" [");
154 			for (j = 0; j < (int)argv[i].sz; j++)
155 				printf(" [%s]", argv[i].value[j]);
156 			if (argv[i].sz > 0)
157 				printf(" ]");
158 		}
159 
160 		putchar(' ');
161 		if (MDOC_LINE & n->flags)
162 			putchar('*');
163 		printf("%d:%d", n->line, n->pos + 1);
164 		if (n->lastline != n->line)
165 			printf("-%d", n->lastline);
166 		putchar('\n');
167 	}
168 
169 	if (n->child)
170 		print_mdoc(n->child, indent + 1);
171 	if (n->next)
172 		print_mdoc(n->next, indent);
173 }
174 
175 static void
176 print_man(const struct man_node *n, int indent)
177 {
178 	const char	 *p, *t;
179 	int		  i;
180 
181 	t = p = NULL;
182 
183 	switch (n->type) {
184 	case MAN_ROOT:
185 		t = "root";
186 		break;
187 	case MAN_ELEM:
188 		t = "elem";
189 		break;
190 	case MAN_TEXT:
191 		t = "text";
192 		break;
193 	case MAN_BLOCK:
194 		t = "block";
195 		break;
196 	case MAN_HEAD:
197 		t = "block-head";
198 		break;
199 	case MAN_BODY:
200 		t = "block-body";
201 		break;
202 	case MAN_TAIL:
203 		t = "block-tail";
204 		break;
205 	case MAN_TBL:
206 		/* FALLTHROUGH */
207 	case MAN_EQN:
208 		break;
209 	default:
210 		abort();
211 		/* NOTREACHED */
212 	}
213 
214 	switch (n->type) {
215 	case MAN_TEXT:
216 		p = n->string;
217 		break;
218 	case MAN_ELEM:
219 		/* FALLTHROUGH */
220 	case MAN_BLOCK:
221 		/* FALLTHROUGH */
222 	case MAN_HEAD:
223 		/* FALLTHROUGH */
224 	case MAN_TAIL:
225 		/* FALLTHROUGH */
226 	case MAN_BODY:
227 		p = man_macronames[n->tok];
228 		break;
229 	case MAN_ROOT:
230 		p = "root";
231 		break;
232 	case MAN_TBL:
233 		/* FALLTHROUGH */
234 	case MAN_EQN:
235 		break;
236 	default:
237 		abort();
238 		/* NOTREACHED */
239 	}
240 
241 	if (n->span) {
242 		assert(NULL == p && NULL == t);
243 		print_span(n->span, indent);
244 	} else if (n->eqn) {
245 		assert(NULL == p && NULL == t);
246 		print_box(n->eqn->root, indent);
247 	} else {
248 		for (i = 0; i < indent; i++)
249 			putchar('\t');
250 		printf("%s (%s) ", p, t);
251 		if (MAN_LINE & n->flags)
252 			putchar('*');
253 		printf("%d:%d\n", n->line, n->pos + 1);
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 + 1, 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