Annotation of mandoc/tree.c, Revision 1.85
1.85 ! schwarze 1: /* $Id: tree.c,v 1.84 2019/01/01 05:56:34 schwarze Exp $ */
1.1 kristaps 2: /*
1.58 schwarze 3: * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
1.85 ! schwarze 4: * Copyright (c) 2013-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 5: *
6: * Permission to use, copy, modify, and distribute this software for any
1.12 kristaps 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.63 schwarze 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1.12 kristaps 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1.63 schwarze 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1.12 kristaps 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.19 kristaps 18: #include "config.h"
1.54 schwarze 19:
20: #include <sys/types.h>
1.19 kristaps 21:
1.8 kristaps 22: #include <assert.h>
1.43 kristaps 23: #include <limits.h>
1.8 kristaps 24: #include <stdio.h>
1.1 kristaps 25: #include <stdlib.h>
1.17 kristaps 26: #include <time.h>
1.1 kristaps 27:
1.20 kristaps 28: #include "mandoc.h"
1.63 schwarze 29: #include "roff.h"
1.1 kristaps 30: #include "mdoc.h"
1.10 kristaps 31: #include "man.h"
1.81 schwarze 32: #include "tbl.h"
1.82 schwarze 33: #include "eqn.h"
1.16 kristaps 34: #include "main.h"
1.1 kristaps 35:
1.38 kristaps 36: static void print_box(const struct eqn_box *, int);
1.85 ! schwarze 37: static void print_cellt(enum tbl_cellt);
1.64 schwarze 38: static void print_man(const struct roff_node *, int);
1.72 schwarze 39: static void print_meta(const struct roff_meta *);
1.64 schwarze 40: static void print_mdoc(const struct roff_node *, int);
1.30 kristaps 41: static void print_span(const struct tbl_span *, int);
1.8 kristaps 42:
43:
1.15 kristaps 44: void
1.83 schwarze 45: tree_mdoc(void *arg, const struct roff_meta *mdoc)
1.8 kristaps 46: {
1.83 schwarze 47: print_meta(mdoc);
1.72 schwarze 48: putchar('\n');
1.66 schwarze 49: print_mdoc(mdoc->first->child, 0);
1.11 kristaps 50: }
51:
1.15 kristaps 52: void
1.83 schwarze 53: tree_man(void *arg, const struct roff_meta *man)
1.11 kristaps 54: {
1.83 schwarze 55: print_meta(man);
56: if (man->hasbody == 0)
1.72 schwarze 57: puts("body = empty");
58: putchar('\n');
59: print_man(man->first->child, 0);
60: }
1.11 kristaps 61:
1.72 schwarze 62: static void
63: print_meta(const struct roff_meta *meta)
64: {
65: if (meta->title != NULL)
66: printf("title = \"%s\"\n", meta->title);
67: if (meta->name != NULL)
68: printf("name = \"%s\"\n", meta->name);
69: if (meta->msec != NULL)
70: printf("sec = \"%s\"\n", meta->msec);
71: if (meta->vol != NULL)
72: printf("vol = \"%s\"\n", meta->vol);
73: if (meta->arch != NULL)
74: printf("arch = \"%s\"\n", meta->arch);
75: if (meta->os != NULL)
76: printf("os = \"%s\"\n", meta->os);
77: if (meta->date != NULL)
78: printf("date = \"%s\"\n", meta->date);
1.8 kristaps 79: }
1.2 kristaps 80:
1.1 kristaps 81: static void
1.64 schwarze 82: print_mdoc(const struct roff_node *n, int indent)
1.1 kristaps 83: {
84: const char *p, *t;
85: int i, j;
1.48 schwarze 86: size_t argc;
1.8 kristaps 87: struct mdoc_argv *argv;
1.1 kristaps 88:
1.61 schwarze 89: if (n == NULL)
90: return;
91:
1.1 kristaps 92: argv = NULL;
1.48 schwarze 93: argc = 0;
1.38 kristaps 94: t = p = NULL;
1.1 kristaps 95:
1.2 kristaps 96: switch (n->type) {
1.63 schwarze 97: case ROFFT_ROOT:
1.2 kristaps 98: t = "root";
99: break;
1.63 schwarze 100: case ROFFT_BLOCK:
1.2 kristaps 101: t = "block";
102: break;
1.63 schwarze 103: case ROFFT_HEAD:
1.68 schwarze 104: t = "head";
1.2 kristaps 105: break;
1.63 schwarze 106: case ROFFT_BODY:
1.23 schwarze 107: if (n->end)
108: t = "body-end";
109: else
1.68 schwarze 110: t = "body";
1.2 kristaps 111: break;
1.63 schwarze 112: case ROFFT_TAIL:
1.68 schwarze 113: t = "tail";
1.2 kristaps 114: break;
1.63 schwarze 115: case ROFFT_ELEM:
1.2 kristaps 116: t = "elem";
117: break;
1.63 schwarze 118: case ROFFT_TEXT:
1.2 kristaps 119: t = "text";
120: break;
1.78 schwarze 121: case ROFFT_COMMENT:
122: t = "comment";
123: break;
1.63 schwarze 124: case ROFFT_TBL:
1.59 schwarze 125: break;
1.63 schwarze 126: case ROFFT_EQN:
1.59 schwarze 127: t = "eqn";
1.33 kristaps 128: break;
1.2 kristaps 129: default:
130: abort();
131: }
1.1 kristaps 132:
133: switch (n->type) {
1.63 schwarze 134: case ROFFT_TEXT:
1.78 schwarze 135: case ROFFT_COMMENT:
1.8 kristaps 136: p = n->string;
1.1 kristaps 137: break;
1.63 schwarze 138: case ROFFT_BODY:
1.74 schwarze 139: p = roff_name[n->tok];
1.1 kristaps 140: break;
1.63 schwarze 141: case ROFFT_HEAD:
1.74 schwarze 142: p = roff_name[n->tok];
1.1 kristaps 143: break;
1.63 schwarze 144: case ROFFT_TAIL:
1.74 schwarze 145: p = roff_name[n->tok];
1.1 kristaps 146: break;
1.63 schwarze 147: case ROFFT_ELEM:
1.74 schwarze 148: p = roff_name[n->tok];
1.8 kristaps 149: if (n->args) {
150: argv = n->args->argv;
151: argc = n->args->argc;
152: }
1.1 kristaps 153: break;
1.63 schwarze 154: case ROFFT_BLOCK:
1.74 schwarze 155: p = roff_name[n->tok];
1.8 kristaps 156: if (n->args) {
157: argv = n->args->argv;
158: argc = n->args->argc;
159: }
1.1 kristaps 160: break;
1.63 schwarze 161: case ROFFT_TBL:
1.59 schwarze 162: break;
1.63 schwarze 163: case ROFFT_EQN:
1.59 schwarze 164: p = "EQ";
1.33 kristaps 165: break;
1.63 schwarze 166: case ROFFT_ROOT:
1.1 kristaps 167: p = "root";
168: break;
169: default:
170: abort();
171: }
172:
1.26 kristaps 173: if (n->span) {
1.38 kristaps 174: assert(NULL == p && NULL == t);
1.30 kristaps 175: print_span(n->span, indent);
1.26 kristaps 176: } else {
1.30 kristaps 177: for (i = 0; i < indent; i++)
1.61 schwarze 178: putchar(' ');
1.30 kristaps 179:
1.26 kristaps 180: printf("%s (%s)", p, t);
181:
182: for (i = 0; i < (int)argc; i++) {
183: printf(" -%s", mdoc_argnames[argv[i].arg]);
184: if (argv[i].sz > 0)
185: printf(" [");
186: for (j = 0; j < (int)argv[i].sz; j++)
187: printf(" [%s]", argv[i].value[j]);
188: if (argv[i].sz > 0)
189: printf(" ]");
190: }
1.49 schwarze 191:
192: putchar(' ');
1.84 schwarze 193: if (n->flags & NODE_DELIMO)
1.68 schwarze 194: putchar('(');
1.84 schwarze 195: if (n->flags & NODE_LINE)
1.49 schwarze 196: putchar('*');
1.68 schwarze 197: printf("%d:%d", n->line, n->pos + 1);
1.84 schwarze 198: if (n->flags & NODE_DELIMC)
1.68 schwarze 199: putchar(')');
1.84 schwarze 200: if (n->flags & NODE_EOS)
1.68 schwarze 201: putchar('.');
1.84 schwarze 202: if (n->flags & NODE_BROKEN)
1.73 schwarze 203: printf(" BROKEN");
1.84 schwarze 204: if (n->flags & NODE_NOFILL)
205: printf(" NOFILL");
206: if (n->flags & NODE_NOSRC)
1.70 schwarze 207: printf(" NOSRC");
1.84 schwarze 208: if (n->flags & NODE_NOPRT)
1.70 schwarze 209: printf(" NOPRT");
1.68 schwarze 210: putchar('\n');
1.1 kristaps 211: }
212:
1.59 schwarze 213: if (n->eqn)
1.77 schwarze 214: print_box(n->eqn->first, indent + 4);
1.1 kristaps 215: if (n->child)
1.61 schwarze 216: print_mdoc(n->child, indent +
1.63 schwarze 217: (n->type == ROFFT_BLOCK ? 2 : 4));
1.1 kristaps 218: if (n->next)
1.11 kristaps 219: print_mdoc(n->next, indent);
1.1 kristaps 220: }
1.2 kristaps 221:
1.10 kristaps 222: static void
1.64 schwarze 223: print_man(const struct roff_node *n, int indent)
1.10 kristaps 224: {
225: const char *p, *t;
226: int i;
227:
1.61 schwarze 228: if (n == NULL)
229: return;
230:
1.38 kristaps 231: t = p = NULL;
232:
1.10 kristaps 233: switch (n->type) {
1.63 schwarze 234: case ROFFT_ROOT:
1.10 kristaps 235: t = "root";
236: break;
1.63 schwarze 237: case ROFFT_ELEM:
1.10 kristaps 238: t = "elem";
239: break;
1.63 schwarze 240: case ROFFT_TEXT:
1.10 kristaps 241: t = "text";
242: break;
1.78 schwarze 243: case ROFFT_COMMENT:
244: t = "comment";
245: break;
1.63 schwarze 246: case ROFFT_BLOCK:
1.14 kristaps 247: t = "block";
248: break;
1.63 schwarze 249: case ROFFT_HEAD:
1.68 schwarze 250: t = "head";
1.14 kristaps 251: break;
1.63 schwarze 252: case ROFFT_BODY:
1.68 schwarze 253: t = "body";
1.14 kristaps 254: break;
1.63 schwarze 255: case ROFFT_TBL:
1.59 schwarze 256: break;
1.63 schwarze 257: case ROFFT_EQN:
1.59 schwarze 258: t = "eqn";
1.33 kristaps 259: break;
1.10 kristaps 260: default:
261: abort();
262: }
263:
264: switch (n->type) {
1.63 schwarze 265: case ROFFT_TEXT:
1.78 schwarze 266: case ROFFT_COMMENT:
1.10 kristaps 267: p = n->string;
268: break;
1.63 schwarze 269: case ROFFT_ELEM:
270: case ROFFT_BLOCK:
271: case ROFFT_HEAD:
272: case ROFFT_BODY:
1.74 schwarze 273: p = roff_name[n->tok];
1.10 kristaps 274: break;
1.63 schwarze 275: case ROFFT_ROOT:
1.10 kristaps 276: p = "root";
1.25 kristaps 277: break;
1.63 schwarze 278: case ROFFT_TBL:
1.59 schwarze 279: break;
1.63 schwarze 280: case ROFFT_EQN:
1.59 schwarze 281: p = "EQ";
1.10 kristaps 282: break;
283: default:
284: abort();
285: }
286:
1.26 kristaps 287: if (n->span) {
1.38 kristaps 288: assert(NULL == p && NULL == t);
1.30 kristaps 289: print_span(n->span, indent);
290: } else {
291: for (i = 0; i < indent; i++)
1.61 schwarze 292: putchar(' ');
1.51 schwarze 293: printf("%s (%s) ", p, t);
1.84 schwarze 294: if (n->flags & NODE_LINE)
1.51 schwarze 295: putchar('*');
1.68 schwarze 296: printf("%d:%d", n->line, n->pos + 1);
1.84 schwarze 297: if (n->flags & NODE_DELIMC)
1.79 schwarze 298: putchar(')');
1.84 schwarze 299: if (n->flags & NODE_EOS)
1.68 schwarze 300: putchar('.');
1.84 schwarze 301: if (n->flags & NODE_NOFILL)
302: printf(" NOFILL");
1.68 schwarze 303: putchar('\n');
1.30 kristaps 304: }
1.26 kristaps 305:
1.59 schwarze 306: if (n->eqn)
1.77 schwarze 307: print_box(n->eqn->first, indent + 4);
1.10 kristaps 308: if (n->child)
1.61 schwarze 309: print_man(n->child, indent +
1.63 schwarze 310: (n->type == ROFFT_BLOCK ? 2 : 4));
1.10 kristaps 311: if (n->next)
1.11 kristaps 312: print_man(n->next, indent);
1.28 kristaps 313: }
314:
315: static void
1.38 kristaps 316: print_box(const struct eqn_box *ep, int indent)
317: {
318: int i;
1.46 kristaps 319: const char *t;
1.38 kristaps 320:
1.57 schwarze 321: static const char *posnames[] = {
322: NULL, "sup", "subsup", "sub",
323: "to", "from", "fromto",
324: "over", "sqrt", NULL };
325:
1.38 kristaps 326: if (NULL == ep)
327: return;
328: for (i = 0; i < indent; i++)
1.61 schwarze 329: putchar(' ');
1.38 kristaps 330:
1.46 kristaps 331: t = NULL;
1.38 kristaps 332: switch (ep->type) {
1.52 schwarze 333: case EQN_LIST:
1.46 kristaps 334: t = "eqn-list";
1.39 kristaps 335: break;
1.52 schwarze 336: case EQN_SUBEXPR:
1.46 kristaps 337: t = "eqn-expr";
1.39 kristaps 338: break;
1.52 schwarze 339: case EQN_TEXT:
1.46 kristaps 340: t = "eqn-text";
1.39 kristaps 341: break;
1.56 kristaps 342: case EQN_PILE:
343: t = "eqn-pile";
344: break;
1.52 schwarze 345: case EQN_MATRIX:
1.46 kristaps 346: t = "eqn-matrix";
1.38 kristaps 347: break;
348: }
1.39 kristaps 349:
1.57 schwarze 350: fputs(t, stdout);
351: if (ep->pos)
352: printf(" pos=%s", posnames[ep->pos]);
353: if (ep->left)
354: printf(" left=\"%s\"", ep->left);
355: if (ep->right)
356: printf(" right=\"%s\"", ep->right);
357: if (ep->top)
358: printf(" top=\"%s\"", ep->top);
359: if (ep->bottom)
360: printf(" bottom=\"%s\"", ep->bottom);
361: if (ep->text)
362: printf(" text=\"%s\"", ep->text);
363: if (ep->font)
364: printf(" font=%d", ep->font);
365: if (ep->size != EQN_DEFSIZE)
366: printf(" size=%d", ep->size);
367: if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args)
368: printf(" badargs=%zu(%zu)", ep->args, ep->expectargs);
369: else if (ep->args)
370: printf(" args=%zu", ep->args);
371: putchar('\n');
1.46 kristaps 372:
1.61 schwarze 373: print_box(ep->first, indent + 4);
1.39 kristaps 374: print_box(ep->next, indent);
1.38 kristaps 375: }
376:
377: static void
1.85 ! schwarze 378: print_cellt(enum tbl_cellt pos)
! 379: {
! 380: switch(pos) {
! 381: case TBL_CELL_LEFT:
! 382: putchar('L');
! 383: break;
! 384: case TBL_CELL_LONG:
! 385: putchar('a');
! 386: break;
! 387: case TBL_CELL_CENTRE:
! 388: putchar('c');
! 389: break;
! 390: case TBL_CELL_RIGHT:
! 391: putchar('r');
! 392: break;
! 393: case TBL_CELL_NUMBER:
! 394: putchar('n');
! 395: break;
! 396: case TBL_CELL_SPAN:
! 397: putchar('s');
! 398: break;
! 399: case TBL_CELL_DOWN:
! 400: putchar('^');
! 401: break;
! 402: case TBL_CELL_HORIZ:
! 403: putchar('-');
! 404: break;
! 405: case TBL_CELL_DHORIZ:
! 406: putchar('=');
! 407: break;
! 408: case TBL_CELL_MAX:
! 409: putchar('#');
! 410: break;
! 411: }
! 412: }
! 413:
! 414: static void
1.30 kristaps 415: print_span(const struct tbl_span *sp, int indent)
1.28 kristaps 416: {
417: const struct tbl_dat *dp;
1.85 ! schwarze 418: const struct tbl_cell *cp;
1.30 kristaps 419: int i;
420:
1.85 ! schwarze 421: if (sp->prev == NULL) {
! 422: for (i = 0; i < indent; i++)
! 423: putchar(' ');
! 424: printf("%d", sp->opts->cols);
! 425: if (sp->opts->opts & TBL_OPT_CENTRE)
! 426: fputs(" center", stdout);
! 427: if (sp->opts->opts & TBL_OPT_EXPAND)
! 428: fputs(" expand", stdout);
! 429: if (sp->opts->opts & TBL_OPT_ALLBOX)
! 430: fputs(" allbox", stdout);
! 431: if (sp->opts->opts & TBL_OPT_BOX)
! 432: fputs(" box", stdout);
! 433: if (sp->opts->opts & TBL_OPT_DBOX)
! 434: fputs(" doublebox", stdout);
! 435: if (sp->opts->opts & TBL_OPT_NOKEEP)
! 436: fputs(" nokeep", stdout);
! 437: if (sp->opts->opts & TBL_OPT_NOSPACE)
! 438: fputs(" nospaces", stdout);
! 439: if (sp->opts->opts & TBL_OPT_NOWARN)
! 440: fputs(" nowarn", stdout);
! 441: printf(" (tbl options) %d:1\n", sp->line);
! 442: }
! 443:
1.30 kristaps 444: for (i = 0; i < indent; i++)
1.61 schwarze 445: putchar(' ');
1.28 kristaps 446:
447: switch (sp->pos) {
1.52 schwarze 448: case TBL_SPAN_HORIZ:
1.28 kristaps 449: putchar('-');
1.80 schwarze 450: putchar(' ');
451: break;
1.52 schwarze 452: case TBL_SPAN_DHORIZ:
1.28 kristaps 453: putchar('=');
1.80 schwarze 454: putchar(' ');
455: break;
1.28 kristaps 456: default:
1.85 ! schwarze 457: for (cp = sp->layout->first; cp != NULL; cp = cp->next)
! 458: print_cellt(cp->pos);
! 459: putchar(' ');
1.80 schwarze 460: for (dp = sp->first; dp; dp = dp->next) {
1.85 ! schwarze 461: if ((cp = dp->layout) == NULL)
! 462: putchar('*');
! 463: else {
! 464: printf("%d", cp->col);
! 465: print_cellt(dp->layout->pos);
! 466: if (cp->flags & TBL_CELL_BOLD)
! 467: putchar('b');
! 468: if (cp->flags & TBL_CELL_ITALIC)
! 469: putchar('i');
! 470: if (cp->flags & TBL_CELL_TALIGN)
! 471: putchar('t');
! 472: if (cp->flags & TBL_CELL_UP)
! 473: putchar('u');
! 474: if (cp->flags & TBL_CELL_BALIGN)
! 475: putchar('d');
! 476: if (cp->flags & TBL_CELL_WIGN)
! 477: putchar('z');
! 478: if (cp->flags & TBL_CELL_EQUAL)
! 479: putchar('e');
! 480: if (cp->flags & TBL_CELL_WMAX)
! 481: putchar('x');
! 482: }
1.80 schwarze 483: switch (dp->pos) {
484: case TBL_DATA_HORIZ:
485: case TBL_DATA_NHORIZ:
486: putchar('-');
1.85 ! schwarze 487: break;
1.80 schwarze 488: case TBL_DATA_DHORIZ:
489: case TBL_DATA_NDHORIZ:
490: putchar('=');
1.85 ! schwarze 491: break;
1.80 schwarze 492: default:
1.85 ! schwarze 493: putchar(dp->block ? '{' : '[');
! 494: if (dp->string != NULL)
! 495: fputs(dp->string, stdout);
! 496: putchar(dp->block ? '}' : ']');
1.80 schwarze 497: break;
498: }
499: if (dp->hspans)
500: printf(">%d", dp->hspans);
501: if (dp->vspans)
502: printf("v%d", dp->vspans);
503: putchar(' ');
504: }
1.28 kristaps 505: break;
506: }
1.38 kristaps 507: printf("(tbl) %d:1\n", sp->line);
1.10 kristaps 508: }
CVSweb