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