Annotation of src/usr.bin/mandoc/tree.c, Revision 1.28
1.28 ! schwarze 1: /* $OpenBSD: tree.c,v 1.27 2014/11/28 05:51:29 schwarze Exp $ */
1.1 kristaps 2: /*
1.24 schwarze 3: * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.28 ! schwarze 4: * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 5: *
6: * Permission to use, copy, modify, and distribute this software for any
1.2 schwarze 7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
1.1 kristaps 9: *
1.2 schwarze 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.
1.1 kristaps 17: */
1.24 schwarze 18: #include <sys/types.h>
19:
1.1 kristaps 20: #include <assert.h>
1.16 schwarze 21: #include <limits.h>
1.1 kristaps 22: #include <stdio.h>
23: #include <stdlib.h>
1.6 schwarze 24: #include <time.h>
1.1 kristaps 25:
1.7 schwarze 26: #include "mandoc.h"
1.1 kristaps 27: #include "mdoc.h"
28: #include "man.h"
1.5 schwarze 29: #include "main.h"
1.1 kristaps 30:
1.16 schwarze 31: static void print_box(const struct eqn_box *, int);
32: static void print_man(const struct man_node *, int);
1.1 kristaps 33: static void print_mdoc(const struct mdoc_node *, int);
1.11 schwarze 34: static void print_span(const struct tbl_span *, int);
1.1 kristaps 35:
36:
1.4 schwarze 37: void
1.1 kristaps 38: tree_mdoc(void *arg, const struct mdoc *mdoc)
39: {
40:
1.28 ! schwarze 41: print_mdoc(mdoc_node(mdoc)->child, 0);
1.1 kristaps 42: }
43:
1.4 schwarze 44: void
1.1 kristaps 45: tree_man(void *arg, const struct man *man)
46: {
47:
1.28 ! schwarze 48: print_man(man_node(man)->child, 0);
1.1 kristaps 49: }
50:
51: static void
52: print_mdoc(const struct mdoc_node *n, int indent)
53: {
54: const char *p, *t;
55: int i, j;
1.17 schwarze 56: size_t argc;
1.1 kristaps 57: struct mdoc_argv *argv;
58:
1.28 ! schwarze 59: if (n == NULL)
! 60: return;
! 61:
1.1 kristaps 62: argv = NULL;
1.17 schwarze 63: argc = 0;
1.16 schwarze 64: t = p = NULL;
1.1 kristaps 65:
66: switch (n->type) {
1.21 schwarze 67: case MDOC_ROOT:
1.1 kristaps 68: t = "root";
69: break;
1.21 schwarze 70: case MDOC_BLOCK:
1.1 kristaps 71: t = "block";
72: break;
1.21 schwarze 73: case MDOC_HEAD:
1.1 kristaps 74: t = "block-head";
75: break;
1.21 schwarze 76: case MDOC_BODY:
1.9 schwarze 77: if (n->end)
78: t = "body-end";
79: else
80: t = "block-body";
1.1 kristaps 81: break;
1.21 schwarze 82: case MDOC_TAIL:
1.1 kristaps 83: t = "block-tail";
84: break;
1.21 schwarze 85: case MDOC_ELEM:
1.1 kristaps 86: t = "elem";
87: break;
1.21 schwarze 88: case MDOC_TEXT:
1.1 kristaps 89: t = "text";
90: break;
1.21 schwarze 91: case MDOC_TBL:
1.26 schwarze 92: break;
1.21 schwarze 93: case MDOC_EQN:
1.26 schwarze 94: t = "eqn";
1.14 schwarze 95: break;
1.1 kristaps 96: default:
97: abort();
98: /* NOTREACHED */
99: }
100:
101: switch (n->type) {
1.21 schwarze 102: case MDOC_TEXT:
1.1 kristaps 103: p = n->string;
104: break;
1.21 schwarze 105: case MDOC_BODY:
1.1 kristaps 106: p = mdoc_macronames[n->tok];
107: break;
1.21 schwarze 108: case MDOC_HEAD:
1.1 kristaps 109: p = mdoc_macronames[n->tok];
110: break;
1.21 schwarze 111: case MDOC_TAIL:
1.1 kristaps 112: p = mdoc_macronames[n->tok];
113: break;
1.21 schwarze 114: case MDOC_ELEM:
1.1 kristaps 115: p = mdoc_macronames[n->tok];
116: if (n->args) {
117: argv = n->args->argv;
118: argc = n->args->argc;
119: }
120: break;
1.21 schwarze 121: case MDOC_BLOCK:
1.1 kristaps 122: p = mdoc_macronames[n->tok];
123: if (n->args) {
124: argv = n->args->argv;
125: argc = n->args->argc;
126: }
127: break;
1.21 schwarze 128: case MDOC_TBL:
1.26 schwarze 129: break;
1.21 schwarze 130: case MDOC_EQN:
1.26 schwarze 131: p = "EQ";
1.14 schwarze 132: break;
1.21 schwarze 133: case MDOC_ROOT:
1.1 kristaps 134: p = "root";
135: break;
136: default:
137: abort();
138: /* NOTREACHED */
139: }
140:
1.11 schwarze 141: if (n->span) {
1.16 schwarze 142: assert(NULL == p && NULL == t);
1.11 schwarze 143: print_span(n->span, indent);
144: } else {
145: for (i = 0; i < indent; i++)
1.28 ! schwarze 146: putchar(' ');
1.11 schwarze 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: }
1.18 schwarze 159:
160: putchar(' ');
161: if (MDOC_LINE & n->flags)
162: putchar('*');
1.22 schwarze 163: printf("%d:%d", n->line, n->pos + 1);
1.19 schwarze 164: if (n->lastline != n->line)
165: printf("-%d", n->lastline);
166: putchar('\n');
1.1 kristaps 167: }
168:
1.26 schwarze 169: if (n->eqn)
1.28 ! schwarze 170: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 171: if (n->child)
1.28 ! schwarze 172: print_mdoc(n->child, indent +
! 173: (n->type == MDOC_BLOCK ? 2 : 4));
1.1 kristaps 174: if (n->next)
175: print_mdoc(n->next, indent);
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:
1.28 ! schwarze 184: if (n == NULL)
! 185: return;
! 186:
1.16 schwarze 187: t = p = NULL;
188:
1.1 kristaps 189: switch (n->type) {
1.21 schwarze 190: case MAN_ROOT:
1.1 kristaps 191: t = "root";
192: break;
1.21 schwarze 193: case MAN_ELEM:
1.1 kristaps 194: t = "elem";
195: break;
1.21 schwarze 196: case MAN_TEXT:
1.1 kristaps 197: t = "text";
198: break;
1.21 schwarze 199: case MAN_BLOCK:
1.3 schwarze 200: t = "block";
201: break;
1.21 schwarze 202: case MAN_HEAD:
1.3 schwarze 203: t = "block-head";
204: break;
1.21 schwarze 205: case MAN_BODY:
1.3 schwarze 206: t = "block-body";
207: break;
1.21 schwarze 208: case MAN_TBL:
1.26 schwarze 209: break;
1.21 schwarze 210: case MAN_EQN:
1.26 schwarze 211: t = "eqn";
1.14 schwarze 212: break;
1.1 kristaps 213: default:
214: abort();
215: /* NOTREACHED */
216: }
217:
218: switch (n->type) {
1.21 schwarze 219: case MAN_TEXT:
1.1 kristaps 220: p = n->string;
221: break;
1.21 schwarze 222: case MAN_ELEM:
1.3 schwarze 223: /* FALLTHROUGH */
1.21 schwarze 224: case MAN_BLOCK:
1.3 schwarze 225: /* FALLTHROUGH */
1.21 schwarze 226: case MAN_HEAD:
1.3 schwarze 227: /* FALLTHROUGH */
1.21 schwarze 228: case MAN_BODY:
1.1 kristaps 229: p = man_macronames[n->tok];
230: break;
1.21 schwarze 231: case MAN_ROOT:
1.1 kristaps 232: p = "root";
233: break;
1.21 schwarze 234: case MAN_TBL:
1.26 schwarze 235: break;
1.21 schwarze 236: case MAN_EQN:
1.26 schwarze 237: p = "EQ";
1.11 schwarze 238: break;
1.1 kristaps 239: default:
240: abort();
241: /* NOTREACHED */
242: }
243:
1.11 schwarze 244: if (n->span) {
1.16 schwarze 245: assert(NULL == p && NULL == t);
1.11 schwarze 246: print_span(n->span, indent);
247: } else {
248: for (i = 0; i < indent; i++)
1.28 ! schwarze 249: putchar(' ');
1.20 schwarze 250: printf("%s (%s) ", p, t);
251: if (MAN_LINE & n->flags)
252: putchar('*');
1.22 schwarze 253: printf("%d:%d\n", n->line, n->pos + 1);
1.11 schwarze 254: }
255:
1.26 schwarze 256: if (n->eqn)
1.28 ! schwarze 257: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 258: if (n->child)
1.28 ! schwarze 259: print_man(n->child, indent +
! 260: (n->type == MAN_BLOCK ? 2 : 4));
1.1 kristaps 261: if (n->next)
262: print_man(n->next, indent);
1.11 schwarze 263: }
264:
265: static void
1.16 schwarze 266: print_box(const struct eqn_box *ep, int indent)
267: {
268: int i;
269: const char *t;
270:
1.24 schwarze 271: static const char *posnames[] = {
272: NULL, "sup", "subsup", "sub",
273: "to", "from", "fromto",
274: "over", "sqrt", NULL };
275:
1.16 schwarze 276: if (NULL == ep)
277: return;
278: for (i = 0; i < indent; i++)
1.28 ! schwarze 279: putchar(' ');
1.16 schwarze 280:
281: t = NULL;
282: switch (ep->type) {
1.21 schwarze 283: case EQN_ROOT:
1.16 schwarze 284: t = "eqn-root";
285: break;
1.24 schwarze 286: case EQN_LISTONE:
1.21 schwarze 287: case EQN_LIST:
1.16 schwarze 288: t = "eqn-list";
289: break;
1.21 schwarze 290: case EQN_SUBEXPR:
1.16 schwarze 291: t = "eqn-expr";
292: break;
1.21 schwarze 293: case EQN_TEXT:
1.16 schwarze 294: t = "eqn-text";
295: break;
1.24 schwarze 296: case EQN_PILE:
297: t = "eqn-pile";
298: break;
1.21 schwarze 299: case EQN_MATRIX:
1.16 schwarze 300: t = "eqn-matrix";
301: break;
302: }
303:
1.24 schwarze 304: fputs(t, stdout);
305: if (ep->pos)
306: printf(" pos=%s", posnames[ep->pos]);
307: if (ep->left)
308: printf(" left=\"%s\"", ep->left);
309: if (ep->right)
310: printf(" right=\"%s\"", ep->right);
311: if (ep->top)
312: printf(" top=\"%s\"", ep->top);
313: if (ep->bottom)
314: printf(" bottom=\"%s\"", ep->bottom);
315: if (ep->text)
316: printf(" text=\"%s\"", ep->text);
317: if (ep->font)
318: printf(" font=%d", ep->font);
319: if (ep->size != EQN_DEFSIZE)
320: printf(" size=%d", ep->size);
321: if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
322: printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
323: else if (ep->args)
324: printf(" args=%zu", ep->args);
325: putchar('\n');
1.16 schwarze 326:
1.28 ! schwarze 327: print_box(ep->first, indent + 4);
1.16 schwarze 328: print_box(ep->next, indent);
329: }
330:
331: static void
1.11 schwarze 332: print_span(const struct tbl_span *sp, int indent)
333: {
334: const struct tbl_dat *dp;
335: int i;
336:
337: for (i = 0; i < indent; i++)
1.28 ! schwarze 338: putchar(' ');
1.11 schwarze 339:
340: switch (sp->pos) {
1.21 schwarze 341: case TBL_SPAN_HORIZ:
1.11 schwarze 342: putchar('-');
343: return;
1.21 schwarze 344: case TBL_SPAN_DHORIZ:
1.11 schwarze 345: putchar('=');
346: return;
347: default:
348: break;
349: }
350:
351: for (dp = sp->first; dp; dp = dp->next) {
352: switch (dp->pos) {
1.21 schwarze 353: case TBL_DATA_HORIZ:
1.11 schwarze 354: /* FALLTHROUGH */
1.21 schwarze 355: case TBL_DATA_NHORIZ:
1.11 schwarze 356: putchar('-');
357: continue;
1.21 schwarze 358: case TBL_DATA_DHORIZ:
1.11 schwarze 359: /* FALLTHROUGH */
1.21 schwarze 360: case TBL_DATA_NDHORIZ:
1.11 schwarze 361: putchar('=');
362: continue;
363: default:
364: break;
365: }
1.12 schwarze 366: printf("[\"%s\"", dp->string ? dp->string : "");
367: if (dp->spans)
368: printf("(%d)", dp->spans);
369: if (NULL == dp->layout)
370: putchar('*');
371: putchar(']');
1.13 schwarze 372: putchar(' ');
1.11 schwarze 373: }
1.13 schwarze 374:
1.16 schwarze 375: printf("(tbl) %d:1\n", sp->line);
1.1 kristaps 376: }