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