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