=================================================================== RCS file: /cvs/mandoc/mdoc_macro.c,v retrieving revision 1.225 retrieving revision 1.232 diff -u -p -r1.225 -r1.232 --- mandoc/mdoc_macro.c 2018/08/17 20:33:37 1.225 +++ mandoc/mdoc_macro.c 2019/01/07 07:26:29 1.232 @@ -1,7 +1,7 @@ -/* $Id: mdoc_macro.c,v 1.225 2018/08/17 20:33:37 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.232 2019/01/07 07:26:29 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons - * Copyright (c) 2010, 2012-2018 Ingo Schwarze + * Copyright (c) 2010, 2012-2019 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 @@ -49,7 +49,7 @@ static void dword(struct roff_man *, int, int, const static int find_pending(struct roff_man *, enum roff_tok, 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 int macro_or_word(MACRO_PROT_ARGS, char *, int); static void break_intermediate(struct roff_node *, struct roff_node *); static int parse_rest(struct roff_man *, enum roff_tok, @@ -228,13 +228,12 @@ mdoc_endparse(struct roff_man *mdoc) for ( ; n; n = n->parent) if (n->type == ROFFT_BLOCK && mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) - mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse, - n->line, n->pos, roff_name[n->tok]); + mandoc_msg(MANDOCERR_BLK_NOEND, + n->line, n->pos, "%s", roff_name[n->tok]); /* Rewind to the first. */ - rew_last(mdoc, mdoc->first); - mdoc_state_reset(mdoc); + rew_last(mdoc, mdoc->meta.first); } /* @@ -255,8 +254,7 @@ lookup(struct roff_man *mdoc, int from, int line, int if (res != TOKEN_NONE) { if (mdoc_macro(res)->flags & MDOC_CALLABLE) return res; - mandoc_msg(MANDOCERR_MACRO_CALL, - mdoc->parse, line, ppos, p); + mandoc_msg(MANDOCERR_MACRO_CALL, line, ppos, "%s", p); } } return TOKEN_NONE; @@ -297,6 +295,8 @@ rew_pending(struct roff_man *mdoc, const struct roff_n case ROFFT_HEAD: roff_body_alloc(mdoc, n->line, n->pos, n->tok); + if (n->tok == MDOC_Ss) + mdoc->flags &= ~ROFF_NONOFILL; break; case ROFFT_BLOCK: break; @@ -421,10 +421,9 @@ find_pending(struct roff_man *mdoc, enum roff_tok tok, if (target->type == ROFFT_HEAD) target->flags |= NODE_ENDED; else if ( ! (target->flags & NODE_ENDED)) { - mandoc_vmsg(MANDOCERR_BLK_NEST, - mdoc->parse, line, ppos, - "%s breaks %s", roff_name[tok], - roff_name[n->tok]); + mandoc_msg(MANDOCERR_BLK_NEST, + line, ppos, "%s breaks %s", + roff_name[tok], roff_name[n->tok]); mdoc_endbody_alloc(mdoc, line, ppos, tok, target); } @@ -476,14 +475,15 @@ append_delims(struct roff_man *mdoc, int line, int *po { char *p; int la; + enum margserr ac; if (buf[*pos] == '\0') return; for (;;) { la = *pos; - if (mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p) == - ARGS_EOLN) + ac = mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p); + if (ac == ARGS_EOLN) break; dword(mdoc, line, la, p, DELIM_MAX, 1); @@ -501,6 +501,8 @@ append_delims(struct roff_man *mdoc, int line, int *po if (mandoc_eos(p, strlen(p))) mdoc->last->flags |= NODE_EOS; + if (ac == ARGS_ALLOC) + free(p); } } @@ -510,17 +512,13 @@ append_delims(struct roff_man *mdoc, int line, int *po * Otherwise, allocate it and return 0. */ static int -macro_or_word(MACRO_PROT_ARGS, int parsed) +macro_or_word(MACRO_PROT_ARGS, char *p, int parsed) { - char *p; int ntok; - p = buf + ppos; - ntok = TOKEN_NONE; - if (*p == '"') - p++; - else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT)) - ntok = lookup(mdoc, tok, line, ppos, p); + ntok = buf[ppos] == '"' || parsed == 0 || + mdoc->flags & MDOC_PHRASELIT ? TOKEN_NONE : + lookup(mdoc, tok, line, ppos, p); if (ntok == TOKEN_NONE) { dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE || @@ -635,7 +633,7 @@ blk_exp_close(MACRO_PROT_ARGS) * the scope - of the current block ends. */ - mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, + mandoc_msg(MANDOCERR_BLK_NEST, line, ppos, "%s breaks %s", roff_name[atok], roff_name[later->tok]); @@ -678,8 +676,8 @@ blk_exp_close(MACRO_PROT_ARGS) } if (body == NULL) { - mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse, - line, ppos, roff_name[tok]); + mandoc_msg(MANDOCERR_BLK_NOTOPEN, line, ppos, + "%s", roff_name[tok]); if (maxargs && endbody == NULL) { /* * Stray .Ec without previous .Eo: @@ -696,12 +694,23 @@ blk_exp_close(MACRO_PROT_ARGS) if ((mdoc_macro(tok)->flags & MDOC_PARSED) == 0) { if (buf[*pos] != '\0') - mandoc_vmsg(MANDOCERR_ARG_SKIP, - mdoc->parse, line, ppos, - "%s %s", roff_name[tok], - buf + *pos); + mandoc_msg(MANDOCERR_ARG_SKIP, line, ppos, + "%s %s", roff_name[tok], buf + *pos); if (endbody == NULL && n != NULL) rew_pending(mdoc, n); + + /* + * Restore the fill mode that was set before the display. + * This needs to be done here rather than during validation + * such that subsequent nodes get the right flags. + */ + + if (tok == MDOC_Ed && body != NULL) { + if (body->flags & NODE_NOFILL) + mdoc->flags |= ROFF_NOFILL; + else + mdoc->flags &= ~ROFF_NOFILL; + } return; } @@ -724,8 +733,12 @@ blk_exp_close(MACRO_PROT_ARGS) if (ntok == TOKEN_NONE) { dword(mdoc, line, lastarg, p, DELIM_MAX, mdoc_macro(tok)->flags & MDOC_JOIN); + if (ac == ARGS_ALLOC) + free(p); continue; } + if (ac == ARGS_ALLOC) + free(p); if (n != NULL) rew_last(mdoc, n); @@ -834,13 +847,14 @@ in_line(MACRO_PROT_ARGS) } else if ( ! nc && ! cnt) { mdoc_argv_free(arg); mandoc_msg(MANDOCERR_MACRO_EMPTY, - mdoc->parse, line, ppos, - roff_name[tok]); + line, ppos, "%s", roff_name[tok]); } (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, la, pos, buf); if (nl) append_delims(mdoc, line, pos, buf); + if (ac == ARGS_ALLOC) + free(p); return; } @@ -884,6 +898,9 @@ in_line(MACRO_PROT_ARGS) dword(mdoc, line, la, p, d, mdoc_macro(tok)->flags & MDOC_JOIN); + if (ac == ARGS_ALLOC) + free(p); + /* * If the first argument is a closing delimiter, * do not suppress spacing before it. @@ -921,8 +938,8 @@ in_line(MACRO_PROT_ARGS) rew_last(mdoc, mdoc->last); } else { mdoc_argv_free(arg); - mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, roff_name[tok]); + mandoc_msg(MANDOCERR_MACRO_EMPTY, + line, ppos, "%s", roff_name[tok]); } } if (nl) @@ -934,20 +951,21 @@ in_line(MACRO_PROT_ARGS) static void blk_full(MACRO_PROT_ARGS) { - int la, nl, parsed; struct mdoc_arg *arg; struct roff_node *blk; /* Our own or a broken block. */ struct roff_node *head; /* Our own head. */ struct roff_node *body; /* Our own body. */ struct roff_node *n; - enum margserr ac, lac; char *p; + size_t iarg; + int done, la, nl, parsed; + enum margserr ac, lac; nl = MDOC_NEWLINE & mdoc->flags; if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) { - mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, roff_name[tok]); + mandoc_msg(MANDOCERR_MACRO_EMPTY, + line, ppos, "%s", roff_name[tok]); return; } @@ -967,9 +985,8 @@ blk_full(MACRO_PROT_ARGS) if (tok == MDOC_It && n->tok == MDOC_Bl) { if (blk != NULL) { - mandoc_vmsg(MANDOCERR_BLK_BROKEN, - mdoc->parse, line, ppos, - "It breaks %s", + mandoc_msg(MANDOCERR_BLK_BROKEN, + line, ppos, "It breaks %s", roff_name[blk->tok]); rew_pending(mdoc, blk); } @@ -980,8 +997,8 @@ blk_full(MACRO_PROT_ARGS) switch (tok) { case MDOC_Sh: case MDOC_Ss: - mandoc_vmsg(MANDOCERR_BLK_BROKEN, - mdoc->parse, line, ppos, + mandoc_msg(MANDOCERR_BLK_BROKEN, + line, ppos, "%s breaks %s", roff_name[tok], roff_name[n->tok]); rew_pending(mdoc, n); @@ -1007,8 +1024,7 @@ blk_full(MACRO_PROT_ARGS) /* Item breaking an explicit block. */ if (blk != NULL) { - mandoc_vmsg(MANDOCERR_BLK_BROKEN, - mdoc->parse, line, ppos, + mandoc_msg(MANDOCERR_BLK_BROKEN, line, ppos, "It breaks %s", roff_name[blk->tok]); rew_pending(mdoc, blk); blk = NULL; @@ -1022,7 +1038,7 @@ blk_full(MACRO_PROT_ARGS) /* Skip items outside lists. */ if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) { - mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse, + mandoc_msg(MANDOCERR_IT_STRAY, line, ppos, "It %s", buf + *pos); roff_elem_alloc(mdoc, line, ppos, ROFF_br); rew_elem(mdoc, ROFF_br); @@ -1039,6 +1055,16 @@ blk_full(MACRO_PROT_ARGS) * regular child nodes. */ + switch (tok) { + case MDOC_Sh: + mdoc->flags &= ~ROFF_NOFILL; + break; + case MDOC_Ss: + mdoc->flags |= ROFF_NONOFILL; + break; + default: + break; + } mdoc_argv(mdoc, line, tok, &arg, pos, buf); blk = mdoc_block_alloc(mdoc, line, ppos, tok, arg); head = body = NULL; @@ -1100,14 +1126,17 @@ blk_full(MACRO_PROT_ARGS) } if (tok == MDOC_Bd || tok == MDOC_Bk) { - mandoc_vmsg(MANDOCERR_ARG_EXCESS, - mdoc->parse, line, la, "%s ... %s", - roff_name[tok], buf + la); + mandoc_msg(MANDOCERR_ARG_EXCESS, line, la, + "%s ... %s", roff_name[tok], buf + la); + if (ac == ARGS_ALLOC) + free(p); break; } if (tok == MDOC_Rs) { - mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, + mandoc_msg(MANDOCERR_ARG_SKIP, line, la, "Rs %s", buf + la); + if (ac == ARGS_ALLOC) + free(p); break; } if (ac == ARGS_PUNCT) @@ -1122,6 +1151,8 @@ blk_full(MACRO_PROT_ARGS) ac != ARGS_PHRASE && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); + if (ac == ARGS_ALLOC) + free(p); continue; } @@ -1153,7 +1184,10 @@ blk_full(MACRO_PROT_ARGS) continue; } - if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed)) + done = macro_or_word(mdoc, tok, line, la, pos, buf, p, parsed); + if (ac == ARGS_ALLOC) + free(p); + if (done) break; } @@ -1172,6 +1206,33 @@ blk_full(MACRO_PROT_ARGS) rew_last(mdoc, head); body = roff_body_alloc(mdoc, line, ppos, tok); + if (tok == MDOC_Ss) + mdoc->flags &= ~ROFF_NONOFILL; + + /* + * Set up fill mode for display blocks. + * This needs to be done here up front rather than during + * validation such that child nodes get the right flags. + */ + + if (tok == MDOC_Bd && arg != NULL) { + for (iarg = 0; iarg < arg->argc; iarg++) { + switch (arg->argv[iarg].arg) { + case MDOC_Unfilled: + case MDOC_Literal: + mdoc->flags |= ROFF_NOFILL; + break; + case MDOC_Filled: + case MDOC_Ragged: + case MDOC_Centred: + mdoc->flags &= ~ROFF_NOFILL; + break; + default: + continue; + } + break; + } + } out: if (mdoc->flags & MDOC_FREECOL) { rew_last(mdoc, body); @@ -1183,7 +1244,7 @@ out: static void blk_part_imp(MACRO_PROT_ARGS) { - int la, nl; + int done, la, nl; enum margserr ac; char *p; struct roff_node *blk; /* saved block context */ @@ -1218,13 +1279,18 @@ blk_part_imp(MACRO_PROT_ARGS) if (body == NULL && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); + if (ac == ARGS_ALLOC) + free(p); continue; } if (body == NULL) body = roff_body_alloc(mdoc, line, ppos, tok); - if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) + done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1); + if (ac == ARGS_ALLOC) + free(p); + if (done) break; } if (body == NULL) @@ -1243,13 +1309,13 @@ blk_part_imp(MACRO_PROT_ARGS) for (n = body->child; n && n->next; n = n->next) /* Do nothing. */ ; if (n && n->tok == MDOC_Ns) - mdoc_node_relink(mdoc, n); + roff_node_relink(mdoc, n); } static void blk_part_exp(MACRO_PROT_ARGS) { - int la, nl; + int done, la, nl; enum margserr ac; struct roff_node *head; /* keep track of head */ char *p; @@ -1274,6 +1340,8 @@ blk_part_exp(MACRO_PROT_ARGS) if (head == NULL && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); + if (ac == ARGS_ALLOC) + free(p); continue; } @@ -1283,11 +1351,17 @@ blk_part_exp(MACRO_PROT_ARGS) dword(mdoc, line, la, p, DELIM_MAX, 0); rew_last(mdoc, head); roff_body_alloc(mdoc, line, ppos, tok); - if (tok == MDOC_Eo) + if (tok == MDOC_Eo) { + if (ac == ARGS_ALLOC) + free(p); continue; + } } - if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) + done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1); + if (ac == ARGS_ALLOC) + free(p); + if (done) break; } @@ -1345,10 +1419,12 @@ in_line_argn(MACRO_PROT_ARGS) la = *pos; ac = mdoc_args(mdoc, line, pos, buf, tok, &p); - if (ac == ARGS_WORD && state == -1 && + if ((ac == ARGS_WORD || ac == ARGS_ALLOC) && state == -1 && (mdoc_macro(tok)->flags & MDOC_IGNDELIM) == 0 && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); + if (ac == ARGS_ALLOC) + free(p); continue; } @@ -1360,8 +1436,8 @@ in_line_argn(MACRO_PROT_ARGS) if (ac == ARGS_PUNCT || ac == ARGS_EOLN) { if (abs(state) < 2 && tok == MDOC_Pf) - mandoc_vmsg(MANDOCERR_PF_SKIP, - mdoc->parse, line, ppos, "Pf %s", + mandoc_msg(MANDOCERR_PF_SKIP, + line, ppos, "Pf %s", p == NULL ? "at eol" : p); break; } @@ -1381,6 +1457,8 @@ in_line_argn(MACRO_PROT_ARGS) } (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, la, pos, buf); + if (ac == ARGS_ALLOC) + free(p); break; } @@ -1398,11 +1476,14 @@ in_line_argn(MACRO_PROT_ARGS) dword(mdoc, line, la, p, DELIM_MAX, mdoc_macro(tok)->flags & MDOC_JOIN); + if (ac == ARGS_ALLOC) + free(p); + p = mdoc->last->string; } if (state == -1) { - mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, roff_name[tok]); + mandoc_msg(MANDOCERR_MACRO_EMPTY, + line, ppos, "%s", roff_name[tok]); return; } @@ -1431,8 +1512,8 @@ in_line_eoln(MACRO_PROT_ARGS) if (buf[*pos] == '\0' && (tok == MDOC_Fd || *roff_name[tok] == '%')) { - mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, - line, ppos, roff_name[tok]); + mandoc_msg(MANDOCERR_MACRO_EMPTY, + line, ppos, "%s", roff_name[tok]); return; } @@ -1452,13 +1533,19 @@ static int parse_rest(struct roff_man *mdoc, enum roff_tok tok, int line, int *pos, char *buf) { - int la; + char *p; + int done, la; + enum margserr ac; for (;;) { la = *pos; - if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN) + ac = mdoc_args(mdoc, line, pos, buf, tok, &p); + if (ac == ARGS_EOLN) return 0; - if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) + done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1); + if (ac == ARGS_ALLOC) + free(p); + if (done) return 1; } } @@ -1500,8 +1587,7 @@ phrase_ta(MACRO_PROT_ARGS) } if (n == NULL || n->norm->Bl.type != LIST_column) { - mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse, - line, ppos, "Ta"); + mandoc_msg(MANDOCERR_TA_STRAY, line, ppos, "Ta"); return; }