Annotation of src/usr.bin/mandoc/tree.c, Revision 1.48
1.48 ! schwarze 1: /* $OpenBSD: tree.c,v 1.47 2018/11/25 19:23:59 schwarze Exp $ */
1.1 kristaps 2: /*
1.24 schwarze 3: * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.45 schwarze 4: * Copyright (c) 2013,2014,2015,2017,2018 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.48 ! schwarze 30: #include "tbl.h"
1.5 schwarze 31: #include "main.h"
1.1 kristaps 32:
1.16 schwarze 33: static void print_box(const struct eqn_box *, int);
1.31 schwarze 34: static void print_man(const struct roff_node *, int);
1.39 schwarze 35: static void print_meta(const struct roff_meta *);
1.31 schwarze 36: static void print_mdoc(const struct roff_node *, int);
1.11 schwarze 37: static void print_span(const struct tbl_span *, int);
1.1 kristaps 38:
39:
1.4 schwarze 40: void
1.32 schwarze 41: tree_mdoc(void *arg, const struct roff_man *mdoc)
1.1 kristaps 42: {
1.39 schwarze 43: print_meta(&mdoc->meta);
44: putchar('\n');
1.33 schwarze 45: print_mdoc(mdoc->first->child, 0);
1.1 kristaps 46: }
47:
1.4 schwarze 48: void
1.32 schwarze 49: tree_man(void *arg, const struct roff_man *man)
1.1 kristaps 50: {
1.39 schwarze 51: print_meta(&man->meta);
52: if (man->meta.hasbody == 0)
53: puts("body = empty");
54: putchar('\n');
55: print_man(man->first->child, 0);
56: }
1.1 kristaps 57:
1.39 schwarze 58: static void
59: print_meta(const struct roff_meta *meta)
60: {
61: if (meta->title != NULL)
62: printf("title = \"%s\"\n", meta->title);
63: if (meta->name != NULL)
64: printf("name = \"%s\"\n", meta->name);
65: if (meta->msec != NULL)
66: printf("sec = \"%s\"\n", meta->msec);
67: if (meta->vol != NULL)
68: printf("vol = \"%s\"\n", meta->vol);
69: if (meta->arch != NULL)
70: printf("arch = \"%s\"\n", meta->arch);
71: if (meta->os != NULL)
72: printf("os = \"%s\"\n", meta->os);
73: if (meta->date != NULL)
74: printf("date = \"%s\"\n", meta->date);
1.1 kristaps 75: }
76:
77: static void
1.31 schwarze 78: print_mdoc(const struct roff_node *n, int indent)
1.1 kristaps 79: {
80: const char *p, *t;
81: int i, j;
1.17 schwarze 82: size_t argc;
1.1 kristaps 83: struct mdoc_argv *argv;
84:
1.28 schwarze 85: if (n == NULL)
86: return;
87:
1.1 kristaps 88: argv = NULL;
1.17 schwarze 89: argc = 0;
1.16 schwarze 90: t = p = NULL;
1.1 kristaps 91:
92: switch (n->type) {
1.30 schwarze 93: case ROFFT_ROOT:
1.1 kristaps 94: t = "root";
95: break;
1.30 schwarze 96: case ROFFT_BLOCK:
1.1 kristaps 97: t = "block";
98: break;
1.30 schwarze 99: case ROFFT_HEAD:
1.35 schwarze 100: t = "head";
1.1 kristaps 101: break;
1.30 schwarze 102: case ROFFT_BODY:
1.9 schwarze 103: if (n->end)
104: t = "body-end";
105: else
1.35 schwarze 106: t = "body";
1.1 kristaps 107: break;
1.30 schwarze 108: case ROFFT_TAIL:
1.35 schwarze 109: t = "tail";
1.1 kristaps 110: break;
1.30 schwarze 111: case ROFFT_ELEM:
1.1 kristaps 112: t = "elem";
113: break;
1.30 schwarze 114: case ROFFT_TEXT:
1.1 kristaps 115: t = "text";
116: break;
1.45 schwarze 117: case ROFFT_COMMENT:
118: t = "comment";
119: break;
1.30 schwarze 120: case ROFFT_TBL:
1.26 schwarze 121: break;
1.30 schwarze 122: case ROFFT_EQN:
1.26 schwarze 123: t = "eqn";
1.14 schwarze 124: break;
1.1 kristaps 125: default:
126: abort();
127: }
128:
129: switch (n->type) {
1.30 schwarze 130: case ROFFT_TEXT:
1.45 schwarze 131: case ROFFT_COMMENT:
1.1 kristaps 132: p = n->string;
133: break;
1.30 schwarze 134: case ROFFT_BODY:
1.41 schwarze 135: p = roff_name[n->tok];
1.1 kristaps 136: break;
1.30 schwarze 137: case ROFFT_HEAD:
1.41 schwarze 138: p = roff_name[n->tok];
1.1 kristaps 139: break;
1.30 schwarze 140: case ROFFT_TAIL:
1.41 schwarze 141: p = roff_name[n->tok];
1.1 kristaps 142: break;
1.30 schwarze 143: case ROFFT_ELEM:
1.41 schwarze 144: p = roff_name[n->tok];
1.1 kristaps 145: if (n->args) {
146: argv = n->args->argv;
147: argc = n->args->argc;
148: }
149: break;
1.30 schwarze 150: case ROFFT_BLOCK:
1.41 schwarze 151: p = roff_name[n->tok];
1.1 kristaps 152: if (n->args) {
153: argv = n->args->argv;
154: argc = n->args->argc;
155: }
156: break;
1.30 schwarze 157: case ROFFT_TBL:
1.26 schwarze 158: break;
1.30 schwarze 159: case ROFFT_EQN:
1.26 schwarze 160: p = "EQ";
1.14 schwarze 161: break;
1.30 schwarze 162: case ROFFT_ROOT:
1.1 kristaps 163: p = "root";
164: break;
165: default:
166: abort();
167: }
168:
1.11 schwarze 169: if (n->span) {
1.16 schwarze 170: assert(NULL == p && NULL == t);
1.11 schwarze 171: print_span(n->span, indent);
172: } else {
173: for (i = 0; i < indent; i++)
1.28 schwarze 174: putchar(' ');
1.11 schwarze 175:
176: printf("%s (%s)", p, t);
177:
178: for (i = 0; i < (int)argc; i++) {
179: printf(" -%s", mdoc_argnames[argv[i].arg]);
180: if (argv[i].sz > 0)
181: printf(" [");
182: for (j = 0; j < (int)argv[i].sz; j++)
183: printf(" [%s]", argv[i].value[j]);
184: if (argv[i].sz > 0)
185: printf(" ]");
186: }
1.18 schwarze 187:
188: putchar(' ');
1.38 schwarze 189: if (NODE_DELIMO & n->flags)
1.35 schwarze 190: putchar('(');
1.38 schwarze 191: if (NODE_LINE & n->flags)
1.18 schwarze 192: putchar('*');
1.35 schwarze 193: printf("%d:%d", n->line, n->pos + 1);
1.38 schwarze 194: if (NODE_DELIMC & n->flags)
1.35 schwarze 195: putchar(')');
1.38 schwarze 196: if (NODE_EOS & n->flags)
1.35 schwarze 197: putchar('.');
1.40 schwarze 198: if (NODE_BROKEN & n->flags)
199: printf(" BROKEN");
1.37 schwarze 200: if (NODE_NOSRC & n->flags)
201: printf(" NOSRC");
202: if (NODE_NOPRT & n->flags)
203: printf(" NOPRT");
1.35 schwarze 204: putchar('\n');
1.1 kristaps 205: }
206:
1.26 schwarze 207: if (n->eqn)
1.44 schwarze 208: print_box(n->eqn->first, indent + 4);
1.1 kristaps 209: if (n->child)
1.28 schwarze 210: print_mdoc(n->child, indent +
1.30 schwarze 211: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 212: if (n->next)
213: print_mdoc(n->next, indent);
214: }
215:
216: static void
1.31 schwarze 217: print_man(const struct roff_node *n, int indent)
1.1 kristaps 218: {
219: const char *p, *t;
220: int i;
221:
1.28 schwarze 222: if (n == NULL)
223: return;
224:
1.16 schwarze 225: t = p = NULL;
226:
1.1 kristaps 227: switch (n->type) {
1.30 schwarze 228: case ROFFT_ROOT:
1.1 kristaps 229: t = "root";
230: break;
1.30 schwarze 231: case ROFFT_ELEM:
1.1 kristaps 232: t = "elem";
233: break;
1.30 schwarze 234: case ROFFT_TEXT:
1.1 kristaps 235: t = "text";
236: break;
1.45 schwarze 237: case ROFFT_COMMENT:
238: t = "comment";
239: break;
1.30 schwarze 240: case ROFFT_BLOCK:
1.3 schwarze 241: t = "block";
242: break;
1.30 schwarze 243: case ROFFT_HEAD:
1.35 schwarze 244: t = "head";
1.3 schwarze 245: break;
1.30 schwarze 246: case ROFFT_BODY:
1.35 schwarze 247: t = "body";
1.3 schwarze 248: break;
1.30 schwarze 249: case ROFFT_TBL:
1.26 schwarze 250: break;
1.30 schwarze 251: case ROFFT_EQN:
1.26 schwarze 252: t = "eqn";
1.14 schwarze 253: break;
1.1 kristaps 254: default:
255: abort();
256: }
257:
258: switch (n->type) {
1.30 schwarze 259: case ROFFT_TEXT:
1.45 schwarze 260: case ROFFT_COMMENT:
1.1 kristaps 261: p = n->string;
262: break;
1.30 schwarze 263: case ROFFT_ELEM:
264: case ROFFT_BLOCK:
265: case ROFFT_HEAD:
266: case ROFFT_BODY:
1.41 schwarze 267: p = roff_name[n->tok];
1.1 kristaps 268: break;
1.30 schwarze 269: case ROFFT_ROOT:
1.1 kristaps 270: p = "root";
271: break;
1.30 schwarze 272: case ROFFT_TBL:
1.26 schwarze 273: break;
1.30 schwarze 274: case ROFFT_EQN:
1.26 schwarze 275: p = "EQ";
1.11 schwarze 276: break;
1.1 kristaps 277: default:
278: abort();
279: }
280:
1.11 schwarze 281: if (n->span) {
1.16 schwarze 282: assert(NULL == p && NULL == t);
1.11 schwarze 283: print_span(n->span, indent);
284: } else {
285: for (i = 0; i < indent; i++)
1.28 schwarze 286: putchar(' ');
1.20 schwarze 287: printf("%s (%s) ", p, t);
1.38 schwarze 288: if (NODE_LINE & n->flags)
1.20 schwarze 289: putchar('*');
1.35 schwarze 290: printf("%d:%d", n->line, n->pos + 1);
1.46 schwarze 291: if (NODE_DELIMC & n->flags)
292: putchar(')');
1.38 schwarze 293: if (NODE_EOS & n->flags)
1.35 schwarze 294: putchar('.');
295: putchar('\n');
1.11 schwarze 296: }
297:
1.26 schwarze 298: if (n->eqn)
1.44 schwarze 299: print_box(n->eqn->first, indent + 4);
1.1 kristaps 300: if (n->child)
1.28 schwarze 301: print_man(n->child, indent +
1.30 schwarze 302: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 303: if (n->next)
304: print_man(n->next, indent);
1.11 schwarze 305: }
306:
307: static void
1.16 schwarze 308: print_box(const struct eqn_box *ep, int indent)
309: {
310: int i;
311: const char *t;
312:
1.24 schwarze 313: static const char *posnames[] = {
314: NULL, "sup", "subsup", "sub",
315: "to", "from", "fromto",
316: "over", "sqrt", NULL };
317:
1.16 schwarze 318: if (NULL == ep)
319: return;
320: for (i = 0; i < indent; i++)
1.28 schwarze 321: putchar(' ');
1.16 schwarze 322:
323: t = NULL;
324: switch (ep->type) {
1.21 schwarze 325: case EQN_LIST:
1.16 schwarze 326: t = "eqn-list";
327: break;
1.21 schwarze 328: case EQN_SUBEXPR:
1.16 schwarze 329: t = "eqn-expr";
330: break;
1.21 schwarze 331: case EQN_TEXT:
1.16 schwarze 332: t = "eqn-text";
333: break;
1.24 schwarze 334: case EQN_PILE:
335: t = "eqn-pile";
336: break;
1.21 schwarze 337: case EQN_MATRIX:
1.16 schwarze 338: t = "eqn-matrix";
339: break;
340: }
341:
1.24 schwarze 342: fputs(t, stdout);
343: if (ep->pos)
344: printf(" pos=%s", posnames[ep->pos]);
345: if (ep->left)
346: printf(" left=\"%s\"", ep->left);
347: if (ep->right)
348: printf(" right=\"%s\"", ep->right);
349: if (ep->top)
350: printf(" top=\"%s\"", ep->top);
351: if (ep->bottom)
352: printf(" bottom=\"%s\"", ep->bottom);
353: if (ep->text)
354: printf(" text=\"%s\"", ep->text);
355: if (ep->font)
356: printf(" font=%d", ep->font);
357: if (ep->size != EQN_DEFSIZE)
358: printf(" size=%d", ep->size);
359: if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
360: printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
361: else if (ep->args)
362: printf(" args=%zu", ep->args);
363: putchar('\n');
1.16 schwarze 364:
1.28 schwarze 365: print_box(ep->first, indent + 4);
1.16 schwarze 366: print_box(ep->next, indent);
367: }
368:
369: static void
1.11 schwarze 370: print_span(const struct tbl_span *sp, int indent)
371: {
372: const struct tbl_dat *dp;
373: int i;
374:
375: for (i = 0; i < indent; i++)
1.28 schwarze 376: putchar(' ');
1.11 schwarze 377:
378: switch (sp->pos) {
1.21 schwarze 379: case TBL_SPAN_HORIZ:
1.11 schwarze 380: putchar('-');
1.47 schwarze 381: putchar(' ');
382: break;
1.21 schwarze 383: case TBL_SPAN_DHORIZ:
1.11 schwarze 384: putchar('=');
1.47 schwarze 385: putchar(' ');
386: break;
1.11 schwarze 387: default:
1.47 schwarze 388: for (dp = sp->first; dp; dp = dp->next) {
389: switch (dp->pos) {
390: case TBL_DATA_HORIZ:
391: case TBL_DATA_NHORIZ:
392: putchar('-');
393: putchar(' ');
394: continue;
395: case TBL_DATA_DHORIZ:
396: case TBL_DATA_NDHORIZ:
397: putchar('=');
398: putchar(' ');
399: continue;
400: default:
401: break;
402: }
403: printf("[\"%s\"", dp->string ? dp->string : "");
404: if (dp->hspans)
405: printf(">%d", dp->hspans);
406: if (dp->vspans)
407: printf("v%d", dp->vspans);
408: if (dp->layout == NULL)
409: putchar('*');
410: else if (dp->layout->pos == TBL_CELL_DOWN)
411: putchar('^');
412: putchar(']');
413: putchar(' ');
414: }
1.11 schwarze 415: break;
416: }
1.16 schwarze 417: printf("(tbl) %d:1\n", sp->line);
1.1 kristaps 418: }