xref: /openbsd-src/usr.bin/mandoc/tree.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$Id: tree.c,v 1.15 2011/04/24 16:22:02 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 <stdio.h>
19 #include <stdlib.h>
20 #include <time.h>
21 
22 #include "mandoc.h"
23 #include "mdoc.h"
24 #include "man.h"
25 #include "main.h"
26 
27 static	void	print_mdoc(const struct mdoc_node *, int);
28 static	void	print_man(const struct man_node *, int);
29 static	void	print_span(const struct tbl_span *, int);
30 
31 
32 /* ARGSUSED */
33 void
34 tree_mdoc(void *arg, const struct mdoc *mdoc)
35 {
36 
37 	print_mdoc(mdoc_node(mdoc), 0);
38 }
39 
40 
41 /* ARGSUSED */
42 void
43 tree_man(void *arg, const struct man *man)
44 {
45 
46 	print_man(man_node(man), 0);
47 }
48 
49 
50 static void
51 print_mdoc(const struct mdoc_node *n, int indent)
52 {
53 	const char	 *p, *t;
54 	int		  i, j;
55 	size_t		  argc, sz;
56 	char		**params;
57 	struct mdoc_argv *argv;
58 
59 	argv = NULL;
60 	argc = sz = 0;
61 	params = NULL;
62 
63 	switch (n->type) {
64 	case (MDOC_ROOT):
65 		t = "root";
66 		break;
67 	case (MDOC_BLOCK):
68 		t = "block";
69 		break;
70 	case (MDOC_HEAD):
71 		t = "block-head";
72 		break;
73 	case (MDOC_BODY):
74 		if (n->end)
75 			t = "body-end";
76 		else
77 			t = "block-body";
78 		break;
79 	case (MDOC_TAIL):
80 		t = "block-tail";
81 		break;
82 	case (MDOC_ELEM):
83 		t = "elem";
84 		break;
85 	case (MDOC_TEXT):
86 		t = "text";
87 		break;
88 	case (MDOC_TBL):
89 		t = "tbl";
90 		break;
91 	case (MDOC_EQN):
92 		t = "eqn";
93 		break;
94 	default:
95 		abort();
96 		/* NOTREACHED */
97 	}
98 
99 	p = NULL;
100 
101 	switch (n->type) {
102 	case (MDOC_TEXT):
103 		p = n->string;
104 		break;
105 	case (MDOC_BODY):
106 		p = mdoc_macronames[n->tok];
107 		break;
108 	case (MDOC_HEAD):
109 		p = mdoc_macronames[n->tok];
110 		break;
111 	case (MDOC_TAIL):
112 		p = mdoc_macronames[n->tok];
113 		break;
114 	case (MDOC_ELEM):
115 		p = mdoc_macronames[n->tok];
116 		if (n->args) {
117 			argv = n->args->argv;
118 			argc = n->args->argc;
119 		}
120 		break;
121 	case (MDOC_BLOCK):
122 		p = mdoc_macronames[n->tok];
123 		if (n->args) {
124 			argv = n->args->argv;
125 			argc = n->args->argc;
126 		}
127 		break;
128 	case (MDOC_TBL):
129 		break;
130 	case (MDOC_EQN):
131 		p = n->eqn->data;
132 		break;
133 	case (MDOC_ROOT):
134 		p = "root";
135 		break;
136 	default:
137 		abort();
138 		/* NOTREACHED */
139 	}
140 
141 	if (n->span) {
142 		assert(NULL == p);
143 		print_span(n->span, 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 		for (i = 0; i < (int)sz; i++)
161 			printf(" [%s]", params[i]);
162 
163 		printf(" %d:%d", n->line, n->pos);
164 	}
165 
166 	putchar('\n');
167 
168 	if (n->child)
169 		print_mdoc(n->child, indent + 1);
170 	if (n->next)
171 		print_mdoc(n->next, indent);
172 }
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 	switch (n->type) {
182 	case (MAN_ROOT):
183 		t = "root";
184 		break;
185 	case (MAN_ELEM):
186 		t = "elem";
187 		break;
188 	case (MAN_TEXT):
189 		t = "text";
190 		break;
191 	case (MAN_BLOCK):
192 		t = "block";
193 		break;
194 	case (MAN_HEAD):
195 		t = "block-head";
196 		break;
197 	case (MAN_BODY):
198 		t = "block-body";
199 		break;
200 	case (MAN_TAIL):
201 		t = "block-tail";
202 		break;
203 	case (MAN_TBL):
204 		t = "tbl";
205 		break;
206 	case (MAN_EQN):
207 		t = "eqn";
208 		break;
209 	default:
210 		abort();
211 		/* NOTREACHED */
212 	}
213 
214 	p = NULL;
215 
216 	switch (n->type) {
217 	case (MAN_TEXT):
218 		p = n->string;
219 		break;
220 	case (MAN_ELEM):
221 		/* FALLTHROUGH */
222 	case (MAN_BLOCK):
223 		/* FALLTHROUGH */
224 	case (MAN_HEAD):
225 		/* FALLTHROUGH */
226 	case (MAN_TAIL):
227 		/* FALLTHROUGH */
228 	case (MAN_BODY):
229 		p = man_macronames[n->tok];
230 		break;
231 	case (MAN_ROOT):
232 		p = "root";
233 		break;
234 	case (MAN_TBL):
235 		break;
236 	case (MAN_EQN):
237 		p = n->eqn->data;
238 		break;
239 	default:
240 		abort();
241 		/* NOTREACHED */
242 	}
243 
244 	if (n->span) {
245 		assert(NULL == p);
246 		print_span(n->span, indent);
247 	} else {
248 		for (i = 0; i < indent; i++)
249 			putchar('\t');
250 		printf("%s (%s) %d:%d", p, t, n->line, n->pos);
251 	}
252 
253 	putchar('\n');
254 
255 	if (n->child)
256 		print_man(n->child, indent + 1);
257 	if (n->next)
258 		print_man(n->next, indent);
259 }
260 
261 static void
262 print_span(const struct tbl_span *sp, int indent)
263 {
264 	const struct tbl_dat *dp;
265 	int		 i;
266 
267 	for (i = 0; i < indent; i++)
268 		putchar('\t');
269 
270 	switch (sp->pos) {
271 	case (TBL_SPAN_HORIZ):
272 		putchar('-');
273 		return;
274 	case (TBL_SPAN_DHORIZ):
275 		putchar('=');
276 		return;
277 	default:
278 		break;
279 	}
280 
281 	for (dp = sp->first; dp; dp = dp->next) {
282 		switch (dp->pos) {
283 		case (TBL_DATA_HORIZ):
284 			/* FALLTHROUGH */
285 		case (TBL_DATA_NHORIZ):
286 			putchar('-');
287 			continue;
288 		case (TBL_DATA_DHORIZ):
289 			/* FALLTHROUGH */
290 		case (TBL_DATA_NDHORIZ):
291 			putchar('=');
292 			continue;
293 		default:
294 			break;
295 		}
296 		printf("[\"%s\"", dp->string ? dp->string : "");
297 		if (dp->spans)
298 			printf("(%d)", dp->spans);
299 		if (NULL == dp->layout)
300 			putchar('*');
301 		putchar(']');
302 		putchar(' ');
303 	}
304 
305 	printf("(tbl) %d:1", sp->line);
306 }
307