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