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