From 6833508f150b9e1131c3e4446b71833171c103f0 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Mon, 31 Dec 2018 07:08:12 +0000 Subject: Move parsing of the .nf and .fi (fill mode) requests from the man(7) parser to the roff(7) parser. As a side effect, .nf and .fi are now also parsed in mdoc(7) input, though the mdoc(7) formatters still ignore most of their effect. --- man.c | 24 ++++++++++++------------ man_html.c | 36 +++++++++++++++++------------------- man_macro.c | 15 ++++----------- man_term.c | 11 +++++++---- man_validate.c | 7 +++---- roff.c | 50 +++++++++++++++++++++++++++++--------------------- roff.h | 8 +++----- roff_html.c | 4 +++- roff_int.h | 6 +++--- roff_term.c | 6 +++++- roff_validate.c | 29 +++++++++++++++++++---------- 11 files changed, 105 insertions(+), 91 deletions(-) diff --git a/man.c b/man.c index 8eb8e757..a7c8004d 100644 --- a/man.c +++ b/man.c @@ -1,4 +1,4 @@ -/* $Id: man.c,v 1.183 2018/12/31 04:55:46 schwarze Exp $ */ +/* $Id: man.c,v 1.184 2018/12/31 07:08:12 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2013,2014,2015,2017,2018 Ingo Schwarze @@ -103,9 +103,9 @@ man_ptext(struct roff_man *man, int line, char *buf, int offs) int i; char *ep; - /* Literal free-form text whitespace is preserved. */ + /* In no-fill mode, whitespace is preserved on text lines. */ - if (man->flags & MAN_LITERAL) { + if (man->flags & ROFF_NOFILL) { roff_word_alloc(man, line, offs, buf + offs); man_descope(man, line, offs, buf + offs); return 1; @@ -308,7 +308,7 @@ man_breakscope(struct roff_man *man, int tok) */ if (man->flags & MAN_BLINE && - (tok == MAN_nf || tok == MAN_fi) && + (tok == ROFF_nf || tok == ROFF_fi) && (man->last->tok == MAN_SH || man->last->tok == MAN_SS)) { n = man->last; man_unscope(man, n); @@ -322,8 +322,8 @@ man_breakscope(struct roff_man *man, int tok) * Delete the block that is being broken. */ - if (man->flags & MAN_BLINE && (tok < MAN_TH || - man_macro(tok)->flags & MAN_XSCOPE)) { + if (man->flags & MAN_BLINE && tok != ROFF_nf && tok != ROFF_fi && + (tok < MAN_TH || man_macro(tok)->flags & MAN_XSCOPE)) { n = man->last; if (n->type == ROFFT_TEXT) n = n->parent; @@ -349,18 +349,18 @@ man_state(struct roff_man *man, struct roff_node *n) { switch(n->tok) { - case MAN_nf: + case ROFF_nf: case MAN_EX: - if (man->flags & MAN_LITERAL && ! (n->flags & NODE_VALID)) + if (man->flags & ROFF_NOFILL && (n->flags & NODE_VALID) == 0) mandoc_msg(MANDOCERR_NF_SKIP, n->line, n->pos, "nf"); - man->flags |= MAN_LITERAL; + man->flags |= ROFF_NOFILL; break; - case MAN_fi: + case ROFF_fi: case MAN_EE: - if ( ! (man->flags & MAN_LITERAL) && + if ( (man->flags & ROFF_NOFILL) == 0 && ! (n->flags & NODE_VALID)) mandoc_msg(MANDOCERR_FI_SKIP, n->line, n->pos, "fi"); - man->flags &= ~MAN_LITERAL; + man->flags &= ~ROFF_NOFILL; break; default: break; diff --git a/man_html.c b/man_html.c index e226e563..fa6ba205 100644 --- a/man_html.c +++ b/man_html.c @@ -1,4 +1,4 @@ -/* $Id: man_html.c,v 1.161 2018/12/30 00:49:55 schwarze Exp $ */ +/* $Id: man_html.c,v 1.162 2018/12/31 07:08:12 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2013,2014,2015,2017,2018 Ingo Schwarze @@ -94,8 +94,6 @@ static const struct man_html_act man_html_acts[MAN_MAX - MAN_TH] = { { man_I_pre, NULL }, /* I */ { man_alt_pre, NULL }, /* IR */ { man_alt_pre, NULL }, /* RI */ - { NULL, NULL }, /* nf */ - { NULL, NULL }, /* fi */ { NULL, NULL }, /* RE */ { man_RS_pre, NULL }, /* RS */ { man_ign_pre, NULL }, /* DT */ @@ -192,7 +190,7 @@ print_man_nodelist(MAN_ARGS) static void print_man_node(MAN_ARGS) { - static int want_fillmode = MAN_fi; + static int want_fillmode = ROFF_fi; static int save_fillmode; struct tag *t; @@ -204,14 +202,14 @@ print_man_node(MAN_ARGS) */ switch (n->tok) { - case MAN_nf: + case ROFF_nf: case MAN_EX: - want_fillmode = MAN_nf; + want_fillmode = ROFF_nf; return; - case MAN_fi: + case ROFF_fi: case MAN_EE: - want_fillmode = MAN_fi; - if (fillmode(h, 0) == MAN_fi) + want_fillmode = ROFF_fi; + if (fillmode(h, 0) == ROFF_fi) print_otag(h, TAG_BR, ""); return; default: @@ -232,20 +230,20 @@ print_man_node(MAN_ARGS) /* FALLTHROUGH */ case MAN_SH: /* Section headers */ case MAN_SS: /* permanently cancel .nf. */ - want_fillmode = MAN_fi; + want_fillmode = ROFF_fi; /* FALLTHROUGH */ case MAN_PP: /* These have no head. */ case MAN_RS: /* They will simply */ case MAN_UR: /* reopen .nf in the body. */ case MAN_MT: - fillmode(h, MAN_fi); + fillmode(h, ROFF_fi); break; default: break; } break; case ROFFT_TBL: - fillmode(h, MAN_fi); + fillmode(h, ROFF_fi); break; case ROFFT_ELEM: /* @@ -258,12 +256,12 @@ print_man_node(MAN_ARGS) fillmode(h, want_fillmode); break; case ROFFT_TEXT: - if (fillmode(h, want_fillmode) == MAN_fi && - want_fillmode == MAN_fi && + if (fillmode(h, want_fillmode) == ROFF_fi && + want_fillmode == ROFF_fi && n->flags & NODE_LINE && *n->string == ' ' && (h->flags & HTML_NONEWLINE) == 0) print_otag(h, TAG_BR, ""); - if (want_fillmode == MAN_nf || *n->string != '\0') + if (want_fillmode == ROFF_nf || *n->string != '\0') break; print_paragraph(h); return; @@ -336,7 +334,7 @@ print_man_node(MAN_ARGS) /* This will automatically close out any font scope. */ print_stagq(h, t); - if (fillmode(h, 0) == MAN_nf && + if (fillmode(h, 0) == ROFF_nf && n->next != NULL && n->next->flags & NODE_LINE) { /* In .nf =
, print even empty lines. */
 		h->col++;
@@ -345,7 +343,7 @@ print_man_node(MAN_ARGS)
 }
 
 /*
- * MAN_nf switches to no-fill mode, MAN_fi to fill mode.
+ * ROFF_nf switches to no-fill mode, ROFF_fi to fill mode.
  * Other arguments do not switch.
  * The old mode is returned.
  */
@@ -359,10 +357,10 @@ fillmode(struct html *h, int want)
 		if (pre->tag == TAG_PRE)
 			break;
 
-	had = pre == NULL ? MAN_fi : MAN_nf;
+	had = pre == NULL ? ROFF_fi : ROFF_nf;
 
 	if (want && want != had) {
-		if (want == MAN_nf)
+		if (want == ROFF_nf)
 			print_otag(h, TAG_PRE, "");
 		else
 			print_tagq(h, pre);
diff --git a/man_macro.c b/man_macro.c
index 30d3cfd9..48b9858a 100644
--- a/man_macro.c
+++ b/man_macro.c
@@ -1,4 +1,4 @@
-/*	$Id: man_macro.c,v 1.139 2018/12/31 04:55:46 schwarze Exp $ */
+/*	$Id: man_macro.c,v 1.140 2018/12/31 07:08:12 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons 
  * Copyright (c) 2012-2015, 2017, 2018 Ingo Schwarze 
@@ -63,8 +63,6 @@ static const struct man_macro man_macros[MAN_MAX - MAN_TH] = {
 	{ in_line_eoln, MAN_NSCOPED | MAN_ESCOPED | MAN_JOIN }, /* I */
 	{ in_line_eoln, 0 }, /* IR */
 	{ in_line_eoln, 0 }, /* RI */
-	{ in_line_eoln, MAN_NSCOPED }, /* nf */
-	{ in_line_eoln, MAN_NSCOPED }, /* fi */
 	{ blk_close, MAN_XSCOPE }, /* RE */
 	{ blk_exp, MAN_XSCOPE }, /* RS */
 	{ in_line_eoln, 0 }, /* DT */
@@ -340,9 +338,9 @@ blk_imp(MACRO_PROT_ARGS)
 	struct roff_node *n;
 
 	rew_scope(man, tok);
-	n = roff_block_alloc(man, line, ppos, tok);
-	if (n->tok == MAN_SH || n->tok == MAN_SS)
-		man->flags &= ~MAN_LITERAL;
+	if (tok == MAN_SH || tok == MAN_SS)
+		man->flags &= ~ROFF_NOFILL;
+	roff_block_alloc(man, line, ppos, tok);
 	n = roff_head_alloc(man, line, ppos, tok);
 
 	/* Add line arguments. */
@@ -384,11 +382,6 @@ in_line_eoln(MACRO_PROT_ARGS)
 	n = man->last;
 
 	for (;;) {
-		if (buf[*pos] != '\0' && (tok == MAN_fi || tok == MAN_nf)) {
-			mandoc_msg(MANDOCERR_ARG_SKIP, line, *pos,
-			    "%s %s", roff_name[tok], buf + *pos);
-			break;
-		}
 		if (buf[*pos] != '\0' && man->last != n && tok == MAN_PD) {
 			mandoc_msg(MANDOCERR_ARG_EXCESS, line, *pos,
 			    "%s ... %s", roff_name[tok], buf + *pos);
diff --git a/man_term.c b/man_term.c
index 99c2b794..9aa97df2 100644
--- a/man_term.c
+++ b/man_term.c
@@ -1,4 +1,4 @@
-/*	$Id: man_term.c,v 1.223 2018/12/30 00:49:55 schwarze Exp $ */
+/*	$Id: man_term.c,v 1.224 2018/12/31 07:08:12 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons 
  * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze 
@@ -117,8 +117,6 @@ static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = {
 	{ pre_I, NULL, 0 }, /* I */
 	{ pre_alternate, NULL, 0 }, /* IR */
 	{ pre_alternate, NULL, 0 }, /* RI */
-	{ pre_literal, NULL, MAN_NOTEXT }, /* nf */
-	{ pre_literal, NULL, MAN_NOTEXT }, /* fi */
 	{ NULL, NULL, 0 }, /* RE */
 	{ pre_RS, post_RS, 0 }, /* RS */
 	{ pre_DT, NULL, 0 }, /* DT */
@@ -247,7 +245,7 @@ pre_literal(DECL_ARGS)
 
 	term_newln(p);
 
-	if (n->tok == MAN_nf || n->tok == MAN_EX)
+	if (n->tok == MAN_EX)
 		mt->fl |= MANT_LITERAL;
 	else
 		mt->fl &= ~MANT_LITERAL;
@@ -984,6 +982,11 @@ print_man_node(DECL_ARGS)
 		break;
 	}
 
+	if (n->tok == ROFF_nf)
+		n->tok = MAN_EX;
+	else if (n->tok == ROFF_fi)
+		n->tok = MAN_EE;
+
 	if (n->tok < ROFF_MAX) {
 		roff_term_pre(p, n);
 		return;
diff --git a/man_validate.c b/man_validate.c
index b6262599..208b7d24 100644
--- a/man_validate.c
+++ b/man_validate.c
@@ -1,4 +1,4 @@
-/*	$Id: man_validate.c,v 1.143 2018/12/31 04:55:46 schwarze Exp $ */
+/*	$Id: man_validate.c,v 1.144 2018/12/31 07:08:12 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons 
  * Copyright (c) 2010, 2012-2018 Ingo Schwarze 
@@ -78,8 +78,6 @@ static	const v_check man_valids[MAN_MAX - MAN_TH] = {
 	NULL,       /* I */
 	NULL,       /* IR */
 	NULL,       /* RI */
-	NULL,       /* nf */
-	NULL,       /* fi */
 	NULL,       /* RE */
 	check_part, /* RS */
 	NULL,       /* DT */
@@ -153,6 +151,7 @@ man_validate(struct roff_man *man)
 	default:
 		if (n->tok < ROFF_MAX) {
 			roff_validate(man);
+			man_state(man, n);
 			break;
 		}
 		assert(n->tok >= MAN_TH && n->tok < MAN_MAX);
@@ -207,7 +206,7 @@ check_text(CHKARGS)
 {
 	char		*cp, *p;
 
-	if (MAN_LITERAL & man->flags)
+	if (man->flags & ROFF_NOFILL)
 		return;
 
 	cp = n->string;
diff --git a/roff.c b/roff.c
index 77ae8632..f0c56a2b 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/*	$Id: roff.c,v 1.357 2018/12/31 04:55:47 schwarze Exp $ */
+/*	$Id: roff.c,v 1.358 2018/12/31 07:08:12 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons 
  * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze 
@@ -181,7 +181,6 @@ static	int		 roff_als(ROFF_ARGS);
 static	int		 roff_block(ROFF_ARGS);
 static	int		 roff_block_text(ROFF_ARGS);
 static	int		 roff_block_sub(ROFF_ARGS);
-static	int		 roff_br(ROFF_ARGS);
 static	int		 roff_cblock(ROFF_ARGS);
 static	int		 roff_cc(ROFF_ARGS);
 static	int		 roff_ccond(struct roff *, int, int);
@@ -221,6 +220,7 @@ static	int		 roff_line_ignore(ROFF_ARGS);
 static	void		 roff_man_alloc1(struct roff_man *);
 static	void		 roff_man_free1(struct roff_man *);
 static	int		 roff_manyarg(ROFF_ARGS);
+static	int		 roff_noarg(ROFF_ARGS);
 static	int		 roff_nop(ROFF_ARGS);
 static	int		 roff_nr(ROFF_ARGS);
 static	int		 roff_onearg(ROFF_ARGS);
@@ -257,8 +257,9 @@ static	int		 roff_userdef(ROFF_ARGS);
 #define	ROFFNUM_WHITE	(1 << 1)  /* Skip whitespace in roff_evalnum(). */
 
 const char *__roff_name[MAN_MAX + 1] = {
-	"br",		"ce",		"ft",		"ll",
-	"mc",		"po",		"rj",		"sp",
+	"br",		"ce",		"fi",		"ft",
+	"ll",		"mc",		"nf",
+	"po",		"rj",		"sp",
 	"ta",		"ti",		NULL,
 	"ab",		"ad",		"af",		"aln",
 	"als",		"am",		"am1",		"ami",
@@ -357,7 +358,6 @@ const char *__roff_name[MAN_MAX + 1] = {
 	"HP",		"SM",		"SB",		"BI",
 	"IB",		"BR",		"RB",		"R",
 	"B",		"I",		"IR",		"RI",
-	"nf",		"fi",
 	"RE",		"RS",		"DT",		"UC",
 	"PD",		"AT",		"in",
 	"SY",		"YS",		"OP",
@@ -367,11 +367,13 @@ const char *__roff_name[MAN_MAX + 1] = {
 const	char *const *roff_name = __roff_name;
 
 static	struct roffmac	 roffs[TOKEN_NONE] = {
-	{ roff_br, NULL, NULL, 0 },  /* br */
+	{ roff_noarg, NULL, NULL, 0 },  /* br */
 	{ roff_onearg, NULL, NULL, 0 },  /* ce */
+	{ roff_noarg, NULL, NULL, 0 },  /* fi */
 	{ roff_onearg, NULL, NULL, 0 },  /* ft */
 	{ roff_onearg, NULL, NULL, 0 },  /* ll */
 	{ roff_onearg, NULL, NULL, 0 },  /* mc */
+	{ roff_noarg, NULL, NULL, 0 },  /* nf */
 	{ roff_onearg, NULL, NULL, 0 },  /* po */
 	{ roff_onearg, NULL, NULL, 0 },  /* rj */
 	{ roff_onearg, NULL, NULL, 0 },  /* sp */
@@ -401,7 +403,7 @@ static	struct roffmac	 roffs[TOKEN_NONE] = {
 	{ roff_unsupp, NULL, NULL, 0 },  /* break */
 	{ roff_line_ignore, NULL, NULL, 0 },  /* breakchar */
 	{ roff_line_ignore, NULL, NULL, 0 },  /* brnl */
-	{ roff_br, NULL, NULL, 0 },  /* brp */
+	{ roff_noarg, NULL, NULL, 0 },  /* brp */
 	{ roff_line_ignore, NULL, NULL, 0 },  /* brpnl */
 	{ roff_unsupp, NULL, NULL, 0 },  /* c2 */
 	{ roff_cc, NULL, NULL, 0 },  /* cc */
@@ -3337,6 +3339,26 @@ roff_TS(ROFF_ARGS)
 	return ROFF_IGN;
 }
 
+static int
+roff_noarg(ROFF_ARGS)
+{
+	if (r->man->flags & (MAN_BLINE | MAN_ELINE))
+		man_breakscope(r->man, tok);
+	if (tok == ROFF_brp)
+		tok = ROFF_br;
+	roff_elem_alloc(r->man, ln, ppos, tok);
+	if (buf->buf[pos] != '\0')
+		mandoc_msg(MANDOCERR_ARG_SKIP, ln, pos,
+		   "%s %s", roff_name[tok], buf->buf + pos);
+	if (tok == ROFF_nf)
+		r->man->flags |= ROFF_NOFILL;
+	else if (tok == ROFF_fi)
+		r->man->flags &= ~ROFF_NOFILL;
+	r->man->last->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
+	r->man->next = ROFF_NEXT_SIBLING;
+	return ROFF_IGN;
+}
+
 static int
 roff_onearg(ROFF_ARGS)
 {
@@ -3447,20 +3469,6 @@ roff_als(ROFF_ARGS)
 	return ROFF_IGN;
 }
 
-static int
-roff_br(ROFF_ARGS)
-{
-	if (r->man->flags & (MAN_BLINE | MAN_ELINE))
-		man_breakscope(r->man, ROFF_br);
-	roff_elem_alloc(r->man, ln, ppos, ROFF_br);
-	if (buf->buf[pos] != '\0')
-		mandoc_msg(MANDOCERR_ARG_SKIP, ln, pos,
-		    "%s %s", roff_name[tok], buf->buf + pos);
-	r->man->last->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
-	r->man->next = ROFF_NEXT_SIBLING;
-	return ROFF_IGN;
-}
-
 static int
 roff_cc(ROFF_ARGS)
 {
diff --git a/roff.h b/roff.h
index 8af8661b..1e7bd1a3 100644
--- a/roff.h
+++ b/roff.h
@@ -1,4 +1,4 @@
-/*	$Id: roff.h,v 1.66 2018/12/30 00:49:56 schwarze Exp $	*/
+/*	$Id: roff.h,v 1.67 2018/12/31 07:08:12 schwarze Exp $	*/
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons 
  * Copyright (c) 2013,2014,2015,2017,2018 Ingo Schwarze 
@@ -73,9 +73,11 @@ enum	roff_type {
 enum	roff_tok {
 	ROFF_br = 0,
 	ROFF_ce,
+	ROFF_fi,
 	ROFF_ft,
 	ROFF_ll,
 	ROFF_mc,
+	ROFF_nf,
 	ROFF_po,
 	ROFF_rj,
 	ROFF_sp,
@@ -160,7 +162,6 @@ enum	roff_tok {
 	ROFF_fcolor,
 	ROFF_fdeferlig,
 	ROFF_feature,
-	/* MAN_fi; ignored in mdoc(7) */
 	ROFF_fkern,
 	ROFF_fl,
 	ROFF_flig,
@@ -220,7 +221,6 @@ enum	roff_tok {
 	ROFF_mso,
 	ROFF_na,
 	ROFF_ne,
-	/* MAN_nf; ignored in mdoc(7) */
 	ROFF_nh,
 	ROFF_nhychar,
 	ROFF_nm,
@@ -459,8 +459,6 @@ enum	roff_tok {
 	MAN_I,
 	MAN_IR,
 	MAN_RI,
-	MAN_nf,
-	MAN_fi,
 	MAN_RE,
 	MAN_RS,
 	MAN_DT,
diff --git a/roff_html.c b/roff_html.c
index adcbbf5b..a4d4468d 100644
--- a/roff_html.c
+++ b/roff_html.c
@@ -1,4 +1,4 @@
-/*	$Id: roff_html.c,v 1.15 2018/12/16 00:17:02 schwarze Exp $ */
+/*	$Id: roff_html.c,v 1.16 2018/12/31 07:08:12 schwarze Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons 
  * Copyright (c) 2014, 2017, 2018 Ingo Schwarze 
@@ -38,9 +38,11 @@ static	void	  roff_html_pre_sp(ROFF_HTML_ARGS);
 static	const roff_html_pre_fp roff_html_pre_acts[ROFF_MAX] = {
 	roff_html_pre_br,  /* br */
 	roff_html_pre_ce,  /* ce */
+	roff_html_pre_br,  /* fi */
 	roff_html_pre_ft,  /* ft */
 	NULL,  /* ll */
 	NULL,  /* mc */
+	roff_html_pre_br,  /* nf */
 	NULL,  /* po */
 	roff_html_pre_ce,  /* rj */
 	roff_html_pre_sp,  /* sp */
diff --git a/roff_int.h b/roff_int.h
index ac876434..29afb92f 100644
--- a/roff_int.h
+++ b/roff_int.h
@@ -1,4 +1,4 @@
-/*	$Id: roff_int.h,v 1.13 2018/12/31 04:55:47 schwarze Exp $	*/
+/*	$Id: roff_int.h,v 1.14 2018/12/31 07:08:12 schwarze Exp $	*/
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons 
  * Copyright (c) 2013,2014,2015,2017,2018 Ingo Schwarze 
@@ -39,7 +39,7 @@ struct	roff_man {
 	struct roff_node *last_es; /* The most recent Es node. */
 	int		  quick;   /* Abort parse early. */
 	int		  flags;   /* Parse flags. */
-#define	MDOC_LITERAL	 (1 << 1)  /* In a literal scope. */
+#define	ROFF_NOFILL	 (1 << 1)  /* Fill mode switched off. */
 #define	MDOC_PBODY	 (1 << 2)  /* In the document body. */
 #define	MDOC_NEWLINE	 (1 << 3)  /* First macro/text in a line. */
 #define	MDOC_PHRASE	 (1 << 4)  /* In a Bl -column phrase. */
@@ -54,7 +54,7 @@ struct	roff_man {
 #define	MDOC_PHRASEQF	 (1 << 13) /* Quote first word encountered. */
 #define	MDOC_PHRASEQL	 (1 << 14) /* Quote last word of this phrase. */
 #define	MDOC_PHRASEQN	 (1 << 15) /* Quote first word of the next phrase. */
-#define	MAN_LITERAL	  MDOC_LITERAL
+#define	MDOC_LITERAL	  ROFF_NOFILL
 #define	MAN_NEWLINE	  MDOC_NEWLINE
 	enum roff_sec	  lastsec; /* Last section seen. */
 	enum roff_sec	  lastnamed; /* Last standard section seen. */
diff --git a/roff_term.c b/roff_term.c
index a98f88f9..6ce4b7fb 100644
--- a/roff_term.c
+++ b/roff_term.c
@@ -1,4 +1,4 @@
-/*	$Id: roff_term.c,v 1.17 2018/12/16 00:17:02 schwarze Exp $ */
+/*	$Id: roff_term.c,v 1.18 2018/12/31 07:08:12 schwarze Exp $ */
 /*
  * Copyright (c) 2010,2014,2015,2017,2018 Ingo Schwarze 
  *
@@ -42,9 +42,11 @@ static	void	  roff_term_pre_ti(ROFF_TERM_ARGS);
 static	const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
 	roff_term_pre_br,  /* br */
 	roff_term_pre_ce,  /* ce */
+	roff_term_pre_br,  /* fi */
 	roff_term_pre_ft,  /* ft */
 	roff_term_pre_ll,  /* ll */
 	roff_term_pre_mc,  /* mc */
+	roff_term_pre_br,  /* nf */
 	roff_term_pre_po,  /* po */
 	roff_term_pre_ce,  /* rj */
 	roff_term_pre_sp,  /* sp */
@@ -67,7 +69,9 @@ roff_term_pre_br(ROFF_TERM_ARGS)
 	if (p->flags & TERMP_BRIND) {
 		p->tcol->offset = p->tcol->rmargin;
 		p->tcol->rmargin = p->maxrmargin;
+		p->trailspace = 0;
 		p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
+		p->flags |= TERMP_NOSPACE;
 	}
 }
 
diff --git a/roff_validate.c b/roff_validate.c
index d4cf6f6b..24d748b1 100644
--- a/roff_validate.c
+++ b/roff_validate.c
@@ -1,4 +1,4 @@
-/*	$Id: roff_validate.c,v 1.15 2018/12/16 00:17:02 schwarze Exp $ */
+/*	$Id: roff_validate.c,v 1.16 2018/12/31 07:08:12 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2017, 2018 Ingo Schwarze 
  *
@@ -30,15 +30,19 @@
 typedef	void	(*roff_valid_fp)(ROFF_VALID_ARGS);
 
 static	void	  roff_valid_br(ROFF_VALID_ARGS);
+static	void	  roff_valid_fi(ROFF_VALID_ARGS);
 static	void	  roff_valid_ft(ROFF_VALID_ARGS);
+static	void	  roff_valid_nf(ROFF_VALID_ARGS);
 static	void	  roff_valid_sp(ROFF_VALID_ARGS);
 
 static	const roff_valid_fp roff_valids[ROFF_MAX] = {
 	roff_valid_br,  /* br */
 	NULL,  /* ce */
+	roff_valid_fi,  /* fi */
 	roff_valid_ft,  /* ft */
 	NULL,  /* ll */
 	NULL,  /* mc */
+	roff_valid_nf,  /* nf */
 	NULL,  /* po */
 	NULL,  /* rj */
 	roff_valid_sp,  /* sp */
@@ -63,10 +67,6 @@ roff_valid_br(ROFF_VALID_ARGS)
 {
 	struct roff_node	*np;
 
-	if (n->child != NULL)
-		mandoc_msg(MANDOCERR_ARG_SKIP,
-		    n->line, n->pos, "br %s", n->child->string);
-
 	if (n->next != NULL && n->next->type == ROFFT_TEXT &&
 	    *n->next->string == ' ') {
 		mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos,
@@ -91,6 +91,13 @@ roff_valid_br(ROFF_VALID_ARGS)
 	}
 }
 
+static void
+roff_valid_fi(ROFF_VALID_ARGS)
+{
+	if ((man->flags & ROFF_NOFILL) == 0)
+		mandoc_msg(MANDOCERR_FI_SKIP, n->line, n->pos, "fi");
+}
+
 static void
 roff_valid_ft(ROFF_VALID_ARGS)
 {
@@ -110,16 +117,18 @@ roff_valid_ft(ROFF_VALID_ARGS)
 	roff_node_delete(man, n);
 }
 
+static void
+roff_valid_nf(ROFF_VALID_ARGS)
+{
+	if (man->flags & ROFF_NOFILL)
+		mandoc_msg(MANDOCERR_NF_SKIP, n->line, n->pos, "nf");
+}
+
 static void
 roff_valid_sp(ROFF_VALID_ARGS)
 {
 	struct roff_node	*np;
 
-	if (n->child != NULL && n->child->next != NULL)
-		mandoc_msg(MANDOCERR_ARG_EXCESS,
-		    n->child->next->line, n->child->next->pos,
-		    "sp ... %s", n->child->next->string);
-
 	if ((np = n->prev) == NULL)
 		return;
 
-- 
cgit v1.2.3-56-ge451