- /* NOTREACHED */
-}
-
-/*
- * 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_FORCE: *p is explicit, but tok is full, force rewinding *p.
- * 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_ROOT == p->parent->type)
- return(REWIND_THIS);
- 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.
- * Do not warn again when closing a block,
- * since closing the body already warned.
- */
- if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok ||
- MDOC_BLOCK == type || (MDOC_BLOCK == p->type &&
- ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)))
- return(REWIND_MORE);
-
- /*
- * By default, closing out full blocks
- * forces closing of broken explicit blocks,
- * while closing out partial blocks
- * allows delayed rewinding by default.
- */
- return (&blk_full == mdoc_macros[tok].fp ?
- REWIND_FORCE : REWIND_LATER);