summaryrefslogtreecommitdiffstats
path: root/roff.c
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2010-12-06 13:25:25 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2010-12-06 13:25:25 +0000
commit3b30acd05567b2083b205cf8d1dfc5548ba0df39 (patch)
tree4a4dd744e9054b35565ec4712b59443d171a40d0 /roff.c
parent8c61f2c921a13b11e670f0f4a8195c1b11045c8d (diff)
downloadmandoc-3b30acd05567b2083b205cf8d1dfc5548ba0df39.tar.gz
Track down a bug of empty `de XX' macros causing uncertain behaviour by
returning empty strings in roff_getstrn() instead of NULL. This caused maddeningly irregular segfaults in the pod2man preamble for `de IX'. But only on DEC alpha. Also integrate the kinda-probably-safe assertion relaxation in term.c, field-tested by schwarze@. This allows ALL [unpreprocessed] base and xenocara manuals for all BSD systems to run without segfault.
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/roff.c b/roff.c
index 09a68991..c0889560 100644
--- a/roff.c
+++ b/roff.c
@@ -463,8 +463,10 @@ roff_parseln(struct roff *r, int ln, char **bufp,
if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos)))
return(ROFF_CONT);
- ROFF_DEBUG("roff: intercept new-scope: %s, [%s]\n",
- roffs[t].name, &(*bufp)[pos]);
+ ROFF_DEBUG("roff: intercept new-scope: [%s], [%s]\n",
+ ROFF_USERDEF == t ? r->current_string : roffs[t].name,
+ &(*bufp)[pos]);
+
assert(roffs[t].proc);
return((*roffs[t].proc)
(r, t, bufp, szp,
@@ -650,6 +652,12 @@ roff_block(ROFF_ARGS)
(*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL);
return(ROFF_IGN);
}
+
+ /*
+ * Re-write `de1', since we don't really care about
+ * groff's strange compatibility mode, into `de'.
+ */
+
if (ROFF_de1 == tok)
tok = ROFF_de;
if (ROFF_de == tok)
@@ -657,8 +665,10 @@ roff_block(ROFF_ARGS)
else
(*r->msg)(MANDOCERR_REQUEST, r->data, ln, ppos,
roffs[tok].name);
+
while ((*bufp)[pos] && ' ' != (*bufp)[pos])
pos++;
+
while (' ' == (*bufp)[pos])
(*bufp)[pos++] = '\0';
}
@@ -670,14 +680,18 @@ roff_block(ROFF_ARGS)
* with the same name, if there is one. New content will be
* added from roff_block_text() in multiline mode.
*/
+
if (ROFF_de == tok)
- roff_setstr(r, name, "", 0);
+ roff_setstr(r, name, NULL, 0);
if ('\0' == (*bufp)[pos])
return(ROFF_IGN);
+ /* If present, process the custom end-of-line marker. */
+
sv = pos;
- while ((*bufp)[pos] && ' ' != (*bufp)[pos] &&
+ while ((*bufp)[pos] &&
+ ' ' != (*bufp)[pos] &&
'\t' != (*bufp)[pos])
pos++;
@@ -699,8 +713,7 @@ roff_block(ROFF_ARGS)
r->last->end[(int)sz] = '\0';
if ((*bufp)[pos])
- if ( ! (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL))
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL);
return(ROFF_IGN);
}
@@ -933,9 +946,8 @@ roff_cond(ROFF_ARGS)
*/
if ('\0' == (*bufp)[pos] && sv != pos) {
- if ((*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL))
- return(ROFF_IGN);
- return(ROFF_ERR);
+ (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL);
+ return(ROFF_IGN);
}
roffnode_push(r, tok, NULL, ln, ppos);