Annotation of src/usr.bin/mandoc/tree.c, Revision 1.35
1.35 ! schwarze 1: /* $OpenBSD: tree.c,v 1.34 2015/09/26 00:53:15 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.30 schwarze 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1.2 schwarze 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1.30 schwarze 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1.2 schwarze 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.30 schwarze 27: #include "roff.h"
1.1 kristaps 28: #include "mdoc.h"
29: #include "man.h"
1.5 schwarze 30: #include "main.h"
1.1 kristaps 31:
1.16 schwarze 32: static void print_box(const struct eqn_box *, int);
1.31 schwarze 33: static void print_man(const struct roff_node *, int);
34: static void print_mdoc(const struct roff_node *, int);
1.11 schwarze 35: static void print_span(const struct tbl_span *, int);
1.1 kristaps 36:
37:
1.4 schwarze 38: void
1.32 schwarze 39: tree_mdoc(void *arg, const struct roff_man *mdoc)
1.1 kristaps 40: {
41:
1.33 schwarze 42: print_mdoc(mdoc->first->child, 0);
1.1 kristaps 43: }
44:
1.4 schwarze 45: void
1.32 schwarze 46: tree_man(void *arg, const struct roff_man *man)
1.1 kristaps 47: {
48:
1.33 schwarze 49: print_man(man->first->child, 0);
1.1 kristaps 50: }
51:
52: static void
1.31 schwarze 53: print_mdoc(const struct roff_node *n, int indent)
1.1 kristaps 54: {
55: const char *p, *t;
56: int i, j;
1.17 schwarze 57: size_t argc;
1.1 kristaps 58: struct mdoc_argv *argv;
59:
1.28 schwarze 60: if (n == NULL)
61: return;
62:
1.1 kristaps 63: argv = NULL;
1.17 schwarze 64: argc = 0;
1.16 schwarze 65: t = p = NULL;
1.1 kristaps 66:
67: switch (n->type) {
1.30 schwarze 68: case ROFFT_ROOT:
1.1 kristaps 69: t = "root";
70: break;
1.30 schwarze 71: case ROFFT_BLOCK:
1.1 kristaps 72: t = "block";
73: break;
1.30 schwarze 74: case ROFFT_HEAD:
1.35 ! schwarze 75: t = "head";
1.1 kristaps 76: break;
1.30 schwarze 77: case ROFFT_BODY:
1.9 schwarze 78: if (n->end)
79: t = "body-end";
80: else
1.35 ! schwarze 81: t = "body";
1.1 kristaps 82: break;
1.30 schwarze 83: case ROFFT_TAIL:
1.35 ! schwarze 84: t = "tail";
1.1 kristaps 85: break;
1.30 schwarze 86: case ROFFT_ELEM:
1.1 kristaps 87: t = "elem";
88: break;
1.30 schwarze 89: case ROFFT_TEXT:
1.1 kristaps 90: t = "text";
91: break;
1.30 schwarze 92: case ROFFT_TBL:
1.26 schwarze 93: break;
1.30 schwarze 94: case ROFFT_EQN:
1.26 schwarze 95: t = "eqn";
1.14 schwarze 96: break;
1.1 kristaps 97: default:
98: abort();
99: }
100:
101: switch (n->type) {
1.30 schwarze 102: case ROFFT_TEXT:
1.1 kristaps 103: p = n->string;
104: break;
1.30 schwarze 105: case ROFFT_BODY:
1.1 kristaps 106: p = mdoc_macronames[n->tok];
107: break;
1.30 schwarze 108: case ROFFT_HEAD:
1.1 kristaps 109: p = mdoc_macronames[n->tok];
110: break;
1.30 schwarze 111: case ROFFT_TAIL:
1.1 kristaps 112: p = mdoc_macronames[n->tok];
113: break;
1.30 schwarze 114: case ROFFT_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.30 schwarze 121: case ROFFT_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.30 schwarze 128: case ROFFT_TBL:
1.26 schwarze 129: break;
1.30 schwarze 130: case ROFFT_EQN:
1.26 schwarze 131: p = "EQ";
1.14 schwarze 132: break;
1.30 schwarze 133: case ROFFT_ROOT:
1.1 kristaps 134: p = "root";
135: break;
136: default:
137: abort();
138: }
139:
1.11 schwarze 140: if (n->span) {
1.16 schwarze 141: assert(NULL == p && NULL == t);
1.11 schwarze 142: print_span(n->span, indent);
143: } else {
144: for (i = 0; i < indent; i++)
1.28 schwarze 145: putchar(' ');
1.11 schwarze 146:
147: printf("%s (%s)", p, t);
148:
149: for (i = 0; i < (int)argc; i++) {
150: printf(" -%s", mdoc_argnames[argv[i].arg]);
151: if (argv[i].sz > 0)
152: printf(" [");
153: for (j = 0; j < (int)argv[i].sz; j++)
154: printf(" [%s]", argv[i].value[j]);
155: if (argv[i].sz > 0)
156: printf(" ]");
157: }
1.18 schwarze 158:
159: putchar(' ');
1.35 ! schwarze 160: if (MDOC_DELIMO & n->flags)
! 161: putchar('(');
1.18 schwarze 162: if (MDOC_LINE & n->flags)
163: putchar('*');
1.35 ! schwarze 164: printf("%d:%d", n->line, n->pos + 1);
! 165: if (MDOC_DELIMC & n->flags)
! 166: putchar(')');
! 167: if (MDOC_EOS & n->flags)
! 168: putchar('.');
! 169: putchar('\n');
1.1 kristaps 170: }
171:
1.26 schwarze 172: if (n->eqn)
1.28 schwarze 173: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 174: if (n->child)
1.28 schwarze 175: print_mdoc(n->child, indent +
1.30 schwarze 176: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 177: if (n->next)
178: print_mdoc(n->next, indent);
179: }
180:
181: static void
1.31 schwarze 182: print_man(const struct roff_node *n, int indent)
1.1 kristaps 183: {
184: const char *p, *t;
185: int i;
186:
1.28 schwarze 187: if (n == NULL)
188: return;
189:
1.16 schwarze 190: t = p = NULL;
191:
1.1 kristaps 192: switch (n->type) {
1.30 schwarze 193: case ROFFT_ROOT:
1.1 kristaps 194: t = "root";
195: break;
1.30 schwarze 196: case ROFFT_ELEM:
1.1 kristaps 197: t = "elem";
198: break;
1.30 schwarze 199: case ROFFT_TEXT:
1.1 kristaps 200: t = "text";
201: break;
1.30 schwarze 202: case ROFFT_BLOCK:
1.3 schwarze 203: t = "block";
204: break;
1.30 schwarze 205: case ROFFT_HEAD:
1.35 ! schwarze 206: t = "head";
1.3 schwarze 207: break;
1.30 schwarze 208: case ROFFT_BODY:
1.35 ! schwarze 209: t = "body";
1.3 schwarze 210: break;
1.30 schwarze 211: case ROFFT_TBL:
1.26 schwarze 212: break;
1.30 schwarze 213: case ROFFT_EQN:
1.26 schwarze 214: t = "eqn";
1.14 schwarze 215: break;
1.1 kristaps 216: default:
217: abort();
218: }
219:
220: switch (n->type) {
1.30 schwarze 221: case ROFFT_TEXT:
1.1 kristaps 222: p = n->string;
223: break;
1.30 schwarze 224: case ROFFT_ELEM:
1.3 schwarze 225: /* FALLTHROUGH */
1.30 schwarze 226: case ROFFT_BLOCK:
1.3 schwarze 227: /* FALLTHROUGH */
1.30 schwarze 228: case ROFFT_HEAD:
1.3 schwarze 229: /* FALLTHROUGH */
1.30 schwarze 230: case ROFFT_BODY:
1.1 kristaps 231: p = man_macronames[n->tok];
232: break;
1.30 schwarze 233: case ROFFT_ROOT:
1.1 kristaps 234: p = "root";
235: break;
1.30 schwarze 236: case ROFFT_TBL:
1.26 schwarze 237: break;
1.30 schwarze 238: case ROFFT_EQN:
1.26 schwarze 239: p = "EQ";
1.11 schwarze 240: break;
1.1 kristaps 241: default:
242: abort();
243: }
244:
1.11 schwarze 245: if (n->span) {
1.16 schwarze 246: assert(NULL == p && NULL == t);
1.11 schwarze 247: print_span(n->span, indent);
248: } else {
249: for (i = 0; i < indent; i++)
1.28 schwarze 250: putchar(' ');
1.20 schwarze 251: printf("%s (%s) ", p, t);
252: if (MAN_LINE & n->flags)
253: putchar('*');
1.35 ! schwarze 254: printf("%d:%d", n->line, n->pos + 1);
! 255: if (MAN_EOS & n->flags)
! 256: putchar('.');
! 257: putchar('\n');
1.11 schwarze 258: }
259:
1.26 schwarze 260: if (n->eqn)
1.28 schwarze 261: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 262: if (n->child)
1.28 schwarze 263: print_man(n->child, indent +
1.30 schwarze 264: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 265: if (n->next)
266: print_man(n->next, indent);
1.11 schwarze 267: }
268:
269: static void
1.16 schwarze 270: print_box(const struct eqn_box *ep, int indent)
271: {
272: int i;
273: const char *t;
274:
1.24 schwarze 275: static const char *posnames[] = {
276: NULL, "sup", "subsup", "sub",
277: "to", "from", "fromto",
278: "over", "sqrt", NULL };
279:
1.16 schwarze 280: if (NULL == ep)
281: return;
282: for (i = 0; i < indent; i++)
1.28 schwarze 283: putchar(' ');
1.16 schwarze 284:
285: t = NULL;
286: switch (ep->type) {
1.21 schwarze 287: case EQN_ROOT:
1.16 schwarze 288: t = "eqn-root";
289: break;
1.24 schwarze 290: case EQN_LISTONE:
1.21 schwarze 291: case EQN_LIST:
1.16 schwarze 292: t = "eqn-list";
293: break;
1.21 schwarze 294: case EQN_SUBEXPR:
1.16 schwarze 295: t = "eqn-expr";
296: break;
1.21 schwarze 297: case EQN_TEXT:
1.16 schwarze 298: t = "eqn-text";
299: break;
1.24 schwarze 300: case EQN_PILE:
301: t = "eqn-pile";
302: break;
1.21 schwarze 303: case EQN_MATRIX:
1.16 schwarze 304: t = "eqn-matrix";
305: break;
306: }
307:
1.24 schwarze 308: fputs(t, stdout);
309: if (ep->pos)
310: printf(" pos=%s", posnames[ep->pos]);
311: if (ep->left)
312: printf(" left=\"%s\"", ep->left);
313: if (ep->right)
314: printf(" right=\"%s\"", ep->right);
315: if (ep->top)
316: printf(" top=\"%s\"", ep->top);
317: if (ep->bottom)
318: printf(" bottom=\"%s\"", ep->bottom);
319: if (ep->text)
320: printf(" text=\"%s\"", ep->text);
321: if (ep->font)
322: printf(" font=%d", ep->font);
323: if (ep->size != EQN_DEFSIZE)
324: printf(" size=%d", ep->size);
325: if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
326: printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
327: else if (ep->args)
328: printf(" args=%zu", ep->args);
329: putchar('\n');
1.16 schwarze 330:
1.28 schwarze 331: print_box(ep->first, indent + 4);
1.16 schwarze 332: print_box(ep->next, indent);
333: }
334:
335: static void
1.11 schwarze 336: print_span(const struct tbl_span *sp, int indent)
337: {
338: const struct tbl_dat *dp;
339: int i;
340:
341: for (i = 0; i < indent; i++)
1.28 schwarze 342: putchar(' ');
1.11 schwarze 343:
344: switch (sp->pos) {
1.21 schwarze 345: case TBL_SPAN_HORIZ:
1.11 schwarze 346: putchar('-');
347: return;
1.21 schwarze 348: case TBL_SPAN_DHORIZ:
1.11 schwarze 349: putchar('=');
350: return;
351: default:
352: break;
353: }
354:
355: for (dp = sp->first; dp; dp = dp->next) {
356: switch (dp->pos) {
1.21 schwarze 357: case TBL_DATA_HORIZ:
1.11 schwarze 358: /* FALLTHROUGH */
1.21 schwarze 359: case TBL_DATA_NHORIZ:
1.11 schwarze 360: putchar('-');
361: continue;
1.21 schwarze 362: case TBL_DATA_DHORIZ:
1.11 schwarze 363: /* FALLTHROUGH */
1.21 schwarze 364: case TBL_DATA_NDHORIZ:
1.11 schwarze 365: putchar('=');
366: continue;
367: default:
368: break;
369: }
1.12 schwarze 370: printf("[\"%s\"", dp->string ? dp->string : "");
371: if (dp->spans)
372: printf("(%d)", dp->spans);
373: if (NULL == dp->layout)
374: putchar('*');
375: putchar(']');
1.13 schwarze 376: putchar(' ');
1.11 schwarze 377: }
1.13 schwarze 378:
1.16 schwarze 379: printf("(tbl) %d:1\n", sp->line);
1.1 kristaps 380: }