From 75666cb76815ffd35a30153c6cabc53601e9e2de Mon Sep 17 00:00:00 2001
From: Cem Keylan <cem@ckyln.com>
Date: Mon, 19 Oct 2020 13:43:05 +0300
Subject: usr.bin: update to 6.8

---
 usr.bin/mandoc/CVS/Entries  |  38 +++++++-------
 usr.bin/mandoc/apropos.1    |  11 ++--
 usr.bin/mandoc/arch.c       |   4 +-
 usr.bin/mandoc/cgi.c        |  11 ++--
 usr.bin/mandoc/main.c       |  81 ++++++++++++++++++----------
 usr.bin/mandoc/man.1        |  12 ++---
 usr.bin/mandoc/man_macro.c  |  12 +++--
 usr.bin/mandoc/manconf.h    |   4 +-
 usr.bin/mandoc/mandoc.1     |  46 ++++++++++++----
 usr.bin/mandoc/mandoc.h     |   3 +-
 usr.bin/mandoc/mandoc_msg.c |   3 +-
 usr.bin/mandoc/manpath.c    |  39 +++++++++++---
 usr.bin/mandoc/roff.c       | 125 +++++++++++++++++++++++---------------------
 usr.bin/mandoc/roff_term.c  |  50 ++++++++++++------
 usr.bin/mandoc/tbl_layout.c |   9 +++-
 usr.bin/mandoc/term.c       |  21 ++++----
 usr.bin/mandoc/term_ascii.c |  32 +++++++++---
 usr.bin/mandoc/term_ps.c    |   9 ++--
 usr.bin/mandoc/term_tag.c   |  57 ++++++++++++++------
 usr.bin/mandoc/term_tag.h   |   8 +--
 20 files changed, 363 insertions(+), 212 deletions(-)

(limited to 'usr.bin/mandoc')

diff --git a/usr.bin/mandoc/CVS/Entries b/usr.bin/mandoc/CVS/Entries
index 30e23be..3091a79 100644
--- a/usr.bin/mandoc/CVS/Entries
+++ b/usr.bin/mandoc/CVS/Entries
@@ -1,8 +1,8 @@
 /Makefile/1.118/Fri Mar 13 00:31:04 2020//
-/apropos.1/1.41/Thu Nov 22 12:32:10 2018//
-/arch.c/1.11/Sat May 11 07:18:17 2019//
+/apropos.1/1.43/Mon Jul 20 14:52:12 2020//
+/arch.c/1.12/Mon Jun 29 19:16:59 2020//
 /att.c/1.14/Thu Dec 13 11:55:14 2018//
-/cgi.c/1.110/Fri Apr  3 11:34:19 2020//
+/cgi.c/1.111/Mon Jun 29 19:16:59 2020//
 /cgi.h.example/1.6/Sat Mar 18 16:48:07 2017//
 /chars.c/1.49/Thu Feb 13 16:16:03 2020//
 /dba.c/1.7/Thu Feb  9 18:26:17 2017//
@@ -26,33 +26,33 @@
 /libman.h/1.61/Mon Dec 31 10:03:38 2018//
 /libmandoc.h/1.64/Fri Apr  3 11:34:19 2020//
 /libmdoc.h/1.88/Mon Dec 31 04:55:42 2018//
-/main.c/1.251/Thu Apr  2 22:10:27 2020//
+/main.c/1.255/Tue Jul 21 15:08:48 2020//
 /main.h/1.25/Sun Mar  3 13:01:47 2019//
 /makewhatis.8/1.14/Wed May 17 22:26:52 2017//
-/man.1/1.36/Mon Feb 10 13:49:04 2020//
+/man.1/1.39/Mon Jul 20 14:52:12 2020//
 /man.c/1.135/Sat Jan  5 00:36:46 2019//
 /man.cgi.8/1.22/Sun May 20 21:48:23 2018//
 /man.conf.5/1.8/Mon Feb 10 14:42:03 2020//
 /man.h/1.59/Thu Aug 23 19:32:03 2018//
 /man_html.c/1.131/Sat Apr  4 20:23:06 2020//
-/man_macro.c/1.106/Sat Jan  5 18:59:37 2019//
+/man_macro.c/1.107/Wed Sep  9 16:57:05 2020//
 /man_term.c/1.188/Fri Mar 13 00:31:05 2020//
 /man_validate.c/1.124/Fri Apr 24 11:58:02 2020//
-/manconf.h/1.8/Thu Apr  2 22:10:27 2020//
-/mandoc.1/1.167/Fri Apr 24 11:58:02 2020//
+/manconf.h/1.9/Tue Jul 21 15:08:49 2020//
+/mandoc.1/1.173/Tue Sep  1 18:24:09 2020//
 /mandoc.c/1.85/Sun Jan 19 16:16:32 2020//
 /mandoc.css/1.33/Sun Jun  2 16:50:46 2019//
-/mandoc.h/1.210/Fri Apr 24 11:58:02 2020//
+/mandoc.h/1.211/Tue Sep  1 18:24:09 2020//
 /mandoc_aux.c/1.9/Wed Feb  7 20:04:33 2018//
 /mandoc_aux.h/1.9/Mon Jun 12 18:55:42 2017//
-/mandoc_msg.c/1.9/Fri Apr 24 11:58:02 2020//
+/mandoc_msg.c/1.10/Tue Sep  1 18:24:10 2020//
 /mandoc_ohash.c/1.2/Mon Oct 19 18:58:20 2015//
 /mandoc_ohash.h/1.2/Sat Nov  7 13:57:55 2015//
 /mandoc_parse.h/1.4/Sat Nov  9 14:39:42 2019//
 /mandoc_xr.c/1.3/Sun Jul  2 21:17:12 2017//
 /mandoc_xr.h/1.3/Sun Jul  2 21:17:12 2017//
 /mandocdb.c/1.216/Fri Apr  3 11:34:19 2020//
-/manpath.c/1.28/Mon Feb 10 14:42:03 2020//
+/manpath.c/1.30/Thu Aug 27 14:59:42 2020//
 /mansearch.c/1.65/Mon Jul  1 22:43:03 2019//
 /mansearch.h/1.24/Tue Apr 30 18:48:26 2019//
 /mdoc.c/1.164/Mon Apr  6 09:55:49 2020//
@@ -72,11 +72,11 @@
 /preconv.c/1.9/Thu Dec 13 11:55:14 2018//
 /predefs.in/1.4/Fri Nov 28 19:25:03 2014//
 /read.c/1.190/Fri Apr 24 11:58:02 2020//
-/roff.c/1.246/Wed Apr  8 11:54:14 2020//
+/roff.c/1.248/Thu Aug 27 12:58:00 2020//
 /roff.h/1.56/Wed Apr  8 11:54:14 2020//
 /roff_html.c/1.20/Tue Apr 30 15:52:42 2019//
 /roff_int.h/1.17/Fri Apr 24 11:58:02 2020//
-/roff_term.c/1.19/Fri Jan  4 03:24:30 2019//
+/roff_term.c/1.21/Thu Sep  3 20:33:20 2020//
 /roff_validate.c/1.19/Thu Feb 27 01:25:58 2020//
 /st.c/1.13/Fri Dec 14 01:17:46 2018//
 /tag.c/1.36/Sun Apr 19 16:26:11 2020//
@@ -86,16 +86,16 @@
 /tbl_data.c/1.40/Sat Jan 11 20:48:13 2020//
 /tbl_html.c/1.28/Sun Mar 17 18:20:07 2019//
 /tbl_int.h/1.2/Fri Dec 14 06:33:03 2018//
-/tbl_layout.c/1.35/Fri Dec 14 05:17:45 2018//
+/tbl_layout.c/1.36/Tue Sep  1 18:24:10 2020//
 /tbl_opts.c/1.16/Fri Dec 14 05:17:45 2018//
 /tbl_parse.h/1.2/Fri Dec 14 06:33:03 2018//
 /tbl_term.c/1.61/Sat Jan 11 16:24:33 2020//
-/term.c/1.141/Mon Jun  3 20:23:39 2019//
+/term.c/1.142/Wed Sep  2 16:36:48 2020//
 /term.h/1.75/Fri Jan  4 03:20:44 2019//
-/term_ascii.c/1.50/Fri Jul 19 21:45:37 2019//
-/term_ps.c/1.55/Fri Nov 10 14:16:28 2017//
+/term_ascii.c/1.52/Wed Sep  9 13:40:24 2020//
+/term_ps.c/1.56/Sun Sep  6 14:44:19 2020//
 /term_tab.c/1.4/Sat Jun 17 14:55:02 2017//
-/term_tag.c/1.4/Sat Apr 18 20:28:46 2020//
-/term_tag.h/1.2/Thu Apr  2 22:10:27 2020//
+/term_tag.c/1.5/Tue Jul 21 15:08:49 2020//
+/term_tag.h/1.3/Tue Jul 21 15:08:49 2020//
 /tree.c/1.56/Wed Apr  8 11:54:14 2020//
 D
diff --git a/usr.bin/mandoc/apropos.1 b/usr.bin/mandoc/apropos.1
index 401976f..c81add1 100644
--- a/usr.bin/mandoc/apropos.1
+++ b/usr.bin/mandoc/apropos.1
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: apropos.1,v 1.41 2018/11/22 12:32:10 schwarze Exp $
+.\"	$OpenBSD: apropos.1,v 1.43 2020/07/20 14:52:12 schwarze Exp $
 .\"
 .\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
 .\" Copyright (c) 2011,2012,2014,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: November 22 2018 $
+.Dd $Mdocdate: July 20 2020 $
 .Dt APROPOS 1
 .Os
 .Sh NAME
@@ -73,7 +73,7 @@ would.
 If the standard output is a terminal device and
 .Fl c
 is not specified, use
-.Xr more 1
+.Xr less 1
 to paginate them.
 In
 .Fl a
@@ -340,7 +340,7 @@ types appearing in function arguments in the SYNOPSIS
 Any non-empty value of the environment variable
 .Ev MANPAGER
 is used instead of the standard pagination program,
-.Xr more 1 ;
+.Xr less 1 ;
 see
 .Xr man 1
 for details.
@@ -363,8 +363,7 @@ Specifies the pagination program to use when
 .Ev MANPAGER
 is not defined.
 If neither PAGER nor MANPAGER is defined,
-.Xr more 1
-.Fl s
+.Xr less 1
 is used.
 Only used if
 .Fl a
diff --git a/usr.bin/mandoc/arch.c b/usr.bin/mandoc/arch.c
index 68a20bb..782f2c7 100644
--- a/usr.bin/mandoc/arch.c
+++ b/usr.bin/mandoc/arch.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: arch.c,v 1.11 2019/05/11 07:18:17 deraadt Exp $ */
+/*	$OpenBSD: arch.c,v 1.12 2020/06/29 19:16:59 schwarze Exp $ */
 /*
  * Copyright (c) 2017, 2019 Ingo Schwarze <schwarze@openbsd.org>
  *
@@ -24,7 +24,7 @@ arch_valid(const char *arch, enum mandoc_os os)
 	const char *openbsd_arch[] = {
 		"alpha", "amd64", "arm64", "armv7", "hppa", "i386",
 		"landisk", "loongson", "luna88k", "macppc", "mips64",
-		"octeon", "sgi", "sparc64", NULL
+		"octeon", "powerpc64", "sgi", "sparc64", NULL
 	};
 	const char *netbsd_arch[] = {
 		"acorn26", "acorn32", "algor", "alpha", "amiga",
diff --git a/usr.bin/mandoc/cgi.c b/usr.bin/mandoc/cgi.c
index 766ac06..c6db66f 100644
--- a/usr.bin/mandoc/cgi.c
+++ b/usr.bin/mandoc/cgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cgi.c,v 1.110 2020/04/03 11:34:19 schwarze Exp $ */
+/* $OpenBSD: cgi.c,v 1.111 2020/06/29 19:16:59 schwarze Exp $ */
 /*
  * Copyright (c) 2014-2019 Ingo Schwarze <schwarze@usta.de>
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -118,10 +118,11 @@ static	const char *const sec_names[] = {
 static	const int sec_MAX = sizeof(sec_names) / sizeof(char *);
 
 static	const char *const arch_names[] = {
-    "amd64",       "alpha",       "armv7",	"arm64",
-    "hppa",        "i386",        "landisk",
-    "loongson",    "luna88k",     "macppc",      "mips64",
-    "octeon",      "sgi",         "socppc",      "sparc64",
+    "amd64",       "alpha",       "armv7",       "arm64",
+    "hppa",        "i386",        "landisk",     "loongson",
+    "luna88k",     "macppc",      "mips64",      "octeon",
+    "powerpc64",   "sgi",         "socppc",      "sparc64",
+
     "amiga",       "arc",         "armish",      "arm32",
     "atari",       "aviion",      "beagle",      "cats",
     "hppa64",      "hp300",
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index acdbd91..e472977 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: main.c,v 1.251 2020/04/02 22:10:27 schwarze Exp $ */
+/* $OpenBSD: main.c,v 1.255 2020/07/21 15:08:48 schwarze Exp $ */
 /*
  * Copyright (c) 2010-2012, 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -107,8 +107,8 @@ static	void		  parse(struct mparse *, int, const char *,
 static	void		  passthrough(int, int);
 static	void		  process_onefile(struct mparse *, struct manpage *,
 				int, struct outstate *, struct manconf *);
-static	void		  run_pager(struct tag_files *, char *);
-static	pid_t		  spawn_pager(struct tag_files *, char *);
+static	void		  run_pager(struct outstate *, char *);
+static	pid_t		  spawn_pager(struct outstate *, char *);
 static	void		  usage(enum argmode) __attribute__((__noreturn__));
 static	int		  woptions(char *, enum mandoc_os *, int *);
 
@@ -152,7 +152,7 @@ main(int argc, char *argv[])
 	    strcmp(progname, BINM_MAKEWHATIS) == 0)
 		return mandocdb(argc, argv);
 
-	if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) {
+	if (pledge("stdio rpath wpath cpath tmppath tty proc exec", NULL) == -1) {
 		mandoc_msg(MANDOCERR_PLEDGE, 0, 0, "%s", strerror(errno));
 		return mandoc_msg_getrc();
 	}
@@ -355,7 +355,9 @@ main(int argc, char *argv[])
 
 	if (outmode == OUTMODE_FLN ||
 	    outmode == OUTMODE_LST ||
-	    !isatty(STDOUT_FILENO))
+	    (conf.output.outfilename == NULL &&
+	     conf.output.tagfilename == NULL &&
+	     isatty(STDOUT_FILENO) == 0))
 		outst.use_pager = 0;
 
 	if (outst.use_pager &&
@@ -368,12 +370,16 @@ main(int argc, char *argv[])
 			conf.output.indent = 3;
 	}
 
-	if (outst.use_pager == 0) {
-		if (pledge("stdio rpath", NULL) == -1) {
-			mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
-			    "%s", strerror(errno));
-			return mandoc_msg_getrc();
-		}
+	if (outst.use_pager == 0)
+		c = pledge("stdio rpath", NULL);
+	else if (conf.output.outfilename != NULL ||
+	    conf.output.tagfilename != NULL)
+		c = pledge("stdio rpath wpath cpath", NULL);
+	else
+		c = pledge("stdio rpath tmppath tty proc exec", NULL);
+	if (c == -1) {
+		mandoc_msg(MANDOCERR_PLEDGE, 0, 0, "%s", strerror(errno));
+		return mandoc_msg_getrc();
 	}
 
 	/* Parse arguments. */
@@ -622,8 +628,10 @@ out:
 		manconf_free(&conf);
 
 	if (outst.tag_files != NULL) {
-		if (term_tag_close() != -1)
-			run_pager(outst.tag_files, conf.output.tag);
+		if (term_tag_close() != -1 &&
+		    conf.output.outfilename == NULL &&
+		    conf.output.tagfilename == NULL)
+			run_pager(&outst, conf.output.tag);
 		term_tag_unlink();
 	} else if (outst.had_output && outst.outtype != OUTT_LINT)
 		mandoc_msg_summary();
@@ -817,7 +825,15 @@ process_onefile(struct mparse *mp, struct manpage *resp, int startdir,
 
 	if (outst->use_pager) {
 		outst->use_pager = 0;
-		outst->tag_files = term_tag_init();
+		outst->tag_files = term_tag_init(conf->output.outfilename,
+		    conf->output.tagfilename);
+		if ((conf->output.outfilename != NULL ||
+		     conf->output.tagfilename != NULL) &&
+		    pledge("stdio rpath cpath", NULL) == -1) {
+			mandoc_msg(MANDOCERR_PLEDGE, 0, 0,
+			    "%s", strerror(errno));
+			exit(mandoc_msg_getrc());
+		}
 	}
 	if (outst->had_output && outst->outtype <= OUTT_UTF8) {
 		if (outst->outdata == NULL)
@@ -876,7 +892,7 @@ parse(struct mparse *mp, int fd, const char *file,
 	if (outst->outdata == NULL)
 		outdata_alloc(outst, outconf);
 	else if (outst->outtype == OUTT_HTML)
-		html_reset(outst);
+		html_reset(outst->outdata);
 
 	mandoc_xr_reset();
 	meta = mparse_result(mp);
@@ -1124,15 +1140,15 @@ woptions(char *arg, enum mandoc_os *os_e, int *wstop)
  * then fork the pager and wait for the user to close it.
  */
 static void
-run_pager(struct tag_files *tag_files, char *tag_target)
+run_pager(struct outstate *outst, char *tag_target)
 {
 	int	 signum, status;
 	pid_t	 man_pgid, tc_pgid;
 	pid_t	 pager_pid, wait_pid;
 
 	man_pgid = getpgid(0);
-	tag_files->tcpgid = man_pgid == getpid() ? getpgid(getppid()) :
-	    man_pgid;
+	outst->tag_files->tcpgid =
+	    man_pgid == getpid() ? getpgid(getppid()) : man_pgid;
 	pager_pid = 0;
 	signum = SIGSTOP;
 
@@ -1146,7 +1162,7 @@ run_pager(struct tag_files *tag_files, char *tag_target)
 				if (signum == SIGTTIN)
 					continue;
 			} else
-				tag_files->tcpgid = tc_pgid;
+				outst->tag_files->tcpgid = tc_pgid;
 			kill(0, signum);
 			continue;
 		}
@@ -1157,7 +1173,7 @@ run_pager(struct tag_files *tag_files, char *tag_target)
 			(void)tcsetpgrp(STDOUT_FILENO, pager_pid);
 			kill(pager_pid, SIGCONT);
 		} else
-			pager_pid = spawn_pager(tag_files, tag_target);
+			pager_pid = spawn_pager(outst, tag_target);
 
 		/* Wait for the pager to stop or exit. */
 
@@ -1178,7 +1194,7 @@ run_pager(struct tag_files *tag_files, char *tag_target)
 }
 
 static pid_t
-spawn_pager(struct tag_files *tag_files, char *tag_target)
+spawn_pager(struct outstate *outst, char *tag_target)
 {
 	const struct timespec timeout = { 0, 100000000 };  /* 0.1s */
 #define MAX_PAGER_ARGS 16
@@ -1191,14 +1207,14 @@ spawn_pager(struct tag_files *tag_files, char *tag_target)
 	int		 argc, use_ofn;
 	pid_t		 pager_pid;
 
-	assert(tag_files->ofd == -1);
-	assert(tag_files->tfs == NULL);
+	assert(outst->tag_files->ofd == -1);
+	assert(outst->tag_files->tfs == NULL);
 
 	pager = getenv("MANPAGER");
 	if (pager == NULL || *pager == '\0')
 		pager = getenv("PAGER");
 	if (pager == NULL || *pager == '\0')
-		pager = "more -s";
+		pager = "less";
 	cp = mandoc_strdup(pager);
 
 	/*
@@ -1223,11 +1239,12 @@ spawn_pager(struct tag_files *tag_files, char *tag_target)
 
 	use_ofn = 1;
 #ifdef HAVE_LESS_T
-	if (*tag_files->tfn != '\0' && (cmdlen = strlen(argv[0])) >= 4) {
+	if (*outst->tag_files->tfn != '\0' &&
+	    (cmdlen = strlen(argv[0])) >= 4) {
 		cp = argv[0] + cmdlen - 4;
 		if (strcmp(cp, "less") == 0 || strcmp(cp, "more") == 0) {
 			argv[argc++] = mandoc_strdup("-T");
-			argv[argc++] = tag_files->tfn;
+			argv[argc++] = outst->tag_files->tfn;
 			if (tag_target != NULL) {
 				argv[argc++] = mandoc_strdup("-t");
 				argv[argc++] = tag_target;
@@ -1236,8 +1253,14 @@ spawn_pager(struct tag_files *tag_files, char *tag_target)
 		}
 	}
 #endif
-	if (use_ofn)
-		argv[argc++] = tag_files->ofn;
+	if (use_ofn) {
+		if (outst->outtype == OUTT_HTML && tag_target != NULL)
+			mandoc_asprintf(&argv[argc], "file://%s#%s",
+			    outst->tag_files->ofn, tag_target);
+		else
+			argv[argc] = outst->tag_files->ofn;
+		argc++;
+	}
 	argv[argc] = NULL;
 
 	switch (pager_pid = fork()) {
@@ -1254,7 +1277,7 @@ spawn_pager(struct tag_files *tag_files, char *tag_target)
 			    "%s", strerror(errno));
 			exit(mandoc_msg_getrc());
 		}
-		tag_files->pager_pid = pager_pid;
+		outst->tag_files->pager_pid = pager_pid;
 		return pager_pid;
 	}
 
diff --git a/usr.bin/mandoc/man.1 b/usr.bin/mandoc/man.1
index 2d4d33a..eb0fae7 100644
--- a/usr.bin/mandoc/man.1
+++ b/usr.bin/mandoc/man.1
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: man.1,v 1.36 2020/02/10 13:49:04 schwarze Exp $
+.\"	$OpenBSD: man.1,v 1.39 2020/07/20 14:52:12 schwarze Exp $
 .\"
 .\" Copyright (c) 1989, 1990, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -31,7 +31,7 @@
 .\"
 .\"     @(#)man.1	8.2 (Berkeley) 1/2/94
 .\"
-.Dd $Mdocdate: February 10 2020 $
+.Dd $Mdocdate: July 20 2020 $
 .Dt MAN 1
 .Os
 .Sh NAME
@@ -74,7 +74,7 @@ See
 for a description of the contents of this file.
 .It Fl c
 Copy the manual page to the standard output instead of using
-.Xr more 1
+.Xr less 1
 to paginate it.
 This is done by default if the standard output is not a terminal device.
 .Pp
@@ -167,6 +167,7 @@ architecture whilst using another.
 This option overrides the
 .Ev MACHINE
 environment variable.
+.Tg s
 .It Oo Fl s Oc Ar section
 Only select manuals from the specified
 .Ar section .
@@ -274,7 +275,7 @@ is case insensitive.
 Any non-empty value of the environment variable
 .Ev MANPAGER
 is used instead of the standard pagination program,
-.Xr more 1 .
+.Xr less 1 .
 If
 .Xr less 1
 is used, the interactive
@@ -328,8 +329,7 @@ Specifies the pagination program to use when
 .Ev MANPAGER
 is not defined.
 If neither PAGER nor MANPAGER is defined,
-.Xr more 1
-.Fl s
+.Xr less 1
 is used.
 .El
 .Sh FILES
diff --git a/usr.bin/mandoc/man_macro.c b/usr.bin/mandoc/man_macro.c
index dc0bcfd..dc3832d 100644
--- a/usr.bin/mandoc/man_macro.c
+++ b/usr.bin/mandoc/man_macro.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: man_macro.c,v 1.106 2019/01/05 18:59:37 schwarze Exp $ */
+/* $OpenBSD: man_macro.c,v 1.107 2020/09/09 16:57:05 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012-2015, 2017-2019 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -105,9 +105,11 @@ man_unscope(struct roff_man *man, const struct roff_node *to)
 				mandoc_msg(MANDOCERR_BLK_LINE,
 				    n->line, n->pos,
 				    "EOF breaks %s", roff_name[n->tok]);
-				if (man->flags & MAN_ELINE)
-					man->flags &= ~MAN_ELINE;
-				else {
+				if (man->flags & MAN_ELINE) {
+					if ((man_macro(n->parent->tok)->flags &
+					    MAN_ESCOPED) == 0)
+						man->flags &= ~MAN_ELINE;
+				} else {
 					assert(n->type == ROFFT_HEAD);
 					n = n->parent;
 					man->flags &= ~MAN_BLINE;
diff --git a/usr.bin/mandoc/manconf.h b/usr.bin/mandoc/manconf.h
index 4cc623f..5073121 100644
--- a/usr.bin/mandoc/manconf.h
+++ b/usr.bin/mandoc/manconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: manconf.h,v 1.8 2020/04/02 22:10:27 schwarze Exp $ */
+/* $OpenBSD: manconf.h,v 1.9 2020/07/21 15:08:49 schwarze Exp $ */
 /*
  * Copyright (c) 2011,2015,2017,2018,2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -31,9 +31,11 @@ struct	manpaths {
 struct	manoutput {
 	char	 *includes;
 	char	 *man;
+	char	 *outfilename;
 	char	 *paper;
 	char	 *style;
 	char	 *tag;
+	char	 *tagfilename;
 	size_t	  indent;
 	size_t	  width;
 	int	  fragment;
diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1
index a5ea382..78c5a4c 100644
--- a/usr.bin/mandoc/mandoc.1
+++ b/usr.bin/mandoc/mandoc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mandoc.1,v 1.167 2020/04/24 11:58:02 schwarze Exp $
+.\" $OpenBSD: mandoc.1,v 1.173 2020/09/01 18:24:09 schwarze Exp $
 .\"
 .\" Copyright (c) 2012, 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: April 24 2020 $
+.Dd $Mdocdate: September 1 2020 $
 .Dt MANDOC 1
 .Os
 .Sh NAME
@@ -52,13 +52,13 @@ The options are as follows:
 If the standard output is a terminal device and
 .Fl c
 is not specified, use
-.Xr more 1
+.Xr less 1
 to paginate the output, just like
 .Xr man 1
 would.
 .It Fl c
 Copy the formatted manual pages to the standard output without using
-.Xr more 1
+.Xr less 1
 to paginate them.
 This is the default.
 It can be specified to override
@@ -410,6 +410,30 @@ The file
 is used for an external style-sheet.
 This must be a valid absolute or
 relative URI.
+.It Cm tag Ns Op = Ns Ar term
+Same syntax and semantics as for
+.Sx ASCII Output .
+This is implemented by passing a
+.Ic file://
+URI ending in a fragment identifier to the pager
+rather than passing merely a file name.
+When using this argument, use a pager supporting such URIs, for example
+.Bd -literal -offset 3n
+MANPAGER='lynx -force_html' man -T html -O tag=MANPAGER man
+MANPAGER='w3m -T text/html' man -T html -O tag=toc mandoc
+.Ed
+.Pp
+Consequently, for HTML output, this argument does not work with
+.Xr more 1
+or
+.Xr less 1 .
+For example,
+.Ql MANPAGER=less man -T html -O tag=toc mandoc
+does not work because
+.Xr less 1
+does not support
+.Ic file://
+URIs.
 .It Cm toc
 If an input file contains at least two non-standard sections,
 print a table of contents near the beginning of the output.
@@ -451,10 +475,7 @@ code is not supported.
 .Pp
 If the input format of a file is
 .Xr man 7 ,
-the input is copied to the output, expanding any
-.Xr roff 7
-.Ic so
-requests.
+the input is copied to the output.
 The parser is also run, and as usual, the
 .Fl W
 level controls which
@@ -633,7 +654,7 @@ It never affects the interpretation of input files.
 Any non-empty value of the environment variable
 .Ev MANPAGER
 is used instead of the standard pagination program,
-.Xr more 1 ;
+.Xr less 1 ;
 see
 .Xr man 1
 for details.
@@ -647,8 +668,7 @@ Specifies the pagination program to use when
 .Ev MANPAGER
 is not defined.
 If neither PAGER nor MANPAGER is defined,
-.Xr more 1
-.Fl s
+.Xr less 1
 is used.
 Only used if
 .Fl a
@@ -1830,6 +1850,10 @@ The invalid character is discarded.
 A table layout specification contains an opening parenthesis,
 but no matching closing parenthesis.
 The rest of the input line, starting from the parenthesis, has no effect.
+.It Sy "ignoring excessive spacing in tbl layout"
+.Pq tbl
+A spacing modifier in a table layout is unreasonably large.
+The default spacing of 3n is used instead.
 .It Sy "tbl without any data cells"
 .Pq tbl
 A table does not contain any data cells.
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h
index 3a48c89..3d1a3f9 100644
--- a/usr.bin/mandoc/mandoc.h
+++ b/usr.bin/mandoc/mandoc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mandoc.h,v 1.210 2020/04/24 11:58:02 schwarze Exp $ */
+/* $OpenBSD: mandoc.h,v 1.211 2020/09/01 18:24:09 schwarze Exp $ */
 /*
  * Copyright (c) 2012-2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -189,6 +189,7 @@ enum	mandocerr {
 	MANDOCERR_TBLLAYOUT_NONE, /* empty tbl layout */
 	MANDOCERR_TBLLAYOUT_CHAR, /* invalid character in tbl layout: char */
 	MANDOCERR_TBLLAYOUT_PAR, /* unmatched parenthesis in tbl layout */
+	MANDOCERR_TBLLAYOUT_SPC, /* ignoring excessive spacing in tbl layout */
 	MANDOCERR_TBLDATA_NONE, /* tbl without any data cells */
 	MANDOCERR_TBLDATA_SPAN, /* ignoring data in spanned tbl cell: data */
 	MANDOCERR_TBLDATA_EXTRA, /* ignoring extra tbl data cells: data */
diff --git a/usr.bin/mandoc/mandoc_msg.c b/usr.bin/mandoc/mandoc_msg.c
index a9334ae..d40b7e5 100644
--- a/usr.bin/mandoc/mandoc_msg.c
+++ b/usr.bin/mandoc/mandoc_msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mandoc_msg.c,v 1.9 2020/04/24 11:58:02 schwarze Exp $ */
+/* $OpenBSD: mandoc_msg.c,v 1.10 2020/09/01 18:24:10 schwarze Exp $ */
 /*
  * Copyright (c) 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -188,6 +188,7 @@ static	const char *const type_message[MANDOCERR_MAX] = {
 	"empty tbl layout",
 	"invalid character in tbl layout",
 	"unmatched parenthesis in tbl layout",
+	"ignoring excessive spacing in tbl layout",
 	"tbl without any data cells",
 	"ignoring data in spanned tbl cell",
 	"ignoring extra tbl data cells",
diff --git a/usr.bin/mandoc/manpath.c b/usr.bin/mandoc/manpath.c
index dcd12a0..96d08ae 100644
--- a/usr.bin/mandoc/manpath.c
+++ b/usr.bin/mandoc/manpath.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: manpath.c,v 1.28 2020/02/10 14:42:03 schwarze Exp $ */
+/*	$OpenBSD: manpath.c,v 1.30 2020/08/27 14:59:42 schwarze Exp $ */
 /*
  * Copyright (c) 2011,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -225,8 +225,13 @@ int
 manconf_output(struct manoutput *conf, const char *cp, int fromfile)
 {
 	const char *const toks[] = {
+	    /* Tokens requiring an argument. */
 	    "includes", "man", "paper", "style", "indent", "width",
-	    "tag", "fragment", "mdoc", "noval", "toc"
+	    "outfilename", "tagfilename",
+	    /* Token taking an optional argument. */
+	    "tag",
+	    /* Tokens not taking arguments. */
+	    "fragment", "mdoc", "noval", "toc"
 	};
 	const size_t ntoks = sizeof(toks) / sizeof(toks[0]);
 
@@ -247,11 +252,11 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
 		}
 	}
 
-	if (tok < 6 && *cp == '\0') {
+	if (tok < 8 && *cp == '\0') {
 		mandoc_msg(MANDOCERR_BADVAL_MISS, 0, 0, "-O %s=?", toks[tok]);
 		return -1;
 	}
-	if (tok > 6 && tok < ntoks && *cp != '\0') {
+	if (tok > 8 && tok < ntoks && *cp != '\0') {
 		mandoc_msg(MANDOCERR_BADVAL, 0, 0, "-O %s=%s", toks[tok], cp);
 		return -1;
 	}
@@ -308,22 +313,40 @@ manconf_output(struct manoutput *conf, const char *cp, int fromfile)
 		    "-O width=%s is %s", cp, errstr);
 		return -1;
 	case 6:
+		if (conf->outfilename != NULL) {
+			oldval = mandoc_strdup(conf->outfilename);
+			break;
+		}
+		conf->outfilename = mandoc_strdup(cp);
+		return 0;
+	case 7:
+		if (conf->tagfilename != NULL) {
+			oldval = mandoc_strdup(conf->tagfilename);
+			break;
+		}
+		conf->tagfilename = mandoc_strdup(cp);
+		return 0;
+	/*
+	 * If the index of the following token changes,
+	 * do not forget to adjust the range check above the switch.
+	 */
+	case 8:
 		if (conf->tag != NULL) {
 			oldval = mandoc_strdup(conf->tag);
 			break;
 		}
 		conf->tag = mandoc_strdup(cp);
 		return 0;
-	case 7:
+	case 9:
 		conf->fragment = 1;
 		return 0;
-	case 8:
+	case 10:
 		conf->mdoc = 1;
 		return 0;
-	case 9:
+	case 11:
 		conf->noval = 1;
 		return 0;
-	case 10:
+	case 12:
 		conf->toc = 1;
 		return 0;
 	default:
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 870305e..07c977d 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff.c,v 1.246 2020/04/08 11:54:14 schwarze Exp $ */
+/* $OpenBSD: roff.c,v 1.248 2020/08/27 12:58:00 schwarze Exp $ */
 /*
  * Copyright (c) 2010-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -191,6 +191,7 @@ static	int		 roff_cc(ROFF_ARGS);
 static	int		 roff_ccond(struct roff *, int, int);
 static	int		 roff_char(ROFF_ARGS);
 static	int		 roff_cond(ROFF_ARGS);
+static	int		 roff_cond_checkend(ROFF_ARGS);
 static	int		 roff_cond_text(ROFF_ARGS);
 static	int		 roff_cond_sub(ROFF_ARGS);
 static	int		 roff_ds(ROFF_ARGS);
@@ -2033,14 +2034,13 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos)
 
 /* --- handling of request blocks ----------------------------------------- */
 
+/*
+ * Close a macro definition block or an "ignore" block.
+ */
 static int
 roff_cblock(ROFF_ARGS)
 {
-
-	/*
-	 * A block-close `..' should only be invoked as a child of an
-	 * ignore macro, otherwise raise a warning and just ignore it.
-	 */
+	int	 rr;
 
 	if (r->last == NULL) {
 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, ppos, "..");
@@ -2049,26 +2049,38 @@ roff_cblock(ROFF_ARGS)
 
 	switch (r->last->tok) {
 	case ROFF_am:
-		/* ROFF_am1 is remapped to ROFF_am in roff_block(). */
 	case ROFF_ami:
 	case ROFF_de:
-		/* ROFF_de1 is remapped to ROFF_de in roff_block(). */
 	case ROFF_dei:
 	case ROFF_ig:
 		break;
+	case ROFF_am1:
+	case ROFF_de1:
+		/* Remapped in roff_block(). */
+		abort();
 	default:
 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, ln, ppos, "..");
 		return ROFF_IGN;
 	}
 
+	roffnode_pop(r);
+	roffnode_cleanscope(r);
+
+	/*
+	 * If a conditional block with braces is still open,
+	 * check for "\}" block end markers.
+	 */
+
+	if (r->last != NULL && r->last->endspan < 0) {
+		rr = 1;  /* If arguments follow "\}", warn about them. */
+		roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
+	}
+
 	if (buf->buf[pos] != '\0')
 		mandoc_msg(MANDOCERR_ARG_SKIP, ln, pos,
 		    ".. %s", buf->buf + pos);
 
-	roffnode_pop(r);
-	roffnode_cleanscope(r);
 	return ROFF_IGN;
-
 }
 
 /*
@@ -2081,7 +2093,7 @@ roffnode_cleanscope(struct roff *r)
 	int inloop;
 
 	inloop = 0;
-	while (r->last != NULL) {
+	while (r->last != NULL && r->last->endspan > 0) {
 		if (--r->last->endspan != 0)
 			break;
 		inloop += roffnode_pop(r);
@@ -2090,7 +2102,7 @@ roffnode_cleanscope(struct roff *r)
 }
 
 /*
- * Handle the closing \} of a conditional block.
+ * Handle the closing "\}" of a conditional block.
  * Apart from generating warnings, this only pops nodes.
  * Return the number of loops ended.
  */
@@ -2310,13 +2322,20 @@ roff_block_text(ROFF_ARGS)
 	return ROFF_IGN;
 }
 
+/*
+ * Check for a closing "\}" and handle it.
+ * In this function, the final "int *offs" argument is used for
+ * different purposes than elsewhere:
+ * Input: *offs == 0: caller wants to discard arguments following \}
+ *        *offs == 1: caller wants to preserve text following \}
+ * Output: *offs = 0: tell caller to discard input line
+ *         *offs = 1: tell caller to use input line
+ */
 static int
-roff_cond_sub(ROFF_ARGS)
+roff_cond_checkend(ROFF_ARGS)
 {
-	struct roffnode	*bl;
 	char		*ep;
 	int		 endloop, irc, rr;
-	enum roff_tok	 t;
 
 	irc = ROFF_IGN;
 	rr = r->last->rule;
@@ -2326,23 +2345,28 @@ roff_cond_sub(ROFF_ARGS)
 		irc |= endloop;
 
 	/*
-	 * If `\}' occurs on a macro line without a preceding macro,
-	 * drop the line completely.
+	 * If "\}" occurs on a macro line without a preceding macro or
+	 * a text line contains nothing else, drop the line completely.
 	 */
 
 	ep = buf->buf + pos;
-	if (ep[0] == '\\' && ep[1] == '}')
+	if (ep[0] == '\\' && ep[1] == '}' && (ep[2] == '\0' || *offs == 0))
 		rr = 0;
 
 	/*
-	 * The closing delimiter `\}' rewinds the conditional scope
+	 * The closing delimiter "\}" rewinds the conditional scope
 	 * but is otherwise ignored when interpreting the line.
 	 */
 
 	while ((ep = strchr(ep, '\\')) != NULL) {
 		switch (ep[1]) {
 		case '}':
-			memmove(ep, ep + 2, strlen(ep + 2) + 1);
+			if (ep[2] == '\0')
+				ep[0] = '\0';
+			else if (rr)
+				ep[1] = '&';
+			else
+				memmove(ep, ep + 2, strlen(ep + 2) + 1);
 			if (roff_ccond(r, ln, ep - buf->buf))
 				irc |= endloop;
 			break;
@@ -2354,7 +2378,22 @@ roff_cond_sub(ROFF_ARGS)
 			break;
 		}
 	}
+	*offs = rr;
+	return irc;
+}
 
+/*
+ * Parse and process a request or macro line in conditional scope.
+ */
+static int
+roff_cond_sub(ROFF_ARGS)
+{
+	struct roffnode	*bl;
+	int		 irc, rr;
+	enum roff_tok	 t;
+
+	rr = 0;  /* If arguments follow "\}", skip them. */
+	irc = roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
 	t = roff_parse(r, buf->buf, &pos, ln, ppos);
 
 	/* For now, let high level macros abort .ce mode. */
@@ -2391,48 +2430,16 @@ roff_cond_sub(ROFF_ARGS)
 	return irc;
 }
 
+/*
+ * Parse and process a text line in conditional scope.
+ */
 static int
 roff_cond_text(ROFF_ARGS)
 {
-	char		*ep;
-	int		 endloop, irc, rr;
-
-	irc = ROFF_IGN;
-	rr = r->last->rule;
-	endloop = tok != ROFF_while ? ROFF_IGN :
-	    rr ? ROFF_LOOPCONT : ROFF_LOOPEXIT;
-	if (roffnode_cleanscope(r))
-		irc |= endloop;
-
-	/*
-	 * If `\}' occurs on a text line with neither preceding
-	 * nor following characters, drop the line completely.
-	 */
-
-	ep = buf->buf + pos;
-	if (strcmp(ep, "\\}") == 0)
-		rr = 0;
-
-	/*
-	 * The closing delimiter `\}' rewinds the conditional scope
-	 * but is otherwise ignored when interpreting the line.
-	 */
+	int	 irc, rr;
 
-	while ((ep = strchr(ep, '\\')) != NULL) {
-		switch (ep[1]) {
-		case '}':
-			memmove(ep, ep + 2, strlen(ep + 2) + 1);
-			if (roff_ccond(r, ln, ep - buf->buf))
-				irc |= endloop;
-			break;
-		case '\0':
-			++ep;
-			break;
-		default:
-			ep += 2;
-			break;
-		}
-	}
+	rr = 1;  /* If arguments follow "\}", preserve them. */
+	irc = roff_cond_checkend(r, tok, buf, ln, ppos, pos, &rr);
 	if (rr)
 		irc |= ROFF_CONT;
 	return irc;
diff --git a/usr.bin/mandoc/roff_term.c b/usr.bin/mandoc/roff_term.c
index ef90623..069206a 100644
--- a/usr.bin/mandoc/roff_term.c
+++ b/usr.bin/mandoc/roff_term.c
@@ -1,6 +1,6 @@
-/*	$OpenBSD: roff_term.c,v 1.19 2019/01/04 03:24:30 schwarze Exp $ */
+/* $OpenBSD: roff_term.c,v 1.21 2020/09/03 20:33:20 schwarze Exp $ */
 /*
- * Copyright (c) 2010,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010,2014,2015,2017-2020 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -155,9 +155,13 @@ static void
 roff_term_pre_po(ROFF_TERM_ARGS)
 {
 	struct roffsu	 su;
-	static int	 po, polast;
+	static int	 po, pouse, polast;
 	int		 ponew;
 
+	/* Revert the currently active page offset. */
+	p->tcol->offset -= pouse;
+
+	/* Determine the requested page offset. */
 	if (n->child != NULL &&
 	    a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
 		ponew = term_hen(p, &su);
@@ -166,11 +170,15 @@ roff_term_pre_po(ROFF_TERM_ARGS)
 			ponew += po;
 	} else
 		ponew = polast;
+
+	/* Remeber both the previous and the newly requested offset. */
 	polast = po;
 	po = ponew;
 
-	ponew = po - polast + (int)p->tcol->offset;
-	p->tcol->offset = ponew > 0 ? ponew : 0;
+	/* Truncate to the range [-offset, 60], remember, and apply it. */
+	pouse = po >= 60 ? 60 :
+	    po < -(int)p->tcol->offset ? -p->tcol->offset : po;
+	p->tcol->offset += pouse;
 }
 
 static void
@@ -208,6 +216,7 @@ roff_term_pre_ti(ROFF_TERM_ARGS)
 {
 	struct roffsu	 su;
 	const char	*cp;
+	const size_t	 maxoff = 72;
 	int		 len, sign;
 
 	roff_term_pre_br(p, n);
@@ -228,17 +237,26 @@ roff_term_pre_ti(ROFF_TERM_ARGS)
 		return;
 	len = term_hen(p, &su);
 
-	if (sign == 0) {
+	switch (sign) {
+	case 1:
+		if (p->tcol->offset + len <= maxoff)
+			p->ti = len;
+		else if (p->tcol->offset < maxoff)
+			p->ti = maxoff - p->tcol->offset;
+		else
+			p->ti = 0;
+		break;
+	case -1:
+		if ((size_t)len < p->tcol->offset)
+			p->ti = -len;
+		else
+			p->ti = -p->tcol->offset;
+		break;
+	default:
+		if ((size_t)len > maxoff)
+			len = maxoff;
 		p->ti = len - p->tcol->offset;
-		p->tcol->offset = len;
-	} else if (sign == 1) {
-		p->ti = len;
-		p->tcol->offset += len;
-	} else if ((size_t)len < p->tcol->offset) {
-		p->ti = -len;
-		p->tcol->offset -= len;
-	} else {
-		p->ti = -p->tcol->offset;
-		p->tcol->offset = 0;
+		break;
 	}
+	p->tcol->offset += p->ti;
 }
diff --git a/usr.bin/mandoc/tbl_layout.c b/usr.bin/mandoc/tbl_layout.c
index aae36d9..d7ecf3b 100644
--- a/usr.bin/mandoc/tbl_layout.c
+++ b/usr.bin/mandoc/tbl_layout.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: tbl_layout.c,v 1.35 2018/12/14 05:17:45 schwarze Exp $ */
+/*	$OpenBSD: tbl_layout.c,v 1.36 2020/09/01 18:24:10 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -63,6 +63,7 @@ mods(struct tbl_node *tbl, struct tbl_cell *cp,
 		int ln, const char *p, int *pos)
 {
 	char		*endptr;
+	unsigned long	 spacing;
 	size_t		 sz;
 
 mod:
@@ -91,7 +92,11 @@ mod:
 	/* Parse numerical spacing from modifier string. */
 
 	if (isdigit((unsigned char)p[*pos])) {
-		cp->spacing = strtoull(p + *pos, &endptr, 10);
+		if ((spacing = strtoul(p + *pos, &endptr, 10)) > 9)
+			mandoc_msg(MANDOCERR_TBLLAYOUT_SPC, ln, *pos,
+			    "%lu", spacing);
+		else
+			cp->spacing = spacing;
 		*pos = endptr - p;
 		goto mod;
 	}
diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c
index 68f78d7..a3a6c89 100644
--- a/usr.bin/mandoc/term.c
+++ b/usr.bin/mandoc/term.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: term.c,v 1.141 2019/06/03 20:23:39 schwarze Exp $ */
+/* $OpenBSD: term.c,v 1.142 2020/09/02 16:36:48 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -36,8 +36,7 @@ static	void		 bufferc(struct termp *, char);
 static	void		 encode(struct termp *, const char *, size_t);
 static	void		 encode1(struct termp *, int);
 static	void		 endline(struct termp *);
-static	void		 term_field(struct termp *, size_t, size_t,
-				size_t, size_t);
+static	void		 term_field(struct termp *, size_t, size_t);
 static	void		 term_fill(struct termp *, size_t *, size_t *,
 				size_t);
 
@@ -125,8 +124,7 @@ term_flushln(struct termp *p)
 		 * and with the BRNEVER flag, never break it at all.
 		 */
 
-		vtarget = p->flags & TERMP_BRNEVER ? SIZE_MAX :
-		    (p->flags & TERMP_NOBREAK) == 0 ? vfield :
+		vtarget = (p->flags & TERMP_NOBREAK) == 0 ? vfield :
 		    p->maxrmargin > p->viscol + vbl ?
 		    p->maxrmargin - p->viscol - vbl : 0;
 
@@ -135,7 +133,8 @@ term_flushln(struct termp *p)
 		 * If there is whitespace only, print nothing.
 		 */
 
-		term_fill(p, &nbr, &vbr, vtarget);
+		term_fill(p, &nbr, &vbr,
+		    p->flags & TERMP_BRNEVER ? SIZE_MAX : vtarget);
 		if (nbr == 0)
 			break;
 
@@ -154,7 +153,7 @@ term_flushln(struct termp *p)
 
 		/* Finally, print the field content. */
 
-		term_field(p, vbl, nbr, vbr, vtarget);
+		term_field(p, vbl, nbr);
 
 		/*
 		 * If there is no text left in the field, exit the loop.
@@ -343,12 +342,10 @@ term_fill(struct termp *p, size_t *nbr, size_t *vbr, size_t vtarget)
 /*
  * Print the contents of one field
  * with an indentation of	 vbl	  visual columns,
- * an input string length of	 nbr	  characters,
- * an output width of		 vbr	  visual columns,
- * and a desired field width of	 vtarget  visual columns.
+ * and an input string length of nbr	  characters.
  */
 static void
-term_field(struct termp *p, size_t vbl, size_t nbr, size_t vbr, size_t vtarget)
+term_field(struct termp *p, size_t vbl, size_t nbr)
 {
 	size_t	 ic;	/* Character position in the input buffer. */
 	size_t	 vis;	/* Visual position of the current character. */
diff --git a/usr.bin/mandoc/term_ascii.c b/usr.bin/mandoc/term_ascii.c
index 9b28060..8b89deb 100644
--- a/usr.bin/mandoc/term_ascii.c
+++ b/usr.bin/mandoc/term_ascii.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: term_ascii.c,v 1.50 2019/07/19 21:45:37 schwarze Exp $ */
+/* $OpenBSD: term_ascii.c,v 1.52 2020/09/09 13:40:24 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014,2015,2017,2018,2020 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -222,7 +222,10 @@ ascii_endline(struct termp *p)
 {
 
 	p->line++;
-	p->tcol->offset -= p->ti;
+	if ((int)p->tcol->offset > p->ti)
+		p->tcol->offset -= p->ti;
+	else
+		p->tcol->offset = 0;
 	p->ti = 0;
 	putchar('\n');
 }
@@ -232,7 +235,14 @@ ascii_advance(struct termp *p, size_t len)
 {
 	size_t		i;
 
-	assert(len < UINT16_MAX);
+	/*
+	 * XXX We used to have "assert(len < UINT16_MAX)" here.
+	 * that is not quite right because the input document
+	 * can trigger that by merely providing large input.
+	 * For now, simply truncate.
+	 */
+	if (len > 256)
+		len = 256;
 	for (i = 0; i < len; i++)
 		putchar(' ');
 }
@@ -369,7 +379,14 @@ locale_advance(struct termp *p, size_t len)
 {
 	size_t		i;
 
-	assert(len < UINT16_MAX);
+	/*
+	 * XXX We used to have "assert(len < UINT16_MAX)" here.
+	 * that is not quite right because the input document
+	 * can trigger that by merely providing large input.
+	 * For now, simply truncate.
+	 */
+	if (len > 256)
+		len = 256;
 	for (i = 0; i < len; i++)
 		putwchar(L' ');
 }
@@ -379,7 +396,10 @@ locale_endline(struct termp *p)
 {
 
 	p->line++;
-	p->tcol->offset -= p->ti;
+	if ((int)p->tcol->offset > p->ti)
+		p->tcol->offset -= p->ti;
+	else 
+		p->tcol->offset = 0;
 	p->ti = 0;
 	putwchar(L'\n');
 }
diff --git a/usr.bin/mandoc/term_ps.c b/usr.bin/mandoc/term_ps.c
index 9460c88..3d16520 100644
--- a/usr.bin/mandoc/term_ps.c
+++ b/usr.bin/mandoc/term_ps.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: term_ps.c,v 1.55 2017/11/10 14:16:28 espie Exp $ */
+/* $OpenBSD: term_ps.c,v 1.56 2020/09/06 14:44:19 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015, 2016, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014,2015,2016,2017,2020 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2017 Marc Espie <espie@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -1248,7 +1248,10 @@ ps_endline(struct termp *p)
 
 	ps_closepage(p);
 
-	p->tcol->offset -= p->ti;
+	if ((int)p->tcol->offset > p->ti)
+		p->tcol->offset -= p->ti;
+	else 
+		p->tcol->offset = 0;
 	p->ti = 0;
 }
 
diff --git a/usr.bin/mandoc/term_tag.c b/usr.bin/mandoc/term_tag.c
index 1c67dcc..86ad01e 100644
--- a/usr.bin/mandoc/term_tag.c
+++ b/usr.bin/mandoc/term_tag.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: term_tag.c,v 1.4 2020/04/18 20:28:46 schwarze Exp $ */
+/* $OpenBSD: term_tag.c,v 1.5 2020/07/21 15:08:49 schwarze Exp $ */
 /*
  * Copyright (c) 2015,2016,2018,2019,2020 Ingo Schwarze <schwarze@openbsd.org>
  *
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #include <signal.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -44,7 +45,7 @@ static struct tag_files tag_files;
  * but for simplicity, create it anyway.
  */
 struct tag_files *
-term_tag_init(void)
+term_tag_init(const char *outfilename, const char *tagfilename)
 {
 	struct sigaction	 sa;
 	int			 ofd;	/* In /tmp/, dup(2)ed to stdout. */
@@ -81,19 +82,43 @@ term_tag_init(void)
 
 	/* Create both temporary output files. */
 
-	(void)strlcpy(tag_files.ofn, "/tmp/man.XXXXXXXXXX",
-	    sizeof(tag_files.ofn));
-	(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
-	    sizeof(tag_files.tfn));
-	if ((ofd = mkstemp(tag_files.ofn)) == -1) {
-		mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
-		    "%s: %s", tag_files.ofn, strerror(errno));
-		goto fail;
+	if (outfilename == NULL) {
+		(void)strlcpy(tag_files.ofn, "/tmp/man.XXXXXXXXXX",
+		    sizeof(tag_files.ofn));
+		if ((ofd = mkstemp(tag_files.ofn)) == -1) {
+			mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
+			    "%s: %s", tag_files.ofn, strerror(errno));
+			goto fail;
+		}
+	} else {
+		(void)strlcpy(tag_files.ofn, outfilename,
+		   sizeof(tag_files.ofn));
+		unlink(outfilename);
+		ofd = open(outfilename, O_WRONLY | O_CREAT | O_EXCL, 0644);
+		if (ofd == -1) {
+			mandoc_msg(MANDOCERR_OPEN, 0, 0,
+			    "%s: %s", outfilename, strerror(errno));
+			goto fail;
+		}
 	}
-	if ((tfd = mkstemp(tag_files.tfn)) == -1) {
-		mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
-		    "%s: %s", tag_files.tfn, strerror(errno));
-		goto fail;
+	if (tagfilename == NULL) {
+		(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
+		    sizeof(tag_files.tfn));
+		if ((tfd = mkstemp(tag_files.tfn)) == -1) {
+			mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
+			    "%s: %s", tag_files.tfn, strerror(errno));
+			goto fail;
+		}
+	} else {
+		(void)strlcpy(tag_files.tfn, tagfilename,
+		    sizeof(tag_files.tfn));
+		unlink(tagfilename);
+		tfd = open(tagfilename, O_WRONLY | O_CREAT | O_EXCL, 0644);
+		if (tfd == -1) {
+			mandoc_msg(MANDOCERR_OPEN, 0, 0,
+			    "%s: %s", tagfilename, strerror(errno));
+			goto fail;
+		}
 	}
 	if ((tag_files.tfs = fdopen(tfd, "w")) == NULL) {
 		mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
@@ -173,11 +198,11 @@ term_tag_unlink(void)
 		    getpgid(tc_pgid) == -1)
 			(void)tcsetpgrp(STDOUT_FILENO, tag_files.tcpgid);
 	}
-	if (*tag_files.ofn != '\0') {
+	if (strncmp(tag_files.ofn, "/tmp/man.", 9) == 0) {
 		unlink(tag_files.ofn);
 		*tag_files.ofn = '\0';
 	}
-	if (*tag_files.tfn != '\0') {
+	if (strncmp(tag_files.tfn, "/tmp/man.", 9) == 0) {
 		unlink(tag_files.tfn);
 		*tag_files.tfn = '\0';
 	}
diff --git a/usr.bin/mandoc/term_tag.h b/usr.bin/mandoc/term_tag.h
index 62be2d3..fc692d7 100644
--- a/usr.bin/mandoc/term_tag.h
+++ b/usr.bin/mandoc/term_tag.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: term_tag.h,v 1.2 2020/04/02 22:10:27 schwarze Exp $ */
+/* $OpenBSD: term_tag.h,v 1.3 2020/07/21 15:08:49 schwarze Exp $ */
 /*
  * Copyright (c) 2015, 2018, 2019, 2020 Ingo Schwarze <schwarze@openbsd.org>
  *
@@ -19,8 +19,8 @@
  */
 
 struct	tag_files {
-	char	 ofn[20];	/* Output file name. */
-	char	 tfn[20];	/* Tag file name. */
+	char	 ofn[80];	/* Output file name. */
+	char	 tfn[80];	/* Tag file name. */
 	FILE	*tfs;		/* Tag file object. */
 	int	 ofd;		/* Original output file descriptor. */
 	pid_t	 tcpgid;	/* Process group controlling the terminal. */
@@ -28,7 +28,7 @@ struct	tag_files {
 };
 
 
-struct tag_files	*term_tag_init(void);
+struct tag_files	*term_tag_init(const char *, const char *);
 void			 term_tag_write(struct roff_node *, size_t);
 int			 term_tag_close(void);
 void			 term_tag_unlink(void);
-- 
cgit v1.2.3