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 }