=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.198 retrieving revision 1.209 diff -u -p -r1.198 -r1.209 --- mandoc/mdoc_macro.c 2015/05/01 15:27:54 1.198 +++ mandoc/mdoc_macro.c 2016/08/20 17:59:34 1.209 @@ -1,7 +1,7 @@ -/* $Id: mdoc_macro.c,v 1.198 2015/05/01 15:27:54 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,17 +240,21 @@ 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) { if (mdoc_macros[res].flags & MDOC_CALLABLE) - return(res); + return res; if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll) mandoc_msg(MANDOCERR_MACRO_CALL, mdoc->parse, line, ppos, p); } } - return(TOKEN_NONE); + return TOKEN_NONE; } /* @@ -258,27 +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 *n, *np; if (to->flags & MDOC_VALID) return; - mdoc->next = ROFF_NEXT_SIBLING; 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); - n = mdoc->last; - mdoc->last = np; - assert(mdoc->last); - mdoc->last->last = n; + mdoc_state(mdoc, mdoc->last); + mdoc->last->flags |= MDOC_VALID | MDOC_ENDED; + mdoc->last = mdoc->last->parent; } - mdoc_valid_post(mdoc); + mdoc_state(mdoc, mdoc->last); + mdoc->last->flags |= MDOC_VALID | MDOC_ENDED; + mdoc->next = ROFF_NEXT_SIBLING; } /* @@ -296,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: @@ -331,41 +327,40 @@ rew_alt(int tok) { switch (tok) { case MDOC_Ac: - return(MDOC_Ao); + return MDOC_Ao; case MDOC_Bc: - return(MDOC_Bo); + return MDOC_Bo; case MDOC_Brc: - return(MDOC_Bro); + return MDOC_Bro; case MDOC_Dc: - return(MDOC_Do); + return MDOC_Do; case MDOC_Ec: - return(MDOC_Eo); + return MDOC_Eo; case MDOC_Ed: - return(MDOC_Bd); + return MDOC_Bd; case MDOC_Ef: - return(MDOC_Bf); + return MDOC_Bf; case MDOC_Ek: - return(MDOC_Bk); + return MDOC_Bk; case MDOC_El: - return(MDOC_Bl); + return MDOC_Bl; case MDOC_Fc: - return(MDOC_Fo); + return MDOC_Fo; case MDOC_Oc: - return(MDOC_Oo); + return MDOC_Oo; case MDOC_Pc: - return(MDOC_Po); + return MDOC_Po; case MDOC_Qc: - return(MDOC_Qo); + return MDOC_Qo; case MDOC_Re: - return(MDOC_Rs); + return MDOC_Rs; case MDOC_Sc: - return(MDOC_So); + return MDOC_So; case MDOC_Xc: - return(MDOC_Xo); + return MDOC_Xo; default: - return(tok); + return tok; } - /* NOTREACHED */ } static void @@ -416,7 +411,7 @@ find_pending(struct roff_man *mdoc, int tok, int line, } } } - return(irc); + return irc; } /* @@ -511,14 +506,14 @@ macro_or_word(MACRO_PROT_ARGS, int parsed) if (ntok == TOKEN_NONE) { dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE || mdoc_macros[tok].flags & MDOC_JOIN); - return(0); + return 0; } else { if (mdoc_macros[tok].fp == in_line_eoln) rew_elem(mdoc, tok); mdoc_macro(mdoc, ntok, line, ppos, pos, buf); if (tok == TOKEN_NONE) append_delims(mdoc, line, pos, buf); - return(1); + return 1; } } @@ -554,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)) @@ -568,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; @@ -644,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: @@ -737,15 +741,10 @@ in_line(MACRO_PROT_ARGS) switch (tok) { case MDOC_An: - /* FALLTHROUGH */ case MDOC_Ar: - /* FALLTHROUGH */ case MDOC_Fl: - /* FALLTHROUGH */ case MDOC_Mt: - /* FALLTHROUGH */ case MDOC_Nm: - /* FALLTHROUGH */ case MDOC_Pa: nc = 1; break; @@ -949,7 +948,6 @@ blk_full(MACRO_PROT_ARGS) if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { switch (tok) { case MDOC_Sh: - /* FALLTHROUGH */ case MDOC_Ss: mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, @@ -1039,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", @@ -1079,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); @@ -1093,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 @@ -1105,18 +1112,16 @@ 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. */ + + while (body->next != NULL) + body = body->next; continue; } @@ -1292,16 +1297,12 @@ in_line_argn(MACRO_PROT_ARGS) switch (tok) { case MDOC_Ap: - /* FALLTHROUGH */ case MDOC_Ns: - /* FALLTHROUGH */ case MDOC_Ux: maxargs = 0; break; case MDOC_Bx: - /* FALLTHROUGH */ case MDOC_Es: - /* FALLTHROUGH */ case MDOC_Xr: maxargs = 2; break; @@ -1429,9 +1430,9 @@ parse_rest(struct roff_man *mdoc, int tok, int line, i for (;;) { la = *pos; if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN) - return(0); + return 0; if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) - return(1); + return 1; } } @@ -1467,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; }