aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/mdoc_macro.c
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
commit302ff93bdc843162c49bacd6b5b4d5eda4b1363b (patch)
treead2d07b35b547dac9521af880034141dca50d3b7 /mdoc_macro.c
parenta1e139e18be826b9f2602662943487a88e0deb85 (diff)
downloadmandoc-302ff93bdc843162c49bacd6b5b4d5eda4b1363b.tar.gz
mandoc-302ff93bdc843162c49bacd6b5b4d5eda4b1363b.tar.zst
mandoc-302ff93bdc843162c49bacd6b5b4d5eda4b1363b.zip
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.
Diffstat (limited to 'mdoc_macro.c')
-rw-r--r--mdoc_macro.c47
1 files changed, 43 insertions, 4 deletions
diff --git a/mdoc_macro.c b/mdoc_macro.c
index 59739af8..20ce96fb 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_macro.c,v 1.85 2010/06/29 19:45:06 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.86 2010/06/30 04:05:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -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);
}