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