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