=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.204 retrieving revision 1.209 diff -u -p -r1.204 -r1.209 --- mandoc/mdoc_macro.c 2015/10/15 22:27:24 1.204 +++ mandoc/mdoc_macro.c 2016/08/20 17:59:34 1.209 @@ -1,7 +1,7 @@ -/* $Id: mdoc_macro.c,v 1.204 2015/10/15 22:27:24 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.209 2016/08/20 17:59:34 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 @@ -228,6 +228,7 @@ mdoc_endparse(struct roff_man *mdoc) /* Rewind to the first. */ rew_last(mdoc, mdoc->first); + mdoc_state_reset(mdoc); } /* @@ -239,6 +240,10 @@ lookup(struct roff_man *mdoc, int from, int line, int { int res; + if (mdoc->flags & MDOC_PHRASEQF) { + mdoc->flags &= ~MDOC_PHRASEQF; + return TOKEN_NONE; + } if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) { res = mdoc_hash_find(p); if (res != TOKEN_NONE) { @@ -258,25 +263,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) 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 |= MDOC_VALID | MDOC_ENDED; + mdoc->last = mdoc->last->parent; } + mdoc_state(mdoc, mdoc->last); + mdoc->last->flags |= MDOC_VALID | MDOC_ENDED; mdoc->next = ROFF_NEXT_SIBLING; - mdoc_valid_post(mdoc); } /* @@ -294,7 +292,7 @@ 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: @@ -551,13 +549,24 @@ 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 & MDOC_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)) @@ -565,17 +574,17 @@ blk_exp_close(MACRO_PROT_ARGS) continue; } - /* Remember the start of our own body. */ + /* + * Mismatching end macros can never break anything, + * SYNOPSIS name blocks can never be broken, + * 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->tok == MDOC_Nm || + n->type != ROFFT_BLOCK) continue; - } - if (n->type != ROFFT_BLOCK || n->tok == MDOC_Nm) - continue; - if (n->tok == MDOC_It) { itblk = n; continue; @@ -641,8 +650,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: @@ -1030,26 +1037,39 @@ blk_full(MACRO_PROT_ARGS) if (tok == MDOC_Bk) mdoc->flags |= MDOC_KEEP; - ac = ARGS_PEND; + ac = ARGS_EOLN; for (;;) { + + /* + * If we are right after a tab character, + * do not parse the first word for macros. + */ + + if (mdoc->flags & MDOC_PHRASEQN) { + mdoc->flags &= ~MDOC_PHRASEQN; + mdoc->flags |= MDOC_PHRASEQF; + } + la = *pos; lac = ac; ac = mdoc_args(mdoc, line, pos, buf, tok, &p); if (ac == ARGS_EOLN) { - if (lac != ARGS_PPHRASE && lac != ARGS_PHRASE) + if (lac != ARGS_PHRASE || + ! (mdoc->flags & MDOC_PHRASEQF)) break; + /* - * This is necessary: if the last token on a - * line is a `Ta' or tab, then we'll get - * ARGS_EOLN, so we must be smart enough to - * reopen our scope if the last parse was a - * phrase or partial phrase. + * This line ends in a tab; start the next + * column now, with a leading blank. */ + if (body != NULL) rew_last(mdoc, body); body = roff_body_alloc(mdoc, line, ppos, tok); + roff_word_alloc(mdoc, line, ppos, "\\&"); break; } + if (tok == MDOC_Bd || tok == MDOC_Bk) { mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, line, la, "%s ... %s", @@ -1070,9 +1090,7 @@ blk_full(MACRO_PROT_ARGS) */ if (head == NULL && - ac != ARGS_PEND && ac != ARGS_PHRASE && - ac != ARGS_PPHRASE && ac != ARGS_QWORD && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); @@ -1084,9 +1102,7 @@ blk_full(MACRO_PROT_ARGS) if (head == NULL) head = roff_head_alloc(mdoc, line, ppos, tok); - if (ac == ARGS_PHRASE || - ac == ARGS_PEND || - ac == ARGS_PPHRASE) { + if (ac == ARGS_PHRASE) { /* * If we haven't opened a body yet, rewind the @@ -1096,18 +1112,11 @@ blk_full(MACRO_PROT_ARGS) rew_last(mdoc, body == NULL ? head : body); body = roff_body_alloc(mdoc, line, ppos, tok); - /* - * Process phrases: set whether we're in a - * partial-phrase (this effects line handling) - * then call down into the phrase parser. - */ + /* Process to the tab or to the end of the line. */ - if (ac == ARGS_PPHRASE) - mdoc->flags |= MDOC_PPHRASE; - if (ac == ARGS_PEND && lac == ARGS_PPHRASE) - mdoc->flags |= MDOC_PPHRASE; + mdoc->flags |= MDOC_PHRASE; parse_rest(mdoc, TOKEN_NONE, line, &la, buf); - mdoc->flags &= ~MDOC_PPHRASE; + mdoc->flags &= ~MDOC_PHRASE; /* There may have been `Ta' macros. */ @@ -1459,7 +1468,7 @@ phrase_ta(MACRO_PROT_ARGS) 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; }