summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2010-06-30 04:05:02 +0000
committerIngo Schwarze <schwarze@openbsd.org>2010-06-30 04:05:02 +0000
commit25b3bcbde4cab98bd4a3175d20053187201d2dce (patch)
tree87ee4f656dcc58da214d2b0190916785fae6b479
parent72452c8d8f8859768d309309a7ebca1cb366e063 (diff)
downloadmandoc-25b3bcbde4cab98bd4a3175d20053187201d2dce.tar.gz
Closing of full blocks (Bd Bf Bk Bl It Fo Nd Rs Sh Ss) may never be
delayed: It must either succeed right away or fail outright. As noticed by Kristaps, neglecting to fail properly when required could make invalid input screw up the syntax tree and ultimately trigger assertions in other, unrelated parts of the program. This fix tested by and OK by kristaps@. While here, comment the rather tricky function rew_dohalt(). This function will probably need more tweaks later on.
-rw-r--r--mdoc_macro.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/mdoc_macro.c b/mdoc_macro.c
index f292affc..10baaec7 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -335,21 +335,44 @@ rew_dohalt(enum mdoct tok, enum mdoc_type type,
const struct mdoc_node *p)
{
+ /*
+ * No matching token, no delimiting block, no broken block.
+ * This can happen when full implicit macros are called for
+ * the first time but try to rewind their previous
+ * instance anyway.
+ */
if (MDOC_ROOT == p->type)
return(MDOC_BLOCK == type &&
MDOC_EXPLICIT & mdoc_macros[tok].flags ?
REWIND_ERROR : REWIND_NONE);
+
+ /*
+ * When starting to rewind, skip plain text
+ * and nodes that have already been rewound.
+ */
if (MDOC_TEXT == p->type || MDOC_VALID & p->flags)
return(REWIND_MORE);
+ /*
+ * The easiest case: Found a matching token.
+ * This applies to both blocks and elements.
+ */
tok = rew_alt(tok);
if (tok == p->tok)
return(p->end ? REWIND_NONE :
type == p->type ? REWIND_THIS : REWIND_MORE);
+ /*
+ * While elements do require rewinding for themselves,
+ * they never affect rewinding of other nodes.
+ */
if (MDOC_ELEM == p->type)
return(REWIND_MORE);
+ /*
+ * Blocks delimited by our target token get REWIND_MORE.
+ * Blocks delimiting our target token get REWIND_NONE.
+ */
switch (tok) {
case (MDOC_Bl):
if (MDOC_It == p->tok)
@@ -384,9 +407,25 @@ rew_dohalt(enum mdoct tok, enum mdoc_type type,
break;
}
- return(p->end || (MDOC_BLOCK == p->type &&
- ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) ?
- REWIND_MORE : REWIND_LATER);
+ /*
+ * Default block rewinding rules.
+ * In particular, always skip block end markers.
+ */
+ if (p->end || (MDOC_BLOCK == p->type &&
+ ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)))
+ return(REWIND_MORE);
+
+ /*
+ * Partial blocks allow delayed rewinding by default.
+ */
+ if (&blk_full != mdoc_macros[tok].fp)
+ return (REWIND_LATER);
+
+ /*
+ * Full blocks can only be rewound when matching
+ * or when there is an explicit rule.
+ */
+ return(REWIND_ERROR);
}