Annotation of src/usr.bin/mandoc/tree.c, Revision 1.31
1.31 ! schwarze 1: /* $OpenBSD: tree.c,v 1.30 2015/04/02 21:03:18 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.1 kristaps 39: tree_mdoc(void *arg, const struct mdoc *mdoc)
40: {
41:
1.28 schwarze 42: print_mdoc(mdoc_node(mdoc)->child, 0);
1.1 kristaps 43: }
44:
1.4 schwarze 45: void
1.1 kristaps 46: tree_man(void *arg, const struct man *man)
47: {
48:
1.28 schwarze 49: print_man(man_node(man)->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: /* NOTREACHED */
100: }
101:
102: switch (n->type) {
1.30 schwarze 103: case ROFFT_TEXT:
1.1 kristaps 104: p = n->string;
105: break;
1.30 schwarze 106: case ROFFT_BODY:
1.1 kristaps 107: p = mdoc_macronames[n->tok];
108: break;
1.30 schwarze 109: case ROFFT_HEAD:
1.1 kristaps 110: p = mdoc_macronames[n->tok];
111: break;
1.30 schwarze 112: case ROFFT_TAIL:
1.1 kristaps 113: p = mdoc_macronames[n->tok];
114: break;
1.30 schwarze 115: case ROFFT_ELEM:
1.1 kristaps 116: p = mdoc_macronames[n->tok];
117: if (n->args) {
118: argv = n->args->argv;
119: argc = n->args->argc;
120: }
121: break;
1.30 schwarze 122: case ROFFT_BLOCK:
1.1 kristaps 123: p = mdoc_macronames[n->tok];
124: if (n->args) {
125: argv = n->args->argv;
126: argc = n->args->argc;
127: }
128: break;
1.30 schwarze 129: case ROFFT_TBL:
1.26 schwarze 130: break;
1.30 schwarze 131: case ROFFT_EQN:
1.26 schwarze 132: p = "EQ";
1.14 schwarze 133: break;
1.30 schwarze 134: case ROFFT_ROOT:
1.1 kristaps 135: p = "root";
136: break;
137: default:
138: abort();
139: /* NOTREACHED */
140: }
141:
1.11 schwarze 142: if (n->span) {
1.16 schwarze 143: assert(NULL == p && NULL == t);
1.11 schwarze 144: print_span(n->span, indent);
145: } else {
146: for (i = 0; i < indent; i++)
1.28 schwarze 147: putchar(' ');
1.11 schwarze 148:
149: printf("%s (%s)", p, t);
150:
151: for (i = 0; i < (int)argc; i++) {
152: printf(" -%s", mdoc_argnames[argv[i].arg]);
153: if (argv[i].sz > 0)
154: printf(" [");
155: for (j = 0; j < (int)argv[i].sz; j++)
156: printf(" [%s]", argv[i].value[j]);
157: if (argv[i].sz > 0)
158: printf(" ]");
159: }
1.18 schwarze 160:
161: putchar(' ');
162: if (MDOC_LINE & n->flags)
163: putchar('*');
1.29 schwarze 164: printf("%d:%d\n", n->line, n->pos + 1);
1.1 kristaps 165: }
166:
1.26 schwarze 167: if (n->eqn)
1.28 schwarze 168: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 169: if (n->child)
1.28 schwarze 170: print_mdoc(n->child, indent +
1.30 schwarze 171: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 172: if (n->next)
173: print_mdoc(n->next, indent);
174: }
175:
176: static void
1.31 ! schwarze 177: print_man(const struct roff_node *n, int indent)
1.1 kristaps 178: {
179: const char *p, *t;
180: int i;
181:
1.28 schwarze 182: if (n == NULL)
183: return;
184:
1.16 schwarze 185: t = p = NULL;
186:
1.1 kristaps 187: switch (n->type) {
1.30 schwarze 188: case ROFFT_ROOT:
1.1 kristaps 189: t = "root";
190: break;
1.30 schwarze 191: case ROFFT_ELEM:
1.1 kristaps 192: t = "elem";
193: break;
1.30 schwarze 194: case ROFFT_TEXT:
1.1 kristaps 195: t = "text";
196: break;
1.30 schwarze 197: case ROFFT_BLOCK:
1.3 schwarze 198: t = "block";
199: break;
1.30 schwarze 200: case ROFFT_HEAD:
1.3 schwarze 201: t = "block-head";
202: break;
1.30 schwarze 203: case ROFFT_BODY:
1.3 schwarze 204: t = "block-body";
205: break;
1.30 schwarze 206: case ROFFT_TBL:
1.26 schwarze 207: break;
1.30 schwarze 208: case ROFFT_EQN:
1.26 schwarze 209: t = "eqn";
1.14 schwarze 210: break;
1.1 kristaps 211: default:
212: abort();
213: /* NOTREACHED */
214: }
215:
216: switch (n->type) {
1.30 schwarze 217: case ROFFT_TEXT:
1.1 kristaps 218: p = n->string;
219: break;
1.30 schwarze 220: case ROFFT_ELEM:
1.3 schwarze 221: /* FALLTHROUGH */
1.30 schwarze 222: case ROFFT_BLOCK:
1.3 schwarze 223: /* FALLTHROUGH */
1.30 schwarze 224: case ROFFT_HEAD:
1.3 schwarze 225: /* FALLTHROUGH */
1.30 schwarze 226: case ROFFT_BODY:
1.1 kristaps 227: p = man_macronames[n->tok];
228: break;
1.30 schwarze 229: case ROFFT_ROOT:
1.1 kristaps 230: p = "root";
231: break;
1.30 schwarze 232: case ROFFT_TBL:
1.26 schwarze 233: break;
1.30 schwarze 234: case ROFFT_EQN:
1.26 schwarze 235: p = "EQ";
1.11 schwarze 236: break;
1.1 kristaps 237: default:
238: abort();
239: /* NOTREACHED */
240: }
241:
1.11 schwarze 242: if (n->span) {
1.16 schwarze 243: assert(NULL == p && NULL == t);
1.11 schwarze 244: print_span(n->span, indent);
245: } else {
246: for (i = 0; i < indent; i++)
1.28 schwarze 247: putchar(' ');
1.20 schwarze 248: printf("%s (%s) ", p, t);
249: if (MAN_LINE & n->flags)
250: putchar('*');
1.22 schwarze 251: printf("%d:%d\n", n->line, n->pos + 1);
1.11 schwarze 252: }
253:
1.26 schwarze 254: if (n->eqn)
1.28 schwarze 255: print_box(n->eqn->root->first, indent + 4);
1.1 kristaps 256: if (n->child)
1.28 schwarze 257: print_man(n->child, indent +
1.30 schwarze 258: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 259: if (n->next)
260: print_man(n->next, indent);
1.11 schwarze 261: }
262:
263: static void
1.16 schwarze 264: print_box(const struct eqn_box *ep, int indent)
265: {
266: int i;
267: const char *t;
268:
1.24 schwarze 269: static const char *posnames[] = {
270: NULL, "sup", "subsup", "sub",
271: "to", "from", "fromto",
272: "over", "sqrt", NULL };
273:
1.16 schwarze 274: if (NULL == ep)
275: return;
276: for (i = 0; i < indent; i++)
1.28 schwarze 277: putchar(' ');
1.16 schwarze 278:
279: t = NULL;
280: switch (ep->type) {
1.21 schwarze 281: case EQN_ROOT:
1.16 schwarze 282: t = "eqn-root";
283: break;
1.24 schwarze 284: case EQN_LISTONE:
1.21 schwarze 285: case EQN_LIST:
1.16 schwarze 286: t = "eqn-list";
287: break;
1.21 schwarze 288: case EQN_SUBEXPR:
1.16 schwarze 289: t = "eqn-expr";
290: break;
1.21 schwarze 291: case EQN_TEXT:
1.16 schwarze 292: t = "eqn-text";
293: break;
1.24 schwarze 294: case EQN_PILE:
295: t = "eqn-pile";
296: break;
1.21 schwarze 297: case EQN_MATRIX:
1.16 schwarze 298: t = "eqn-matrix";
299: break;
300: }
301:
1.24 schwarze 302: fputs(t, stdout);
303: if (ep->pos)
304: printf(" pos=%s", posnames[ep->pos]);
305: if (ep->left)
306: printf(" left=\"%s\"", ep->left);
307: if (ep->right)
308: printf(" right=\"%s\"", ep->right);
309: if (ep->top)
310: printf(" top=\"%s\"", ep->top);
311: if (ep->bottom)
312: printf(" bottom=\"%s\"", ep->bottom);
313: if (ep->text)
314: printf(" text=\"%s\"", ep->text);
315: if (ep->font)
316: printf(" font=%d", ep->font);
317: if (ep->size != EQN_DEFSIZE)
318: printf(" size=%d", ep->size);
319: if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
320: printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
321: else if (ep->args)
322: printf(" args=%zu", ep->args);
323: putchar('\n');
1.16 schwarze 324:
1.28 schwarze 325: print_box(ep->first, indent + 4);
1.16 schwarze 326: print_box(ep->next, indent);
327: }
328:
329: static void
1.11 schwarze 330: print_span(const struct tbl_span *sp, int indent)
331: {
332: const struct tbl_dat *dp;
333: int i;
334:
335: for (i = 0; i < indent; i++)
1.28 schwarze 336: putchar(' ');
1.11 schwarze 337:
338: switch (sp->pos) {
1.21 schwarze 339: case TBL_SPAN_HORIZ:
1.11 schwarze 340: putchar('-');
341: return;
1.21 schwarze 342: case TBL_SPAN_DHORIZ:
1.11 schwarze 343: putchar('=');
344: return;
345: default:
346: break;
347: }
348:
349: for (dp = sp->first; dp; dp = dp->next) {
350: switch (dp->pos) {
1.21 schwarze 351: case TBL_DATA_HORIZ:
1.11 schwarze 352: /* FALLTHROUGH */
1.21 schwarze 353: case TBL_DATA_NHORIZ:
1.11 schwarze 354: putchar('-');
355: continue;
1.21 schwarze 356: case TBL_DATA_DHORIZ:
1.11 schwarze 357: /* FALLTHROUGH */
1.21 schwarze 358: case TBL_DATA_NDHORIZ:
1.11 schwarze 359: putchar('=');
360: continue;
361: default:
362: break;
363: }
1.12 schwarze 364: printf("[\"%s\"", dp->string ? dp->string : "");
365: if (dp->spans)
366: printf("(%d)", dp->spans);
367: if (NULL == dp->layout)
368: putchar('*');
369: putchar(']');
1.13 schwarze 370: putchar(' ');
1.11 schwarze 371: }
1.13 schwarze 372:
1.16 schwarze 373: printf("(tbl) %d:1\n", sp->line);
1.1 kristaps 374: }