- struct tm tm;
- char buf[5];
- char *p;
- size_t nsz;
-
- assert(sz > 1);
- localtime_r(&t, &tm);
-
- p = dst;
- nsz = 0;
-
- dst[0] = '\0';
-
- if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
- return;
-
- p += (int)nsz;
- sz -= nsz;
-
- if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
- return;
-
- nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
-
- if (nsz >= sz)
- return;
-
- p += (int)nsz;
- sz -= nsz;
-
- (void)strftime(p, sz, "%Y", &tm);
-}
-
-
-/*
- * Returns length of parsed string (the leading "\" should NOT be
- * included). This can be zero if the current character is the nil
- * terminator. "d" is set to the type of parsed decorator, which may
- * have an adjoining "word" of size "sz" (e.g., "(ab" -> "ab", 2).
- */
-int
-a2roffdeco(enum roffdeco *d,
- const char **word, size_t *sz)
-{
- int j, type, term, lim;
- const char *wp, *sp;
-
- *d = DECO_NONE;
- wp = *word;
- type = 1;
-
- switch (*wp) {
- case ('\0'):
- return(0);
-
- case ('('):
- if ('\0' == *(++wp))
- return(1);
- if ('\0' == *(wp + 1))
- return(2);
-
- *d = DECO_SPECIAL;
- *sz = 2;
- *word = wp;
- return(3);
-
- case ('*'):
- switch (*(++wp)) {
- case ('\0'):
- return(1);
-
- case ('('):
- if ('\0' == *(++wp))
- return(2);
- if ('\0' == *(wp + 1))
- return(3);
-
- *d = DECO_RESERVED;
- *sz = 2;
- *word = wp;
- return(4);
-
- case ('['):
- type = 0;
- break;
-
- default:
- *d = DECO_RESERVED;
- *sz = 1;
- *word = wp;
- return(2);
- }
- break;
-
- case ('s'):
- sp = wp;
- if ('\0' == *(++wp))
- return(1);
-
- C2LIM(*wp, lim);
- C2TERM(*wp, term);
-
- if (term)
- wp++;
-
- *word = wp;
-
- if (*wp == '+' || *wp == '-')
- ++wp;
-
- switch (*wp) {
- case ('\''):
- /* FALLTHROUGH */
- case ('['):
- /* FALLTHROUGH */
- case ('('):
- if (term)
- return((int)(wp - sp));
-
- C2LIM(*wp, lim);
- C2TERM(*wp, term);
- wp++;
- break;
- default:
- break;
- }
-
- if ( ! isdigit((u_char)*wp))
- return((int)(wp - sp));
-
- for (j = 0; isdigit((u_char)*wp); j++) {
- if (lim && j >= lim)
- break;
- ++wp;
- }
-
- if (term && term < 3) {
- if (1 == term && *wp != '\'')
- return((int)(wp - sp));
- if (2 == term && *wp != ']')
- return((int)(wp - sp));
- ++wp;
+ const struct tbl_dat *dp;
+ const struct tbl_head *hp;
+ struct roffcol *col;
+ int spans;
+
+ /*
+ * Allocate the master column specifiers. These will hold the
+ * widths and decimal positions for all cells in the column. It
+ * must be freed and nullified by the caller.
+ */
+
+ assert(NULL == tbl->cols);
+ tbl->cols = mandoc_calloc
+ ((size_t)sp->tbl->cols, sizeof(struct roffcol));
+
+ hp = sp->head;
+
+ for ( ; sp; sp = sp->next) {
+ if (TBL_SPAN_DATA != sp->pos)
+ continue;
+ spans = 1;
+ /*
+ * Account for the data cells in the layout, matching it
+ * to data cells in the data section.
+ */
+ for (dp = sp->first; dp; dp = dp->next) {
+ /* Do not used spanned cells in the calculation. */
+ if (0 < --spans)
+ continue;
+ spans = dp->spans;
+ if (1 < spans)
+ continue;
+ assert(dp->layout);
+ col = &tbl->cols[dp->layout->head->ident];
+ tblcalc_data(tbl, col, sp->tbl, dp);