=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.205 retrieving revision 1.213 diff -u -p -r1.205 -r1.213 --- mandoc/mdoc_macro.c 2015/10/17 00:21:07 1.205 +++ mandoc/mdoc_macro.c 2017/02/11 13:24:12 1.213 @@ -1,7 +1,7 @@ -/* $Id: mdoc_macro.c,v 1.205 2015/10/17 00:21:07 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.213 2017/02/11 13:24:12 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons - * Copyright (c) 2010, 2012-2015 Ingo Schwarze + * Copyright (c) 2010, 2012-2016 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -50,6 +50,8 @@ static int find_pending(struct roff_man *, int, int, struct roff_node *); static int lookup(struct roff_man *, int, int, int, const char *); static int macro_or_word(MACRO_PROT_ARGS, int); +static void break_intermediate(struct roff_node *, + struct roff_node *); static int parse_rest(struct roff_man *, int, int, int *, char *); static int rew_alt(int); static void rew_elem(struct roff_man *, int); @@ -216,7 +218,7 @@ mdoc_endparse(struct roff_man *mdoc) /* Scan for open explicit scopes. */ - n = mdoc->last->flags & MDOC_VALID ? + n = mdoc->last->flags & NODE_VALID ? mdoc->last->parent : mdoc->last; for ( ; n; n = n->parent) @@ -228,6 +230,7 @@ mdoc_endparse(struct roff_man *mdoc) /* Rewind to the first. */ rew_last(mdoc, mdoc->first); + mdoc_state_reset(mdoc); } /* @@ -262,25 +265,18 @@ lookup(struct roff_man *mdoc, int from, int line, int static void rew_last(struct roff_man *mdoc, const struct roff_node *to) { - struct roff_node *np; - if (to->flags & MDOC_VALID) + if (to->flags & NODE_VALID) return; while (mdoc->last != to) { - /* - * Save the parent here, because we may delete the - * mdoc->last node in the post-validation phase and reset - * it to mdoc->last->parent, causing a step in the closing - * out to be lost. - */ - np = mdoc->last->parent; - mdoc_valid_post(mdoc); - mdoc->last = np; - assert(mdoc->last); + mdoc_state(mdoc, mdoc->last); + mdoc->last->flags |= NODE_VALID | NODE_ENDED; + mdoc->last = mdoc->last->parent; } + mdoc_state(mdoc, mdoc->last); + mdoc->last->flags |= NODE_VALID | NODE_ENDED; mdoc->next = ROFF_NEXT_SIBLING; - mdoc_valid_post(mdoc); } /* @@ -298,13 +294,13 @@ rew_pending(struct roff_man *mdoc, const struct roff_n case ROFFT_HEAD: roff_body_alloc(mdoc, n->line, n->pos, n->tok); - return; + break; case ROFFT_BLOCK: break; default: return; } - if ( ! (n->flags & MDOC_BROKEN)) + if ( ! (n->flags & NODE_BROKEN)) return; } else n = mdoc->last; @@ -315,7 +311,7 @@ rew_pending(struct roff_man *mdoc, const struct roff_n if (n->type == ROFFT_BLOCK || n->type == ROFFT_HEAD) { - if (n->flags & MDOC_ENDED) + if (n->flags & NODE_ENDED) break; else return; @@ -382,6 +378,16 @@ rew_elem(struct roff_man *mdoc, int tok) rew_last(mdoc, n); } +static void +break_intermediate(struct roff_node *n, struct roff_node *breaker) +{ + while (n != breaker) { + if ( ! (n->flags & NODE_VALID)) + n->flags |= NODE_BROKEN; + n = n->parent; + } +} + /* * If there is an open sub-block of the target requiring * explicit close-out, postpone closing out the target until @@ -396,18 +402,16 @@ find_pending(struct roff_man *mdoc, int tok, int line, irc = 0; for (n = mdoc->last; n != NULL && n != target; n = n->parent) { - if (n->flags & MDOC_ENDED) { - if ( ! (n->flags & MDOC_VALID)) - n->flags |= MDOC_BROKEN; + if (n->flags & NODE_ENDED) continue; - } if (n->type == ROFFT_BLOCK && mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { irc = 1; - n->flags = MDOC_BROKEN; + break_intermediate(mdoc->last, n); + n->flags |= NODE_BROKEN; if (target->type == ROFFT_HEAD) - target->flags = MDOC_ENDED; - else if ( ! (target->flags & MDOC_ENDED)) { + target->flags |= NODE_ENDED; + else if ( ! (target->flags & NODE_ENDED)) { mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, "%s breaks %s", mdoc_macronames[tok], @@ -450,11 +454,11 @@ dword(struct roff_man *mdoc, int line, int col, const */ if (d == DELIM_OPEN) - mdoc->last->flags |= MDOC_DELIMO; + mdoc->last->flags |= NODE_DELIMO; else if (d == DELIM_CLOSE && ! (mdoc->flags & MDOC_NODELIMC) && mdoc->last->parent->tok != MDOC_Fd) - mdoc->last->flags |= MDOC_DELIMC; + mdoc->last->flags |= NODE_DELIMC; mdoc->flags &= ~MDOC_NODELIMC; } @@ -487,7 +491,7 @@ append_delims(struct roff_man *mdoc, int line, int *po */ if (mandoc_eos(p, strlen(p))) - mdoc->last->flags |= MDOC_EOS; + mdoc->last->flags |= NODE_EOS; } } @@ -555,30 +559,46 @@ blk_exp_close(MACRO_PROT_ARGS) break; } + /* Search backwards for the beginning of our own body. */ + + atok = rew_alt(tok); + body = NULL; + for (n = mdoc->last; n; n = n->parent) { + if (n->flags & NODE_ENDED || n->tok != atok || + n->type != ROFFT_BODY || n->end != ENDBODY_NOT) + continue; + body = n; + break; + } + /* * Search backwards for beginnings of blocks, * both of our own and of pending sub-blocks. */ - atok = rew_alt(tok); - body = endbody = itblk = later = NULL; + 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; + if (n->flags & NODE_ENDED) continue; - } - /* Remember the start of our own body. */ + /* + * Mismatching end macros can never break anything + * and we only care about the breaking of BLOCKs. + */ - if (n->type == ROFFT_BODY && atok == n->tok) { - if (n->end == ENDBODY_NOT) - body = n; + if (body == NULL || n->type != ROFFT_BLOCK) continue; - } - if (n->type != ROFFT_BLOCK || n->tok == MDOC_Nm) + /* + * SYNOPSIS name blocks can not be broken themselves, + * but they do get broken together with a broken child. + */ + + if (n->tok == MDOC_Nm) { + if (later != NULL) + n->flags |= NODE_BROKEN | NODE_ENDED; continue; + } if (n->tok == MDOC_It) { itblk = n; @@ -586,7 +606,6 @@ blk_exp_close(MACRO_PROT_ARGS) } if (atok == n->tok) { - assert(body); /* * Found the start of our own block. @@ -615,7 +634,7 @@ blk_exp_close(MACRO_PROT_ARGS) atok, body, ENDBODY_SPACE); if (tok == MDOC_El) - itblk->flags |= MDOC_ENDED | MDOC_BROKEN; + itblk->flags |= NODE_ENDED | NODE_BROKEN; /* * If a block closing macro taking arguments @@ -637,7 +656,8 @@ blk_exp_close(MACRO_PROT_ARGS) /* Breaking an open sub block. */ - n->flags |= MDOC_BROKEN; + break_intermediate(mdoc->last, body); + n->flags |= NODE_BROKEN; if (later == NULL) later = n; } @@ -645,8 +665,6 @@ blk_exp_close(MACRO_PROT_ARGS) if (body == NULL) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse, line, ppos, mdoc_macronames[tok]); - if (later != NULL) - later->flags &= ~MDOC_BROKEN; if (maxargs && endbody == NULL) { /* * Stray .Ec without previous .Eo: @@ -703,15 +721,16 @@ blk_exp_close(MACRO_PROT_ARGS) } if (n != NULL) { - if (ntok != TOKEN_NONE && n->flags & MDOC_BROKEN) { + pending = 0; + if (ntok != TOKEN_NONE && n->flags & NODE_BROKEN) { target = n; do target = target->parent; - while ( ! (target->flags & MDOC_ENDED)); - pending = find_pending(mdoc, ntok, line, ppos, - target); - } else - pending = 0; + while ( ! (target->flags & NODE_ENDED)); + if ( ! (target->flags & NODE_VALID)) + pending = find_pending(mdoc, ntok, + line, ppos, target); + } if ( ! pending) rew_pending(mdoc, n); } @@ -766,7 +785,7 @@ in_line(MACRO_PROT_ARGS) if (ac == ARGS_EOLN) { if (d == DELIM_OPEN) - mdoc->last->flags &= ~MDOC_DELIMO; + mdoc->last->flags &= ~NODE_DELIMO; break; } @@ -860,7 +879,7 @@ in_line(MACRO_PROT_ARGS) */ if (firstarg && d == DELIM_CLOSE && !nc) - mdoc->last->flags &= ~MDOC_DELIMC; + mdoc->last->flags &= ~NODE_DELIMC; firstarg = 0; /* @@ -923,9 +942,9 @@ blk_full(MACRO_PROT_ARGS) 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; + if (n->flags & NODE_ENDED) { + if ( ! (n->flags & NODE_VALID)) + n->flags |= NODE_BROKEN; continue; } if (n->type != ROFFT_BLOCK) @@ -984,7 +1003,7 @@ blk_full(MACRO_PROT_ARGS) /* Close out prior implicit scopes. */ - rew_last(mdoc, n); + rew_pending(mdoc, n); } /* Skip items outside lists. */ @@ -1126,7 +1145,7 @@ blk_full(MACRO_PROT_ARGS) break; } - if (blk->flags & MDOC_VALID) + if (blk->flags & NODE_VALID) return; if (head == NULL) head = roff_head_alloc(mdoc, line, ppos, tok); @@ -1461,11 +1480,11 @@ phrase_ta(MACRO_PROT_ARGS) body = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { - if (n->flags & MDOC_ENDED) + if (n->flags & NODE_ENDED) continue; if (n->tok == MDOC_It && n->type == ROFFT_BODY) body = n; - if (n->tok == MDOC_Bl) + if (n->tok == MDOC_Bl && n->end == ENDBODY_NOT) break; }