]> git.cameronkatri.com Git - mandoc.git/blobdiff - tbl_layout.c
Reject the escape sequences \[uD800] to \[uDFFF] in the parser.
[mandoc.git] / tbl_layout.c
index 4b34e74a8842cdfad792d5cf65ea549e1a64566c..c0eafbddbf05cdbfb0528644d470bf73597236d9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: tbl_layout.c,v 1.33 2015/01/27 05:21:45 schwarze Exp $ */
+/*     $Id: tbl_layout.c,v 1.41 2015/10/12 00:08:16 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -97,12 +97,8 @@ mod:
 
        switch (tolower((unsigned char)p[(*pos)++])) {
        case 'b':
-               /* FALLTHROUGH */
-       case 'i':
-               /* FALLTHROUGH */
-       case 'r':
-               (*pos)--;
-               break;
+               cp->flags |= TBL_CELL_BOLD;
+               goto mod;
        case 'd':
                cp->flags |= TBL_CELL_BALIGN;
                goto mod;
@@ -111,12 +107,14 @@ mod:
                goto mod;
        case 'f':
                break;
+       case 'i':
+               cp->flags |= TBL_CELL_ITALIC;
+               goto mod;
        case 'm':
                mandoc_msg(MANDOCERR_TBLLAYOUT_MOD, tbl->parse,
                    ln, *pos, "m");
                goto mod;
        case 'p':
-               /* FALLTHROUGH */
        case 'v':
                if (p[*pos] == '-' || p[*pos] == '+')
                        (*pos)++;
@@ -150,20 +148,34 @@ mod:
                goto mod;
        }
 
-       switch (tolower((unsigned char)p[(*pos)++])) {
+       /* Ignore parenthised font names for now. */
+
+       if (p[*pos] == '(')
+               goto mod;
+
+       /* Support only one-character font-names for now. */
+
+       if (p[*pos] == '\0' || (p[*pos + 1] != ' ' && p[*pos + 1] != '.')) {
+               mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse,
+                   ln, *pos, "TS %s", p + *pos - 1);
+               if (p[*pos] != '\0')
+                       (*pos)++;
+               if (p[*pos] != '\0')
+                       (*pos)++;
+               goto mod;
+       }
+
+       switch (p[(*pos)++]) {
        case '3':
-               /* FALLTHROUGH */
-       case 'b':
+       case 'B':
                cp->flags |= TBL_CELL_BOLD;
                goto mod;
        case '2':
-               /* FALLTHROUGH */
-       case 'i':
+       case 'I':
                cp->flags |= TBL_CELL_ITALIC;
                goto mod;
        case '1':
-               /* FALLTHROUGH */
-       case 'r':
+       case 'R':
                goto mod;
        default:
                mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse,
@@ -234,14 +246,11 @@ again:
 }
 
 void
-tbl_layout(struct tbl_node *tbl, int ln, const char *p)
+tbl_layout(struct tbl_node *tbl, int ln, const char *p, int pos)
 {
        struct tbl_row  *rp;
-       int              pos;
 
-       pos = 0;
        rp = NULL;
-
        for (;;) {
                /* Skip whitespace before and after each cell. */
 
@@ -265,11 +274,14 @@ tbl_layout(struct tbl_node *tbl, int ln, const char *p)
                         */
 
                        if (tbl->first_row == NULL) {
+                               tbl->first_row = tbl->last_row =
+                                   mandoc_calloc(1, sizeof(*rp));
+                       }
+                       if (tbl->first_row->first == NULL) {
                                mandoc_msg(MANDOCERR_TBLLAYOUT_NONE,
                                    tbl->parse, ln, pos, NULL);
-                               rp = mandoc_calloc(1, sizeof(*rp));
-                               cell_alloc(tbl, rp, TBL_CELL_LEFT);
-                               tbl->first_row = tbl->last_row = rp;
+                               cell_alloc(tbl, tbl->first_row,
+                                   TBL_CELL_LEFT);
                                return;
                        }
 
@@ -282,22 +294,40 @@ tbl_layout(struct tbl_node *tbl, int ln, const char *p)
                                if (tbl->opts.lvert < rp->vert)
                                        tbl->opts.lvert = rp->vert;
                                if (rp->last != NULL &&
-                                   rp->last->head == tbl->last_head &&
+                                   rp->last->col + 1 == tbl->opts.cols &&
                                    tbl->opts.rvert < rp->last->vert)
                                        tbl->opts.rvert = rp->last->vert;
+
+                               /* If the last line is empty, drop it. */
+
+                               if (rp->next != NULL &&
+                                   rp->next->first == NULL) {
+                                       free(rp->next);
+                                       rp->next = NULL;
+                                       tbl->last_row = rp;
+                               }
                        }
                        return;
                default:  /* Cell. */
                        break;
                }
 
-               if (rp == NULL) {  /* First cell on this line. */
-                       rp = mandoc_calloc(1, sizeof(*rp));
-                       if (tbl->last_row)
-                               tbl->last_row->next = rp;
-                       else
-                               tbl->first_row = rp;
-                       tbl->last_row = rp;
+               /*
+                * If the last line had at least one cell,
+                * start a new one; otherwise, continue it.
+                */
+
+               if (rp == NULL) {
+                       if (tbl->last_row == NULL ||
+                           tbl->last_row->first != NULL) {
+                               rp = mandoc_calloc(1, sizeof(*rp));
+                               if (tbl->last_row)
+                                       tbl->last_row->next = rp;
+                               else
+                                       tbl->first_row = rp;
+                               tbl->last_row = rp;
+                       } else
+                               rp = tbl->last_row;
                }
                cell(tbl, rp, ln, p, &pos);
        }
@@ -307,38 +337,19 @@ static struct tbl_cell *
 cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
 {
        struct tbl_cell *p, *pp;
-       struct tbl_head *h, *hp;
 
-       p = mandoc_calloc(1, sizeof(struct tbl_cell));
+       p = mandoc_calloc(1, sizeof(*p));
+       p->pos = pos;
 
-       if (NULL != (pp = rp->last)) {
+       if ((pp = rp->last) != NULL) {
                pp->next = p;
-               h = pp->head->next;
-       } else {
+               p->col = pp->col + 1;
+       } else
                rp->first = p;
-               h = tbl->first_head;
-       }
        rp->last = p;
 
-       p->pos = pos;
-
-       /* Re-use header. */
-
-       if (h) {
-               p->head = h;
-               return(p);
-       }
-
-       hp = mandoc_calloc(1, sizeof(struct tbl_head));
-       hp->ident = tbl->opts.cols++;
-
-       if (tbl->last_head) {
-               hp->prev = tbl->last_head;
-               tbl->last_head->next = hp;
-       } else
-               tbl->first_head = hp;
-       tbl->last_head = hp;
+       if (tbl->opts.cols <= p->col)
+               tbl->opts.cols = p->col + 1;
 
-       p->head = hp;
-       return(p);
+       return p;
 }