summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2011-01-10 14:40:30 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2011-01-10 14:40:30 +0000
commitdede963eacb17dcdbe0624bf76ab3f4045147541 (patch)
treec83ed7ba5f2d938f2f5cd04b659ac67d5da157ee
parent4f674421b17961b1c6630a984ebea196eb7eed7a (diff)
downloadmandoc-dede963eacb17dcdbe0624bf76ab3f4045147541.tar.gz
First, make extra data cells be thrown away. This makes "dp->layout"
always hold, which cleans up the table stuff a bit. Second, set a "spans" value per data cell consisting of the number of skipped TBL_CELL_SPAN layout cells. Third, make tbl_term.c understand how to skip over spanned sections when iterating over the header queue. What remains is to calculate the widths of spanned cells.
-rw-r--r--main.c4
-rw-r--r--mandoc.h5
-rw-r--r--out.c3
-rw-r--r--tbl.78
-rw-r--r--tbl_data.c29
-rw-r--r--tbl_layout.c23
-rw-r--r--tbl_term.c37
-rw-r--r--tree.c7
8 files changed, 83 insertions, 33 deletions
diff --git a/main.c b/main.c
index 499427b5..055ad2d1 100644
--- a/main.c
+++ b/main.c
@@ -178,9 +178,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"unknown escape sequence",
"unterminated quoted string",
- /* related to tables */
- "extra data cells",
-
"generic error",
/* related to tables */
@@ -191,6 +188,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"no table data cells specified",
"ignore data in cell",
"data block still open",
+ "ignoring extra data cells",
"input stack limit exceeded, infinite loop?",
"skipping bad character",
diff --git a/mandoc.h b/mandoc.h
index 8e0d7583..f32db5a4 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -100,9 +100,6 @@ enum mandocerr {
MANDOCERR_BADESCAPE, /* unknown escape sequence */
MANDOCERR_BADQUOTE, /* unterminated quoted string */
- /* related to tables */
- MANDOCERR_TBLEXTRADAT, /* extra data cells */
-
MANDOCERR_ERROR, /* ===== start of errors ===== */
/* related to tables */
@@ -113,6 +110,7 @@ enum mandocerr {
MANDOCERR_TBLNODATA, /* no table data cells specified */
MANDOCERR_TBLIGNDATA, /* ignore data in cell */
MANDOCERR_TBLBLOCK, /* data block still open */
+ MANDOCERR_TBLEXTRADAT, /* ignoring extra data cells */
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
MANDOCERR_BADCHAR, /* skipping bad character */
@@ -238,6 +236,7 @@ enum tbl_datt {
*/
struct tbl_dat {
struct tbl_cell *layout; /* layout cell: CAN BE NULL */
+ int spans; /* how many spans follow */
struct tbl_dat *next;
char *string;
enum tbl_datt pos;
diff --git a/out.c b/out.c
index 5d7ba217..1a647922 100644
--- a/out.c
+++ b/out.c
@@ -399,8 +399,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
* to data cells in the data section.
*/
for (dp = sp->first; dp; dp = dp->next) {
- if (NULL == dp->layout)
- continue;
+ assert(dp->layout);
col = &tbl->cols[dp->layout->head->ident];
tblcalc_data(tbl, col, sp->tbl, dp);
}
diff --git a/tbl.7 b/tbl.7
index fe4ca7a5..abc2ba3a 100644
--- a/tbl.7
+++ b/tbl.7
@@ -209,8 +209,12 @@ Justify a number around its last decimal point.
If the decimal point is not found on the number, it's assumed to trail
the number.
.It Cm s
-This option is not supported by
-.Xr mandoc 1 .
+Span columns from the last non-span data cell.
+It is an error if spanning columns follow a
+.Cm \-
+or
+.Cm \(ba
+cell, or come first.
.It Cm a
Left-justify a literal string and pad with one space.
.It Cm ^
diff --git a/tbl_data.c b/tbl_data.c
index 7c316aad..ecf3f1a1 100644
--- a/tbl_data.c
+++ b/tbl_data.c
@@ -37,7 +37,7 @@ data(struct tbl_node *tbl, struct tbl_span *dp,
{
struct tbl_dat *dat;
struct tbl_cell *cp;
- int sv;
+ int sv, spans;
cp = NULL;
if (dp->last && dp->last->layout)
@@ -55,12 +55,32 @@ data(struct tbl_node *tbl, struct tbl_span *dp,
TBL_CELL_SPAN == cp->pos))
cp = cp->next;
+ /*
+ * Stop processing when we reach the end of the available layout
+ * cells. This means that we have extra input.
+ */
+
+ if (NULL == cp) {
+ TBL_MSG(tbl, MANDOCERR_TBLEXTRADAT, ln, *pos);
+ /* Skip to the end... */
+ while (p[*pos])
+ (*pos)++;
+ return(1);
+ }
+
dat = mandoc_calloc(1, sizeof(struct tbl_dat));
dat->layout = cp;
dat->pos = TBL_DATA_NONE;
- if (NULL == dat->layout)
- TBL_MSG(tbl, MANDOCERR_TBLEXTRADAT, ln, *pos);
+ assert(TBL_CELL_SPAN != cp->pos);
+
+ for (spans = 0, cp = cp->next; cp; cp = cp->next)
+ if (TBL_CELL_SPAN == cp->pos)
+ spans++;
+ else
+ break;
+
+ dat->spans = spans;
if (dp->last) {
dp->last->next = dat;
@@ -101,9 +121,6 @@ data(struct tbl_node *tbl, struct tbl_span *dp,
else
dat->pos = TBL_DATA_DATA;
- if (NULL == dat->layout)
- return(1);
-
if (TBL_CELL_HORIZ == dat->layout->pos ||
TBL_CELL_DHORIZ == dat->layout->pos)
if (TBL_DATA_DATA == dat->pos && '\0' != *dat->string)
diff --git a/tbl_layout.c b/tbl_layout.c
index cc4fdfb5..ea93f645 100644
--- a/tbl_layout.c
+++ b/tbl_layout.c
@@ -197,12 +197,27 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
/*
* If a span cell is found first, raise a warning and abort the
- * parse. FIXME: recover from this somehow?
+ * parse. If a span cell is found and the last layout element
+ * isn't a "normal" layout, bail.
+ *
+ * FIXME: recover from this somehow?
*/
- if (NULL == rp->first && TBL_CELL_SPAN == c) {
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
- return(0);
+ if (TBL_CELL_SPAN == c) {
+ if (NULL == rp->first) {
+ TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ return(0);
+ } else if (rp->last)
+ switch (rp->last->pos) {
+ case (TBL_CELL_VERT):
+ case (TBL_CELL_DVERT):
+ case (TBL_CELL_HORIZ):
+ case (TBL_CELL_DHORIZ):
+ TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ return(0);
+ default:
+ break;
+ }
}
(*pos)++;
diff --git a/tbl_term.c b/tbl_term.c
index 6f8f87f3..872fc8f9 100644
--- a/tbl_term.c
+++ b/tbl_term.c
@@ -64,6 +64,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
const struct tbl_head *hp;
const struct tbl_dat *dp;
struct roffcol *col;
+ int spans;
size_t rmargin, maxrmargin;
rmargin = tp->rmargin;
@@ -115,23 +116,39 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
case (TBL_SPAN_DATA):
/* Iterate over template headers. */
dp = sp->first;
+ spans = 0;
for (hp = sp->head; hp; hp = hp->next) {
+ /*
+ * If the current data header is invoked during
+ * a spanner ("spans" > 0), don't emit anything
+ * at all.
+ */
switch (hp->pos) {
case (TBL_HEAD_VERT):
/* FALLTHROUGH */
case (TBL_HEAD_DVERT):
- tbl_vrule(tp, hp);
+ if (spans <= 0)
+ tbl_vrule(tp, hp);
continue;
case (TBL_HEAD_DATA):
break;
}
+ if (--spans >= 0)
+ continue;
+
col = &tp->tbl.cols[hp->ident];
tbl_data(tp, sp->tbl, dp, col);
- /* Go to the next data cell. */
- if (dp)
+ /*
+ * Go to the next data cell and assign the
+ * number of subsequent spans, if applicable.
+ */
+
+ if (dp) {
+ spans = dp->spans;
dp = dp->next;
+ }
}
break;
}
@@ -244,12 +261,12 @@ tbl_data(struct termp *tp, const struct tbl *tbl,
const struct tbl_dat *dp,
const struct roffcol *col)
{
- enum tbl_cellt pos;
if (NULL == dp) {
tbl_char(tp, ASCII_NBRSP, col->width);
return;
}
+ assert(dp->layout);
switch (dp->pos) {
case (TBL_DATA_NONE):
@@ -269,9 +286,7 @@ tbl_data(struct termp *tp, const struct tbl *tbl,
break;
}
- pos = dp && dp->layout ? dp->layout->pos : TBL_CELL_LEFT;
-
- switch (pos) {
+ switch (dp->layout->pos) {
case (TBL_CELL_HORIZ):
tbl_char(tp, '-', col->width);
break;
@@ -340,17 +355,15 @@ tbl_literal(struct termp *tp, const struct tbl_dat *dp,
const struct roffcol *col)
{
size_t padl, padr, ssz;
- enum tbl_cellt pos;
const char *str;
padl = padr = 0;
- pos = dp && dp->layout ? dp->layout->pos : TBL_CELL_LEFT;
- str = dp && dp->string ? dp->string : "";
+ str = dp->string ? dp->string : "";
ssz = term_len(tp, 1);
- switch (pos) {
+ switch (dp->layout->pos) {
case (TBL_CELL_LONG):
padl = ssz;
padr = col->width - term_strlen(tp, str) - ssz;
@@ -391,7 +404,7 @@ tbl_number(struct termp *tp, const struct tbl *tbl,
* and the maximum decimal; right-pad by the remaining amount.
*/
- str = dp && dp->string ? dp->string : "";
+ str = dp->string ? dp->string : "";
sz = term_strlen(tp, str);
diff --git a/tree.c b/tree.c
index 80293948..fb565d23 100644
--- a/tree.c
+++ b/tree.c
@@ -282,7 +282,12 @@ print_span(const struct tbl_span *sp, int indent)
default:
break;
}
- printf("[%s%s]", dp->string, dp->layout ? "" : "*");
+ printf("[\"%s\"", dp->string ? dp->string : "");
+ if (dp->spans)
+ printf("(%d)", dp->spans);
+ if (NULL == dp->layout)
+ putchar('*');
+ putchar(']');
if (dp->next)
putchar(' ');
}