1 /* $Id: tree.c,v 1.47 2011/09/18 14:14:15 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, sz; 62 char **params; 63 struct mdoc_argv *argv; 64 65 argv = NULL; 66 argc = sz = 0; 67 params = NULL; 68 t = p = NULL; 69 70 switch (n->type) { 71 case (MDOC_ROOT): 72 t = "root"; 73 break; 74 case (MDOC_BLOCK): 75 t = "block"; 76 break; 77 case (MDOC_HEAD): 78 t = "block-head"; 79 break; 80 case (MDOC_BODY): 81 if (n->end) 82 t = "body-end"; 83 else 84 t = "block-body"; 85 break; 86 case (MDOC_TAIL): 87 t = "block-tail"; 88 break; 89 case (MDOC_ELEM): 90 t = "elem"; 91 break; 92 case (MDOC_TEXT): 93 t = "text"; 94 break; 95 case (MDOC_TBL): 96 /* FALLTHROUGH */ 97 case (MDOC_EQN): 98 break; 99 default: 100 abort(); 101 /* NOTREACHED */ 102 } 103 104 switch (n->type) { 105 case (MDOC_TEXT): 106 p = n->string; 107 break; 108 case (MDOC_BODY): 109 p = mdoc_macronames[n->tok]; 110 break; 111 case (MDOC_HEAD): 112 p = mdoc_macronames[n->tok]; 113 break; 114 case (MDOC_TAIL): 115 p = mdoc_macronames[n->tok]; 116 break; 117 case (MDOC_ELEM): 118 p = mdoc_macronames[n->tok]; 119 if (n->args) { 120 argv = n->args->argv; 121 argc = n->args->argc; 122 } 123 break; 124 case (MDOC_BLOCK): 125 p = mdoc_macronames[n->tok]; 126 if (n->args) { 127 argv = n->args->argv; 128 argc = n->args->argc; 129 } 130 break; 131 case (MDOC_TBL): 132 /* FALLTHROUGH */ 133 case (MDOC_EQN): 134 break; 135 case (MDOC_ROOT): 136 p = "root"; 137 break; 138 default: 139 abort(); 140 /* NOTREACHED */ 141 } 142 143 if (n->span) { 144 assert(NULL == p && NULL == t); 145 print_span(n->span, indent); 146 } else if (n->eqn) { 147 assert(NULL == p && NULL == t); 148 print_box(n->eqn->root, indent); 149 } else { 150 for (i = 0; i < indent; i++) 151 putchar('\t'); 152 153 printf("%s (%s)", p, t); 154 155 for (i = 0; i < (int)argc; i++) { 156 printf(" -%s", mdoc_argnames[argv[i].arg]); 157 if (argv[i].sz > 0) 158 printf(" ["); 159 for (j = 0; j < (int)argv[i].sz; j++) 160 printf(" [%s]", argv[i].value[j]); 161 if (argv[i].sz > 0) 162 printf(" ]"); 163 } 164 165 for (i = 0; i < (int)sz; i++) 166 printf(" [%s]", params[i]); 167 168 printf(" %d:%d\n", n->line, n->pos); 169 } 170 171 if (n->child) 172 print_mdoc(n->child, indent + 1); 173 if (n->next) 174 print_mdoc(n->next, indent); 175 } 176 177 178 static void 179 print_man(const struct man_node *n, int indent) 180 { 181 const char *p, *t; 182 int i; 183 184 t = p = NULL; 185 186 switch (n->type) { 187 case (MAN_ROOT): 188 t = "root"; 189 break; 190 case (MAN_ELEM): 191 t = "elem"; 192 break; 193 case (MAN_TEXT): 194 t = "text"; 195 break; 196 case (MAN_BLOCK): 197 t = "block"; 198 break; 199 case (MAN_HEAD): 200 t = "block-head"; 201 break; 202 case (MAN_BODY): 203 t = "block-body"; 204 break; 205 case (MAN_TAIL): 206 t = "block-tail"; 207 break; 208 case (MAN_TBL): 209 /* FALLTHROUGH */ 210 case (MAN_EQN): 211 break; 212 default: 213 abort(); 214 /* NOTREACHED */ 215 } 216 217 switch (n->type) { 218 case (MAN_TEXT): 219 p = n->string; 220 break; 221 case (MAN_ELEM): 222 /* FALLTHROUGH */ 223 case (MAN_BLOCK): 224 /* FALLTHROUGH */ 225 case (MAN_HEAD): 226 /* FALLTHROUGH */ 227 case (MAN_TAIL): 228 /* FALLTHROUGH */ 229 case (MAN_BODY): 230 p = man_macronames[n->tok]; 231 break; 232 case (MAN_ROOT): 233 p = "root"; 234 break; 235 case (MAN_TBL): 236 /* FALLTHROUGH */ 237 case (MAN_EQN): 238 break; 239 default: 240 abort(); 241 /* NOTREACHED */ 242 } 243 244 if (n->span) { 245 assert(NULL == p && NULL == t); 246 print_span(n->span, indent); 247 } else if (n->eqn) { 248 assert(NULL == p && NULL == t); 249 print_box(n->eqn->root, indent); 250 } else { 251 for (i = 0; i < indent; i++) 252 putchar('\t'); 253 printf("%s (%s) %d:%d\n", p, t, n->line, n->pos); 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, 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 }