Annotation of src/usr.bin/mandoc/tree.c, Revision 1.34
1.34 ! schwarze 1: /* $OpenBSD: tree.c,v 1.33 2015/04/18 17:50:02 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.1 kristaps 75: t = "block-head";
76: break;
1.30 schwarze 77: case ROFFT_BODY:
1.9 schwarze 78: if (n->end)
79: t = "body-end";
80: else
81: t = "block-body";
1.1 kristaps 82: break;
1.30 schwarze 83: case ROFFT_TAIL:
1.1 kristaps 84: t = "block-tail";
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(' ');
160: if (MDOC_LINE & n->flags)
161: putchar('*');
1.29 schwarze 162: printf("%d:%d\n", n->line, n->pos + 1);
1.1 kristaps 163: }
164:
1.26 schwarze 165: if (n->eqn)
1.28 schwarze 166: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 167: if (n->child)
1.28 schwarze 168: print_mdoc(n->child, indent +
1.30 schwarze 169: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 170: if (n->next)
171: print_mdoc(n->next, indent);
172: }
173:
174: static void
1.31 schwarze 175: print_man(const struct roff_node *n, int indent)
1.1 kristaps 176: {
177: const char *p, *t;
178: int i;
179:
1.28 schwarze 180: if (n == NULL)
181: return;
182:
1.16 schwarze 183: t = p = NULL;
184:
1.1 kristaps 185: switch (n->type) {
1.30 schwarze 186: case ROFFT_ROOT:
1.1 kristaps 187: t = "root";
188: break;
1.30 schwarze 189: case ROFFT_ELEM:
1.1 kristaps 190: t = "elem";
191: break;
1.30 schwarze 192: case ROFFT_TEXT:
1.1 kristaps 193: t = "text";
194: break;
1.30 schwarze 195: case ROFFT_BLOCK:
1.3 schwarze 196: t = "block";
197: break;
1.30 schwarze 198: case ROFFT_HEAD:
1.3 schwarze 199: t = "block-head";
200: break;
1.30 schwarze 201: case ROFFT_BODY:
1.3 schwarze 202: t = "block-body";
203: break;
1.30 schwarze 204: case ROFFT_TBL:
1.26 schwarze 205: break;
1.30 schwarze 206: case ROFFT_EQN:
1.26 schwarze 207: t = "eqn";
1.14 schwarze 208: break;
1.1 kristaps 209: default:
210: abort();
211: }
212:
213: switch (n->type) {
1.30 schwarze 214: case ROFFT_TEXT:
1.1 kristaps 215: p = n->string;
216: break;
1.30 schwarze 217: case ROFFT_ELEM:
1.3 schwarze 218: /* FALLTHROUGH */
1.30 schwarze 219: case ROFFT_BLOCK:
1.3 schwarze 220: /* FALLTHROUGH */
1.30 schwarze 221: case ROFFT_HEAD:
1.3 schwarze 222: /* FALLTHROUGH */
1.30 schwarze 223: case ROFFT_BODY:
1.1 kristaps 224: p = man_macronames[n->tok];
225: break;
1.30 schwarze 226: case ROFFT_ROOT:
1.1 kristaps 227: p = "root";
228: break;
1.30 schwarze 229: case ROFFT_TBL:
1.26 schwarze 230: break;
1.30 schwarze 231: case ROFFT_EQN:
1.26 schwarze 232: p = "EQ";
1.11 schwarze 233: break;
1.1 kristaps 234: default:
235: abort();
236: }
237:
1.11 schwarze 238: if (n->span) {
1.16 schwarze 239: assert(NULL == p && NULL == t);
1.11 schwarze 240: print_span(n->span, indent);
241: } else {
242: for (i = 0; i < indent; i++)
1.28 schwarze 243: putchar(' ');
1.20 schwarze 244: printf("%s (%s) ", p, t);
245: if (MAN_LINE & n->flags)
246: putchar('*');
1.22 schwarze 247: printf("%d:%d\n", n->line, n->pos + 1);
1.11 schwarze 248: }
249:
1.26 schwarze 250: if (n->eqn)
1.28 schwarze 251: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 252: if (n->child)
1.28 schwarze 253: print_man(n->child, indent +
1.30 schwarze 254: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 255: if (n->next)
256: print_man(n->next, indent);
1.11 schwarze 257: }
258:
259: static void
1.16 schwarze 260: print_box(const struct eqn_box *ep, int indent)
261: {
262: int i;
263: const char *t;
264:
1.24 schwarze 265: static const char *posnames[] = {
266: NULL, "sup", "subsup", "sub",
267: "to", "from", "fromto",
268: "over", "sqrt", NULL };
269:
1.16 schwarze 270: if (NULL == ep)
271: return;
272: for (i = 0; i < indent; i++)
1.28 schwarze 273: putchar(' ');
1.16 schwarze 274:
275: t = NULL;
276: switch (ep->type) {
1.21 schwarze 277: case EQN_ROOT:
1.16 schwarze 278: t = "eqn-root";
279: break;
1.24 schwarze 280: case EQN_LISTONE:
1.21 schwarze 281: case EQN_LIST:
1.16 schwarze 282: t = "eqn-list";
283: break;
1.21 schwarze 284: case EQN_SUBEXPR:
1.16 schwarze 285: t = "eqn-expr";
286: break;
1.21 schwarze 287: case EQN_TEXT:
1.16 schwarze 288: t = "eqn-text";
289: break;
1.24 schwarze 290: case EQN_PILE:
291: t = "eqn-pile";
292: break;
1.21 schwarze 293: case EQN_MATRIX:
1.16 schwarze 294: t = "eqn-matrix";
295: break;
296: }
297:
1.24 schwarze 298: fputs(t, stdout);
299: if (ep->pos)
300: printf(" pos=%s", posnames[ep->pos]);
301: if (ep->left)
302: printf(" left=\"%s\"", ep->left);
303: if (ep->right)
304: printf(" right=\"%s\"", ep->right);
305: if (ep->top)
306: printf(" top=\"%s\"", ep->top);
307: if (ep->bottom)
308: printf(" bottom=\"%s\"", ep->bottom);
309: if (ep->text)
310: printf(" text=\"%s\"", ep->text);
311: if (ep->font)
312: printf(" font=%d", ep->font);
313: if (ep->size != EQN_DEFSIZE)
314: printf(" size=%d", ep->size);
315: if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
316: printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
317: else if (ep->args)
318: printf(" args=%zu", ep->args);
319: putchar('\n');
1.16 schwarze 320:
1.28 schwarze 321: print_box(ep->first, indent + 4);
1.16 schwarze 322: print_box(ep->next, indent);
323: }
324:
325: static void
1.11 schwarze 326: print_span(const struct tbl_span *sp, int indent)
327: {
328: const struct tbl_dat *dp;
329: int i;
330:
331: for (i = 0; i < indent; i++)
1.28 schwarze 332: putchar(' ');
1.11 schwarze 333:
334: switch (sp->pos) {
1.21 schwarze 335: case TBL_SPAN_HORIZ:
1.11 schwarze 336: putchar('-');
337: return;
1.21 schwarze 338: case TBL_SPAN_DHORIZ:
1.11 schwarze 339: putchar('=');
340: return;
341: default:
342: break;
343: }
344:
345: for (dp = sp->first; dp; dp = dp->next) {
346: switch (dp->pos) {
1.21 schwarze 347: case TBL_DATA_HORIZ:
1.11 schwarze 348: /* FALLTHROUGH */
1.21 schwarze 349: case TBL_DATA_NHORIZ:
1.11 schwarze 350: putchar('-');
351: continue;
1.21 schwarze 352: case TBL_DATA_DHORIZ:
1.11 schwarze 353: /* FALLTHROUGH */
1.21 schwarze 354: case TBL_DATA_NDHORIZ:
1.11 schwarze 355: putchar('=');
356: continue;
357: default:
358: break;
359: }
1.12 schwarze 360: printf("[\"%s\"", dp->string ? dp->string : "");
361: if (dp->spans)
362: printf("(%d)", dp->spans);
363: if (NULL == dp->layout)
364: putchar('*');
365: putchar(']');
1.13 schwarze 366: putchar(' ');
1.11 schwarze 367: }
1.13 schwarze 368:
1.16 schwarze 369: printf("(tbl) %d:1\n", sp->line);
1.1 kristaps 370: }