-row: /*
- * EBNF describing this section:
- *
- * row ::= row_list [:space:]* [.]?[\n]
- * row_list ::= [:space:]* row_elem row_tail
- * row_tail ::= [:space:]*[,] row_list |
- * epsilon
- * row_elem ::= [\t\ ]*[:alpha:]+
- */
-
- rp = mandoc_calloc(1, sizeof(struct tbl_row));
- if (tbl->last_row) {
- tbl->last_row->next = rp;
- tbl->last_row = rp;
- } else
- tbl->last_row = tbl->first_row = rp;
-
-cell:
- while (isspace((unsigned char)p[*pos]))
- (*pos)++;
-
- /* Safely exit layout context. */
+ rp = NULL;
+ for (;;) {
+ /* Skip whitespace before and after each cell. */
+
+ while (p[pos] == ' ' || p[pos] == '\t')
+ pos++;
+
+ switch (p[pos]) {
+ case ',': /* Next row on this input line. */
+ pos++;
+ rp = NULL;
+ continue;
+ case '\0': /* Next row on next input line. */
+ return;
+ case '.': /* End of layout. */
+ pos++;
+ tbl->part = TBL_PART_DATA;
+
+ /*
+ * When the layout is completely empty,
+ * default to one left-justified column.
+ */
+
+ 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,
+ ln, pos, NULL);
+ cell_alloc(tbl, tbl->first_row,
+ TBL_CELL_LEFT);
+ if (tbl->opts.lvert < tbl->first_row->vert)
+ tbl->opts.lvert = tbl->first_row->vert;
+ return;
+ }
+
+ /*
+ * Search for the widest line
+ * along the left and right margins.
+ */
+
+ for (rp = tbl->first_row; rp; rp = rp->next) {
+ if (tbl->opts.lvert < rp->vert)
+ tbl->opts.lvert = rp->vert;
+ if (rp->last != NULL &&
+ 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;
+ }