1 /* $Id: tree.c,v 1.21 2014/04/20 16:44:44 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2008, 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4 * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 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. 17 */ 18 #include <assert.h> 19 #include <limits.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <time.h> 23 24 #include "mandoc.h" 25 #include "mdoc.h" 26 #include "man.h" 27 #include "main.h" 28 29 static void print_box(const struct eqn_box *, int); 30 static void print_man(const struct man_node *, int); 31 static void print_mdoc(const struct mdoc_node *, int); 32 static void print_span(const struct tbl_span *, int); 33 34 35 void 36 tree_mdoc(void *arg, const struct mdoc *mdoc) 37 { 38 39 print_mdoc(mdoc_node(mdoc), 0); 40 } 41 42 void 43 tree_man(void *arg, const struct man *man) 44 { 45 46 print_man(man_node(man), 0); 47 } 48 49 static void 50 print_mdoc(const struct mdoc_node *n, int indent) 51 { 52 const char *p, *t; 53 int i, j; 54 size_t argc; 55 struct mdoc_argv *argv; 56 57 argv = NULL; 58 argc = 0; 59 t = p = NULL; 60 61 switch (n->type) { 62 case MDOC_ROOT: 63 t = "root"; 64 break; 65 case MDOC_BLOCK: 66 t = "block"; 67 break; 68 case MDOC_HEAD: 69 t = "block-head"; 70 break; 71 case MDOC_BODY: 72 if (n->end) 73 t = "body-end"; 74 else 75 t = "block-body"; 76 break; 77 case MDOC_TAIL: 78 t = "block-tail"; 79 break; 80 case MDOC_ELEM: 81 t = "elem"; 82 break; 83 case MDOC_TEXT: 84 t = "text"; 85 break; 86 case MDOC_TBL: 87 /* FALLTHROUGH */ 88 case MDOC_EQN: 89 break; 90 default: 91 abort(); 92 /* NOTREACHED */ 93 } 94 95 switch (n->type) { 96 case MDOC_TEXT: 97 p = n->string; 98 break; 99 case MDOC_BODY: 100 p = mdoc_macronames[n->tok]; 101 break; 102 case MDOC_HEAD: 103 p = mdoc_macronames[n->tok]; 104 break; 105 case MDOC_TAIL: 106 p = mdoc_macronames[n->tok]; 107 break; 108 case MDOC_ELEM: 109 p = mdoc_macronames[n->tok]; 110 if (n->args) { 111 argv = n->args->argv; 112 argc = n->args->argc; 113 } 114 break; 115 case MDOC_BLOCK: 116 p = mdoc_macronames[n->tok]; 117 if (n->args) { 118 argv = n->args->argv; 119 argc = n->args->argc; 120 } 121 break; 122 case MDOC_TBL: 123 /* FALLTHROUGH */ 124 case MDOC_EQN: 125 break; 126 case MDOC_ROOT: 127 p = "root"; 128 break; 129 default: 130 abort(); 131 /* NOTREACHED */ 132 } 133 134 if (n->span) { 135 assert(NULL == p && NULL == t); 136 print_span(n->span, indent); 137 } else if (n->eqn) { 138 assert(NULL == p && NULL == t); 139 print_box(n->eqn->root, indent); 140 } else { 141 for (i = 0; i < indent; i++) 142 putchar('\t'); 143 144 printf("%s (%s)", p, t); 145 146 for (i = 0; i < (int)argc; i++) { 147 printf(" -%s", mdoc_argnames[argv[i].arg]); 148 if (argv[i].sz > 0) 149 printf(" ["); 150 for (j = 0; j < (int)argv[i].sz; j++) 151 printf(" [%s]", argv[i].value[j]); 152 if (argv[i].sz > 0) 153 printf(" ]"); 154 } 155 156 putchar(' '); 157 if (MDOC_LINE & n->flags) 158 putchar('*'); 159 printf("%d:%d", n->line, n->pos); 160 if (n->lastline != n->line) 161 printf("-%d", n->lastline); 162 putchar('\n'); 163 } 164 165 if (n->child) 166 print_mdoc(n->child, indent + 1); 167 if (n->next) 168 print_mdoc(n->next, indent); 169 } 170 171 static void 172 print_man(const struct man_node *n, int indent) 173 { 174 const char *p, *t; 175 int i; 176 177 t = p = NULL; 178 179 switch (n->type) { 180 case MAN_ROOT: 181 t = "root"; 182 break; 183 case MAN_ELEM: 184 t = "elem"; 185 break; 186 case MAN_TEXT: 187 t = "text"; 188 break; 189 case MAN_BLOCK: 190 t = "block"; 191 break; 192 case MAN_HEAD: 193 t = "block-head"; 194 break; 195 case MAN_BODY: 196 t = "block-body"; 197 break; 198 case MAN_TAIL: 199 t = "block-tail"; 200 break; 201 case MAN_TBL: 202 /* FALLTHROUGH */ 203 case MAN_EQN: 204 break; 205 default: 206 abort(); 207 /* NOTREACHED */ 208 } 209 210 switch (n->type) { 211 case MAN_TEXT: 212 p = n->string; 213 break; 214 case MAN_ELEM: 215 /* FALLTHROUGH */ 216 case MAN_BLOCK: 217 /* FALLTHROUGH */ 218 case MAN_HEAD: 219 /* FALLTHROUGH */ 220 case MAN_TAIL: 221 /* FALLTHROUGH */ 222 case MAN_BODY: 223 p = man_macronames[n->tok]; 224 break; 225 case MAN_ROOT: 226 p = "root"; 227 break; 228 case MAN_TBL: 229 /* FALLTHROUGH */ 230 case MAN_EQN: 231 break; 232 default: 233 abort(); 234 /* NOTREACHED */ 235 } 236 237 if (n->span) { 238 assert(NULL == p && NULL == t); 239 print_span(n->span, indent); 240 } else if (n->eqn) { 241 assert(NULL == p && NULL == t); 242 print_box(n->eqn->root, indent); 243 } else { 244 for (i = 0; i < indent; i++) 245 putchar('\t'); 246 printf("%s (%s) ", p, t); 247 if (MAN_LINE & n->flags) 248 putchar('*'); 249 printf("%d:%d\n", n->line, n->pos); 250 } 251 252 if (n->child) 253 print_man(n->child, indent + 1); 254 if (n->next) 255 print_man(n->next, indent); 256 } 257 258 static void 259 print_box(const struct eqn_box *ep, int indent) 260 { 261 int i; 262 const char *t; 263 264 if (NULL == ep) 265 return; 266 for (i = 0; i < indent; i++) 267 putchar('\t'); 268 269 t = NULL; 270 switch (ep->type) { 271 case EQN_ROOT: 272 t = "eqn-root"; 273 break; 274 case EQN_LIST: 275 t = "eqn-list"; 276 break; 277 case EQN_SUBEXPR: 278 t = "eqn-expr"; 279 break; 280 case EQN_TEXT: 281 t = "eqn-text"; 282 break; 283 case EQN_MATRIX: 284 t = "eqn-matrix"; 285 break; 286 } 287 288 assert(t); 289 printf("%s(%d, %d, %d, %d, %d, \"%s\", \"%s\") %s\n", 290 t, EQN_DEFSIZE == ep->size ? 0 : ep->size, 291 ep->pos, ep->font, ep->mark, ep->pile, 292 ep->left ? ep->left : "", 293 ep->right ? ep->right : "", 294 ep->text ? ep->text : ""); 295 296 print_box(ep->first, indent + 1); 297 print_box(ep->next, indent); 298 } 299 300 static void 301 print_span(const struct tbl_span *sp, int indent) 302 { 303 const struct tbl_dat *dp; 304 int i; 305 306 for (i = 0; i < indent; i++) 307 putchar('\t'); 308 309 switch (sp->pos) { 310 case TBL_SPAN_HORIZ: 311 putchar('-'); 312 return; 313 case TBL_SPAN_DHORIZ: 314 putchar('='); 315 return; 316 default: 317 break; 318 } 319 320 for (dp = sp->first; dp; dp = dp->next) { 321 switch (dp->pos) { 322 case TBL_DATA_HORIZ: 323 /* FALLTHROUGH */ 324 case TBL_DATA_NHORIZ: 325 putchar('-'); 326 continue; 327 case TBL_DATA_DHORIZ: 328 /* FALLTHROUGH */ 329 case TBL_DATA_NDHORIZ: 330 putchar('='); 331 continue; 332 default: 333 break; 334 } 335 printf("[\"%s\"", dp->string ? dp->string : ""); 336 if (dp->spans) 337 printf("(%d)", dp->spans); 338 if (NULL == dp->layout) 339 putchar('*'); 340 putchar(']'); 341 putchar(' '); 342 } 343 344 printf("(tbl) %d:1\n", sp->line); 345 } 346