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