]> git.cameronkatri.com Git - mandoc.git/blob - tree.c
Print more tbl(7) details to help debugging:
[mandoc.git] / tree.c
1 /* $Id: tree.c,v 1.85 2020/01/11 16:03:42 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2013-2015, 2017-2020 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 AUTHORS DISCLAIM ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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 "roff.h"
30 #include "mdoc.h"
31 #include "man.h"
32 #include "tbl.h"
33 #include "eqn.h"
34 #include "main.h"
35
36 static void print_box(const struct eqn_box *, int);
37 static void print_cellt(enum tbl_cellt);
38 static void print_man(const struct roff_node *, int);
39 static void print_meta(const struct roff_meta *);
40 static void print_mdoc(const struct roff_node *, int);
41 static void print_span(const struct tbl_span *, int);
42
43
44 void
45 tree_mdoc(void *arg, const struct roff_meta *mdoc)
46 {
47 print_meta(mdoc);
48 putchar('\n');
49 print_mdoc(mdoc->first->child, 0);
50 }
51
52 void
53 tree_man(void *arg, const struct roff_meta *man)
54 {
55 print_meta(man);
56 if (man->hasbody == 0)
57 puts("body = empty");
58 putchar('\n');
59 print_man(man->first->child, 0);
60 }
61
62 static void
63 print_meta(const struct roff_meta *meta)
64 {
65 if (meta->title != NULL)
66 printf("title = \"%s\"\n", meta->title);
67 if (meta->name != NULL)
68 printf("name = \"%s\"\n", meta->name);
69 if (meta->msec != NULL)
70 printf("sec = \"%s\"\n", meta->msec);
71 if (meta->vol != NULL)
72 printf("vol = \"%s\"\n", meta->vol);
73 if (meta->arch != NULL)
74 printf("arch = \"%s\"\n", meta->arch);
75 if (meta->os != NULL)
76 printf("os = \"%s\"\n", meta->os);
77 if (meta->date != NULL)
78 printf("date = \"%s\"\n", meta->date);
79 }
80
81 static void
82 print_mdoc(const struct roff_node *n, int indent)
83 {
84 const char *p, *t;
85 int i, j;
86 size_t argc;
87 struct mdoc_argv *argv;
88
89 if (n == NULL)
90 return;
91
92 argv = NULL;
93 argc = 0;
94 t = p = NULL;
95
96 switch (n->type) {
97 case ROFFT_ROOT:
98 t = "root";
99 break;
100 case ROFFT_BLOCK:
101 t = "block";
102 break;
103 case ROFFT_HEAD:
104 t = "head";
105 break;
106 case ROFFT_BODY:
107 if (n->end)
108 t = "body-end";
109 else
110 t = "body";
111 break;
112 case ROFFT_TAIL:
113 t = "tail";
114 break;
115 case ROFFT_ELEM:
116 t = "elem";
117 break;
118 case ROFFT_TEXT:
119 t = "text";
120 break;
121 case ROFFT_COMMENT:
122 t = "comment";
123 break;
124 case ROFFT_TBL:
125 break;
126 case ROFFT_EQN:
127 t = "eqn";
128 break;
129 default:
130 abort();
131 }
132
133 switch (n->type) {
134 case ROFFT_TEXT:
135 case ROFFT_COMMENT:
136 p = n->string;
137 break;
138 case ROFFT_BODY:
139 p = roff_name[n->tok];
140 break;
141 case ROFFT_HEAD:
142 p = roff_name[n->tok];
143 break;
144 case ROFFT_TAIL:
145 p = roff_name[n->tok];
146 break;
147 case ROFFT_ELEM:
148 p = roff_name[n->tok];
149 if (n->args) {
150 argv = n->args->argv;
151 argc = n->args->argc;
152 }
153 break;
154 case ROFFT_BLOCK:
155 p = roff_name[n->tok];
156 if (n->args) {
157 argv = n->args->argv;
158 argc = n->args->argc;
159 }
160 break;
161 case ROFFT_TBL:
162 break;
163 case ROFFT_EQN:
164 p = "EQ";
165 break;
166 case ROFFT_ROOT:
167 p = "root";
168 break;
169 default:
170 abort();
171 }
172
173 if (n->span) {
174 assert(NULL == p && NULL == t);
175 print_span(n->span, indent);
176 } else {
177 for (i = 0; i < indent; i++)
178 putchar(' ');
179
180 printf("%s (%s)", p, t);
181
182 for (i = 0; i < (int)argc; i++) {
183 printf(" -%s", mdoc_argnames[argv[i].arg]);
184 if (argv[i].sz > 0)
185 printf(" [");
186 for (j = 0; j < (int)argv[i].sz; j++)
187 printf(" [%s]", argv[i].value[j]);
188 if (argv[i].sz > 0)
189 printf(" ]");
190 }
191
192 putchar(' ');
193 if (n->flags & NODE_DELIMO)
194 putchar('(');
195 if (n->flags & NODE_LINE)
196 putchar('*');
197 printf("%d:%d", n->line, n->pos + 1);
198 if (n->flags & NODE_DELIMC)
199 putchar(')');
200 if (n->flags & NODE_EOS)
201 putchar('.');
202 if (n->flags & NODE_BROKEN)
203 printf(" BROKEN");
204 if (n->flags & NODE_NOFILL)
205 printf(" NOFILL");
206 if (n->flags & NODE_NOSRC)
207 printf(" NOSRC");
208 if (n->flags & NODE_NOPRT)
209 printf(" NOPRT");
210 putchar('\n');
211 }
212
213 if (n->eqn)
214 print_box(n->eqn->first, indent + 4);
215 if (n->child)
216 print_mdoc(n->child, indent +
217 (n->type == ROFFT_BLOCK ? 2 : 4));
218 if (n->next)
219 print_mdoc(n->next, indent);
220 }
221
222 static void
223 print_man(const struct roff_node *n, int indent)
224 {
225 const char *p, *t;
226 int i;
227
228 if (n == NULL)
229 return;
230
231 t = p = NULL;
232
233 switch (n->type) {
234 case ROFFT_ROOT:
235 t = "root";
236 break;
237 case ROFFT_ELEM:
238 t = "elem";
239 break;
240 case ROFFT_TEXT:
241 t = "text";
242 break;
243 case ROFFT_COMMENT:
244 t = "comment";
245 break;
246 case ROFFT_BLOCK:
247 t = "block";
248 break;
249 case ROFFT_HEAD:
250 t = "head";
251 break;
252 case ROFFT_BODY:
253 t = "body";
254 break;
255 case ROFFT_TBL:
256 break;
257 case ROFFT_EQN:
258 t = "eqn";
259 break;
260 default:
261 abort();
262 }
263
264 switch (n->type) {
265 case ROFFT_TEXT:
266 case ROFFT_COMMENT:
267 p = n->string;
268 break;
269 case ROFFT_ELEM:
270 case ROFFT_BLOCK:
271 case ROFFT_HEAD:
272 case ROFFT_BODY:
273 p = roff_name[n->tok];
274 break;
275 case ROFFT_ROOT:
276 p = "root";
277 break;
278 case ROFFT_TBL:
279 break;
280 case ROFFT_EQN:
281 p = "EQ";
282 break;
283 default:
284 abort();
285 }
286
287 if (n->span) {
288 assert(NULL == p && NULL == t);
289 print_span(n->span, indent);
290 } else {
291 for (i = 0; i < indent; i++)
292 putchar(' ');
293 printf("%s (%s) ", p, t);
294 if (n->flags & NODE_LINE)
295 putchar('*');
296 printf("%d:%d", n->line, n->pos + 1);
297 if (n->flags & NODE_DELIMC)
298 putchar(')');
299 if (n->flags & NODE_EOS)
300 putchar('.');
301 if (n->flags & NODE_NOFILL)
302 printf(" NOFILL");
303 putchar('\n');
304 }
305
306 if (n->eqn)
307 print_box(n->eqn->first, indent + 4);
308 if (n->child)
309 print_man(n->child, indent +
310 (n->type == ROFFT_BLOCK ? 2 : 4));
311 if (n->next)
312 print_man(n->next, indent);
313 }
314
315 static void
316 print_box(const struct eqn_box *ep, int indent)
317 {
318 int i;
319 const char *t;
320
321 static const char *posnames[] = {
322 NULL, "sup", "subsup", "sub",
323 "to", "from", "fromto",
324 "over", "sqrt", NULL };
325
326 if (NULL == ep)
327 return;
328 for (i = 0; i < indent; i++)
329 putchar(' ');
330
331 t = NULL;
332 switch (ep->type) {
333 case EQN_LIST:
334 t = "eqn-list";
335 break;
336 case EQN_SUBEXPR:
337 t = "eqn-expr";
338 break;
339 case EQN_TEXT:
340 t = "eqn-text";
341 break;
342 case EQN_PILE:
343 t = "eqn-pile";
344 break;
345 case EQN_MATRIX:
346 t = "eqn-matrix";
347 break;
348 }
349
350 fputs(t, stdout);
351 if (ep->pos)
352 printf(" pos=%s", posnames[ep->pos]);
353 if (ep->left)
354 printf(" left=\"%s\"", ep->left);
355 if (ep->right)
356 printf(" right=\"%s\"", ep->right);
357 if (ep->top)
358 printf(" top=\"%s\"", ep->top);
359 if (ep->bottom)
360 printf(" bottom=\"%s\"", ep->bottom);
361 if (ep->text)
362 printf(" text=\"%s\"", ep->text);
363 if (ep->font)
364 printf(" font=%d", ep->font);
365 if (ep->size != EQN_DEFSIZE)
366 printf(" size=%d", ep->size);
367 if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
368 printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
369 else if (ep->args)
370 printf(" args=%zu", ep->args);
371 putchar('\n');
372
373 print_box(ep->first, indent + 4);
374 print_box(ep->next, indent);
375 }
376
377 static void
378 print_cellt(enum tbl_cellt pos)
379 {
380 switch(pos) {
381 case TBL_CELL_LEFT:
382 putchar('L');
383 break;
384 case TBL_CELL_LONG:
385 putchar('a');
386 break;
387 case TBL_CELL_CENTRE:
388 putchar('c');
389 break;
390 case TBL_CELL_RIGHT:
391 putchar('r');
392 break;
393 case TBL_CELL_NUMBER:
394 putchar('n');
395 break;
396 case TBL_CELL_SPAN:
397 putchar('s');
398 break;
399 case TBL_CELL_DOWN:
400 putchar('^');
401 break;
402 case TBL_CELL_HORIZ:
403 putchar('-');
404 break;
405 case TBL_CELL_DHORIZ:
406 putchar('=');
407 break;
408 case TBL_CELL_MAX:
409 putchar('#');
410 break;
411 }
412 }
413
414 static void
415 print_span(const struct tbl_span *sp, int indent)
416 {
417 const struct tbl_dat *dp;
418 const struct tbl_cell *cp;
419 int i;
420
421 if (sp->prev == NULL) {
422 for (i = 0; i < indent; i++)
423 putchar(' ');
424 printf("%d", sp->opts->cols);
425 if (sp->opts->opts & TBL_OPT_CENTRE)
426 fputs(" center", stdout);
427 if (sp->opts->opts & TBL_OPT_EXPAND)
428 fputs(" expand", stdout);
429 if (sp->opts->opts & TBL_OPT_ALLBOX)
430 fputs(" allbox", stdout);
431 if (sp->opts->opts & TBL_OPT_BOX)
432 fputs(" box", stdout);
433 if (sp->opts->opts & TBL_OPT_DBOX)
434 fputs(" doublebox", stdout);
435 if (sp->opts->opts & TBL_OPT_NOKEEP)
436 fputs(" nokeep", stdout);
437 if (sp->opts->opts & TBL_OPT_NOSPACE)
438 fputs(" nospaces", stdout);
439 if (sp->opts->opts & TBL_OPT_NOWARN)
440 fputs(" nowarn", stdout);
441 printf(" (tbl options) %d:1\n", sp->line);
442 }
443
444 for (i = 0; i < indent; i++)
445 putchar(' ');
446
447 switch (sp->pos) {
448 case TBL_SPAN_HORIZ:
449 putchar('-');
450 putchar(' ');
451 break;
452 case TBL_SPAN_DHORIZ:
453 putchar('=');
454 putchar(' ');
455 break;
456 default:
457 for (cp = sp->layout->first; cp != NULL; cp = cp->next)
458 print_cellt(cp->pos);
459 putchar(' ');
460 for (dp = sp->first; dp; dp = dp->next) {
461 if ((cp = dp->layout) == NULL)
462 putchar('*');
463 else {
464 printf("%d", cp->col);
465 print_cellt(dp->layout->pos);
466 if (cp->flags & TBL_CELL_BOLD)
467 putchar('b');
468 if (cp->flags & TBL_CELL_ITALIC)
469 putchar('i');
470 if (cp->flags & TBL_CELL_TALIGN)
471 putchar('t');
472 if (cp->flags & TBL_CELL_UP)
473 putchar('u');
474 if (cp->flags & TBL_CELL_BALIGN)
475 putchar('d');
476 if (cp->flags & TBL_CELL_WIGN)
477 putchar('z');
478 if (cp->flags & TBL_CELL_EQUAL)
479 putchar('e');
480 if (cp->flags & TBL_CELL_WMAX)
481 putchar('x');
482 }
483 switch (dp->pos) {
484 case TBL_DATA_HORIZ:
485 case TBL_DATA_NHORIZ:
486 putchar('-');
487 break;
488 case TBL_DATA_DHORIZ:
489 case TBL_DATA_NDHORIZ:
490 putchar('=');
491 break;
492 default:
493 putchar(dp->block ? '{' : '[');
494 if (dp->string != NULL)
495 fputs(dp->string, stdout);
496 putchar(dp->block ? '}' : ']');
497 break;
498 }
499 if (dp->hspans)
500 printf(">%d", dp->hspans);
501 if (dp->vspans)
502 printf("v%d", dp->vspans);
503 putchar(' ');
504 }
505 break;
506 }
507 printf("(tbl) %d:1\n", sp->line);
508 }