1322249Sbapt/* $Id: tree.c,v 1.77 2017/07/08 14:51:05 schwarze Exp $ */ 2241675Suqs/* 3275432Sbapt * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> 4316420Sbapt * Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org> 5241675Suqs * 6241675Suqs * Permission to use, copy, modify, and distribute this software for any 7241675Suqs * purpose with or without fee is hereby granted, provided that the above 8241675Suqs * copyright notice and this permission notice appear in all copies. 9241675Suqs * 10294113Sbapt * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 11241675Suqs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12294113Sbapt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 13241675Suqs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14241675Suqs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15241675Suqs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16241675Suqs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17241675Suqs */ 18241675Suqs#include "config.h" 19241675Suqs 20275432Sbapt#include <sys/types.h> 21275432Sbapt 22241675Suqs#include <assert.h> 23241675Suqs#include <limits.h> 24241675Suqs#include <stdio.h> 25241675Suqs#include <stdlib.h> 26241675Suqs#include <time.h> 27241675Suqs 28241675Suqs#include "mandoc.h" 29294113Sbapt#include "roff.h" 30241675Suqs#include "mdoc.h" 31241675Suqs#include "man.h" 32241675Suqs#include "main.h" 33241675Suqs 34241675Suqsstatic void print_box(const struct eqn_box *, int); 35294113Sbaptstatic void print_man(const struct roff_node *, int); 36316420Sbaptstatic void print_meta(const struct roff_meta *); 37294113Sbaptstatic void print_mdoc(const struct roff_node *, int); 38241675Suqsstatic void print_span(const struct tbl_span *, int); 39241675Suqs 40241675Suqs 41241675Suqsvoid 42294113Sbapttree_mdoc(void *arg, const struct roff_man *mdoc) 43241675Suqs{ 44316420Sbapt print_meta(&mdoc->meta); 45316420Sbapt putchar('\n'); 46294113Sbapt print_mdoc(mdoc->first->child, 0); 47241675Suqs} 48241675Suqs 49241675Suqsvoid 50294113Sbapttree_man(void *arg, const struct roff_man *man) 51241675Suqs{ 52316420Sbapt print_meta(&man->meta); 53316420Sbapt if (man->meta.hasbody == 0) 54316420Sbapt puts("body = empty"); 55316420Sbapt putchar('\n'); 56294113Sbapt print_man(man->first->child, 0); 57241675Suqs} 58241675Suqs 59241675Suqsstatic void 60316420Sbaptprint_meta(const struct roff_meta *meta) 61316420Sbapt{ 62316420Sbapt if (meta->title != NULL) 63316420Sbapt printf("title = \"%s\"\n", meta->title); 64316420Sbapt if (meta->name != NULL) 65316420Sbapt printf("name = \"%s\"\n", meta->name); 66316420Sbapt if (meta->msec != NULL) 67316420Sbapt printf("sec = \"%s\"\n", meta->msec); 68316420Sbapt if (meta->vol != NULL) 69316420Sbapt printf("vol = \"%s\"\n", meta->vol); 70316420Sbapt if (meta->arch != NULL) 71316420Sbapt printf("arch = \"%s\"\n", meta->arch); 72316420Sbapt if (meta->os != NULL) 73316420Sbapt printf("os = \"%s\"\n", meta->os); 74316420Sbapt if (meta->date != NULL) 75316420Sbapt printf("date = \"%s\"\n", meta->date); 76316420Sbapt} 77316420Sbapt 78316420Sbaptstatic void 79294113Sbaptprint_mdoc(const struct roff_node *n, int indent) 80241675Suqs{ 81241675Suqs const char *p, *t; 82241675Suqs int i, j; 83261344Suqs size_t argc; 84241675Suqs struct mdoc_argv *argv; 85241675Suqs 86279527Sbapt if (n == NULL) 87279527Sbapt return; 88279527Sbapt 89241675Suqs argv = NULL; 90261344Suqs argc = 0; 91241675Suqs t = p = NULL; 92241675Suqs 93241675Suqs switch (n->type) { 94294113Sbapt case ROFFT_ROOT: 95241675Suqs t = "root"; 96241675Suqs break; 97294113Sbapt case ROFFT_BLOCK: 98241675Suqs t = "block"; 99241675Suqs break; 100294113Sbapt case ROFFT_HEAD: 101294113Sbapt t = "head"; 102241675Suqs break; 103294113Sbapt case ROFFT_BODY: 104241675Suqs if (n->end) 105241675Suqs t = "body-end"; 106241675Suqs else 107294113Sbapt t = "body"; 108241675Suqs break; 109294113Sbapt case ROFFT_TAIL: 110294113Sbapt t = "tail"; 111241675Suqs break; 112294113Sbapt case ROFFT_ELEM: 113241675Suqs t = "elem"; 114241675Suqs break; 115294113Sbapt case ROFFT_TEXT: 116241675Suqs t = "text"; 117241675Suqs break; 118294113Sbapt case ROFFT_TBL: 119275432Sbapt break; 120294113Sbapt case ROFFT_EQN: 121275432Sbapt t = "eqn"; 122241675Suqs break; 123241675Suqs default: 124241675Suqs abort(); 125241675Suqs } 126241675Suqs 127241675Suqs switch (n->type) { 128294113Sbapt case ROFFT_TEXT: 129241675Suqs p = n->string; 130241675Suqs break; 131294113Sbapt case ROFFT_BODY: 132322249Sbapt p = roff_name[n->tok]; 133241675Suqs break; 134294113Sbapt case ROFFT_HEAD: 135322249Sbapt p = roff_name[n->tok]; 136241675Suqs break; 137294113Sbapt case ROFFT_TAIL: 138322249Sbapt p = roff_name[n->tok]; 139241675Suqs break; 140294113Sbapt case ROFFT_ELEM: 141322249Sbapt p = roff_name[n->tok]; 142241675Suqs if (n->args) { 143241675Suqs argv = n->args->argv; 144241675Suqs argc = n->args->argc; 145241675Suqs } 146241675Suqs break; 147294113Sbapt case ROFFT_BLOCK: 148322249Sbapt p = roff_name[n->tok]; 149241675Suqs if (n->args) { 150241675Suqs argv = n->args->argv; 151241675Suqs argc = n->args->argc; 152241675Suqs } 153241675Suqs break; 154294113Sbapt case ROFFT_TBL: 155275432Sbapt break; 156294113Sbapt case ROFFT_EQN: 157275432Sbapt p = "EQ"; 158241675Suqs break; 159294113Sbapt case ROFFT_ROOT: 160241675Suqs p = "root"; 161241675Suqs break; 162241675Suqs default: 163241675Suqs abort(); 164241675Suqs } 165241675Suqs 166241675Suqs if (n->span) { 167241675Suqs assert(NULL == p && NULL == t); 168241675Suqs print_span(n->span, indent); 169241675Suqs } else { 170241675Suqs for (i = 0; i < indent; i++) 171279527Sbapt putchar(' '); 172241675Suqs 173241675Suqs printf("%s (%s)", p, t); 174241675Suqs 175241675Suqs for (i = 0; i < (int)argc; i++) { 176241675Suqs printf(" -%s", mdoc_argnames[argv[i].arg]); 177241675Suqs if (argv[i].sz > 0) 178241675Suqs printf(" ["); 179241675Suqs for (j = 0; j < (int)argv[i].sz; j++) 180241675Suqs printf(" [%s]", argv[i].value[j]); 181241675Suqs if (argv[i].sz > 0) 182241675Suqs printf(" ]"); 183241675Suqs } 184241675Suqs 185261344Suqs putchar(' '); 186316420Sbapt if (NODE_DELIMO & n->flags) 187294113Sbapt putchar('('); 188316420Sbapt if (NODE_LINE & n->flags) 189261344Suqs putchar('*'); 190294113Sbapt printf("%d:%d", n->line, n->pos + 1); 191316420Sbapt if (NODE_DELIMC & n->flags) 192294113Sbapt putchar(')'); 193316420Sbapt if (NODE_EOS & n->flags) 194294113Sbapt putchar('.'); 195322249Sbapt if (NODE_BROKEN & n->flags) 196322249Sbapt printf(" BROKEN"); 197316420Sbapt if (NODE_NOSRC & n->flags) 198316420Sbapt printf(" NOSRC"); 199316420Sbapt if (NODE_NOPRT & n->flags) 200316420Sbapt printf(" NOPRT"); 201294113Sbapt putchar('\n'); 202241675Suqs } 203241675Suqs 204275432Sbapt if (n->eqn) 205322249Sbapt print_box(n->eqn->first, indent + 4); 206241675Suqs if (n->child) 207279527Sbapt print_mdoc(n->child, indent + 208294113Sbapt (n->type == ROFFT_BLOCK ? 2 : 4)); 209241675Suqs if (n->next) 210241675Suqs print_mdoc(n->next, indent); 211241675Suqs} 212241675Suqs 213241675Suqsstatic void 214294113Sbaptprint_man(const struct roff_node *n, int indent) 215241675Suqs{ 216241675Suqs const char *p, *t; 217241675Suqs int i; 218241675Suqs 219279527Sbapt if (n == NULL) 220279527Sbapt return; 221279527Sbapt 222241675Suqs t = p = NULL; 223241675Suqs 224241675Suqs switch (n->type) { 225294113Sbapt case ROFFT_ROOT: 226241675Suqs t = "root"; 227241675Suqs break; 228294113Sbapt case ROFFT_ELEM: 229241675Suqs t = "elem"; 230241675Suqs break; 231294113Sbapt case ROFFT_TEXT: 232241675Suqs t = "text"; 233241675Suqs break; 234294113Sbapt case ROFFT_BLOCK: 235241675Suqs t = "block"; 236241675Suqs break; 237294113Sbapt case ROFFT_HEAD: 238294113Sbapt t = "head"; 239241675Suqs break; 240294113Sbapt case ROFFT_BODY: 241294113Sbapt t = "body"; 242241675Suqs break; 243294113Sbapt case ROFFT_TBL: 244241675Suqs break; 245294113Sbapt case ROFFT_EQN: 246275432Sbapt t = "eqn"; 247241675Suqs break; 248241675Suqs default: 249241675Suqs abort(); 250241675Suqs } 251241675Suqs 252241675Suqs switch (n->type) { 253294113Sbapt case ROFFT_TEXT: 254241675Suqs p = n->string; 255241675Suqs break; 256294113Sbapt case ROFFT_ELEM: 257294113Sbapt case ROFFT_BLOCK: 258294113Sbapt case ROFFT_HEAD: 259294113Sbapt case ROFFT_BODY: 260322249Sbapt p = roff_name[n->tok]; 261241675Suqs break; 262294113Sbapt case ROFFT_ROOT: 263241675Suqs p = "root"; 264241675Suqs break; 265294113Sbapt case ROFFT_TBL: 266275432Sbapt break; 267294113Sbapt case ROFFT_EQN: 268275432Sbapt p = "EQ"; 269241675Suqs break; 270241675Suqs default: 271241675Suqs abort(); 272241675Suqs } 273241675Suqs 274241675Suqs if (n->span) { 275241675Suqs assert(NULL == p && NULL == t); 276241675Suqs print_span(n->span, indent); 277241675Suqs } else { 278241675Suqs for (i = 0; i < indent; i++) 279279527Sbapt putchar(' '); 280274880Sbapt printf("%s (%s) ", p, t); 281316420Sbapt if (NODE_LINE & n->flags) 282274880Sbapt putchar('*'); 283294113Sbapt printf("%d:%d", n->line, n->pos + 1); 284316420Sbapt if (NODE_EOS & n->flags) 285294113Sbapt putchar('.'); 286294113Sbapt putchar('\n'); 287241675Suqs } 288241675Suqs 289275432Sbapt if (n->eqn) 290322249Sbapt print_box(n->eqn->first, indent + 4); 291241675Suqs if (n->child) 292279527Sbapt print_man(n->child, indent + 293294113Sbapt (n->type == ROFFT_BLOCK ? 2 : 4)); 294241675Suqs if (n->next) 295241675Suqs print_man(n->next, indent); 296241675Suqs} 297241675Suqs 298241675Suqsstatic void 299241675Suqsprint_box(const struct eqn_box *ep, int indent) 300241675Suqs{ 301241675Suqs int i; 302241675Suqs const char *t; 303241675Suqs 304275432Sbapt static const char *posnames[] = { 305275432Sbapt NULL, "sup", "subsup", "sub", 306275432Sbapt "to", "from", "fromto", 307275432Sbapt "over", "sqrt", NULL }; 308275432Sbapt 309241675Suqs if (NULL == ep) 310241675Suqs return; 311241675Suqs for (i = 0; i < indent; i++) 312279527Sbapt putchar(' '); 313241675Suqs 314241675Suqs t = NULL; 315241675Suqs switch (ep->type) { 316274880Sbapt case EQN_LIST: 317241675Suqs t = "eqn-list"; 318241675Suqs break; 319274880Sbapt case EQN_SUBEXPR: 320241675Suqs t = "eqn-expr"; 321241675Suqs break; 322274880Sbapt case EQN_TEXT: 323241675Suqs t = "eqn-text"; 324241675Suqs break; 325275432Sbapt case EQN_PILE: 326275432Sbapt t = "eqn-pile"; 327275432Sbapt break; 328274880Sbapt case EQN_MATRIX: 329241675Suqs t = "eqn-matrix"; 330241675Suqs break; 331241675Suqs } 332241675Suqs 333275432Sbapt fputs(t, stdout); 334275432Sbapt if (ep->pos) 335275432Sbapt printf(" pos=%s", posnames[ep->pos]); 336275432Sbapt if (ep->left) 337275432Sbapt printf(" left=\"%s\"", ep->left); 338275432Sbapt if (ep->right) 339275432Sbapt printf(" right=\"%s\"", ep->right); 340275432Sbapt if (ep->top) 341275432Sbapt printf(" top=\"%s\"", ep->top); 342275432Sbapt if (ep->bottom) 343275432Sbapt printf(" bottom=\"%s\"", ep->bottom); 344275432Sbapt if (ep->text) 345275432Sbapt printf(" text=\"%s\"", ep->text); 346275432Sbapt if (ep->font) 347275432Sbapt printf(" font=%d", ep->font); 348275432Sbapt if (ep->size != EQN_DEFSIZE) 349275432Sbapt printf(" size=%d", ep->size); 350275432Sbapt if (ep->expectargs != UINT_MAX && ep->expectargs != ep->args) 351275432Sbapt printf(" badargs=%zu(%zu)", ep->args, ep->expectargs); 352275432Sbapt else if (ep->args) 353275432Sbapt printf(" args=%zu", ep->args); 354275432Sbapt putchar('\n'); 355241675Suqs 356279527Sbapt print_box(ep->first, indent + 4); 357241675Suqs print_box(ep->next, indent); 358241675Suqs} 359241675Suqs 360241675Suqsstatic void 361241675Suqsprint_span(const struct tbl_span *sp, int indent) 362241675Suqs{ 363241675Suqs const struct tbl_dat *dp; 364241675Suqs int i; 365241675Suqs 366241675Suqs for (i = 0; i < indent; i++) 367279527Sbapt putchar(' '); 368241675Suqs 369241675Suqs switch (sp->pos) { 370274880Sbapt case TBL_SPAN_HORIZ: 371241675Suqs putchar('-'); 372241675Suqs return; 373274880Sbapt case TBL_SPAN_DHORIZ: 374241675Suqs putchar('='); 375241675Suqs return; 376241675Suqs default: 377241675Suqs break; 378241675Suqs } 379241675Suqs 380241675Suqs for (dp = sp->first; dp; dp = dp->next) { 381241675Suqs switch (dp->pos) { 382274880Sbapt case TBL_DATA_HORIZ: 383274880Sbapt case TBL_DATA_NHORIZ: 384241675Suqs putchar('-'); 385241675Suqs continue; 386274880Sbapt case TBL_DATA_DHORIZ: 387274880Sbapt case TBL_DATA_NDHORIZ: 388241675Suqs putchar('='); 389241675Suqs continue; 390241675Suqs default: 391241675Suqs break; 392241675Suqs } 393241675Suqs printf("[\"%s\"", dp->string ? dp->string : ""); 394241675Suqs if (dp->spans) 395241675Suqs printf("(%d)", dp->spans); 396241675Suqs if (NULL == dp->layout) 397241675Suqs putchar('*'); 398241675Suqs putchar(']'); 399241675Suqs putchar(' '); 400241675Suqs } 401241675Suqs 402241675Suqs printf("(tbl) %d:1\n", sp->line); 403241675Suqs} 404