-
-/*
- * Rewinding to tok, how do we have to handle *p?
- * REWIND_NONE: *p would delimit tok, but no tok scope is open
- * inside *p, so there is no need to rewind anything at all.
- * REWIND_THIS: *p matches tok, so rewind *p and nothing else.
- * REWIND_MORE: *p is implicit, rewind it and keep searching for tok.
- * REWIND_LATER: *p is explicit and still open, postpone rewinding.
- * REWIND_ERROR: No tok block is open at all.
- */
-static enum rew
-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)
- return(REWIND_MORE);
- break;
- case (MDOC_It):
- if (MDOC_BODY == p->type && MDOC_Bl == p->tok)
- return(REWIND_NONE);
- break;
- /*
- * XXX Badly nested block handling still fails badly
- * when one block is breaking two blocks of the same type.
- * This is an incomplete and extremely ugly workaround,
- * required to let the OpenBSD tree build.
- */
- case (MDOC_Oo):
- if (MDOC_Op == p->tok)
- return(REWIND_MORE);
- break;
- case (MDOC_Nm):
- return(REWIND_NONE);
- case (MDOC_Nd):
- /* FALLTHROUGH */
- case (MDOC_Ss):
- if (MDOC_BODY == p->type && MDOC_Sh == p->tok)
- return(REWIND_NONE);
- /* FALLTHROUGH */
- case (MDOC_Sh):
- if (MDOC_Nd == p->tok || MDOC_Ss == p->tok ||
- MDOC_Sh == p->tok)
- return(REWIND_MORE);
- break;
- default:
- break;
- }
-
- /*
- * Default block rewinding rules.
- * In particular, always skip block end markers,
- * and let all blocks rewind Nm children.
- */
- if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok ||
- (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);
-}
-
-
-static int