Print this page
Update to 1.12.3.

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/tbl_layout.c
          +++ new/usr/src/cmd/mandoc/tbl_layout.c
   1      -/*      $Id: tbl_layout.c,v 1.22 2011/09/18 14:14:15 schwarze Exp $ */
        1 +/*      $Id: tbl_layout.c,v 1.23 2012/05/27 17:54:54 schwarze Exp $ */
   2    2  /*
   3    3   * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
        4 + * Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org>
   4    5   *
   5    6   * Permission to use, copy, modify, and distribute this software for any
   6    7   * purpose with or without fee is hereby granted, provided that the above
   7    8   * copyright notice and this permission notice appear in all copies.
   8    9   *
   9   10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10   11   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11   12   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12   13   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13   14   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
↓ open down ↓ 30 lines elided ↑ open up ↑
  44   45  static  const struct tbl_phrase keys[KEYS_MAX] = {
  45   46          { 'c',           TBL_CELL_CENTRE },
  46   47          { 'r',           TBL_CELL_RIGHT },
  47   48          { 'l',           TBL_CELL_LEFT },
  48   49          { 'n',           TBL_CELL_NUMBER },
  49   50          { 's',           TBL_CELL_SPAN },
  50   51          { 'a',           TBL_CELL_LONG },
  51   52          { '^',           TBL_CELL_DOWN },
  52   53          { '-',           TBL_CELL_HORIZ },
  53   54          { '_',           TBL_CELL_HORIZ },
  54      -        { '=',           TBL_CELL_DHORIZ },
  55      -        { '|',           TBL_CELL_VERT }
       55 +        { '=',           TBL_CELL_DHORIZ }
  56   56  };
  57   57  
  58   58  static  int              mods(struct tbl_node *, struct tbl_cell *, 
  59   59                                  int, const char *, int *);
  60   60  static  int              cell(struct tbl_node *, struct tbl_row *, 
  61   61                                  int, const char *, int *);
  62   62  static  void             row(struct tbl_node *, int, const char *, int *);
  63      -static  struct tbl_cell *cell_alloc(struct tbl_node *, 
  64      -                                struct tbl_row *, enum tbl_cellt);
  65      -static  void             head_adjust(const struct tbl_cell *, 
  66      -                                struct tbl_head *);
       63 +static  struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *,
       64 +                                enum tbl_cellt, int vert);
  67   65  
  68   66  static int
  69   67  mods(struct tbl_node *tbl, struct tbl_cell *cp, 
  70   68                  int ln, const char *p, int *pos)
  71   69  {
  72   70          char             buf[5];
  73   71          int              i;
  74   72  
  75   73          /* Not all types accept modifiers. */
  76   74  
  77   75          switch (cp->pos) {
  78   76          case (TBL_CELL_DOWN):
  79   77                  /* FALLTHROUGH */
  80   78          case (TBL_CELL_HORIZ):
  81   79                  /* FALLTHROUGH */
  82   80          case (TBL_CELL_DHORIZ):
  83      -                /* FALLTHROUGH */
  84      -        case (TBL_CELL_VERT):
  85      -                /* FALLTHROUGH */
  86      -        case (TBL_CELL_DVERT):
  87   81                  return(1);
  88   82          default:
  89   83                  break;
  90   84          }
  91   85  
  92   86  mod:
  93   87          /* 
  94   88           * XXX: since, at least for now, modifiers are non-conflicting
  95   89           * (are separable by value, regardless of position), we let
  96   90           * modifiers come in any order.  The existing tbl doesn't let
↓ open down ↓ 110 lines elided ↑ open up ↑
 207  201  
 208  202          mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
 209  203                          ln, *pos - 1, NULL);
 210  204          return(0);
 211  205  }
 212  206  
 213  207  static int
 214  208  cell(struct tbl_node *tbl, struct tbl_row *rp, 
 215  209                  int ln, const char *p, int *pos)
 216  210  {
 217      -        int              i;
      211 +        int              vert, i;
 218  212          enum tbl_cellt   c;
 219  213  
 220      -        /* Parse the column position (`r', `R', `|', ...). */
      214 +        /* Handle vertical lines. */
 221  215  
      216 +        for (vert = 0; '|' == p[*pos]; ++*pos)
      217 +                vert++;
      218 +        while (' ' == p[*pos])
      219 +                (*pos)++;
      220 +
      221 +        /* Parse the column position (`c', `l', `r', ...). */
      222 +
 222  223          for (i = 0; i < KEYS_MAX; i++)
 223  224                  if (tolower((unsigned char)p[*pos]) == keys[i].name)
 224  225                          break;
 225  226  
 226  227          if (KEYS_MAX == i) {
 227  228                  mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, 
 228  229                                  ln, *pos, NULL);
 229  230                  return(0);
 230  231          }
 231  232  
↓ open down ↓ 7 lines elided ↑ open up ↑
 239  240           * FIXME: recover from this somehow?
 240  241           */
 241  242  
 242  243          if (TBL_CELL_SPAN == c) {
 243  244                  if (NULL == rp->first) {
 244  245                          mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
 245  246                                          ln, *pos, NULL);
 246  247                          return(0);
 247  248                  } else if (rp->last)
 248  249                          switch (rp->last->pos) {
 249      -                        case (TBL_CELL_VERT):
 250      -                        case (TBL_CELL_DVERT):
 251  250                          case (TBL_CELL_HORIZ):
 252  251                          case (TBL_CELL_DHORIZ):
 253  252                                  mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
 254  253                                                  ln, *pos, NULL);
 255  254                                  return(0);
 256  255                          default:
 257  256                                  break;
 258  257                          }
 259  258          }
 260  259  
↓ open down ↓ 2 lines elided ↑ open up ↑
 263  262           * row.
 264  263           */
 265  264  
 266  265          if (TBL_CELL_DOWN == c && rp == tbl->first_row) {
 267  266                  mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos, NULL);
 268  267                  return(0);
 269  268          }
 270  269  
 271  270          (*pos)++;
 272  271  
 273      -        /* Extra check for the double-vertical. */
 274      -
 275      -        if (TBL_CELL_VERT == c && '|' == p[*pos]) {
 276      -                (*pos)++;
 277      -                c = TBL_CELL_DVERT;
 278      -        } 
 279      -        
 280  272          /* Disallow adjacent spacers. */
 281  273  
 282      -        if (rp->last && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) &&
 283      -                        (TBL_CELL_VERT == rp->last->pos || 
 284      -                         TBL_CELL_DVERT == rp->last->pos)) {
      274 +        if (vert > 2) {
 285  275                  mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos - 1, NULL);
 286  276                  return(0);
 287  277          }
 288  278  
 289  279          /* Allocate cell then parse its modifiers. */
 290  280  
 291      -        return(mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos));
      281 +        return(mods(tbl, cell_alloc(tbl, rp, c, vert), ln, p, pos));
 292  282  }
 293  283  
 294  284  
 295  285  static void
 296  286  row(struct tbl_node *tbl, int ln, const char *p, int *pos)
 297  287  {
 298  288          struct tbl_row  *rp;
 299  289  
 300  290  row:    /*
 301  291           * EBNF describing this section:
 302  292           *
 303  293           * row          ::= row_list [:space:]* [.]?[\n]
 304  294           * row_list     ::= [:space:]* row_elem row_tail
 305  295           * row_tail     ::= [:space:]*[,] row_list |
 306  296           *                  epsilon
 307  297           * row_elem     ::= [\t\ ]*[:alpha:]+
 308  298           */
 309  299  
 310  300          rp = mandoc_calloc(1, sizeof(struct tbl_row));
 311      -        if (tbl->last_row) {
      301 +        if (tbl->last_row)
 312  302                  tbl->last_row->next = rp;
 313      -                tbl->last_row = rp;
 314      -        } else
 315      -                tbl->last_row = tbl->first_row = rp;
      303 +        else
      304 +                tbl->first_row = rp;
      305 +        tbl->last_row = rp;
 316  306  
 317  307  cell:
 318  308          while (isspace((unsigned char)p[*pos]))
 319  309                  (*pos)++;
 320  310  
 321  311          /* Safely exit layout context. */
 322  312  
 323  313          if ('.' == p[*pos]) {
 324  314                  tbl->part = TBL_PART_DATA;
 325  315                  if (NULL == tbl->first_row) 
↓ open down ↓ 24 lines elided ↑ open up ↑
 350  340          int              pos;
 351  341  
 352  342          pos = 0;
 353  343          row(tbl, ln, p, &pos);
 354  344  
 355  345          /* Always succeed. */
 356  346          return(1);
 357  347  }
 358  348  
 359  349  static struct tbl_cell *
 360      -cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
      350 +cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos,
      351 +                int vert)
 361  352  {
 362  353          struct tbl_cell *p, *pp;
 363  354          struct tbl_head *h, *hp;
 364  355  
 365  356          p = mandoc_calloc(1, sizeof(struct tbl_cell));
 366  357  
 367  358          if (NULL != (pp = rp->last)) {
 368      -                rp->last->next = p;
 369      -                rp->last = p;
 370      -        } else
 371      -                rp->last = rp->first = p;
      359 +                pp->next = p;
      360 +                h = pp->head->next;
      361 +        } else {
      362 +                rp->first = p;
      363 +                h = tbl->first_head;
      364 +        }
      365 +        rp->last = p;
 372  366  
 373  367          p->pos = pos;
      368 +        p->vert = vert;
 374  369  
 375      -        /*
 376      -         * This is a little bit complicated.  Here we determine the
 377      -         * header the corresponds to a cell.  We add headers dynamically
 378      -         * when need be or re-use them, otherwise.  As an example, given
 379      -         * the following:
 380      -         *
 381      -         *      1  c || l 
 382      -         *      2  | c | l
 383      -         *      3  l l
 384      -         *      3  || c | l |.
 385      -         *
 386      -         * We first add the new headers (as there are none) in (1); then
 387      -         * in (2) we insert the first spanner (as it doesn't match up
 388      -         * with the header); then we re-use the prior data headers,
 389      -         * skipping over the spanners; then we re-use everything and add
 390      -         * a last spanner.  Note that VERT headers are made into DVERT
 391      -         * ones.
 392      -         */
      370 +        /* Re-use header. */
 393  371  
 394      -        h = pp ? pp->head->next : tbl->first_head;
 395      -
 396  372          if (h) {
 397      -                /* Re-use data header. */
 398      -                if (TBL_HEAD_DATA == h->pos && 
 399      -                                (TBL_CELL_VERT != p->pos &&
 400      -                                 TBL_CELL_DVERT != p->pos)) {
 401      -                        p->head = h;
 402      -                        return(p);
 403      -                }
 404      -
 405      -                /* Re-use spanner header. */
 406      -                if (TBL_HEAD_DATA != h->pos && 
 407      -                                (TBL_CELL_VERT == p->pos ||
 408      -                                 TBL_CELL_DVERT == p->pos)) {
 409      -                        head_adjust(p, h);
 410      -                        p->head = h;
 411      -                        return(p);
 412      -                }
 413      -
 414      -                /* Right-shift headers with a new spanner. */
 415      -                if (TBL_HEAD_DATA == h->pos && 
 416      -                                (TBL_CELL_VERT == p->pos ||
 417      -                                 TBL_CELL_DVERT == p->pos)) {
 418      -                        hp = mandoc_calloc(1, sizeof(struct tbl_head));
 419      -                        hp->ident = tbl->opts.cols++;
 420      -                        hp->prev = h->prev;
 421      -                        if (h->prev)
 422      -                                h->prev->next = hp;
 423      -                        if (h == tbl->first_head)
 424      -                                tbl->first_head = hp;
 425      -                        h->prev = hp;
 426      -                        hp->next = h;
 427      -                        head_adjust(p, hp);
 428      -                        p->head = hp;
 429      -                        return(p);
 430      -                }
 431      -
 432      -                if (NULL != (h = h->next)) {
 433      -                        head_adjust(p, h);
 434      -                        p->head = h;
 435      -                        return(p);
 436      -                }
 437      -
 438      -                /* Fall through to default case... */
      373 +                p->head = h;
      374 +                return(p);
 439  375          }
 440  376  
 441  377          hp = mandoc_calloc(1, sizeof(struct tbl_head));
 442  378          hp->ident = tbl->opts.cols++;
      379 +        hp->vert = vert;
 443  380  
 444  381          if (tbl->last_head) {
 445  382                  hp->prev = tbl->last_head;
 446  383                  tbl->last_head->next = hp;
 447      -                tbl->last_head = hp;
 448  384          } else
 449      -                tbl->last_head = tbl->first_head = hp;
      385 +                tbl->first_head = hp;
      386 +        tbl->last_head = hp;
 450  387  
 451      -        head_adjust(p, hp);
 452  388          p->head = hp;
 453  389          return(p);
 454  390  }
 455      -
 456      -static void
 457      -head_adjust(const struct tbl_cell *cellp, struct tbl_head *head)
 458      -{
 459      -        if (TBL_CELL_VERT != cellp->pos &&
 460      -                        TBL_CELL_DVERT != cellp->pos) {
 461      -                head->pos = TBL_HEAD_DATA;
 462      -                return;
 463      -        }
 464      -
 465      -        if (TBL_CELL_VERT == cellp->pos)
 466      -                if (TBL_HEAD_DVERT != head->pos)
 467      -                        head->pos = TBL_HEAD_VERT;
 468      -
 469      -        if (TBL_CELL_DVERT == cellp->pos)
 470      -                head->pos = TBL_HEAD_DVERT;
 471      -}
 472      -
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX