=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.167 retrieving revision 1.169 diff -u -p -r1.167 -r1.169 --- mandoc/mdoc_macro.c 2015/02/02 15:02:49 1.167 +++ mandoc/mdoc_macro.c 2015/02/02 19:23:23 1.169 @@ -1,4 +1,4 @@ -/* $Id: mdoc_macro.c,v 1.167 2015/02/02 15:02:49 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.169 2015/02/02 19:23:23 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010, 2012-2015 Ingo Schwarze @@ -54,8 +54,8 @@ static void append_delims(struct mdoc *, int, int *, static enum mdoct lookup(struct mdoc *, enum mdoct, int, int, const char *); static int macro_or_word(MACRO_PROT_ARGS, int); -static int make_pending(struct mdoc_node *, enum mdoct, - struct mdoc *, int, int); +static void make_pending(struct mdoc *, struct mdoc_node *, + struct mdoc_node *, int, int); static int parse_rest(struct mdoc *, enum mdoct, int, int *, char *); static enum mdoct rew_alt(enum mdoct); @@ -460,92 +460,75 @@ rew_elem(struct mdoc *mdoc, enum mdoct tok) } /* - * We are trying to close a block identified by tok, + * We are trying to close the block *breaker, * but the child block *broken is still open. - * Thus, postpone closing the tok block + * Thus, postpone closing the *breaker * until the rew_pending() call closing *broken. */ -static int -make_pending(struct mdoc_node *broken, enum mdoct tok, - struct mdoc *mdoc, int line, int ppos) +static void +make_pending(struct mdoc *mdoc, struct mdoc_node *breaker, + struct mdoc_node *broken, int line, int ppos) { - struct mdoc_node *breaker; + struct mdoc_node *n; + mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, + "%s breaks %s", mdoc_macronames[breaker->tok], + mdoc_macronames[broken->tok]); + /* - * Iterate backwards, searching for the block matching tok, - * that is, the block breaking the *broken block. + * If the *broken block (Z) is already broken by a block (B) + * contained in the breaker (A), make the breaker pending + * on that inner breaker (B). Graphically, + * + * breaker=[A! broken=n=[B!->A (old broken=)[Z->B B] A] Z] + * + * In these graphics, "->" indicates the "pending" pointer and + * "!" indicates the MDOC_BREAK flag. Each of the cases gets + * one additional pointer (B->A) and one additional flag (A!). */ - for (breaker = broken->parent; breaker; breaker = breaker->parent) { - /* - * If the *broken block (Z) is already broken and we - * encounter its breaker (B), make the tok block (A) - * pending on that inner breaker (B). - * Graphically, [A breaker=[B! broken=[Z->B B] tok=A] Z] - * becomes breaker=[A broken=[B! [Z->B B] tok=A] Z] - * and finally [A! [B!->A [Z->B B] A] Z]. - * In these graphics, "->" indicates the "pending" - * pointer and "!" indicates the MDOC_BREAK flag. - * Each of the cases gets one additional pointer (B->A) - * and one additional flag (A!). - */ - if (breaker == broken->pending) { - broken = breaker; - continue; - } + for (n = broken->parent; ; n = n->parent) + if (n == broken->pending) + broken = n; + else if (n == breaker) + break; - if (REWIND_THIS != rew_dohalt(tok, MDOC_BLOCK, breaker)) - continue; - if (MDOC_BODY == broken->type) - broken = broken->parent; + /* + * Found the breaker. + * + * If another, outer breaker (X) is already pending on + * the *broken block (B), we must not clobber the link + * to the outer breaker, but make it pending on the new, + * now inner breaker (A). Graphically, + * + * [X! n=breaker=[A!->X broken=[B(->X)->A X] A] B]. + */ - /* - * Found the breaker. - * If another, outer breaker (X) is already pending on - * the *broken block (B), we must not clobber the link - * to the outer breaker, but make it pending on the - * new, now inner breaker (A). - * Graphically, [X! breaker=[A broken=[B->X X] tok=A] B] - * becomes [X! breaker=[A->X broken=[B X] tok=A] B] - * and finally [X! [A!->X [B->A X] A] B]. - */ - if (broken->pending) { - struct mdoc_node *taker; + if (broken->pending != NULL) { + n = breaker; - /* - * If the inner breaker (A) is already broken, - * too, it cannot take on the outer breaker (X) - * but must hand it on to its own breakers (Y): - * [X! [Y! breaker=[A->Y Y] broken=[B->X X] tok=A] B] - * [X! take=[Y!->X brea=[A->Y Y] brok=[B X] tok=A] B] - * and finally [X! [Y!->X [A!->Y Y] [B->A X] A] B]. - */ - taker = breaker; - while (taker->pending) - taker = taker->pending; - taker->pending = broken->pending; - } - /* - * Now we have reduced the situation to the simplest - * case, which is just breaker=[A broken=[B tok=A] B] - * and becomes [A! [B->A A] B]. + * If the inner breaker (A) is already broken, too, + * it cannot take on the outer breaker (X) but must + * hand it on to its own breakers (Y). Graphically, + * + * [X! n=[Y!->X breaker=[A!->Y Y] broken=[B(->X)->A X] A] B] */ - broken->pending = breaker; - breaker->flags |= MDOC_BREAK; - if (breaker->body != NULL) - breaker->body->flags |= MDOC_BREAK; - mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, - "%s breaks %s", mdoc_macronames[tok], - mdoc_macronames[broken->tok]); - return(1); + + while (n->pending) + n = n->pending; + n->pending = broken->pending; } /* - * Found no matching block for tok. - * Are you trying to close a block that is not open? + * Now we have reduced the situation to the simplest case: + * breaker=[A! broken=[B->A A] B]. */ - return(0); + + broken->pending = breaker; + breaker->flags |= MDOC_BREAK; + if (breaker->body != NULL) + breaker->body->flags |= MDOC_BREAK; } static void @@ -769,7 +752,7 @@ blk_exp_close(MACRO_PROT_ARGS) * rew_pending() closing out the sub-block. */ - make_pending(later, tok, mdoc, line, ppos); + make_pending(mdoc, n, later, line, ppos); /* * Mark the place where the formatting - but not @@ -1295,7 +1278,7 @@ blk_part_imp(MACRO_PROT_ARGS) if (n->type == MDOC_BLOCK && mdoc_macros[n->tok].flags & MDOC_EXPLICIT && ! (n->flags & MDOC_VALID)) { - make_pending(n, tok, mdoc, line, ppos); + make_pending(mdoc, blk, n, line, ppos); mdoc_endbody_alloc(mdoc, line, ppos, tok, body, ENDBODY_NOSPACE); return;