=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/mdoc_macro.c,v retrieving revision 1.138 retrieving revision 1.139 diff -c -r1.138 -r1.139 *** src/usr.bin/mandoc/mdoc_macro.c 2015/02/11 13:37:31 1.138 --- src/usr.bin/mandoc/mdoc_macro.c 2015/02/12 12:20:47 1.139 *************** *** 1,4 **** ! /* $OpenBSD: mdoc_macro.c,v 1.138 2015/02/11 13:37:31 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010, 2012-2015 Ingo Schwarze --- 1,4 ---- ! /* $OpenBSD: mdoc_macro.c,v 1.139 2015/02/12 12:20:47 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010, 2012-2015 Ingo Schwarze *************** *** 45,52 **** static enum mdoct lookup(struct mdoc *, enum mdoct, int, int, const char *); static int macro_or_word(MACRO_PROT_ARGS, 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); --- 45,50 ---- *************** *** 283,297 **** rew_pending(struct mdoc *mdoc, const struct mdoc_node *n) { ! rew_last(mdoc, n); ! ! if (n->type != MDOC_BLOCK) ! return; ! ! while ((n = n->pending) != NULL) { rew_last(mdoc, n); ! if (n->type == MDOC_HEAD) mdoc_body_alloc(mdoc, n->line, n->pos, n->tok); } } --- 281,314 ---- rew_pending(struct mdoc *mdoc, const struct mdoc_node *n) { ! for (;;) { rew_last(mdoc, n); ! ! switch (n->type) { ! case MDOC_HEAD: mdoc_body_alloc(mdoc, n->line, n->pos, n->tok); + return; + case MDOC_BLOCK: + break; + default: + return; + } + + if ( ! (n->flags & MDOC_BROKEN)) + return; + + for (;;) { + if ((n = n->parent) == NULL) + return; + + if (n->type == MDOC_BLOCK || + n->type == MDOC_HEAD) { + if (n->flags & MDOC_ENDED) + break; + else + return; + } + } } } *************** *** 355,432 **** } /* - * We are trying to close the block *breaker, - * but the child block *broken is still open. - * Thus, postpone closing the *breaker - * until the rew_pending() call closing *broken. - */ - static void - make_pending(struct mdoc *mdoc, struct mdoc_node *breaker, - struct mdoc_node *broken, int line, int ppos) - { - struct mdoc_node *n; - - mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, - "%s breaks %s", mdoc_macronames[breaker->tok], - mdoc_macronames[broken->tok]); - - /* - * 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 (n = broken->parent; ; n = n->parent) - if (n == broken->pending) - broken = n; - else if (n == breaker) - break; - - /* - * 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]. - */ - - 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). Graphically, - * - * [X! n=[Y!->X breaker=[A!->Y Y] broken=[B(->X)->A X] A] B] - */ - - while (n->pending) - n = n->pending; - n->pending = broken->pending; - } - - /* - * Now we have reduced the situation to the simplest case: - * breaker=[A! broken=[B->A A] B]. - */ - - broken->pending = breaker; - breaker->flags |= MDOC_BREAK; - if (breaker->body != NULL) - breaker->body->flags |= MDOC_BREAK; - } - - /* * Allocate a word and check whether it's punctuation or not. * Punctuation consists of those tokens found in mdoc_isdelim(). */ --- 372,377 ---- *************** *** 567,574 **** atok = rew_alt(tok); body = endbody = itblk = later = NULL; for (n = mdoc->last; n; n = n->parent) { ! if (n->flags & (MDOC_VALID | MDOC_BREAK)) continue; /* Remember the start of our own body. */ --- 512,522 ---- atok = rew_alt(tok); body = endbody = itblk = later = NULL; for (n = mdoc->last; n; n = n->parent) { ! if (n->flags & MDOC_ENDED) { ! if ( ! (n->flags & MDOC_VALID)) ! n->flags |= MDOC_BROKEN; continue; + } /* Remember the start of our own body. */ *************** *** 603,622 **** * When there is a pending sub block, postpone * closing out the current block until the * rew_pending() closing out the sub-block. - */ - - make_pending(mdoc, n, later, line, ppos); - if (tok == MDOC_El) - itblk->flags |= MDOC_BREAK; - - /* * Mark the place where the formatting - but not * the scope - of the current block ends. */ endbody = mdoc_endbody_alloc(mdoc, line, ppos, atok, body, ENDBODY_SPACE); /* * If a block closing macro taking arguments * breaks another block, put the arguments --- 551,571 ---- * When there is a pending sub block, postpone * closing out the current block until the * rew_pending() closing out the sub-block. * Mark the place where the formatting - but not * the scope - of the current block ends. */ + mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, + line, ppos, "%s breaks %s", + mdoc_macronames[atok], + mdoc_macronames[later->tok]); + endbody = mdoc_endbody_alloc(mdoc, line, ppos, atok, body, ENDBODY_SPACE); + if (tok == MDOC_El) + itblk->flags |= MDOC_ENDED | MDOC_BROKEN; + /* * If a block closing macro taking arguments * breaks another block, put the arguments *************** *** 635,648 **** continue; } ! /* ! * When finding an open sub block, remember the last ! * open explicit block, or, in case there are only ! * implicit ones, the first open implicit block. ! */ ! if (later == NULL || ! ! (mdoc_macros[later->tok].flags & MDOC_EXPLICIT)) later = n; } --- 584,593 ---- continue; } ! /* Breaking an open sub block. */ ! n->flags |= MDOC_BROKEN; ! if (later == NULL) later = n; } *************** *** 921,929 **** blk = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { ! if (n->flags & (MDOC_VALID | MDOC_BREAK) || ! n->type != MDOC_BLOCK) continue; if (tok == MDOC_It && n->tok == MDOC_Bl) { if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, --- 866,879 ---- blk = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { ! if (n->flags & MDOC_ENDED) { ! if ( ! (n->flags & MDOC_VALID)) ! n->flags |= MDOC_BROKEN; continue; + } + if (n->type != MDOC_BLOCK) + continue; + if (tok == MDOC_It && n->tok == MDOC_Bl) { if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, *************** *** 1129,1141 **** * sub-block. */ for (n = mdoc->last; n && n != head; n = n->parent) { if (n->type == MDOC_BLOCK && ! mdoc_macros[n->tok].flags & MDOC_EXPLICIT && ! ! (n->flags & MDOC_VALID)) { ! n->pending = head; ! return; } } /* Close out scopes to remain in a consistent state. */ --- 1079,1097 ---- * sub-block. */ for (n = mdoc->last; n && n != head; n = n->parent) { + if (n->flags & MDOC_ENDED) { + if ( ! (n->flags & MDOC_VALID)) + n->flags |= MDOC_BROKEN; + continue; + } if (n->type == MDOC_BLOCK && ! mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { ! n->flags = MDOC_BROKEN; ! head->flags = MDOC_ENDED; } } + if (head->flags & MDOC_ENDED) + return; /* Close out scopes to remain in a consistent state. */ *************** *** 1208,1223 **** for (n = mdoc->last; n && n != body && n != blk->parent; n = n->parent) { if (n->type == MDOC_BLOCK && ! mdoc_macros[n->tok].flags & MDOC_EXPLICIT && ! ! (n->flags & MDOC_VALID)) { ! make_pending(mdoc, blk, n, line, ppos); ! mdoc_endbody_alloc(mdoc, line, ppos, ! tok, body, ENDBODY_NOSPACE); ! return; } } assert(n == body); rew_last(mdoc, body); if (nl) append_delims(mdoc, line, pos, buf); --- 1164,1191 ---- for (n = mdoc->last; n && n != body && n != blk->parent; n = n->parent) { + if (n->flags & MDOC_ENDED) { + if ( ! (n->flags & MDOC_VALID)) + n->flags |= MDOC_BROKEN; + continue; + } if (n->type == MDOC_BLOCK && ! mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { ! n->flags |= MDOC_BROKEN; ! if ( ! (body->flags & MDOC_ENDED)) { ! mandoc_vmsg(MANDOCERR_BLK_NEST, ! mdoc->parse, line, ppos, ! "%s breaks %s", mdoc_macronames[tok], ! mdoc_macronames[n->tok]); ! mdoc_endbody_alloc(mdoc, line, ppos, ! tok, body, ENDBODY_NOSPACE); ! } } } assert(n == body); + if (body->flags & MDOC_ENDED) + return; + rew_last(mdoc, body); if (nl) append_delims(mdoc, line, pos, buf); *************** *** 1480,1486 **** body = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { ! if (n->flags & (MDOC_VALID | MDOC_BREAK)) continue; if (n->tok == MDOC_It && n->type == MDOC_BODY) body = n; --- 1448,1454 ---- body = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { ! if (n->flags & MDOC_ENDED) continue; if (n->tok == MDOC_It && n->type == MDOC_BODY) body = n;