summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2020-03-13 00:31:04 +0000
committerschwarze <schwarze@openbsd.org>2020-03-13 00:31:04 +0000
commit0ac7e6ecda86f609ac723da7cedfc4880e082fdd (patch)
tree145820e83a04749363dee9d32390189b6596702c
parentAdd speciulation barrier after the last remaining naked ERET instruction. (diff)
downloadwireguard-openbsd-0ac7e6ecda86f609ac723da7cedfc4880e082fdd.tar.xz
wireguard-openbsd-0ac7e6ecda86f609ac723da7cedfc4880e082fdd.zip
Split tagging into a validation part including prioritization
in tag.{h,c} and {mdoc,man}_validate.c and into a formatting part including command line argument checking in term_tag.{h,c}, html.c, and {mdoc|man}_{term|html}.c. Immediate functional benefits include: * Improved prioritization of automatic tags for .Em and .Sy. * Avoiding bogus automatic tags when .Em, .Fn, or .Sy are explicitly tagged. * Explicit tagging of .Er and .Fl now works in HTML output. * Automatic tagging of .IP and .TP now works in HTML output. But mainly, this patch provides clean earth to build further improvements on. Technical changes: * Main program: Write a tag file for ASCII and UTF-8 output only. * All formatters: There is no more need to delay writing the tags. * mdoc(7)+man(7) formatters: No more need for elaborate syntax tree inspection. * HTML formatter: If available, use the "string" attribute as the tag. * HTML formatter: New function to write permalinks, to reduce code duplication. Style cleanup in the vicinity while here: * mdoc(7) terminal formatter: To set up bold font for children, defer to termp_bold_pre() rather than calling term_fontpush() manually. * mdoc(7) terminal formatter: Garbage collect some duplicate functions. * mdoc(7) HTML formatter: Unify <code> handling, delete redundant functions. * Where possible, use switch statements rather than if cascades. * Get rid of some more Yoda notation. The necessity for such changes was first discussed with kn@, but i didn't bother him with a request to review the resulting -673/+782 line patch.
-rw-r--r--regress/usr.bin/mandoc/Makefile.inc50
-rwxr-xr-xregress/usr.bin/mandoc/copyless14
-rw-r--r--regress/usr.bin/mandoc/man/IP/Makefile7
-rw-r--r--regress/usr.bin/mandoc/man/IP/empty.in4
-rw-r--r--regress/usr.bin/mandoc/man/IP/empty.out_ascii4
-rw-r--r--regress/usr.bin/mandoc/man/IP/empty.out_html18
-rw-r--r--regress/usr.bin/mandoc/man/IP/empty.out_lint4
-rw-r--r--regress/usr.bin/mandoc/man/IP/empty.out_tag3
-rw-r--r--regress/usr.bin/mandoc/man/IP/literal.out_html8
-rw-r--r--regress/usr.bin/mandoc/man/IP/tag.in18
-rw-r--r--regress/usr.bin/mandoc/man/IP/tag.out_ascii23
-rw-r--r--regress/usr.bin/mandoc/man/IP/tag.out_html10
-rw-r--r--regress/usr.bin/mandoc/man/IP/tag.out_tag2
-rw-r--r--regress/usr.bin/mandoc/man/TP/Makefile7
-rw-r--r--regress/usr.bin/mandoc/man/TP/literal.out_html4
-rw-r--r--regress/usr.bin/mandoc/man/TP/tag.in31
-rw-r--r--regress/usr.bin/mandoc/man/TP/tag.out_ascii29
-rw-r--r--regress/usr.bin/mandoc/man/TP/tag.out_html16
-rw-r--r--regress/usr.bin/mandoc/man/TP/tag.out_tag3
-rw-r--r--regress/usr.bin/mandoc/man/TP/vert.out_html4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Cm/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Cm/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Cm/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Cm/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/Cm/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Cm/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Dv/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Dv/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Dv/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Dv/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/Dv/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Dv/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Em/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Em/tag.in23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Em/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Em/tag.out_html10
-rw-r--r--regress/usr.bin/mandoc/mdoc/Em/tag.out_markdown25
-rw-r--r--regress/usr.bin/mandoc/mdoc/Em/tag.out_tag5
-rw-r--r--regress/usr.bin/mandoc/mdoc/Er/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Er/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Er/tag.out_ascii16
-rw-r--r--regress/usr.bin/mandoc/mdoc/Er/tag.out_html12
-rw-r--r--regress/usr.bin/mandoc/mdoc/Er/tag.out_markdown25
-rw-r--r--regress/usr.bin/mandoc/mdoc/Er/tag.out_tag2
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ev/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ev/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ev/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ev/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ev/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ev/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fl/Makefile7
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fl/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fl/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fl/tag.out_html8
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fl/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fl/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fo/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fo/tag.in29
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fo/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fo/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fo/tag.out_markdown27
-rw-r--r--regress/usr.bin/mandoc/mdoc/Fo/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ic/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ic/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ic/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ic/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ic/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ic/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Li/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Li/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Li/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Li/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/Li/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Li/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Makefile4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ms/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ms/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ms/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ms/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ms/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Ms/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/No/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/No/punct.out_lint1
-rw-r--r--regress/usr.bin/mandoc/mdoc/No/tag.in21
-rw-r--r--regress/usr.bin/mandoc/mdoc/No/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/No/tag.out_html9
-rw-r--r--regress/usr.bin/mandoc/mdoc/No/tag.out_markdown23
-rw-r--r--regress/usr.bin/mandoc/mdoc/No/tag.out_tag4
-rw-r--r--regress/usr.bin/mandoc/mdoc/Sy/Makefile6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Sy/tag.in23
-rw-r--r--regress/usr.bin/mandoc/mdoc/Sy/tag.out_ascii17
-rw-r--r--regress/usr.bin/mandoc/mdoc/Sy/tag.out_html10
-rw-r--r--regress/usr.bin/mandoc/mdoc/Sy/tag.out_markdown25
-rw-r--r--regress/usr.bin/mandoc/mdoc/Sy/tag.out_tag5
-rw-r--r--regress/usr.bin/mandoc/mdoc/Tg/Makefile8
-rw-r--r--regress/usr.bin/mandoc/mdoc/Tg/warn.in34
-rw-r--r--regress/usr.bin/mandoc/mdoc/Tg/warn.out_ascii19
-rw-r--r--regress/usr.bin/mandoc/mdoc/Tg/warn.out_html11
-rw-r--r--regress/usr.bin/mandoc/mdoc/Tg/warn.out_lint6
-rw-r--r--regress/usr.bin/mandoc/mdoc/Tg/warn.out_markdown30
-rw-r--r--regress/usr.bin/mandoc/mdoc/Tg/warn.out_tag5
-rw-r--r--usr.bin/mandoc/Makefile18
-rw-r--r--usr.bin/mandoc/html.c78
-rw-r--r--usr.bin/mandoc/html.h9
-rw-r--r--usr.bin/mandoc/main.c38
-rw-r--r--usr.bin/mandoc/man_html.c16
-rw-r--r--usr.bin/mandoc/man_term.c87
-rw-r--r--usr.bin/mandoc/man_validate.c108
-rw-r--r--usr.bin/mandoc/mdoc_html.c200
-rw-r--r--usr.bin/mandoc/mdoc_term.c284
-rw-r--r--usr.bin/mandoc/mdoc_validate.c200
-rw-r--r--usr.bin/mandoc/read.c13
-rw-r--r--usr.bin/mandoc/tag.c280
-rw-r--r--usr.bin/mandoc/tag.h29
-rw-r--r--usr.bin/mandoc/term_tag.c204
-rw-r--r--usr.bin/mandoc/term_tag.h35
-rw-r--r--usr.bin/mandoc/tree.c12
117 files changed, 2125 insertions, 849 deletions
diff --git a/regress/usr.bin/mandoc/Makefile.inc b/regress/usr.bin/mandoc/Makefile.inc
index 7c89c13860e..f80ba133847 100644
--- a/regress/usr.bin/mandoc/Makefile.inc
+++ b/regress/usr.bin/mandoc/Makefile.inc
@@ -1,12 +1,13 @@
-# $OpenBSD: Makefile.inc,v 1.26 2020/01/08 10:17:14 schwarze Exp $
+# $OpenBSD: Makefile.inc,v 1.27 2020/03/13 00:31:05 schwarze Exp $
.include "Makefile.sub"
# --- programs ---
-DIFF = diff -au
-MANDOC ?= mandoc
-MOPTS ?= -mandoc
+DIFF = diff -au
+MAN ?= man
+MANDOC ?= mandoc
+MOPTS ?= -mandoc
# --- lists of targets ---
@@ -33,18 +34,17 @@ _MARKDOWNDIFFS += ${t}.diff_markdown
. endif
.endfor
+_TAGFILES = ${TAG_TARGETS:C/$/.mandoc_tag/}
+_TAGDIFFS = ${TAG_TARGETS:C/$/.diff_tag/}
+
_UTF8FILES = ${UTF8_TARGETS:C/$/.mandoc_utf8/}
_UTF8DIFFS = ${UTF8_TARGETS:C/$/.diff_utf8/}
_HTMLFILES = ${HTML_TARGETS:C/$/.mandoc_html/}
_HTMLDIFFS = ${HTML_TARGETS:C/$/.diff_html/}
-_LINTFILES =
-_LINTDIFFS =
-.for t in ${LINT_TARGETS}
-_LINTFILES += ${t}.mandoc_lint
-_LINTDIFFS += ${t}.diff_lint
-.endfor
+_LINTFILES = ${LINT_TARGETS:C/$/.mandoc_lint/}
+_LINTDIFFS = ${LINT_TARGETS:C/$/.diff_lint/}
_HTMLVALS = ${REGRESS_TARGETS:C/$/.validate_html/}
@@ -53,7 +53,7 @@ _HTMLVALS = ${REGRESS_TARGETS:C/$/.validate_html/}
# Note that bsd.regress.mk automatically adds REGRESS_TARGETS to all.
all: clean
-ascii: ascii-clean ${_ASCIIDIFFS}
+ascii: ascii-clean ${_ASCIIDIFFS} ${_TAGDIFFS}
utf8: utf8-clean ${_UTF8DIFFS}
@@ -70,10 +70,10 @@ htmlval: ${_HTMLVALS}
# --- suffix rules ---
.SUFFIXES: .diff_ascii .diff_html .diff_lint \
- .diff_man .diff_markdown .diff_utf8 \
+ .diff_man .diff_markdown .diff_tag .diff_utf8 \
.in .in_man \
.mandoc_ascii .mandoc_html .mandoc_lint \
- .mandoc_man .mandoc_markdown .mandoc_utf8 \
+ .mandoc_man .mandoc_markdown .mandoc_tag .mandoc_utf8 \
.out_ascii .out_lint .out_utf8
.in.mandoc_ascii:
@@ -82,6 +82,16 @@ htmlval: ${_HTMLVALS}
.mandoc_ascii.diff_ascii:
@${DIFF} ${.CURDIR}/${.IMPSRC:S/mandoc_ascii$/out_ascii/} ${.IMPSRC}
+.in.mandoc_tag:
+ @MANPAGER="${BSDSRCDIR}/regress/usr.bin/mandoc/copyless \
+ ${.TARGET:S/.mandoc_tag$//}" \
+ ${MAN} -l ${MOPTS} -Tascii -Ios=OpenBSD ${.IMPSRC}
+
+.mandoc_tag.diff_tag:
+ @${DIFF} ${.CURDIR}/${.IMPSRC:S/mandoc_tag$/out_tag/} ${.IMPSRC}
+ @${DIFF} ${.CURDIR}/${.IMPSRC:S/mandoc_tag$/out_ascii/} \
+ ${.IMPSRC:S/mandoc_tag$/mandoc_ascii/}
+
.in.mandoc_utf8:
@${MANDOC} ${MOPTS} -Ios=OpenBSD -Tutf8 ${.IMPSRC} > ${.TARGET}
@@ -125,7 +135,11 @@ ${t}.diff_man: ${t}.mandoc_man
. else
${t}.diff_man:
. endif
+. if empty(TAG_TARGETS:M${t})
${t}: ${t}.diff_ascii ${t}.diff_man
+. else
+${t}: ${t}.diff_tag ${t}.diff_man
+. endif
. else
${t}:
. endif
@@ -133,6 +147,10 @@ ${t}.validate_html: ${t}.in
@-${MANDOC} ${MOPTS} -Thtml ${.ALLSRC} | validate
.endfor
+.for t in ${TAG_TARGETS}
+${t}: ${t}.diff_tag
+.endfor
+
.for t in ${UTF8_TARGETS}
${t}: ${t}.diff_utf8
.endfor
@@ -157,7 +175,7 @@ clean: ${_CLEAN_TARGETS}
ascii-clean:
.if !empty(_ASCIIFILES)
- @rm -f ${_ASCIIFILES}
+ @rm -f ${_ASCIIFILES} ${_TAGFILES}
.endif
utf8-clean:
@@ -185,8 +203,8 @@ lint-clean:
@rm -f ${_LINTFILES}
.endif
-.PHONY: ${_ASCIIDIFFS} ${_UTF8DIFFS} ${_HTMLDIFFS} ${_MARKDOWNDIFFS} \
- ${_MANDIFFS} ${_LINTDIFFS} ${_HTMLVALS}
+.PHONY: ${_ASCIIDIFFS} ${_TAGDIFFS} ${_UTF8DIFFS} ${_HTMLDIFFS} \
+ ${_MARKDOWNDIFFS} ${_MANDIFFS} ${_LINTDIFFS} ${_HTMLVALS}
# ----------------------------------------------------------------------
diff --git a/regress/usr.bin/mandoc/copyless b/regress/usr.bin/mandoc/copyless
new file mode 100755
index 00000000000..a00c0009b26
--- /dev/null
+++ b/regress/usr.bin/mandoc/copyless
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+umask 022
+if [ "$#" -ne 4 ]; then
+ echo "$0 $*: $# args instead of 4" 1>&2
+ exit 1
+fi
+if [ "$2" != "-T" ]; then
+ echo "$0 $*: second arg is not -T" 1>&2
+ exit 1
+fi
+cut -d ' ' -f 1,3 "$3" > "$1.mandoc_tag"
+cp "$4" "$1.mandoc_ascii"
+exit 0
diff --git a/regress/usr.bin/mandoc/man/IP/Makefile b/regress/usr.bin/mandoc/man/IP/Makefile
index 70094e5fd16..8d607c62f2f 100644
--- a/regress/usr.bin/mandoc/man/IP/Makefile
+++ b/regress/usr.bin/mandoc/man/IP/Makefile
@@ -1,8 +1,9 @@
-# $OpenBSD: Makefile,v 1.10 2020/02/27 01:25:58 schwarze Exp $
+# $OpenBSD: Makefile,v 1.11 2020/03/13 00:31:05 schwarze Exp $
-REGRESS_TARGETS = bullet empty literal longhead manyargs spacing vert width
+REGRESS_TARGETS = bullet empty literal longhead manyargs spacing tag vert width
+TAG_TARGETS = empty tag
UTF8_TARGETS = bullet
LINT_TARGETS = empty
-HTML_TARGETS = bullet literal
+HTML_TARGETS = bullet empty literal tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/man/IP/empty.in b/regress/usr.bin/mandoc/man/IP/empty.in
index 21c42983ad5..bb814870c96 100644
--- a/regress/usr.bin/mandoc/man/IP/empty.in
+++ b/regress/usr.bin/mandoc/man/IP/empty.in
@@ -1,8 +1,9 @@
-.\" $OpenBSD: empty.in,v 1.2 2017/07/04 14:53:23 schwarze Exp $
+.\" $OpenBSD: empty.in,v 1.3 2020/03/13 00:31:05 schwarze Exp $
.TH IP-EMPTY 1 "July 17, 2012"
.SH NAME
IP-empty \- empty indented paragraphs
.SH DESCRIPTION
+BEGINTEST
regular
text
.IP
@@ -25,3 +26,4 @@ text
.RE
regular
text
+ENDTEST
diff --git a/regress/usr.bin/mandoc/man/IP/empty.out_ascii b/regress/usr.bin/mandoc/man/IP/empty.out_ascii
index 24ab17fab37..b17190ab0bd 100644
--- a/regress/usr.bin/mandoc/man/IP/empty.out_ascii
+++ b/regress/usr.bin/mandoc/man/IP/empty.out_ascii
@@ -6,7 +6,7 @@ NNAAMMEE
IP-empty - empty indented paragraphs
DDEESSCCRRIIPPTTIIOONN
- regular text
+ BEGINTEST regular text
indented text
@@ -19,7 +19,7 @@ DDEESSCCRRIIPPTTIIOONN
Empty IP is deleted, RS does not cause additional spacing:
tag indented text
- regular text
+ regular text ENDTEST
diff --git a/regress/usr.bin/mandoc/man/IP/empty.out_html b/regress/usr.bin/mandoc/man/IP/empty.out_html
new file mode 100644
index 00000000000..f2498dba85a
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/IP/empty.out_html
@@ -0,0 +1,18 @@
+<dl class="Bl-tag">
+ <dt></dt>
+ <dd>indented text</dd>
+</dl>
+<p class="Pp">Empty IP is deleted:</p>
+<dl class="Bl-tag">
+ <dt id="tag1"><a class="permalink" href="#tag1">tag1</a></dt>
+ <dd></dd>
+ <dt id="tag2"><a class="permalink" href="#tag2">tag2</a></dt>
+ <dd>indented text</dd>
+</dl>
+<p class="Pp">Empty IP is deleted, RS does not cause additional spacing:</p>
+<div class="Bd-indent">
+<dl class="Bl-tag">
+ <dt id="tag"><a class="permalink" href="#tag">tag</a></dt>
+ <dd>indented text</dd>
+</dl>
+</div>
diff --git a/regress/usr.bin/mandoc/man/IP/empty.out_lint b/regress/usr.bin/mandoc/man/IP/empty.out_lint
index 6c666c88fee..3514b94f19e 100644
--- a/regress/usr.bin/mandoc/man/IP/empty.out_lint
+++ b/regress/usr.bin/mandoc/man/IP/empty.out_lint
@@ -1,2 +1,2 @@
-mandoc: empty.in:13:2: WARNING: skipping paragraph macro: IP empty
-mandoc: empty.in:20:2: WARNING: skipping paragraph macro: IP empty
+mandoc: empty.in:14:2: WARNING: skipping paragraph macro: IP empty
+mandoc: empty.in:21:2: WARNING: skipping paragraph macro: IP empty
diff --git a/regress/usr.bin/mandoc/man/IP/empty.out_tag b/regress/usr.bin/mandoc/man/IP/empty.out_tag
new file mode 100644
index 00000000000..f35f112014e
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/IP/empty.out_tag
@@ -0,0 +1,3 @@
+tag1 15
+tag2 17
+tag 21
diff --git a/regress/usr.bin/mandoc/man/IP/literal.out_html b/regress/usr.bin/mandoc/man/IP/literal.out_html
index b61fc843f96..3b9cc429a3c 100644
--- a/regress/usr.bin/mandoc/man/IP/literal.out_html
+++ b/regress/usr.bin/mandoc/man/IP/literal.out_html
@@ -1,5 +1,5 @@
<dl class="Bl-tag">
- <dt>tag</dt>
+ <dt id="tag"><a class="permalink" href="#tag">tag</a></dt>
<dd>indented regular text</dd>
</dl>
<p class="Pp">new regular paragraph</p>
@@ -8,7 +8,7 @@ literal
text
</pre>
<dl class="Bl-tag">
- <dt>tag</dt>
+ <dt id="tag_2"><a class="permalink" href="#tag_2">tag</a></dt>
<dd>
<pre>
indented
@@ -32,7 +32,7 @@ literal
text
</pre>
<dl class="Bl-tag">
- <dt>tag</dt>
+ <dt id="tag_3"><a class="permalink" href="#tag_3">tag</a></dt>
<dd>
<pre>
indented
@@ -48,7 +48,7 @@ text
out of indented paragraph</a></h2>
<p class="Pp">regular text</p>
<dl class="Bl-tag">
- <dt>tag</dt>
+ <dt id="tag_4"><a class="permalink" href="#tag_4">tag</a></dt>
<dd>indented regular text
<pre>
indented
diff --git a/regress/usr.bin/mandoc/man/IP/tag.in b/regress/usr.bin/mandoc/man/IP/tag.in
new file mode 100644
index 00000000000..038fa969a3d
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/IP/tag.in
@@ -0,0 +1,18 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:05 schwarze Exp $
+.TH IP-TAG 1 "March 10, 2020"
+.SH NAME
+IP-tag \- automatic tagging of indented blocks
+.SH DESCRIPTION
+BEGINTEST
+initial
+text
+.IP " strong" 10n
+text
+.IP "-strong"
+text
+.IP "\&\fI \-weak\fP"
+text
+.IP " strong"
+text
+.PP
+ENDTEST
diff --git a/regress/usr.bin/mandoc/man/IP/tag.out_ascii b/regress/usr.bin/mandoc/man/IP/tag.out_ascii
new file mode 100644
index 00000000000..afd4f587fca
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/IP/tag.out_ascii
@@ -0,0 +1,23 @@
+IP-TAG(1) General Commands Manual IP-TAG(1)
+
+
+
+NNAAMMEE
+ IP-tag - automatic tagging of indented blocks
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST initial text
+
+ strong text
+
+ -strong text
+
+ _-_w_e_a_k text
+
+ strong text
+
+ ENDTEST
+
+
+
+OpenBSD March 10, 2020 IP-TAG(1)
diff --git a/regress/usr.bin/mandoc/man/IP/tag.out_html b/regress/usr.bin/mandoc/man/IP/tag.out_html
new file mode 100644
index 00000000000..4d25b12b6a9
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/IP/tag.out_html
@@ -0,0 +1,10 @@
+<dl class="Bl-tag">
+ <dt> strong</dt>
+ <dd>text</dd>
+ <dt id="strong"><a class="permalink" href="#strong">-strong</a></dt>
+ <dd>text</dd>
+ <dt id="weak"><a class="permalink" href="#weak"><i> -weak</i></a></dt>
+ <dd>text</dd>
+ <dt> strong</dt>
+ <dd>text</dd>
+</dl>
diff --git a/regress/usr.bin/mandoc/man/IP/tag.out_tag b/regress/usr.bin/mandoc/man/IP/tag.out_tag
new file mode 100644
index 00000000000..5be038dbbdb
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/IP/tag.out_tag
@@ -0,0 +1,2 @@
+strong 13
+weak 15
diff --git a/regress/usr.bin/mandoc/man/TP/Makefile b/regress/usr.bin/mandoc/man/TP/Makefile
index ca2475b0feb..9dd2fde7380 100644
--- a/regress/usr.bin/mandoc/man/TP/Makefile
+++ b/regress/usr.bin/mandoc/man/TP/Makefile
@@ -1,9 +1,10 @@
-# $OpenBSD: Makefile,v 1.16 2020/02/27 01:25:58 schwarze Exp $
+# $OpenBSD: Makefile,v 1.17 2020/03/13 00:31:05 schwarze Exp $
REGRESS_TARGETS = badarg broken double eof fill indent literal longhead
-REGRESS_TARGETS += macrotag manyargs sameline spacing vert width
+REGRESS_TARGETS += macrotag manyargs sameline spacing tag vert width
+TAG_TARGETS = tag
LINT_TARGETS = broken double eof
-HTML_TARGETS = literal vert
+HTML_TARGETS = literal tag vert
# groff-1.22.3 defects:
# - If .TP precedes .RE, the latter does not properly reset indentation.
diff --git a/regress/usr.bin/mandoc/man/TP/literal.out_html b/regress/usr.bin/mandoc/man/TP/literal.out_html
index 7f5b1c1fb5c..8b818ed8c68 100644
--- a/regress/usr.bin/mandoc/man/TP/literal.out_html
+++ b/regress/usr.bin/mandoc/man/TP/literal.out_html
@@ -1,5 +1,5 @@
<dl class="Bl-tag">
- <dt>tag</dt>
+ <dt id="tag"><a class="permalink" href="#tag">tag</a></dt>
<dd>regular indented text</dd>
</dl>
<p class="Pp">regular paragraph</p>
@@ -8,7 +8,7 @@ literal
text
</pre>
<dl class="Bl-tag">
- <dt>tag</dt>
+ <dt id="tag_2"><a class="permalink" href="#tag_2">tag</a></dt>
<dd>
<pre>
indented
diff --git a/regress/usr.bin/mandoc/man/TP/tag.in b/regress/usr.bin/mandoc/man/TP/tag.in
new file mode 100644
index 00000000000..34d1e151062
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/TP/tag.in
@@ -0,0 +1,31 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:05 schwarze Exp $
+.TH IP-TAG 1 "March 10, 2020"
+.SH NAME
+IP-tag \- automatic tagging of indented blocks
+.SH DESCRIPTION
+BEGINTEST
+initial
+text
+.TP 10n
+.I " plain"
+text
+.TP
+plain
+text
+.TP
+.I "plain "
+text
+.TP
+\& strong
+text
+.TP
+.B -strong
+text
+.TP
+\&\fI \-weak\fP
+text
+.TP
+.B "strong "
+text
+.PP
+ENDTEST
diff --git a/regress/usr.bin/mandoc/man/TP/tag.out_ascii b/regress/usr.bin/mandoc/man/TP/tag.out_ascii
new file mode 100644
index 00000000000..4da2efa0052
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/TP/tag.out_ascii
@@ -0,0 +1,29 @@
+IP-TAG(1) General Commands Manual IP-TAG(1)
+
+
+
+NNAAMMEE
+ IP-tag - automatic tagging of indented blocks
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST initial text
+
+ _p_l_a_i_n text
+
+ plain text
+
+ _p_l_a_i_n text
+
+ strong text
+
+ --ssttrroonngg text
+
+ _-_w_e_a_k text
+
+ ssttrroonngg text
+
+ ENDTEST
+
+
+
+OpenBSD March 10, 2020 IP-TAG(1)
diff --git a/regress/usr.bin/mandoc/man/TP/tag.out_html b/regress/usr.bin/mandoc/man/TP/tag.out_html
new file mode 100644
index 00000000000..3fbbe41df0a
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/TP/tag.out_html
@@ -0,0 +1,16 @@
+<dl class="Bl-tag">
+ <dt><i> plain</i></dt>
+ <dd>text</dd>
+ <dt id="plain"><a class="permalink" href="#plain">plain</a></dt>
+ <dd>text</dd>
+ <dt><i>plain </i></dt>
+ <dd>text</dd>
+ <dt> strong</dt>
+ <dd>text</dd>
+ <dt id="strong"><a class="permalink" href="#strong"><b>-strong</b></a></dt>
+ <dd>text</dd>
+ <dt id="weak"><a class="permalink" href="#weak"><i> -weak</i></a></dt>
+ <dd>text</dd>
+ <dt><b>strong </b></dt>
+ <dd>text</dd>
+</dl>
diff --git a/regress/usr.bin/mandoc/man/TP/tag.out_tag b/regress/usr.bin/mandoc/man/TP/tag.out_tag
new file mode 100644
index 00000000000..88f6cff83d0
--- /dev/null
+++ b/regress/usr.bin/mandoc/man/TP/tag.out_tag
@@ -0,0 +1,3 @@
+plain 13
+strong 19
+weak 21
diff --git a/regress/usr.bin/mandoc/man/TP/vert.out_html b/regress/usr.bin/mandoc/man/TP/vert.out_html
index 7301819f916..1124ed33dd7 100644
--- a/regress/usr.bin/mandoc/man/TP/vert.out_html
+++ b/regress/usr.bin/mandoc/man/TP/vert.out_html
@@ -2,8 +2,8 @@
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<dl class="Bl-tag">
- <dt>tag</dt>
+ <dt id="tag"><a class="permalink" href="#tag">tag</a></dt>
<dd>text</dd>
- <dt>tag</dt>
+ <dt id="tag_2"><a class="permalink" href="#tag_2">tag</a></dt>
<dd>text</dd>
</dl>
diff --git a/regress/usr.bin/mandoc/mdoc/Cm/Makefile b/regress/usr.bin/mandoc/mdoc/Cm/Makefile
index 6681facf14a..7bc3fc20125 100644
--- a/regress/usr.bin/mandoc/mdoc/Cm/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Cm/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.6 2017/05/30 16:21:08 schwarze Exp $
+# $OpenBSD: Makefile,v 1.7 2020/03/13 00:31:05 schwarze Exp $
-REGRESS_TARGETS = basic font noarg punct
+REGRESS_TARGETS = basic font noarg punct tag
+TAG_TARGETS = tag
LINT_TARGETS = noarg
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Cm/tag.in b/regress/usr.bin/mandoc/mdoc/Cm/tag.in
new file mode 100644
index 00000000000..3db1d1e0d65
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Cm/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:05 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt CM-TAG 1
+.Os
+.Sh NAME
+.Nm Cm-tag
+.Nd tagging of command modifier macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Cm one | two
+text
+.It Xo
+.Cm three
+.Xc
+text
+.El
+.Tg
+.Cm four
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Cm/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_ascii
new file mode 100644
index 00000000000..071408c7676
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_ascii
@@ -0,0 +1,17 @@
+CM-TAG(1) General Commands Manual CM-TAG(1)
+
+NNAAMMEE
+ CCmm--ttaagg - tagging of command modifier macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ oonnee | ttwwoo
+ text
+
+ tthhrreeee text
+ ffoouurr
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Cm/tag.out_html b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_html
new file mode 100644
index 00000000000..a140fe3e386
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_html
@@ -0,0 +1,9 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><code class="Cm" id="one">one</code></a>
+ |
+ <a class="permalink" href="#two"><code class="Cm" id="two">two</code></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><code class="Cm" id="three">three</code></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><code class="Cm" id="four">four</code></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Cm/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_markdown
new file mode 100644
index 00000000000..893a8fe5b2b
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_markdown
@@ -0,0 +1,23 @@
+CM-TAG(1) - General Commands Manual
+
+# NAME
+
+**Cm-tag** - tagging of command modifier macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+**one** | **two**
+
+> text
+
+**three**
+
+> text
+
+**four**
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Cm/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_tag
new file mode 100644
index 00000000000..94f0cfb2c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Cm/tag.out_tag
@@ -0,0 +1,4 @@
+one 9
+two 9
+three 12
+four 13
diff --git a/regress/usr.bin/mandoc/mdoc/Dv/Makefile b/regress/usr.bin/mandoc/mdoc/Dv/Makefile
index bbeabf5bc4f..979e182605a 100644
--- a/regress/usr.bin/mandoc/mdoc/Dv/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Dv/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.4 2017/03/08 22:53:35 schwarze Exp $
+# $OpenBSD: Makefile,v 1.5 2020/03/13 00:31:05 schwarze Exp $
-REGRESS_TARGETS = font noarg
+REGRESS_TARGETS = font noarg tag
+TAG_TARGETS = tag
LINT_TARGETS = noarg
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Dv/tag.in b/regress/usr.bin/mandoc/mdoc/Dv/tag.in
new file mode 100644
index 00000000000..b6c79ad14d9
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Dv/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:05 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt DV-TAG 1
+.Os
+.Sh NAME
+.Nm Dv-tag
+.Nd tagging of defined variable macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Dv one | two
+text
+.It Xo
+.Dv three
+.Xc
+text
+.El
+.Tg
+.Dv four
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Dv/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_ascii
new file mode 100644
index 00000000000..119e3509891
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_ascii
@@ -0,0 +1,17 @@
+DV-TAG(1) General Commands Manual DV-TAG(1)
+
+NNAAMMEE
+ DDvv--ttaagg - tagging of defined variable macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ one | two
+ text
+
+ three text
+ four
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Dv/tag.out_html b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_html
new file mode 100644
index 00000000000..cee78340802
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_html
@@ -0,0 +1,9 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><code class="Dv" id="one">one</code></a>
+ |
+ <a class="permalink" href="#two"><code class="Dv" id="two">two</code></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><code class="Dv" id="three">three</code></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><code class="Dv" id="four">four</code></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Dv/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_markdown
new file mode 100644
index 00000000000..29b454bbd23
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_markdown
@@ -0,0 +1,23 @@
+DV-TAG(1) - General Commands Manual
+
+# NAME
+
+**Dv-tag** - tagging of defined variable macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+`one` | `two`
+
+> text
+
+`three`
+
+> text
+
+`four`
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Dv/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_tag
new file mode 100644
index 00000000000..94f0cfb2c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Dv/tag.out_tag
@@ -0,0 +1,4 @@
+one 9
+two 9
+three 12
+four 13
diff --git a/regress/usr.bin/mandoc/mdoc/Em/Makefile b/regress/usr.bin/mandoc/mdoc/Em/Makefile
index ced9d1f0852..2b500444863 100644
--- a/regress/usr.bin/mandoc/mdoc/Em/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Em/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.5 2017/03/08 22:53:35 schwarze Exp $
+# $OpenBSD: Makefile,v 1.6 2020/03/13 00:31:05 schwarze Exp $
-REGRESS_TARGETS = font noarg punct
+REGRESS_TARGETS = font noarg punct tag
+TAG_TARGETS = tag
LINT_TARGETS = noarg punct
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Em/tag.in b/regress/usr.bin/mandoc/mdoc/Em/tag.in
new file mode 100644
index 00000000000..70e6eb447ec
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Em/tag.in
@@ -0,0 +1,23 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:05 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt EM-TAG 1
+.Os
+.Sh NAME
+.Nm Em-tag
+.Nd tagging of emphasis macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Em one | two
+text
+.It Xo
+.Em three
+.Xc
+text
+.El
+.Em four
+.Em one
+.Tg explicit
+.Em five
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Em/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Em/tag.out_ascii
new file mode 100644
index 00000000000..74f8212bf71
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Em/tag.out_ascii
@@ -0,0 +1,17 @@
+EM-TAG(1) General Commands Manual EM-TAG(1)
+
+NNAAMMEE
+ EEmm--ttaagg - tagging of emphasis macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ _o_n_e | _t_w_o
+ text
+
+ _t_h_r_e_e text
+ _f_o_u_r _o_n_e _f_i_v_e
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Em/tag.out_html b/regress/usr.bin/mandoc/mdoc/Em/tag.out_html
new file mode 100644
index 00000000000..4046673f833
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Em/tag.out_html
@@ -0,0 +1,10 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><i class="Em" id="one">one</i></a> |
+ <a class="permalink" href="#two"><i class="Em" id="two">two</i></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><i class="Em" id="three">three</i></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><i class="Em" id="four">four</i></a>
+ <i class="Em">one</i>
+ <a class="permalink" href="#explicit"><i class="Em" id="explicit">five</i></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Em/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Em/tag.out_markdown
new file mode 100644
index 00000000000..4c10715982f
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Em/tag.out_markdown
@@ -0,0 +1,25 @@
+EM-TAG(1) - General Commands Manual
+
+# NAME
+
+**Em-tag** - tagging of emphasis macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+*one* | *two*
+
+> text
+
+*three*
+
+> text
+
+*four*
+*one*
+*five*
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Em/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Em/tag.out_tag
new file mode 100644
index 00000000000..c2fbaf59646
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Em/tag.out_tag
@@ -0,0 +1,5 @@
+one 9
+two 9
+three 12
+four 13
+explicit 13
diff --git a/regress/usr.bin/mandoc/mdoc/Er/Makefile b/regress/usr.bin/mandoc/mdoc/Er/Makefile
index 78da864da6f..55f6cc761f8 100644
--- a/regress/usr.bin/mandoc/mdoc/Er/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Er/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.6 2017/03/08 22:53:35 schwarze Exp $
+# $OpenBSD: Makefile,v 1.7 2020/03/13 00:31:05 schwarze Exp $
-REGRESS_TARGETS = noarg font
+REGRESS_TARGETS = noarg font tag
+TAG_TARGETS = tag
LINT_TARGETS = noarg
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Er/tag.in b/regress/usr.bin/mandoc/mdoc/Er/tag.in
new file mode 100644
index 00000000000..4227648b69f
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Er/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:05 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt ER-TAG 1
+.Os
+.Sh NAME
+.Nm Er-tag
+.Nd tagging of error number macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Er one
+text
+.El
+.Tg
+.Er two
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er ENOENT
+text
+.El
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Er/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Er/tag.out_ascii
new file mode 100644
index 00000000000..62dbf9ca792
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Er/tag.out_ascii
@@ -0,0 +1,16 @@
+ER-TAG(1) General Commands Manual ER-TAG(1)
+
+NNAAMMEE
+ EErr--ttaagg - tagging of error number macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ one text
+ two
+
+EERRRROORRSS
+ [ENOENT] text
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Er/tag.out_html b/regress/usr.bin/mandoc/mdoc/Er/tag.out_html
new file mode 100644
index 00000000000..a2c2978f2dc
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Er/tag.out_html
@@ -0,0 +1,12 @@
+<dl class="Bl-tag">
+ <dt><code class="Er">one</code></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#two"><code class="Er" id="two">two</code></a>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="ERRORS"><a class="permalink" href="#ERRORS">ERRORS</a></h1>
+<dl class="Bl-tag">
+ <dt>[<a class="permalink" href="#ENOENT"><code class="Er" id="ENOENT">ENOENT</code></a>]</dt>
+ <dd>text</dd>
+</dl>
diff --git a/regress/usr.bin/mandoc/mdoc/Er/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Er/tag.out_markdown
new file mode 100644
index 00000000000..d11eb4b9383
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Er/tag.out_markdown
@@ -0,0 +1,25 @@
+ER-TAG(1) - General Commands Manual
+
+# NAME
+
+**Er-tag** - tagging of error number macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+`one`
+
+> text
+
+`two`
+
+# ERRORS
+
+\[`ENOENT`]
+
+> text
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Er/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Er/tag.out_tag
new file mode 100644
index 00000000000..b00a67187e0
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Er/tag.out_tag
@@ -0,0 +1,2 @@
+two 10
+ENOENT 13
diff --git a/regress/usr.bin/mandoc/mdoc/Ev/Makefile b/regress/usr.bin/mandoc/mdoc/Ev/Makefile
index bbeabf5bc4f..979e182605a 100644
--- a/regress/usr.bin/mandoc/mdoc/Ev/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Ev/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.4 2017/03/08 22:53:35 schwarze Exp $
+# $OpenBSD: Makefile,v 1.5 2020/03/13 00:31:05 schwarze Exp $
-REGRESS_TARGETS = font noarg
+REGRESS_TARGETS = font noarg tag
+TAG_TARGETS = tag
LINT_TARGETS = noarg
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Ev/tag.in b/regress/usr.bin/mandoc/mdoc/Ev/tag.in
new file mode 100644
index 00000000000..2627fdeb9af
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ev/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:05 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt EV-TAG 1
+.Os
+.Sh NAME
+.Nm Ev-tag
+.Nd tagging of environment variable macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Ev one | two
+text
+.It Xo
+.Ev three
+.Xc
+text
+.El
+.Tg
+.Ev four
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Ev/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_ascii
new file mode 100644
index 00000000000..5569d1c8e79
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_ascii
@@ -0,0 +1,17 @@
+EV-TAG(1) General Commands Manual EV-TAG(1)
+
+NNAAMMEE
+ EEvv--ttaagg - tagging of environment variable macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ one | two
+ text
+
+ three text
+ four
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Ev/tag.out_html b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_html
new file mode 100644
index 00000000000..1e1c92b9a2f
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_html
@@ -0,0 +1,9 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><code class="Ev" id="one">one</code></a>
+ |
+ <a class="permalink" href="#two"><code class="Ev" id="two">two</code></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><code class="Ev" id="three">three</code></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><code class="Ev" id="four">four</code></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Ev/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_markdown
new file mode 100644
index 00000000000..f9a6712b19c
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_markdown
@@ -0,0 +1,23 @@
+EV-TAG(1) - General Commands Manual
+
+# NAME
+
+**Ev-tag** - tagging of environment variable macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+`one` | `two`
+
+> text
+
+`three`
+
+> text
+
+`four`
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Ev/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_tag
new file mode 100644
index 00000000000..94f0cfb2c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ev/tag.out_tag
@@ -0,0 +1,4 @@
+one 9
+two 9
+three 12
+four 13
diff --git a/regress/usr.bin/mandoc/mdoc/Fl/Makefile b/regress/usr.bin/mandoc/mdoc/Fl/Makefile
index e4e4a6bc958..c061adef434 100644
--- a/regress/usr.bin/mandoc/mdoc/Fl/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Fl/Makefile
@@ -1,6 +1,9 @@
-# $OpenBSD: Makefile,v 1.13 2020/02/27 01:25:58 schwarze Exp $
+# $OpenBSD: Makefile,v 1.14 2020/03/13 00:31:06 schwarze Exp $
-REGRESS_TARGETS = font multiarg noarg parsed punct spacing
+REGRESS_TARGETS = font multiarg noarg parsed punct spacing tag
+TAG_TARGETS = tag
LINT_TARGETS = punct
+HTML_TARGETS = tag
+SKIP_TMAN = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Fl/tag.in b/regress/usr.bin/mandoc/mdoc/Fl/tag.in
new file mode 100644
index 00000000000..f7e24b9f0d2
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fl/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt FL-TAG 1
+.Os
+.Sh NAME
+.Nm Fl-tag
+.Nd tagging of command line option macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Fl a | b
+text
+.It Xo
+.Fl c
+.Xc
+text
+.El
+.Tg
+.Fl d
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Fl/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_ascii
new file mode 100644
index 00000000000..4fcf803c8c0
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_ascii
@@ -0,0 +1,17 @@
+FL-TAG(1) General Commands Manual FL-TAG(1)
+
+NNAAMMEE
+ FFll--ttaagg - tagging of command line option macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ --aa | --bb
+ text
+
+ --cc text
+ --dd
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Fl/tag.out_html b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_html
new file mode 100644
index 00000000000..f67a30c04d8
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_html
@@ -0,0 +1,8 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#a"><code class="Fl" id="a">-a</code></a> |
+ <a class="permalink" href="#b"><code class="Fl" id="b">-b</code></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#c"><code class="Fl" id="c">-c</code></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#d"><code class="Fl" id="d">-d</code></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Fl/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_markdown
new file mode 100644
index 00000000000..1e7c6f14268
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_markdown
@@ -0,0 +1,23 @@
+FL-TAG(1) - General Commands Manual
+
+# NAME
+
+**Fl-tag** - tagging of command line option macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+**-a** | **-b**
+
+> text
+
+**-c**
+
+> text
+
+**-d**
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Fl/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_tag
new file mode 100644
index 00000000000..89a94151c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fl/tag.out_tag
@@ -0,0 +1,4 @@
+a 9
+b 9
+c 12
+d 13
diff --git a/regress/usr.bin/mandoc/mdoc/Fo/Makefile b/regress/usr.bin/mandoc/mdoc/Fo/Makefile
index 7770e9a1921..ce25ddf345a 100644
--- a/regress/usr.bin/mandoc/mdoc/Fo/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Fo/Makefile
@@ -1,8 +1,10 @@
-# $OpenBSD: Makefile,v 1.17 2020/02/27 01:25:58 schwarze Exp $
+# $OpenBSD: Makefile,v 1.18 2020/03/13 00:31:06 schwarze Exp $
REGRESS_TARGETS = basic break eos font noarg nohead
-REGRESS_TARGETS += obsolete punct section transp warn
+REGRESS_TARGETS += obsolete punct section tag transp warn
+TAG_TARGETS = tag
LINT_TARGETS = noarg nohead obsolete punct warn
+HTML_TARGETS = tag
# groff-1.22.3 defects:
# - .Fo without an argument prints unbalanced parentheses
diff --git a/regress/usr.bin/mandoc/mdoc/Fo/tag.in b/regress/usr.bin/mandoc/mdoc/Fo/tag.in
new file mode 100644
index 00000000000..29b84ffef57
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fo/tag.in
@@ -0,0 +1,29 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt FO-TAG 1
+.Os
+.Sh NAME
+.Nm Fo-tag
+.Nd tagging of function name macros
+.Sh DESCRIPTION
+BEGINTEST
+.Pp
+automatic:
+.Fn first
+and
+.Fn second
+.Pp
+.Fn second
+and
+.Fn first
+.Pp
+explicit:
+.Tg e3
+.Fn third
+and
+.Tg e4
+.Fo fourth
+.Fa void
+.Fc
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Fo/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_ascii
new file mode 100644
index 00000000000..505c0b7a2b9
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_ascii
@@ -0,0 +1,17 @@
+FO-TAG(1) General Commands Manual FO-TAG(1)
+
+NNAAMMEE
+ FFoo--ttaagg - tagging of function name macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ automatic: ffiirrsstt() and sseeccoonndd()
+
+ sseeccoonndd() and ffiirrsstt()
+
+ explicit: tthhiirrdd() and ffoouurrtthh(_v_o_i_d)
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Fo/tag.out_html b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_html
new file mode 100644
index 00000000000..b350861482e
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_html
@@ -0,0 +1,9 @@
+<p class="Pp">automatic:
+ <a class="permalink" href="#first"><code class="Fn" id="first">first</code></a>()
+ and <code class="Fn">second</code>()</p>
+<p class="Pp"><a class="permalink" href="#second"><code class="Fn" id="second">second</code></a>()
+ and <code class="Fn">first</code>()</p>
+<p class="Pp">explicit:
+ <a class="permalink" href="#e3"><code class="Fn" id="e3">third</code></a>()
+ and
+ <a class="permalink" href="#e4"><code class="Fn" id="e4">fourth</code></a>(<var class="Fa">void</var>);</p>
diff --git a/regress/usr.bin/mandoc/mdoc/Fo/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_markdown
new file mode 100644
index 00000000000..273a00d4be0
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_markdown
@@ -0,0 +1,27 @@
+FO-TAG(1) - General Commands Manual
+
+# NAME
+
+**Fo-tag** - tagging of function name macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+automatic:
+**first**()
+and
+**second**()
+
+**second**()
+and
+**first**()
+
+explicit:
+**third**()
+and
+**fourth**(*void*)
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Fo/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_tag
new file mode 100644
index 00000000000..2387023c8f4
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Fo/tag.out_tag
@@ -0,0 +1,4 @@
+first 9
+second 11
+e3 13
+e4 13
diff --git a/regress/usr.bin/mandoc/mdoc/Ic/Makefile b/regress/usr.bin/mandoc/mdoc/Ic/Makefile
index bba07fb34b1..4a06ee20eb4 100644
--- a/regress/usr.bin/mandoc/mdoc/Ic/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Ic/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.7 2017/05/30 16:21:08 schwarze Exp $
+# $OpenBSD: Makefile,v 1.8 2020/03/13 00:31:06 schwarze Exp $
-REGRESS_TARGETS = font noarg punct
+REGRESS_TARGETS = font noarg punct tag
+TAG_TARGETS = tag
LINT_TARGETS = noarg
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Ic/tag.in b/regress/usr.bin/mandoc/mdoc/Ic/tag.in
new file mode 100644
index 00000000000..9d21426e8a3
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ic/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt IC-TAG 1
+.Os
+.Sh NAME
+.Nm Ic-tag
+.Nd tagging of internal command macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Ic one | two
+text
+.It Xo
+.Ic three
+.Xc
+text
+.El
+.Tg
+.Ic four
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Ic/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_ascii
new file mode 100644
index 00000000000..513b2638c51
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_ascii
@@ -0,0 +1,17 @@
+IC-TAG(1) General Commands Manual IC-TAG(1)
+
+NNAAMMEE
+ IIcc--ttaagg - tagging of internal command macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ oonnee | ttwwoo
+ text
+
+ tthhrreeee text
+ ffoouurr
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Ic/tag.out_html b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_html
new file mode 100644
index 00000000000..ad3cc1efc52
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_html
@@ -0,0 +1,9 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><code class="Ic" id="one">one</code></a>
+ |
+ <a class="permalink" href="#two"><code class="Ic" id="two">two</code></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><code class="Ic" id="three">three</code></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><code class="Ic" id="four">four</code></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Ic/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_markdown
new file mode 100644
index 00000000000..c0f13879fba
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_markdown
@@ -0,0 +1,23 @@
+IC-TAG(1) - General Commands Manual
+
+# NAME
+
+**Ic-tag** - tagging of internal command macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+**one** | **two**
+
+> text
+
+**three**
+
+> text
+
+**four**
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Ic/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_tag
new file mode 100644
index 00000000000..94f0cfb2c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ic/tag.out_tag
@@ -0,0 +1,4 @@
+one 9
+two 9
+three 12
+four 13
diff --git a/regress/usr.bin/mandoc/mdoc/Li/Makefile b/regress/usr.bin/mandoc/mdoc/Li/Makefile
index 7b2a3313c5a..44dcf01cf83 100644
--- a/regress/usr.bin/mandoc/mdoc/Li/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Li/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.7 2018/12/21 16:58:49 schwarze Exp $
+# $OpenBSD: Makefile,v 1.8 2020/03/13 00:31:06 schwarze Exp $
-REGRESS_TARGETS = arg punct font
+REGRESS_TARGETS = arg punct font tag
+TAG_TARGETS = tag
LINT_TARGETS = punct
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Li/tag.in b/regress/usr.bin/mandoc/mdoc/Li/tag.in
new file mode 100644
index 00000000000..0ee9ce8208f
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Li/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt LI-TAG 1
+.Os
+.Sh NAME
+.Nm Li-tag
+.Nd tagging of literal font macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Li one | two
+text
+.It Xo
+.Li three
+.Xc
+text
+.El
+.Tg
+.Li four
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Li/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Li/tag.out_ascii
new file mode 100644
index 00000000000..e1afda6e9b4
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Li/tag.out_ascii
@@ -0,0 +1,17 @@
+LI-TAG(1) General Commands Manual LI-TAG(1)
+
+NNAAMMEE
+ LLii--ttaagg - tagging of literal font macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ one | two
+ text
+
+ three text
+ four
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Li/tag.out_html b/regress/usr.bin/mandoc/mdoc/Li/tag.out_html
new file mode 100644
index 00000000000..3730caa6a52
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Li/tag.out_html
@@ -0,0 +1,9 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><code class="Li" id="one">one</code></a>
+ |
+ <a class="permalink" href="#two"><code class="Li" id="two">two</code></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><code class="Li" id="three">three</code></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><code class="Li" id="four">four</code></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Li/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Li/tag.out_markdown
new file mode 100644
index 00000000000..6467e16d675
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Li/tag.out_markdown
@@ -0,0 +1,23 @@
+LI-TAG(1) - General Commands Manual
+
+# NAME
+
+**Li-tag** - tagging of literal font macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+`one` | `two`
+
+> text
+
+`three`
+
+> text
+
+`four`
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Li/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Li/tag.out_tag
new file mode 100644
index 00000000000..94f0cfb2c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Li/tag.out_tag
@@ -0,0 +1,4 @@
+one 9
+two 9
+three 12
+four 13
diff --git a/regress/usr.bin/mandoc/mdoc/Makefile b/regress/usr.bin/mandoc/mdoc/Makefile
index 86bdcb7a2ff..83bd7fb7d40 100644
--- a/regress/usr.bin/mandoc/mdoc/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Makefile
@@ -1,9 +1,9 @@
-# $OpenBSD: Makefile,v 1.32 2017/01/11 17:39:45 schwarze Exp $
+# $OpenBSD: Makefile,v 1.33 2020/03/13 00:31:05 schwarze Exp $
SUBDIR = Ad An Ap Aq Ar At Bd Bf Bk Bl Brq Bx Cd Cm
SUBDIR += D1 Db Dd Dl Dq Dt Dv Em Eo Er Ev Ex Fd Fl Fo Ft Ic In Lb Li Lk
SUBDIR += Ms Mt Nd Nm No Ns Oo Op Os Ox Pa Pf Pp Qq Rs Rv
-SUBDIR += Sh Sm Sq St Sx Sy Tn Ud Ux Va Vt Xr blank break
+SUBDIR += Sh Sm Sq St Sx Sy Tg Tn Ud Ux Va Vt Xr blank break
.include "../Makefile.sub"
.include <bsd.subdir.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Ms/Makefile b/regress/usr.bin/mandoc/mdoc/Ms/Makefile
index 78da864da6f..defbb29481a 100644
--- a/regress/usr.bin/mandoc/mdoc/Ms/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Ms/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.6 2017/03/08 22:53:35 schwarze Exp $
+# $OpenBSD: Makefile,v 1.7 2020/03/13 00:31:06 schwarze Exp $
-REGRESS_TARGETS = noarg font
+REGRESS_TARGETS = noarg font tag
+TAG_TARGET = tag
LINT_TARGETS = noarg
+HTML_TARGET = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Ms/tag.in b/regress/usr.bin/mandoc/mdoc/Ms/tag.in
new file mode 100644
index 00000000000..da65a07e51e
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ms/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt MS-TAG 1
+.Os
+.Sh NAME
+.Nm Ms-tag
+.Nd tagging of mathematical symbol macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Ms one | two
+text
+.It Xo
+.Ms three
+.Xc
+text
+.El
+.Tg
+.Ms four
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Ms/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_ascii
new file mode 100644
index 00000000000..2d06f4bffcb
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_ascii
@@ -0,0 +1,17 @@
+MS-TAG(1) General Commands Manual MS-TAG(1)
+
+NNAAMMEE
+ MMss--ttaagg - tagging of mathematical symbol macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ oonnee | ttwwoo
+ text
+
+ tthhrreeee text
+ ffoouurr
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Ms/tag.out_html b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_html
new file mode 100644
index 00000000000..a140fe3e386
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_html
@@ -0,0 +1,9 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><code class="Cm" id="one">one</code></a>
+ |
+ <a class="permalink" href="#two"><code class="Cm" id="two">two</code></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><code class="Cm" id="three">three</code></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><code class="Cm" id="four">four</code></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Ms/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_markdown
new file mode 100644
index 00000000000..055c386002c
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_markdown
@@ -0,0 +1,23 @@
+MS-TAG(1) - General Commands Manual
+
+# NAME
+
+**Ms-tag** - tagging of mathematical symbol macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+**one** | **two**
+
+> text
+
+**three**
+
+> text
+
+**four**
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Ms/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_tag
new file mode 100644
index 00000000000..94f0cfb2c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Ms/tag.out_tag
@@ -0,0 +1,4 @@
+one 9
+two 9
+three 12
+four 13
diff --git a/regress/usr.bin/mandoc/mdoc/No/Makefile b/regress/usr.bin/mandoc/mdoc/No/Makefile
index 1187d98bff1..35aa4e1e19d 100644
--- a/regress/usr.bin/mandoc/mdoc/No/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/No/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.6 2017/03/08 22:53:35 schwarze Exp $
+# $OpenBSD: Makefile,v 1.7 2020/03/13 00:31:06 schwarze Exp $
-REGRESS_TARGETS = punct spacing
+REGRESS_TARGETS = punct spacing tag
+TAG_TARGETS = tag
LINT_TARGETS = punct
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/No/punct.out_lint b/regress/usr.bin/mandoc/mdoc/No/punct.out_lint
index e046da6a10c..6a65c3b4034 100644
--- a/regress/usr.bin/mandoc/mdoc/No/punct.out_lint
+++ b/regress/usr.bin/mandoc/mdoc/No/punct.out_lint
@@ -23,3 +23,4 @@ mandoc: punct.in:72:7: WARNING: skipping empty macro: No
mandoc: punct.in:75:7: WARNING: skipping empty macro: No
mandoc: punct.in:76:7: WARNING: skipping empty macro: No
mandoc: punct.in:84:2: WARNING: skipping empty macro: No
+mandoc: punct.in:87:6: STYLE: no blank before trailing delimiter: No a.
diff --git a/regress/usr.bin/mandoc/mdoc/No/tag.in b/regress/usr.bin/mandoc/mdoc/No/tag.in
new file mode 100644
index 00000000000..a9d4415f799
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/No/tag.in
@@ -0,0 +1,21 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt NO-TAG 1
+.Os
+.Sh NAME
+.Nm No-tag
+.Nd tagging of normal font macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It No one | two
+text
+.It Xo
+.No three
+.Xc
+text
+.El
+.Tg
+.No four
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/No/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/No/tag.out_ascii
new file mode 100644
index 00000000000..44481b02a4e
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/No/tag.out_ascii
@@ -0,0 +1,17 @@
+NO-TAG(1) General Commands Manual NO-TAG(1)
+
+NNAAMMEE
+ NNoo--ttaagg - tagging of normal font macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ one | two
+ text
+
+ three text
+ four
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/No/tag.out_html b/regress/usr.bin/mandoc/mdoc/No/tag.out_html
new file mode 100644
index 00000000000..32696917362
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/No/tag.out_html
@@ -0,0 +1,9 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><span class="No" id="one">one</span></a>
+ |
+ <a class="permalink" href="#two"><span class="No" id="two">two</span></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><span class="No" id="three">three</span></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><span class="No" id="four">four</span></a>
diff --git a/regress/usr.bin/mandoc/mdoc/No/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/No/tag.out_markdown
new file mode 100644
index 00000000000..1590c01059f
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/No/tag.out_markdown
@@ -0,0 +1,23 @@
+NO-TAG(1) - General Commands Manual
+
+# NAME
+
+**No-tag** - tagging of normal font macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+one | two
+
+> text
+
+three
+
+> text
+
+four
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/No/tag.out_tag b/regress/usr.bin/mandoc/mdoc/No/tag.out_tag
new file mode 100644
index 00000000000..94f0cfb2c0d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/No/tag.out_tag
@@ -0,0 +1,4 @@
+one 9
+two 9
+three 12
+four 13
diff --git a/regress/usr.bin/mandoc/mdoc/Sy/Makefile b/regress/usr.bin/mandoc/mdoc/Sy/Makefile
index 6a72abfa5ec..752d1382597 100644
--- a/regress/usr.bin/mandoc/mdoc/Sy/Makefile
+++ b/regress/usr.bin/mandoc/mdoc/Sy/Makefile
@@ -1,6 +1,8 @@
-# $OpenBSD: Makefile,v 1.7 2017/03/08 22:53:36 schwarze Exp $
+# $OpenBSD: Makefile,v 1.8 2020/03/13 00:31:06 schwarze Exp $
-REGRESS_TARGETS = noarg font punct
+REGRESS_TARGETS = noarg font punct tag
+TAG_TARGETS = tag
LINT_TARGETS = noarg punct
+HTML_TARGETS = tag
.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Sy/tag.in b/regress/usr.bin/mandoc/mdoc/Sy/tag.in
new file mode 100644
index 00000000000..1294e17da7d
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Sy/tag.in
@@ -0,0 +1,23 @@
+.\" $OpenBSD: tag.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt SY-TAG 1
+.Os
+.Sh NAME
+.Nm Sy-tag
+.Nd tagging of symbolic font macros
+.Sh DESCRIPTION
+BEGINTEST
+.Bl -tag -width Ds
+.It Sy one | two
+text
+.It Xo
+.Sy three
+.Xc
+text
+.El
+.Sy four
+.Sy one
+.Tg explicit
+.Sy five
+.Pp
+ENDTEST
diff --git a/regress/usr.bin/mandoc/mdoc/Sy/tag.out_ascii b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_ascii
new file mode 100644
index 00000000000..3b89cb4157b
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_ascii
@@ -0,0 +1,17 @@
+SY-TAG(1) General Commands Manual SY-TAG(1)
+
+NNAAMMEE
+ SSyy--ttaagg - tagging of symbolic font macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ oonnee | ttwwoo
+ text
+
+ tthhrreeee text
+ ffoouurr oonnee ffiivvee
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Sy/tag.out_html b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_html
new file mode 100644
index 00000000000..69276a1883b
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_html
@@ -0,0 +1,10 @@
+<dl class="Bl-tag">
+ <dt><a class="permalink" href="#one"><b class="Sy" id="one">one</b></a> |
+ <a class="permalink" href="#two"><b class="Sy" id="two">two</b></a></dt>
+ <dd>text</dd>
+ <dt><a class="permalink" href="#three"><b class="Sy" id="three">three</b></a></dt>
+ <dd>text</dd>
+</dl>
+<a class="permalink" href="#four"><b class="Sy" id="four">four</b></a>
+ <b class="Sy">one</b>
+ <a class="permalink" href="#explicit"><b class="Sy" id="explicit">five</b></a>
diff --git a/regress/usr.bin/mandoc/mdoc/Sy/tag.out_markdown b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_markdown
new file mode 100644
index 00000000000..5382a5e254f
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_markdown
@@ -0,0 +1,25 @@
+SY-TAG(1) - General Commands Manual
+
+# NAME
+
+**Sy-tag** - tagging of symbolic font macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+**one** | **two**
+
+> text
+
+**three**
+
+> text
+
+**four**
+**one**
+**five**
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Sy/tag.out_tag b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_tag
new file mode 100644
index 00000000000..c2fbaf59646
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Sy/tag.out_tag
@@ -0,0 +1,5 @@
+one 9
+two 9
+three 12
+four 13
+explicit 13
diff --git a/regress/usr.bin/mandoc/mdoc/Tg/Makefile b/regress/usr.bin/mandoc/mdoc/Tg/Makefile
new file mode 100644
index 00000000000..7f5387660af
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Tg/Makefile
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+
+REGRESS_TARGETS = warn
+TAG_TARGETS = warn
+LINT_TARGETS = warn
+HTML_TARGETS = warn
+
+.include <bsd.regress.mk>
diff --git a/regress/usr.bin/mandoc/mdoc/Tg/warn.in b/regress/usr.bin/mandoc/mdoc/Tg/warn.in
new file mode 100644
index 00000000000..e36f4506150
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Tg/warn.in
@@ -0,0 +1,34 @@
+.\" $OpenBSD: warn.in,v 1.1 2020/03/13 00:31:06 schwarze Exp $
+.Dd $Mdocdate: March 13 2020 $
+.Dt TG-WARN 1
+.Os
+.Sh NAME
+.Nm Tg-warn
+.Nd warnings about tagging macros
+.Sh DESCRIPTION
+BEGINTEST
+.Pp
+.Tg start
+initial
+text
+.Tg
+.Ic macro
+.Tg "" ignored arguments
+too many
+.Tg \&badstart
+badstart
+.Tg badend\&
+badend
+.Tg "white space"
+whitespace
+.Tg sub
+.Tg double
+.Ss Subsection
+subtext
+.Tg examples
+.Sh EXAMPLES
+example
+text
+.Pp
+ENDTEST
+.Tg
diff --git a/regress/usr.bin/mandoc/mdoc/Tg/warn.out_ascii b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_ascii
new file mode 100644
index 00000000000..8dee9aed406
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_ascii
@@ -0,0 +1,19 @@
+TG-WARN(1) General Commands Manual TG-WARN(1)
+
+NNAAMMEE
+ TTgg--wwaarrnn - warnings about tagging macros
+
+DDEESSCCRRIIPPTTIIOONN
+ BEGINTEST
+
+ initial text mmaaccrroo too many badstart badend whitespace
+
+ SSuubbsseeccttiioonn
+ subtext
+
+EEXXAAMMPPLLEESS
+ example text
+
+ ENDTEST
+
+OpenBSD March 13, 2020 OpenBSD
diff --git a/regress/usr.bin/mandoc/mdoc/Tg/warn.out_html b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_html
new file mode 100644
index 00000000000..b4d3cf74c57
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_html
@@ -0,0 +1,11 @@
+<p class="Pp"><mark id="start"></mark>initial text
+ <a class="permalink" href="#macro"><code class="Ic" id="macro">macro</code></a>
+ too many badstart badend whitespace <mark id="sub"></mark></p>
+<section class="Ss">
+<h2 class="Ss" id="double"><a class="permalink" href="#double">Subsection</a></h2>
+<p class="Pp">subtext</p>
+</section>
+</section>
+<section class="Sh">
+<h1 class="Sh" id="examples"><a class="permalink" href="#examples">EXAMPLES</a></h1>
+<p class="Pp">example text</p>
diff --git a/regress/usr.bin/mandoc/mdoc/Tg/warn.out_lint b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_lint
new file mode 100644
index 00000000000..39c1f541fbc
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_lint
@@ -0,0 +1,6 @@
+mandoc: warn.in:16:2: WARNING: skipping empty macro: Tg
+mandoc: warn.in:16:8: ERROR: skipping excess arguments: Tg ... ignored
+mandoc: warn.in:18:5: ERROR: skipping tag containing whitespace: Tg \&badstart
+mandoc: warn.in:20:11: ERROR: skipping tag containing whitespace: Tg badend\&
+mandoc: warn.in:22:10: ERROR: skipping tag containing whitespace: Tg white space
+mandoc: warn.in:34:2: WARNING: skipping empty macro: Tg
diff --git a/regress/usr.bin/mandoc/mdoc/Tg/warn.out_markdown b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_markdown
new file mode 100644
index 00000000000..872044244a7
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_markdown
@@ -0,0 +1,30 @@
+TG-WARN(1) - General Commands Manual
+
+# NAME
+
+**Tg-warn** - warnings about tagging macros
+
+# DESCRIPTION
+
+BEGINTEST
+
+initial
+text
+**macro**
+too many
+badstart
+badend
+whitespace
+
+## Subsection
+
+subtext
+
+# EXAMPLES
+
+example
+text
+
+ENDTEST
+
+OpenBSD - March 13, 2020
diff --git a/regress/usr.bin/mandoc/mdoc/Tg/warn.out_tag b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_tag
new file mode 100644
index 00000000000..e1fc141c346
--- /dev/null
+++ b/regress/usr.bin/mandoc/mdoc/Tg/warn.out_tag
@@ -0,0 +1,5 @@
+start 9
+macro 9
+sub 9
+double 11
+examples 14
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 8c5a8f7d46b..8d6fec5e060 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,19 +1,19 @@
-# $OpenBSD: Makefile,v 1.117 2019/03/06 12:26:30 schwarze Exp $
+# $OpenBSD: Makefile,v 1.118 2020/03/13 00:31:04 schwarze Exp $
.include <bsd.own.mk>
CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter
-DPADD += ${LIBUTIL}
+DPADD += ${LIBUTIL}
LDADD += -lutil -lz
SRCS= mandoc_aux.c mandoc_ohash.c mandoc.c mandoc_msg.c mandoc_xr.c \
- arch.c chars.c preconv.c read.c \
- roff.c roff_validate.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c eqn.c
-SRCS+= mdoc_macro.c mdoc.c \
- mdoc_argv.c mdoc_state.c mdoc_validate.c att.c msec.c st.c
+ arch.c chars.c msec.c preconv.c read.c tag.c
+SRCS+= roff.c roff_validate.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c eqn.c
+SRCS+= mdoc.c mdoc_argv.c mdoc_macro.c mdoc_state.c mdoc_validate.c \
+ att.c st.c
SRCS+= man_macro.c man.c man_validate.c
-SRCS+= main.c out.c tag.c tree.c
-SRCS+= term.c term_tab.c term_ascii.c term_ps.c
+SRCS+= main.c out.c tree.c
+SRCS+= term.c term_ascii.c term_ps.c term_tab.c term_tag.c
SRCS+= roff_term.c mdoc_term.c man_term.c eqn_term.c tbl_term.c
SRCS+= mdoc_man.c
SRCS+= html.c roff_html.c mdoc_html.c man_html.c eqn_html.c tbl_html.c
@@ -55,7 +55,7 @@ LIBROFF_OBJS = roff.o roff_validate.o eqn.o \
tbl.o tbl_data.o tbl_layout.o tbl_opts.o
LIBMANDOC_OBJS = ${LIBMDOC_OBJS} ${LIBMAN_OBJS} ${LIBROFF_OBJS} \
arch.o mandoc.o mandoc_aux.o mandoc_msg.o mandoc_ohash.o \
- mandoc_xr.o chars.o msec.o preconv.o read.o
+ mandoc_xr.o chars.o msec.o preconv.o read.o tag.o
HTML_OBJS = html.o roff_html.o mdoc_html.o man_html.o \
tbl_html.o eqn_html.o out.o
CGI_OBJS = ${LIBMANDOC_OBJS} ${HTML_OBJS} \
diff --git a/usr.bin/mandoc/html.c b/usr.bin/mandoc/html.c
index 102daabf3d9..c7c87c67a4e 100644
--- a/usr.bin/mandoc/html.c
+++ b/usr.bin/mandoc/html.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: html.c,v 1.134 2020/02/27 22:26:26 schwarze Exp $ */
+/* $OpenBSD: html.c,v 1.135 2020/03/13 00:31:04 schwarze Exp $ */
/*
- * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Common functions for mandoc(1) HTML formatters.
+ * For use by individual formatters and by the main program.
*/
#include <sys/types.h>
#include <sys/stat.h>
@@ -319,6 +322,18 @@ html_fillmode(struct html *h, enum roff_tok want)
return had;
}
+/*
+ * Allocate a string to be used for the "id=" attribute of an HTML
+ * element and/or as a segment identifier for a URI in an <a> element.
+ * The function may fail and return NULL if the node lacks text data
+ * to create the attribute from.
+ * If the "unique" argument is 0, the caller is responsible for
+ * free(3)ing the returned string after using it.
+ * If the "unique" argument is non-zero, the "id_unique" ohash table
+ * is used for de-duplication and owns the returned string, so the
+ * caller must not free(3) it. In this case, it will be freed
+ * automatically by html_reset() or html_free().
+ */
char *
html_make_id(const struct roff_node *n, int unique)
{
@@ -327,14 +342,30 @@ html_make_id(const struct roff_node *n, int unique)
unsigned int slot;
int suffix;
- for (nch = n->child; nch != NULL; nch = nch->next)
- if (nch->type != ROFFT_TEXT)
- return NULL;
-
- buf = NULL;
- deroff(&buf, n);
- if (buf == NULL)
- return NULL;
+ if (n->string != NULL)
+ buf = mandoc_strdup(n->string);
+ else {
+ switch (n->tok) {
+ case MDOC_Sh:
+ case MDOC_Ss:
+ case MDOC_Sx:
+ case MAN_SH:
+ case MAN_SS:
+ for (nch = n->child; nch != NULL; nch = nch->next)
+ if (nch->type != ROFFT_TEXT)
+ return NULL;
+ buf = NULL;
+ deroff(&buf, n);
+ if (buf == NULL)
+ return NULL;
+ break;
+ default:
+ if (n->child->type != ROFFT_TEXT)
+ return NULL;
+ buf = mandoc_strdup(n->child->string);
+ break;
+ }
+ }
/*
* In ID attributes, only use ASCII characters that are
@@ -734,6 +765,33 @@ print_otag(struct html *h, enum htmltag tag, const char *fmt, ...)
return t;
}
+/*
+ * Print an element with an optional "id=" attribute.
+ * If there is an "id=" attribute, also add a permalink:
+ * outside if it's a phrasing element, or inside otherwise.
+ */
+struct tag *
+print_otag_id(struct html *h, enum htmltag elemtype, const char *cattr,
+ struct roff_node *n)
+{
+ struct tag *ret, *t;
+ const char *id;
+
+ ret = NULL;
+ id = NULL;
+ if (n->flags & NODE_ID)
+ id = html_make_id(n, 1);
+ if (id != NULL && htmltags[elemtype].flags & HTML_INPHRASE)
+ ret = print_otag(h, TAG_A, "chR", "permalink", id);
+ t = print_otag(h, elemtype, "ci", cattr, id);
+ if (ret == NULL) {
+ ret = t;
+ if (id != NULL)
+ print_otag(h, TAG_A, "chR", "permalink", id);
+ }
+ return ret;
+}
+
static void
print_ctag(struct html *h, struct tag *tag)
{
diff --git a/usr.bin/mandoc/html.h b/usr.bin/mandoc/html.h
index f0c9fe6d7a4..7bd55d48af5 100644
--- a/usr.bin/mandoc/html.h
+++ b/usr.bin/mandoc/html.h
@@ -1,7 +1,7 @@
-/* $OpenBSD: html.h,v 1.68 2020/01/19 17:59:01 schwarze Exp $ */
+/* $OpenBSD: html.h,v 1.69 2020/03/13 00:31:04 schwarze Exp $ */
/*
+ * Copyright (c) 2017, 2018, 2019, 2020 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2017, 2018, 2019 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
@@ -14,6 +14,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Internal interfaces for mandoc(1) HTML formatters.
+ * For use by the individual HTML formatters only.
*/
enum htmltag {
@@ -120,6 +123,8 @@ void print_gen_comment(struct html *, struct roff_node *);
void print_gen_decls(struct html *);
void print_gen_head(struct html *);
struct tag *print_otag(struct html *, enum htmltag, const char *, ...);
+struct tag *print_otag_id(struct html *, enum htmltag, const char *,
+ struct roff_node *);
void print_tagq(struct html *, const struct tag *);
void print_stagq(struct html *, const struct tag *);
void print_text(struct html *, const char *);
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 5c72f60ce7b..8931df51ea1 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: main.c,v 1.247 2020/02/24 21:15:05 schwarze Exp $ */
+/* $OpenBSD: main.c,v 1.248 2020/03/13 00:31:04 schwarze Exp $ */
/*
- * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,8 +15,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Main program for mandoc(1), man(1), apropos(1), whatis(1), and help(1).
*/
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* MACHINE */
@@ -46,7 +47,7 @@
#include "mdoc.h"
#include "man.h"
#include "mandoc_parse.h"
-#include "tag.h"
+#include "term_tag.h"
#include "main.h"
#include "manconf.h"
#include "mansearch.h"
@@ -577,7 +578,6 @@ main(int argc, char *argv[])
* readable: Maybe it won't be needed after all.
*/
startdir = open(".", O_RDONLY | O_DIRECTORY);
-
for (i = 0; i < ressz; i++) {
process_onefile(mp, res + i, startdir, &outst, &conf);
if (outst.wstop && mandoc_msg_getrc() != MANDOCLEVEL_OK)
@@ -587,7 +587,6 @@ main(int argc, char *argv[])
(void)fchdir(startdir);
close(startdir);
}
-
if (outst.outdata != NULL) {
switch (outst.outtype) {
case OUTT_HTML:
@@ -596,6 +595,7 @@ main(int argc, char *argv[])
case OUTT_UTF8:
case OUTT_LOCALE:
case OUTT_ASCII:
+ term_tag_finish();
ascii_free(outst.outdata);
break;
case OUTT_PDF:
@@ -617,9 +617,8 @@ out:
if (outst.tag_files != NULL) {
fclose(stdout);
- tag_write();
run_pager(outst.tag_files);
- tag_unlink();
+ term_tag_unlink();
} else if (outst.had_output && outst.outtype != OUTT_LINT)
mandoc_msg_summary();
@@ -810,15 +809,16 @@ process_onefile(struct mparse *mp, struct manpage *resp, int startdir,
} else
fd = STDIN_FILENO;
- if (outst->use_pager) {
- outst->use_pager = 0;
- outst->tag_files = tag_init(conf->output.tag);
- }
-
- if (outst->had_output && outst->outtype <= OUTT_UTF8) {
- if (outst->outdata == NULL)
- outdata_alloc(outst, &conf->output);
- terminal_sepline(outst->outdata);
+ if (outst->outtype <= OUTT_UTF8) {
+ if (outst->use_pager) {
+ outst->use_pager = 0;
+ outst->tag_files = term_tag_init(conf->output.tag);
+ }
+ if (outst->had_output) {
+ if (outst->outdata == NULL)
+ outdata_alloc(outst, &conf->output);
+ terminal_sepline(outst->outdata);
+ }
}
if (resp->form == FORM_SRC)
@@ -832,7 +832,7 @@ process_onefile(struct mparse *mp, struct manpage *resp, int startdir,
if (outst->tag_files != NULL) {
mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s: %s",
outst->tag_files->ofn, strerror(errno));
- tag_unlink();
+ term_tag_unlink();
outst->tag_files = NULL;
} else
mandoc_msg(MANDOCERR_WRITE, 0, 0, "%s",
@@ -1251,7 +1251,7 @@ spawn_pager(struct tag_files *tag_files)
_exit(mandoc_msg_getrc());
}
close(tag_files->ofd);
- assert(tag_files->tfd == -1);
+ assert(tag_files->tfs == NULL);
/* Do not start the pager before controlling the terminal. */
diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c
index 589b4114138..dd360649d6d 100644
--- a/usr.bin/mandoc/man_html.c
+++ b/usr.bin/mandoc/man_html.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: man_html.c,v 1.129 2020/02/27 01:25:57 schwarze Exp $ */
+/* $OpenBSD: man_html.c,v 1.130 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,8 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * HTML formatter for man(7) used by mandoc(1).
*/
#include <sys/types.h>
@@ -308,7 +310,6 @@ static int
man_SH_pre(MAN_ARGS)
{
const char *class;
- char *id;
enum htmltag tag;
if (n->tok == MAN_SH) {
@@ -324,10 +325,8 @@ man_SH_pre(MAN_ARGS)
print_otag(h, TAG_SECTION, "c", class);
break;
case ROFFT_HEAD:
- id = html_make_id(n, 1);
- print_otag(h, tag, "ci", class, id);
- if (id != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
+ n->flags |= NODE_ID;
+ print_otag_id(h, tag, class, n);
break;
case ROFFT_BODY:
break;
@@ -487,7 +486,7 @@ man_IP_pre(MAN_ARGS)
case ROFFT_HEAD:
if (body_elem == TAG_LI)
return 0;
- print_otag(h, TAG_DT, "");
+ print_otag_id(h, TAG_DT, NULL, n);
break;
case ROFFT_BODY:
print_otag(h, body_elem, "");
@@ -495,7 +494,6 @@ man_IP_pre(MAN_ARGS)
default:
abort();
}
-
switch(n->tok) {
case MAN_IP: /* Only print the first header element. */
if (n->child != NULL)
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c
index 33ae377ffb9..3bf25adbf54 100644
--- a/usr.bin/mandoc/man_term.c
+++ b/usr.bin/mandoc/man_term.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: man_term.c,v 1.187 2020/02/27 01:25:57 schwarze Exp $ */
+/* $OpenBSD: man_term.c,v 1.188 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Plain text formatter for man(7), used by mandoc(1)
+ * for ASCII, UTF-8, PostScript, and PDF output.
*/
#include <sys/types.h>
@@ -30,7 +33,7 @@
#include "man.h"
#include "out.h"
#include "term.h"
-#include "tag.h"
+#include "term_tag.h"
#include "main.h"
#define MAXMARGINS 64 /* maximum number of indented scopes */
@@ -92,8 +95,6 @@ static void post_SY(DECL_ARGS);
static void post_TP(DECL_ARGS);
static void post_UR(DECL_ARGS);
-static void tag_man(struct termp *, struct roff_node *);
-
static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = {
{ NULL, NULL, 0 }, /* TH */
{ pre_SH, post_SH, 0 }, /* SH */
@@ -537,10 +538,8 @@ pre_IP(DECL_ARGS)
case ROFFT_HEAD:
p->tcol->offset = mt->offset;
p->tcol->rmargin = mt->offset + len;
- if (n->child != NULL) {
+ if (n->child != NULL)
print_man_node(p, mt, n->child, meta);
- tag_man(p, n->child);
- }
return 0;
case ROFFT_BODY:
p->tcol->offset = mt->offset + len;
@@ -620,18 +619,6 @@ pre_TP(DECL_ARGS)
while (nn != NULL && (nn->flags & NODE_LINE) == 0)
nn = nn->next;
- if (nn == NULL)
- return 0;
-
- if (nn->type == ROFFT_TEXT)
- tag_man(p, nn);
- else if (nn->child != NULL &&
- nn->child->type == ROFFT_TEXT &&
- (nn->tok == MAN_B || nn->tok == MAN_BI ||
- nn->tok == MAN_BR || nn->tok == MAN_I ||
- nn->tok == MAN_IB || nn->tok == MAN_IR))
- tag_man(p, nn->child);
-
while (nn != NULL) {
print_man_node(p, mt, nn, meta);
nn = nn->next;
@@ -911,6 +898,9 @@ print_man_node(DECL_ARGS)
const struct man_term_act *act;
int c;
+ if (n->flags & NODE_ID)
+ term_tag_write(n, p->line);
+
switch (n->type) {
case ROFFT_TEXT:
/*
@@ -1157,60 +1147,3 @@ print_man_head(struct termp *p, const struct roff_meta *meta)
}
free(title);
}
-
-/*
- * Skip leading whitespace, dashes, backslashes, and font escapes,
- * then create a tag if the first following byte is a letter.
- * Priority is high unless whitespace is present.
- */
-static void
-tag_man(struct termp *p, struct roff_node *n)
-{
- const char *cp, *arg;
- int prio, sz;
-
- assert(n->type == ROFFT_TEXT);
- cp = n->string;
- prio = TAG_STRONG;
- for (;;) {
- switch (*cp) {
- case ' ':
- case '\t':
- prio = TAG_WEAK;
- /* FALLTHROUGH */
- case '-':
- cp++;
- break;
- case '\\':
- cp++;
- switch (mandoc_escape(&cp, &arg, &sz)) {
- case ESCAPE_FONT:
- case ESCAPE_FONTROMAN:
- case ESCAPE_FONTITALIC:
- case ESCAPE_FONTBOLD:
- case ESCAPE_FONTPREV:
- case ESCAPE_FONTBI:
- break;
- case ESCAPE_SPECIAL:
- if (sz != 1)
- return;
- switch (*arg) {
- case '&':
- case '-':
- case 'e':
- break;
- default:
- return;
- }
- break;
- default:
- return;
- }
- break;
- default:
- if (isalpha((unsigned char)*cp))
- tag_put(cp, prio, p->line);
- return;
- }
- }
-}
diff --git a/usr.bin/mandoc/man_validate.c b/usr.bin/mandoc/man_validate.c
index 897fead07cf..4ab8c2cce11 100644
--- a/usr.bin/mandoc/man_validate.c
+++ b/usr.bin/mandoc/man_validate.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: man_validate.c,v 1.120 2020/01/19 16:16:32 schwarze Exp $ */
+/* $OpenBSD: man_validate.c,v 1.121 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,8 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Validation module for man(7) syntax trees used by mandoc(1).
*/
#include <sys/types.h>
@@ -30,6 +32,7 @@
#include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
+#include "tag.h"
#include "man.h"
#include "libmandoc.h"
#include "roff_int.h"
@@ -43,6 +46,7 @@ static void check_abort(CHKARGS) __attribute__((__noreturn__));
static void check_par(CHKARGS);
static void check_part(CHKARGS);
static void check_root(CHKARGS);
+static void check_tag(struct roff_node *, struct roff_node *);
static void check_text(CHKARGS);
static void post_AT(CHKARGS);
@@ -52,6 +56,7 @@ static void post_IP(CHKARGS);
static void post_OP(CHKARGS);
static void post_SH(CHKARGS);
static void post_TH(CHKARGS);
+static void post_TP(CHKARGS);
static void post_UC(CHKARGS);
static void post_UR(CHKARGS);
static void post_in(CHKARGS);
@@ -60,8 +65,8 @@ static const v_check man_valids[MAN_MAX - MAN_TH] = {
post_TH, /* TH */
post_SH, /* SH */
post_SH, /* SS */
- NULL, /* TP */
- NULL, /* TQ */
+ post_TP, /* TP */
+ post_TP, /* TQ */
check_abort,/* LP */
check_par, /* PP */
check_abort,/* P */
@@ -199,6 +204,66 @@ check_abort(CHKARGS)
abort();
}
+/*
+ * Skip leading whitespace, dashes, backslashes, and font escapes,
+ * then create a tag if the first following byte is a letter.
+ * Priority is high unless whitespace is present.
+ */
+static void
+check_tag(struct roff_node *n, struct roff_node *nt)
+{
+ const char *cp, *arg;
+ int prio, sz;
+
+ if (nt == NULL || nt->type != ROFFT_TEXT)
+ return;
+
+ cp = nt->string;
+ prio = TAG_STRONG;
+ for (;;) {
+ switch (*cp) {
+ case ' ':
+ case '\t':
+ prio = TAG_WEAK;
+ /* FALLTHROUGH */
+ case '-':
+ cp++;
+ break;
+ case '\\':
+ cp++;
+ switch (mandoc_escape(&cp, &arg, &sz)) {
+ case ESCAPE_FONT:
+ case ESCAPE_FONTBOLD:
+ case ESCAPE_FONTITALIC:
+ case ESCAPE_FONTBI:
+ case ESCAPE_FONTROMAN:
+ case ESCAPE_FONTCW:
+ case ESCAPE_FONTPREV:
+ case ESCAPE_IGNORE:
+ break;
+ case ESCAPE_SPECIAL:
+ if (sz != 1)
+ return;
+ switch (*arg) {
+ case '-':
+ case 'e':
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ if (isalpha((unsigned char)*cp))
+ tag_put(cp, prio, n);
+ return;
+ }
+ }
+}
+
static void
check_text(CHKARGS)
{
@@ -330,12 +395,14 @@ check_par(CHKARGS)
static void
post_IP(CHKARGS)
{
-
switch (n->type) {
case ROFFT_BLOCK:
if (n->head->child == NULL && n->body->child == NULL)
roff_node_delete(man, n);
break;
+ case ROFFT_HEAD:
+ check_tag(n, n->child);
+ break;
case ROFFT_BODY:
if (n->parent->head->child == NULL && n->child == NULL)
mandoc_msg(MANDOCERR_PAR_SKIP, n->line, n->pos,
@@ -346,6 +413,37 @@ post_IP(CHKARGS)
}
}
+/*
+ * The first next-line element in the head is the tag.
+ * If that's a font macro, use its first child instead.
+ */
+static void
+post_TP(CHKARGS)
+{
+ struct roff_node *nt;
+
+ if (n->type != ROFFT_HEAD || (nt = n->child) == NULL)
+ return;
+
+ while ((nt->flags & NODE_LINE) == 0)
+ if ((nt = nt->next) == NULL)
+ return;
+
+ switch (nt->tok) {
+ case MAN_B:
+ case MAN_BI:
+ case MAN_BR:
+ case MAN_I:
+ case MAN_IB:
+ case MAN_IR:
+ nt = nt->child;
+ break;
+ default:
+ break;
+ }
+ check_tag(n, nt);
+}
+
static void
post_TH(CHKARGS)
{
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index 2dfc43a2123..e20126a9bd4 100644
--- a/usr.bin/mandoc/mdoc_html.c
+++ b/usr.bin/mandoc/mdoc_html.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: mdoc_html.c,v 1.210 2020/02/27 22:26:26 schwarze Exp $ */
+/* $OpenBSD: mdoc_html.c,v 1.211 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,8 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * HTML formatter for mdoc(7) used by mandoc(1).
*/
#include <sys/types.h>
@@ -45,7 +47,6 @@ struct mdoc_html_act {
void (*post)(MDOC_ARGS);
};
-static char *cond_id(const struct roff_node *);
static void print_mdoc_head(const struct roff_meta *,
struct html *);
static void print_mdoc_node(MDOC_ARGS);
@@ -70,9 +71,8 @@ static void mdoc_bk_post(MDOC_ARGS);
static int mdoc_bk_pre(MDOC_ARGS);
static int mdoc_bl_pre(MDOC_ARGS);
static int mdoc_cd_pre(MDOC_ARGS);
-static int mdoc_cm_pre(MDOC_ARGS);
+static int mdoc_code_pre(MDOC_ARGS);
static int mdoc_d1_pre(MDOC_ARGS);
-static int mdoc_dv_pre(MDOC_ARGS);
static int mdoc_fa_pre(MDOC_ARGS);
static int mdoc_fd_pre(MDOC_ARGS);
static int mdoc_fl_pre(MDOC_ARGS);
@@ -81,20 +81,15 @@ static int mdoc_ft_pre(MDOC_ARGS);
static int mdoc_em_pre(MDOC_ARGS);
static void mdoc_eo_post(MDOC_ARGS);
static int mdoc_eo_pre(MDOC_ARGS);
-static int mdoc_er_pre(MDOC_ARGS);
-static int mdoc_ev_pre(MDOC_ARGS);
static int mdoc_ex_pre(MDOC_ARGS);
static void mdoc_fo_post(MDOC_ARGS);
static int mdoc_fo_pre(MDOC_ARGS);
-static int mdoc_ic_pre(MDOC_ARGS);
static int mdoc_igndelim_pre(MDOC_ARGS);
static int mdoc_in_pre(MDOC_ARGS);
static int mdoc_it_pre(MDOC_ARGS);
static int mdoc_lb_pre(MDOC_ARGS);
-static int mdoc_li_pre(MDOC_ARGS);
static int mdoc_lk_pre(MDOC_ARGS);
static int mdoc_mt_pre(MDOC_ARGS);
-static int mdoc_ms_pre(MDOC_ARGS);
static int mdoc_nd_pre(MDOC_ARGS);
static int mdoc_nm_pre(MDOC_ARGS);
static int mdoc_no_pre(MDOC_ARGS);
@@ -137,19 +132,19 @@ static const struct mdoc_html_act mdoc_html_acts[MDOC_MAX - MDOC_Dd] = {
{mdoc_ap_pre, NULL}, /* Ap */
{mdoc_ar_pre, NULL}, /* Ar */
{mdoc_cd_pre, NULL}, /* Cd */
- {mdoc_cm_pre, NULL}, /* Cm */
- {mdoc_dv_pre, NULL}, /* Dv */
- {mdoc_er_pre, NULL}, /* Er */
- {mdoc_ev_pre, NULL}, /* Ev */
+ {mdoc_code_pre, NULL}, /* Cm */
+ {mdoc_code_pre, NULL}, /* Dv */
+ {mdoc_code_pre, NULL}, /* Er */
+ {mdoc_code_pre, NULL}, /* Ev */
{mdoc_ex_pre, NULL}, /* Ex */
{mdoc_fa_pre, NULL}, /* Fa */
{mdoc_fd_pre, NULL}, /* Fd */
{mdoc_fl_pre, NULL}, /* Fl */
{mdoc_fn_pre, NULL}, /* Fn */
{mdoc_ft_pre, NULL}, /* Ft */
- {mdoc_ic_pre, NULL}, /* Ic */
+ {mdoc_code_pre, NULL}, /* Ic */
{mdoc_in_pre, NULL}, /* In */
- {mdoc_li_pre, NULL}, /* Li */
+ {mdoc_code_pre, NULL}, /* Li */
{mdoc_nd_pre, NULL}, /* Nd */
{mdoc_nm_pre, NULL}, /* Nm */
{mdoc_quote_pre, mdoc_quote_post}, /* Op */
@@ -190,7 +185,7 @@ static const struct mdoc_html_act mdoc_html_acts[MDOC_MAX - MDOC_Dd] = {
{mdoc_em_pre, NULL}, /* Em */
{mdoc_eo_pre, mdoc_eo_post}, /* Eo */
{mdoc_xx_pre, NULL}, /* Fx */
- {mdoc_ms_pre, NULL}, /* Ms */
+ {mdoc_no_pre, NULL}, /* Ms */
{mdoc_no_pre, NULL}, /* No */
{mdoc_ns_pre, NULL}, /* Ns */
{mdoc_xx_pre, NULL}, /* Nx */
@@ -505,20 +500,11 @@ mdoc_root_pre(const struct roff_meta *meta, struct html *h)
return 1;
}
-static char *
-cond_id(const struct roff_node *n)
+static int
+mdoc_code_pre(MDOC_ARGS)
{
- if (n->child != NULL &&
- n->child->type == ROFFT_TEXT &&
- (n->prev == NULL ||
- (n->prev->type == ROFFT_TEXT &&
- strcmp(n->prev->string, "|") == 0)) &&
- (n->parent->tok == MDOC_It ||
- (n->parent->tok == MDOC_Xo &&
- n->parent->parent->prev == NULL &&
- n->parent->parent->parent->tok == MDOC_It)))
- return html_make_id(n, 1);
- return NULL;
+ print_otag_id(h, TAG_CODE, roff_name[n->tok], n);
+ return 1;
}
static int
@@ -581,10 +567,8 @@ mdoc_sh_pre(MDOC_ARGS)
print_otag(h, TAG_SECTION, "c", "Sh");
break;
case ROFFT_HEAD:
- id = html_make_id(n, 1);
- print_otag(h, TAG_H1, "ci", "Sh", id);
- if (id != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
+ n->flags |= NODE_ID;
+ print_otag_id(h, TAG_H1, "Sh", n);
break;
case ROFFT_BODY:
if (n->sec == SEC_AUTHORS)
@@ -599,25 +583,20 @@ mdoc_sh_pre(MDOC_ARGS)
static int
mdoc_ss_pre(MDOC_ARGS)
{
- char *id;
-
switch (n->type) {
case ROFFT_BLOCK:
html_close_paragraph(h);
print_otag(h, TAG_SECTION, "c", "Ss");
- return 1;
+ break;
case ROFFT_HEAD:
+ n->flags |= NODE_ID;
+ print_otag_id(h, TAG_H2, "Ss", n);
break;
case ROFFT_BODY:
- return 1;
+ break;
default:
abort();
}
-
- id = html_make_id(n, 1);
- print_otag(h, TAG_H2, "ci", "Ss", id);
- if (id != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
return 1;
}
@@ -625,12 +604,8 @@ static int
mdoc_fl_pre(MDOC_ARGS)
{
struct roff_node *nn;
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "ci", "Fl", id);
+ print_otag_id(h, TAG_CODE, "Fl", n);
print_text(h, "\\-");
if (n->child != NULL ||
((nn = roff_node_next(n)) != NULL &&
@@ -642,17 +617,6 @@ mdoc_fl_pre(MDOC_ARGS)
}
static int
-mdoc_cm_pre(MDOC_ARGS)
-{
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "ci", "Cm", id);
- return 1;
-}
-
-static int
mdoc_nd_pre(MDOC_ARGS)
{
switch (n->type) {
@@ -924,7 +888,7 @@ mdoc_st_pre(MDOC_ARGS)
static int
mdoc_em_pre(MDOC_ARGS)
{
- print_otag(h, TAG_I, "c", "Em");
+ print_otag_id(h, TAG_I, "Em", n);
return 1;
}
@@ -1050,45 +1014,6 @@ mdoc_cd_pre(MDOC_ARGS)
}
static int
-mdoc_dv_pre(MDOC_ARGS)
-{
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "ci", "Dv", id);
- return 1;
-}
-
-static int
-mdoc_ev_pre(MDOC_ARGS)
-{
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "ci", "Ev", id);
- return 1;
-}
-
-static int
-mdoc_er_pre(MDOC_ARGS)
-{
- char *id;
-
- id = n->sec == SEC_ERRORS &&
- (n->parent->tok == MDOC_It ||
- (n->parent->tok == MDOC_Bq &&
- n->parent->parent->parent->tok == MDOC_It)) ?
- html_make_id(n, 1) : NULL;
-
- if (id != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "ci", "Er", id);
- return 1;
-}
-
-static int
mdoc_fa_pre(MDOC_ARGS)
{
const struct roff_node *nn;
@@ -1220,7 +1145,7 @@ mdoc_fn_pre(MDOC_ARGS)
print_tagq(h, t);
}
- t = print_otag(h, TAG_CODE, "c", "Fn");
+ t = print_otag_id(h, TAG_CODE, "Fn", n);
if (sp)
print_text(h, sp);
@@ -1339,14 +1264,12 @@ mdoc_mt_pre(MDOC_ARGS)
for (n = n->child; n; n = n->next) {
assert(n->type == ROFFT_TEXT);
-
mandoc_asprintf(&cp, "mailto:%s", n->string);
t = print_otag(h, TAG_A, "ch", "Mt", cp);
print_text(h, n->string);
print_tagq(h, t);
free(cp);
}
-
return 0;
}
@@ -1355,30 +1278,30 @@ mdoc_fo_pre(MDOC_ARGS)
{
struct tag *t;
- if (n->type == ROFFT_BODY) {
+ switch (n->type) {
+ case ROFFT_BLOCK:
+ synopsis_pre(h, n);
+ return 1;
+ case ROFFT_HEAD:
+ if (n->child != NULL) {
+ t = print_otag_id(h, TAG_CODE, "Fn", n);
+ print_text(h, n->child->string);
+ print_tagq(h, t);
+ }
+ return 0;
+ case ROFFT_BODY:
h->flags |= HTML_NOSPACE;
print_text(h, "(");
h->flags |= HTML_NOSPACE;
return 1;
- } else if (n->type == ROFFT_BLOCK) {
- synopsis_pre(h, n);
- return 1;
+ default:
+ abort();
}
-
- if (n->child == NULL)
- return 0;
-
- assert(n->child->string);
- t = print_otag(h, TAG_CODE, "c", "Fn");
- print_text(h, n->child->string);
- print_tagq(h, t);
- return 0;
}
static void
mdoc_fo_post(MDOC_ARGS)
{
-
if (n->type != ROFFT_BODY)
return;
h->flags |= HTML_NOSPACE;
@@ -1428,22 +1351,10 @@ mdoc_in_pre(MDOC_ARGS)
assert(n->type == ROFFT_TEXT);
print_text(h, n->string);
}
-
return 0;
}
static int
-mdoc_ic_pre(MDOC_ARGS)
-{
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "ci", "Ic", id);
- return 1;
-}
-
-static int
mdoc_va_pre(MDOC_ARGS)
{
print_otag(h, TAG_VAR, "c", "Va");
@@ -1453,7 +1364,6 @@ mdoc_va_pre(MDOC_ARGS)
static int
mdoc_ap_pre(MDOC_ARGS)
{
-
h->flags |= HTML_NOSPACE;
print_text(h, "\\(aq");
h->flags |= HTML_NOSPACE;
@@ -1492,20 +1402,8 @@ mdoc_bf_pre(MDOC_ARGS)
}
static int
-mdoc_ms_pre(MDOC_ARGS)
-{
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_SPAN, "ci", "Ms", id);
- return 1;
-}
-
-static int
mdoc_igndelim_pre(MDOC_ARGS)
{
-
h->flags |= HTML_IGNDELIM;
return 1;
}
@@ -1513,7 +1411,6 @@ mdoc_igndelim_pre(MDOC_ARGS)
static void
mdoc_pf_post(MDOC_ARGS)
{
-
if ( ! (n->next == NULL || n->next->flags & NODE_LINE))
h->flags |= HTML_NOSPACE;
}
@@ -1542,29 +1439,14 @@ mdoc_rs_pre(MDOC_ARGS)
static int
mdoc_no_pre(MDOC_ARGS)
{
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_SPAN, "ci", "No", id);
- return 1;
-}
-
-static int
-mdoc_li_pre(MDOC_ARGS)
-{
- char *id;
-
- if ((id = cond_id(n)) != NULL)
- print_otag(h, TAG_A, "chR", "permalink", id);
- print_otag(h, TAG_CODE, "ci", "Li", id);
+ print_otag_id(h, TAG_SPAN, roff_name[n->tok], n);
return 1;
}
static int
mdoc_sy_pre(MDOC_ARGS)
{
- print_otag(h, TAG_B, "c", "Sy");
+ print_otag_id(h, TAG_B, "Sy", n);
return 1;
}
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index 54252473702..edbbec08797 100644
--- a/usr.bin/mandoc/mdoc_term.c
+++ b/usr.bin/mandoc/mdoc_term.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: mdoc_term.c,v 1.277 2020/02/27 21:38:27 schwarze Exp $ */
+/* $OpenBSD: mdoc_term.c,v 1.278 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,6 +15,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Plain text formatter for mdoc(7), used by mandoc(1)
+ * for ASCII, UTF-8, PostScript, and PDF output.
*/
#include <sys/types.h>
@@ -31,7 +34,7 @@
#include "mdoc.h"
#include "out.h"
#include "term.h"
-#include "tag.h"
+#include "term_tag.h"
#include "main.h"
struct termpair {
@@ -87,11 +90,8 @@ static int termp_bf_pre(DECL_ARGS);
static int termp_bk_pre(DECL_ARGS);
static int termp_bl_pre(DECL_ARGS);
static int termp_bold_pre(DECL_ARGS);
-static int termp_cd_pre(DECL_ARGS);
static int termp_d1_pre(DECL_ARGS);
static int termp_eo_pre(DECL_ARGS);
-static int termp_em_pre(DECL_ARGS);
-static int termp_er_pre(DECL_ARGS);
static int termp_ex_pre(DECL_ARGS);
static int termp_fa_pre(DECL_ARGS);
static int termp_fd_pre(DECL_ARGS);
@@ -113,8 +113,6 @@ static int termp_skip_pre(DECL_ARGS);
static int termp_sm_pre(DECL_ARGS);
static int termp_pp_pre(DECL_ARGS);
static int termp_ss_pre(DECL_ARGS);
-static int termp_sy_pre(DECL_ARGS);
-static int termp_tag_pre(DECL_ARGS);
static int termp_under_pre(DECL_ARGS);
static int termp_vt_pre(DECL_ARGS);
static int termp_xr_pre(DECL_ARGS);
@@ -138,11 +136,11 @@ static const struct mdoc_term_act mdoc_term_acts[MDOC_MAX - MDOC_Dd] = {
{ termp_an_pre, NULL }, /* An */
{ termp_ap_pre, NULL }, /* Ap */
{ termp_under_pre, NULL }, /* Ar */
- { termp_cd_pre, NULL }, /* Cd */
+ { termp_fd_pre, NULL }, /* Cd */
{ termp_bold_pre, NULL }, /* Cm */
{ termp_li_pre, NULL }, /* Dv */
- { termp_er_pre, NULL }, /* Er */
- { termp_tag_pre, NULL }, /* Ev */
+ { NULL, NULL }, /* Er */
+ { NULL, NULL }, /* Ev */
{ termp_ex_pre, NULL }, /* Ex */
{ termp_fa_pre, NULL }, /* Fa */
{ termp_fd_pre, termp_fd_post }, /* Fd */
@@ -189,7 +187,7 @@ static const struct mdoc_term_act mdoc_term_acts[MDOC_MAX - MDOC_Dd] = {
{ termp_quote_pre, termp_quote_post }, /* Dq */
{ NULL, NULL }, /* Ec */ /* FIXME: no space */
{ NULL, NULL }, /* Ef */
- { termp_em_pre, NULL }, /* Em */
+ { termp_under_pre, NULL }, /* Em */
{ termp_eo_pre, termp_eo_post }, /* Eo */
{ termp_xx_pre, termp_xx_post }, /* Fx */
{ termp_bold_pre, NULL }, /* Ms */
@@ -212,7 +210,7 @@ static const struct mdoc_term_act mdoc_term_acts[MDOC_MAX - MDOC_Dd] = {
{ termp_quote_pre, termp_quote_post }, /* Sq */
{ termp_sm_pre, NULL }, /* Sm */
{ termp_under_pre, NULL }, /* Sx */
- { termp_sy_pre, NULL }, /* Sy */
+ { termp_bold_pre, NULL }, /* Sy */
{ NULL, NULL }, /* Tn */
{ termp_xx_pre, termp_xx_post }, /* Ux */
{ NULL, NULL }, /* Xc */
@@ -244,8 +242,6 @@ static const struct mdoc_term_act mdoc_term_acts[MDOC_MAX - MDOC_Dd] = {
{ termp_skip_pre, NULL }, /* Tg */
};
-static int fn_prio = TAG_STRONG;
-
void
terminal_mdoc(void *arg, const struct roff_meta *mdoc)
@@ -298,7 +294,6 @@ terminal_mdoc(void *arg, const struct roff_meta *mdoc)
static void
print_mdoc_nodelist(DECL_ARGS)
{
-
while (n != NULL) {
print_mdoc_node(p, pair, meta, n);
n = n->next;
@@ -339,8 +334,7 @@ print_mdoc_node(DECL_ARGS)
npair.ppair = pair;
if (n->flags & NODE_ID)
- tag_put(n->string == NULL ? n->child->string : n->string,
- TAG_MANUAL, p->line);
+ term_tag_write(n, p->line);
/*
* Keeps only work until the end of a line. If a keep was
@@ -1006,24 +1000,30 @@ termp_nm_pre(DECL_ARGS)
p->flags |= TERMP_HANG;
}
}
-
- term_fontpush(p, TERMFONT_BOLD);
- return 1;
+ return termp_bold_pre(p, pair, meta, n);
}
static void
termp_nm_post(DECL_ARGS)
{
-
- if (n->type == ROFFT_BLOCK) {
+ switch (n->type) {
+ case ROFFT_BLOCK:
p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
- } else if (n->type == ROFFT_HEAD &&
- NULL != n->next && NULL != n->next->child) {
+ break;
+ case ROFFT_HEAD:
+ if (n->next == NULL || n->next->child == NULL)
+ break;
term_flushln(p);
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG);
p->trailspace = 0;
- } else if (n->type == ROFFT_BODY && n->child != NULL)
- term_flushln(p);
+ break;
+ case ROFFT_BODY:
+ if (n->child != NULL)
+ term_flushln(p);
+ break;
+ default:
+ break;
+ }
}
static int
@@ -1031,7 +1031,6 @@ termp_fl_pre(DECL_ARGS)
{
struct roff_node *nn;
- termp_tag_pre(p, pair, meta, n);
term_fontpush(p, TERMFONT_BOLD);
term_word(p, "\\-");
@@ -1217,24 +1216,22 @@ synopsis_pre(struct termp *p, struct roff_node *n)
static int
termp_vt_pre(DECL_ARGS)
{
-
- if (n->type == ROFFT_ELEM) {
- synopsis_pre(p, n);
- return termp_under_pre(p, pair, meta, n);
- } else if (n->type == ROFFT_BLOCK) {
+ switch (n->type) {
+ case ROFFT_ELEM:
+ return termp_ft_pre(p, pair, meta, n);
+ case ROFFT_BLOCK:
synopsis_pre(p, n);
return 1;
- } else if (n->type == ROFFT_HEAD)
+ case ROFFT_HEAD:
return 0;
-
- return termp_under_pre(p, pair, meta, n);
+ default:
+ return termp_under_pre(p, pair, meta, n);
+ }
}
static int
termp_bold_pre(DECL_ARGS)
{
-
- termp_tag_pre(p, pair, meta, n);
term_fontpush(p, TERMFONT_BOLD);
return 1;
}
@@ -1242,7 +1239,6 @@ termp_bold_pre(DECL_ARGS)
static int
termp_fd_pre(DECL_ARGS)
{
-
synopsis_pre(p, n);
return termp_bold_pre(p, pair, meta, n);
}
@@ -1250,7 +1246,6 @@ termp_fd_pre(DECL_ARGS)
static void
termp_fd_post(DECL_ARGS)
{
-
term_newln(p);
}
@@ -1271,23 +1266,14 @@ termp_sh_pre(DECL_ARGS)
term_vspace(p);
break;
case ROFFT_HEAD:
- term_fontpush(p, TERMFONT_BOLD);
- break;
+ return termp_bold_pre(p, pair, meta, n);
case ROFFT_BODY:
p->tcol->offset = term_len(p, p->defindent);
term_tab_set(p, NULL);
term_tab_set(p, "T");
term_tab_set(p, ".5i");
- switch (n->sec) {
- case SEC_DESCRIPTION:
- fn_prio = TAG_STRONG;
- break;
- case SEC_AUTHORS:
+ if (n->sec == SEC_AUTHORS)
p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT);
- break;
- default:
- break;
- }
break;
default:
break;
@@ -1298,7 +1284,6 @@ termp_sh_pre(DECL_ARGS)
static void
termp_sh_post(DECL_ARGS)
{
-
switch (n->type) {
case ROFFT_HEAD:
term_newln(p);
@@ -1315,15 +1300,13 @@ termp_sh_post(DECL_ARGS)
static void
termp_lb_post(DECL_ARGS)
{
-
- if (SEC_LIBRARY == n->sec && NODE_LINE & n->flags)
+ if (n->sec == SEC_LIBRARY && n->flags & NODE_LINE)
term_newln(p);
}
static int
termp_d1_pre(DECL_ARGS)
{
-
if (n->type != ROFFT_BLOCK)
return 1;
term_newln(p);
@@ -1337,11 +1320,8 @@ termp_d1_pre(DECL_ARGS)
static int
termp_ft_pre(DECL_ARGS)
{
-
- /* NB: NODE_LINE does not effect this! */
synopsis_pre(p, n);
- term_fontpush(p, TERMFONT_UNDER);
- return 1;
+ return termp_under_pre(p, pair, meta, n);
}
static int
@@ -1350,11 +1330,9 @@ termp_fn_pre(DECL_ARGS)
size_t rmargin = 0;
int pretty;
- pretty = NODE_SYNPRETTY & n->flags;
-
synopsis_pre(p, n);
-
- if (NULL == (n = n->child))
+ pretty = n->flags & NODE_SYNPRETTY;
+ if ((n = n->child) == NULL)
return 0;
if (pretty) {
@@ -1368,9 +1346,6 @@ termp_fn_pre(DECL_ARGS)
term_word(p, n->string);
term_fontpop(p);
- if (n->sec == SEC_DESCRIPTION || n->sec == SEC_CUSTOM)
- tag_put(n->string, fn_prio++, p->line);
-
if (pretty) {
term_flushln(p);
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG);
@@ -1405,7 +1380,6 @@ termp_fn_pre(DECL_ARGS)
term_word(p, ";");
term_flushln(p);
}
-
return 0;
}
@@ -1414,10 +1388,9 @@ termp_fa_pre(DECL_ARGS)
{
const struct roff_node *nn;
- if (n->parent->tok != MDOC_Fo) {
- term_fontpush(p, TERMFONT_UNDER);
- return 1;
- }
+ if (n->parent->tok != MDOC_Fo)
+ return termp_under_pre(p, pair, meta, n);
+
for (nn = n->child; nn != NULL; nn = nn->next) {
term_fontpush(p, TERMFONT_UNDER);
p->flags |= TERMP_NBRWORD;
@@ -1528,9 +1501,8 @@ termp_ss_pre(DECL_ARGS)
term_vspace(p);
break;
case ROFFT_HEAD:
- term_fontpush(p, TERMFONT_BOLD);
p->tcol->offset = term_len(p, (p->defindent+1)/2);
- break;
+ return termp_bold_pre(p, pair, meta, n);
case ROFFT_BODY:
p->tcol->offset = term_len(p, p->defindent);
term_tab_set(p, NULL);
@@ -1551,21 +1523,10 @@ termp_ss_post(DECL_ARGS)
}
static int
-termp_cd_pre(DECL_ARGS)
-{
-
- synopsis_pre(p, n);
- term_fontpush(p, TERMFONT_BOLD);
- return 1;
-}
-
-static int
termp_in_pre(DECL_ARGS)
{
-
synopsis_pre(p, n);
-
- if (NODE_SYNPRETTY & n->flags && NODE_LINE & n->flags) {
+ if (n->flags & NODE_SYNPRETTY && n->flags & NODE_LINE) {
term_fontpush(p, TERMFONT_BOLD);
term_word(p, "#include");
term_word(p, "<");
@@ -1573,7 +1534,6 @@ termp_in_pre(DECL_ARGS)
term_word(p, "<");
term_fontpush(p, TERMFONT_UNDER);
}
-
p->flags |= TERMP_NOSPACE;
return 1;
}
@@ -1581,21 +1541,17 @@ termp_in_pre(DECL_ARGS)
static void
termp_in_post(DECL_ARGS)
{
-
- if (NODE_SYNPRETTY & n->flags)
+ if (n->flags & NODE_SYNPRETTY)
term_fontpush(p, TERMFONT_BOLD);
-
p->flags |= TERMP_NOSPACE;
term_word(p, ">");
-
- if (NODE_SYNPRETTY & n->flags)
+ if (n->flags & NODE_SYNPRETTY)
term_fontpop(p);
}
static int
termp_pp_pre(DECL_ARGS)
{
- fn_prio = TAG_STRONG;
term_vspace(p);
return 0;
}
@@ -1603,14 +1559,12 @@ termp_pp_pre(DECL_ARGS)
static int
termp_skip_pre(DECL_ARGS)
{
-
return 0;
}
static int
termp_quote_pre(DECL_ARGS)
{
-
if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM)
return 1;
@@ -1767,17 +1721,15 @@ termp_eo_post(DECL_ARGS)
static int
termp_fo_pre(DECL_ARGS)
{
- size_t rmargin = 0;
- int pretty;
-
- pretty = NODE_SYNPRETTY & n->flags;
+ size_t rmargin;
- if (n->type == ROFFT_BLOCK) {
+ switch (n->type) {
+ case ROFFT_BLOCK:
synopsis_pre(p, n);
return 1;
- } else if (n->type == ROFFT_BODY) {
- if (pretty) {
- rmargin = p->tcol->rmargin;
+ case ROFFT_BODY:
+ rmargin = p->tcol->rmargin;
+ if (n->flags & NODE_SYNPRETTY) {
p->tcol->rmargin = p->tcol->offset + term_len(p, 4);
p->flags |= TERMP_NOBREAK | TERMP_BRIND |
TERMP_HANG;
@@ -1785,7 +1737,7 @@ termp_fo_pre(DECL_ARGS)
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
p->flags |= TERMP_NOSPACE;
- if (pretty) {
+ if (n->flags & NODE_SYNPRETTY) {
term_flushln(p);
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND |
TERMP_HANG);
@@ -1794,30 +1746,21 @@ termp_fo_pre(DECL_ARGS)
p->tcol->rmargin = rmargin;
}
return 1;
+ default:
+ return termp_bold_pre(p, pair, meta, n);
}
-
- if (NULL == n->child)
- return 0;
-
- /* XXX: we drop non-initial arguments as per groff. */
-
- assert(n->child->string);
- term_fontpush(p, TERMFONT_BOLD);
- term_word(p, n->child->string);
- return 0;
}
static void
termp_fo_post(DECL_ARGS)
{
-
if (n->type != ROFFT_BODY)
return;
p->flags |= TERMP_NOSPACE;
term_word(p, ")");
- if (NODE_SYNPRETTY & n->flags) {
+ if (n->flags & NODE_SYNPRETTY) {
p->flags |= TERMP_NOSPACE;
term_word(p, ";");
term_flushln(p);
@@ -1827,29 +1770,30 @@ termp_fo_post(DECL_ARGS)
static int
termp_bf_pre(DECL_ARGS)
{
-
- if (n->type == ROFFT_HEAD)
+ switch (n->type) {
+ case ROFFT_HEAD:
return 0;
- else if (n->type != ROFFT_BODY)
+ case ROFFT_BODY:
+ break;
+ default:
return 1;
-
- if (FONT_Em == n->norm->Bf.font)
- term_fontpush(p, TERMFONT_UNDER);
- else if (FONT_Sy == n->norm->Bf.font)
- term_fontpush(p, TERMFONT_BOLD);
- else
- term_fontpush(p, TERMFONT_NONE);
-
- return 1;
+ }
+ switch (n->norm->Bf.font) {
+ case FONT_Em:
+ return termp_under_pre(p, pair, meta, n);
+ case FONT_Sy:
+ return termp_bold_pre(p, pair, meta, n);
+ default:
+ return termp_li_pre(p, pair, meta, n);
+ }
}
static int
termp_sm_pre(DECL_ARGS)
{
-
- if (NULL == n->child)
+ if (n->child == NULL)
p->flags ^= TERMP_NONOSPACE;
- else if (0 == strcmp("on", n->child->string))
+ else if (strcmp(n->child->string, "on") == 0)
p->flags &= ~TERMP_NONOSPACE;
else
p->flags |= TERMP_NONOSPACE;
@@ -1863,7 +1807,6 @@ termp_sm_pre(DECL_ARGS)
static int
termp_ap_pre(DECL_ARGS)
{
-
p->flags |= TERMP_NOSPACE;
term_word(p, "'");
p->flags |= TERMP_NOSPACE;
@@ -1902,8 +1845,6 @@ termp____post(DECL_ARGS)
static int
termp_li_pre(DECL_ARGS)
{
-
- termp_tag_pre(p, pair, meta, n);
term_fontpush(p, TERMFONT_NONE);
return 1;
}
@@ -1953,7 +1894,6 @@ termp_lk_pre(DECL_ARGS)
static int
termp_bk_pre(DECL_ARGS)
{
-
switch (n->type) {
case ROFFT_BLOCK:
break;
@@ -1966,107 +1906,47 @@ termp_bk_pre(DECL_ARGS)
default:
abort();
}
-
return 1;
}
static void
termp_bk_post(DECL_ARGS)
{
-
if (n->type == ROFFT_BODY)
p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
}
+/*
+ * If we are in an `Rs' and there is a journal present,
+ * then quote us instead of underlining us (for disambiguation).
+ */
static void
termp__t_post(DECL_ARGS)
{
-
- /*
- * If we're in an `Rs' and there's a journal present, then quote
- * us instead of underlining us (for disambiguation).
- */
- if (n->parent && MDOC_Rs == n->parent->tok &&
+ if (n->parent != NULL && n->parent->tok == MDOC_Rs &&
n->parent->norm->Rs.quote_T)
termp_quote_post(p, pair, meta, n);
-
termp____post(p, pair, meta, n);
}
static int
termp__t_pre(DECL_ARGS)
{
-
- /*
- * If we're in an `Rs' and there's a journal present, then quote
- * us instead of underlining us (for disambiguation).
- */
- if (n->parent && MDOC_Rs == n->parent->tok &&
+ if (n->parent != NULL && n->parent->tok == MDOC_Rs &&
n->parent->norm->Rs.quote_T)
return termp_quote_pre(p, pair, meta, n);
-
- term_fontpush(p, TERMFONT_UNDER);
- return 1;
+ else
+ return termp_under_pre(p, pair, meta, n);
}
static int
termp_under_pre(DECL_ARGS)
{
-
- term_fontpush(p, TERMFONT_UNDER);
- return 1;
-}
-
-static int
-termp_em_pre(DECL_ARGS)
-{
- if (n->child != NULL &&
- n->child->type == ROFFT_TEXT)
- tag_put(n->child->string, TAG_FALLBACK, p->line);
term_fontpush(p, TERMFONT_UNDER);
return 1;
}
static int
-termp_sy_pre(DECL_ARGS)
-{
- if (n->child != NULL &&
- n->child->type == ROFFT_TEXT)
- tag_put(n->child->string, TAG_FALLBACK, p->line);
- term_fontpush(p, TERMFONT_BOLD);
- return 1;
-}
-
-static int
-termp_er_pre(DECL_ARGS)
-{
-
- if (n->sec == SEC_ERRORS &&
- (n->parent->tok == MDOC_It ||
- (n->parent->tok == MDOC_Bq &&
- n->parent->parent->parent->tok == MDOC_It)))
- tag_put(n->child->string, TAG_STRONG, p->line);
- return 1;
-}
-
-static int
-termp_tag_pre(DECL_ARGS)
-{
-
- if (n->child != NULL &&
- n->child->type == ROFFT_TEXT &&
- (n->prev == NULL ||
- (n->prev->type == ROFFT_TEXT &&
- strcmp(n->prev->string, "|") == 0)) &&
- (n->parent->tok == MDOC_It ||
- (n->parent->tok == MDOC_Xo &&
- n->parent->parent->prev == NULL &&
- n->parent->parent->parent->tok == MDOC_It)))
- tag_put(n->child->string, TAG_STRONG, p->line);
- return 1;
-}
-
-static int
termp_abort_pre(DECL_ARGS)
{
abort();
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index 033a368cd75..c5497fb87f2 100644
--- a/usr.bin/mandoc/mdoc_validate.c
+++ b/usr.bin/mandoc/mdoc_validate.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: mdoc_validate.c,v 1.294 2020/02/27 21:38:27 schwarze Exp $ */
+/* $OpenBSD: mdoc_validate.c,v 1.295 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,6 +15,8 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Validation module for mdoc(7) syntax trees used by mandoc(1).
*/
#include <sys/types.h>
#ifndef OSNAME
@@ -33,6 +35,7 @@
#include "mandoc.h"
#include "mandoc_xr.h"
#include "roff.h"
+#include "tag.h"
#include "mdoc.h"
#include "libmandoc.h"
#include "roff_int.h"
@@ -80,7 +83,9 @@ static void post_dd(POST_ARGS);
static void post_delim(POST_ARGS);
static void post_delim_nb(POST_ARGS);
static void post_dt(POST_ARGS);
+static void post_em(POST_ARGS);
static void post_en(POST_ARGS);
+static void post_er(POST_ARGS);
static void post_es(POST_ARGS);
static void post_eoln(POST_ARGS);
static void post_ex(POST_ARGS);
@@ -111,6 +116,7 @@ static void post_sm(POST_ARGS);
static void post_st(POST_ARGS);
static void post_std(POST_ARGS);
static void post_sx(POST_ARGS);
+static void post_tag(POST_ARGS);
static void post_tg(POST_ARGS);
static void post_useless(POST_ARGS);
static void post_xr(POST_ARGS);
@@ -135,19 +141,19 @@ static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = {
NULL, /* Ap */
post_defaults, /* Ar */
NULL, /* Cd */
- post_delim_nb, /* Cm */
- post_delim_nb, /* Dv */
- post_delim_nb, /* Er */
- post_delim_nb, /* Ev */
+ post_tag, /* Cm */
+ post_tag, /* Dv */
+ post_er, /* Er */
+ post_tag, /* Ev */
post_ex, /* Ex */
post_fa, /* Fa */
NULL, /* Fd */
- post_delim_nb, /* Fl */
+ post_tag, /* Fl */
post_fn, /* Fn */
post_delim_nb, /* Ft */
- post_delim_nb, /* Ic */
+ post_tag, /* Ic */
post_delim_nb, /* In */
- post_defaults, /* Li */
+ post_tag, /* Li */
post_nd, /* Nd */
post_nm, /* Nm */
post_delim_nb, /* Op */
@@ -185,11 +191,11 @@ static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = {
NULL, /* Dq */
NULL, /* Ec */
NULL, /* Ef */
- post_delim_nb, /* Em */
+ post_em, /* Em */
NULL, /* Eo */
post_xx, /* Fx */
- post_delim_nb, /* Ms */
- NULL, /* No */
+ post_tag, /* Ms */
+ post_tag, /* No */
post_ns, /* Ns */
post_xx, /* Nx */
post_xx, /* Ox */
@@ -208,7 +214,7 @@ static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = {
post_delim_nb, /* Sq */
post_sm, /* Sm */
post_sx, /* Sx */
- post_delim_nb, /* Sy */
+ post_em, /* Sy */
post_useless, /* Tn */
post_xx, /* Ux */
NULL, /* Xc */
@@ -285,6 +291,8 @@ static const char * const secnames[SEC__MAX] = {
NULL
};
+static int fn_prio = TAG_STRONG;
+
/* Validate the subtree rooted at mdoc->last. */
void
@@ -1079,8 +1087,11 @@ post_st(POST_ARGS)
static void
post_tg(POST_ARGS)
{
- struct roff_node *n, *nch, *nn;
- size_t len;
+ struct roff_node *n; /* The .Tg node. */
+ struct roff_node *nch; /* The first child of the .Tg node. */
+ struct roff_node *nn; /* The next node after the .Tg node. */
+ struct roff_node *nt; /* The TEXT node containing the tag. */
+ size_t len; /* The number of bytes in the tag. */
/* Find the next node. */
n = mdoc->last;
@@ -1091,30 +1102,26 @@ post_tg(POST_ARGS)
}
}
- /* Add the default argument, if needed. */
- nch = n->child;
- if (nch == NULL && nn != NULL && nn->child->type == ROFFT_TEXT) {
- mdoc->next = ROFF_NEXT_CHILD;
- roff_word_alloc(mdoc, n->line, n->pos, n->next->child->string);
- nch = mdoc->last;
- nch->flags |= NODE_NOSRC;
- mdoc->last = n;
- }
+ /* Find the tag. */
+ nt = nch = n->child;
+ if (nch == NULL && nn != NULL && nn->child != NULL &&
+ nn->child->type == ROFFT_TEXT)
+ nt = nn->child;
- /* Validate the first argument. */
- if (nch == NULL || *nch->string == '\0')
+ /* Validate the tag. */
+ if (nt == NULL || *nt->string == '\0')
mandoc_msg(MANDOCERR_MACRO_EMPTY, n->line, n->pos, "Tg");
- if (nch == NULL) {
+ if (nt == NULL) {
roff_node_delete(mdoc, n);
return;
}
- len = strcspn(nch->string, " \t");
- if (nch->string[len] != '\0')
- mandoc_msg(MANDOCERR_TG_SPC, nch->line, nch->pos + len + 1,
- "Tg %s", nch->string);
+ len = strcspn(nt->string, " \t\\");
+ if (nt->string[len] != '\0')
+ mandoc_msg(MANDOCERR_TG_SPC, nt->line,
+ nt->pos + len, "Tg %s", nt->string);
/* Keep only the first argument. */
- if (nch->next != NULL) {
+ if (nch != NULL && nch->next != NULL) {
mandoc_msg(MANDOCERR_ARG_EXCESS, nch->next->line,
nch->next->pos, "Tg ... %s", nch->next->string);
while (nch->next != NULL)
@@ -1122,32 +1129,44 @@ post_tg(POST_ARGS)
}
/* Drop the macro if the first argument is invalid. */
- if (len == 0 || nch->string[len] != '\0') {
+ if (len == 0 || nt->string[len] != '\0') {
roff_node_delete(mdoc, n);
return;
}
- /* By default, write a <mark> element. */
- n->flags |= NODE_ID;
+ /* By default, tag the .Tg node itself. */
if (nn == NULL)
- return;
+ nn = n;
/* Explicit tagging of specific macros. */
switch (nn->tok) {
case MDOC_Sh:
case MDOC_Ss:
- if (nn->head->flags & NODE_ID || nn->head->child == NULL)
+ case MDOC_Fo:
+ nn = nn->head;
+ /* FALLTHROUGH */
+ case MDOC_Cm:
+ case MDOC_Dv:
+ case MDOC_Em:
+ case MDOC_Er:
+ case MDOC_Ev:
+ case MDOC_Fl:
+ case MDOC_Fn:
+ case MDOC_Ic:
+ case MDOC_Li:
+ case MDOC_Ms:
+ case MDOC_No:
+ case MDOC_Sy:
+ if (nn->child != NULL && (nn->flags & NODE_ID) == 0)
break;
- n->flags |= NODE_NOPRT;
- nn->head->flags |= NODE_ID | NODE_HREF;
- assert(nn->head->string == NULL);
- nn->head->string = mandoc_strdup(nch->string);
- break;
+ /* FALLTHROUGH */
default:
+ nn = n;
break;
}
- if (n->flags & NODE_NOPRT)
- n->flags &= ~NODE_ID;
+ tag_put(nt->string, TAG_MANUAL, nn);
+ if (nn != n)
+ n->flags |= NODE_NOPRT;
}
static void
@@ -1242,28 +1261,32 @@ post_bf(POST_ARGS)
static void
post_fname(POST_ARGS)
{
- const struct roff_node *n;
+ struct roff_node *n, *nch;
const char *cp;
size_t pos;
- n = mdoc->last->child;
- cp = n->string;
+ n = mdoc->last;
+ nch = n->child;
+ cp = nch->string;
if (*cp == '(') {
if (cp[strlen(cp + 1)] == ')')
return;
pos = 0;
} else {
pos = strcspn(cp, "()");
- if (cp[pos] == '\0')
+ if (cp[pos] == '\0') {
+ if (n->sec == SEC_DESCRIPTION ||
+ n->sec == SEC_CUSTOM)
+ tag_put(NULL, fn_prio++, n);
return;
+ }
}
- mandoc_msg(MANDOCERR_FN_PAREN, n->line, n->pos + pos, "%s", cp);
+ mandoc_msg(MANDOCERR_FN_PAREN, nch->line, nch->pos + pos, "%s", cp);
}
static void
post_fn(POST_ARGS)
{
-
post_fname(mdoc);
post_fa(mdoc);
}
@@ -1427,38 +1450,29 @@ post_display(POST_ARGS)
static void
post_defaults(POST_ARGS)
{
- struct roff_node *nn;
+ struct roff_node *n;
- if (mdoc->last->child != NULL) {
+ n = mdoc->last;
+ if (n->child != NULL) {
post_delim_nb(mdoc);
return;
}
-
- /*
- * The `Ar' defaults to "file ..." if no value is provided as an
- * argument; the `Mt' and `Pa' macros use "~"; the `Li' just
- * gets an empty string.
- */
-
- nn = mdoc->last;
- switch (nn->tok) {
+ mdoc->next = ROFF_NEXT_CHILD;
+ switch (n->tok) {
case MDOC_Ar:
- mdoc->next = ROFF_NEXT_CHILD;
- roff_word_alloc(mdoc, nn->line, nn->pos, "file");
- mdoc->last->flags |= NODE_NOSRC;
- roff_word_alloc(mdoc, nn->line, nn->pos, "...");
+ roff_word_alloc(mdoc, n->line, n->pos, "file");
mdoc->last->flags |= NODE_NOSRC;
+ roff_word_alloc(mdoc, n->line, n->pos, "...");
break;
case MDOC_Pa:
case MDOC_Mt:
- mdoc->next = ROFF_NEXT_CHILD;
- roff_word_alloc(mdoc, nn->line, nn->pos, "~");
- mdoc->last->flags |= NODE_NOSRC;
+ roff_word_alloc(mdoc, n->line, n->pos, "~");
break;
default:
abort();
}
- mdoc->last = nn;
+ mdoc->last->flags |= NODE_NOSRC;
+ mdoc->last = n;
}
static void
@@ -1512,18 +1526,54 @@ post_an(POST_ARGS)
}
static void
-post_en(POST_ARGS)
+post_em(POST_ARGS)
{
+ post_tag(mdoc);
+ tag_put(NULL, TAG_FALLBACK, mdoc->last);
+}
+static void
+post_en(POST_ARGS)
+{
post_obsolete(mdoc);
if (mdoc->last->type == ROFFT_BLOCK)
mdoc->last->norm->Es = mdoc->last_es;
}
static void
-post_es(POST_ARGS)
+post_er(POST_ARGS)
+{
+ struct roff_node *n;
+
+ n = mdoc->last;
+ if (n->sec == SEC_ERRORS &&
+ (n->parent->tok == MDOC_It ||
+ (n->parent->tok == MDOC_Bq &&
+ n->parent->parent->parent->tok == MDOC_It)))
+ tag_put(NULL, TAG_STRONG, n);
+ post_delim_nb(mdoc);
+}
+
+static void
+post_tag(POST_ARGS)
{
+ struct roff_node *n;
+
+ n = mdoc->last;
+ if ((n->prev == NULL ||
+ (n->prev->type == ROFFT_TEXT &&
+ strcmp(n->prev->string, "|") == 0)) &&
+ (n->parent->tok == MDOC_It ||
+ (n->parent->tok == MDOC_Xo &&
+ n->parent->parent->prev == NULL &&
+ n->parent->parent->parent->tok == MDOC_It)))
+ tag_put(NULL, TAG_STRONG, n);
+ post_delim_nb(mdoc);
+}
+static void
+post_es(POST_ARGS)
+{
post_obsolete(mdoc);
mdoc->last_es = mdoc->last;
}
@@ -1620,8 +1670,8 @@ post_it(POST_ARGS)
if ((nch = nit->head->child) != NULL)
mandoc_msg(MANDOCERR_ARG_SKIP,
nit->line, nit->pos, "It %s",
- nch->string == NULL ? roff_name[nch->tok] :
- nch->string);
+ nch->type == ROFFT_TEXT ? nch->string :
+ roff_name[nch->tok]);
break;
case LIST_column:
cols = (int)nbl->norm->Bl.ncols;
@@ -2137,7 +2187,6 @@ post_sx(POST_ARGS)
static void
post_sh(POST_ARGS)
{
-
post_ignpar(mdoc);
switch (mdoc->last->type) {
@@ -2369,6 +2418,8 @@ post_sh_head(POST_ARGS)
roff_setreg(mdoc->roff, "nS", 0, '=');
mdoc->flags &= ~MDOC_SYNOPSIS;
}
+ if (sec == SEC_DESCRIPTION)
+ fn_prio = TAG_STRONG;
/* Mark our last section. */
@@ -2540,6 +2591,7 @@ post_par(POST_ARGS)
{
struct roff_node *np;
+ fn_prio = TAG_STRONG;
post_prevpar(mdoc);
np = mdoc->last;
diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c
index 6dfe2003abd..a32274c5d0a 100644
--- a/usr.bin/mandoc/read.c
+++ b/usr.bin/mandoc/read.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: read.c,v 1.185 2019/07/10 19:38:56 schwarze Exp $ */
+/* $OpenBSD: read.c,v 1.186 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2019 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,6 +15,12 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Top-level functions of the mandoc(3) parser:
+ * Parser and input encoding selection, decompression,
+ * handling of input bytes, characters, lines, and files,
+ * handling of roff(7) loops and file inclusion,
+ * and steering of the various parsers.
*/
#include <sys/types.h>
#include <sys/mman.h>
@@ -34,6 +40,7 @@
#include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
+#include "tag.h"
#include "mdoc.h"
#include "man.h"
#include "mandoc_parse.h"
@@ -662,6 +669,7 @@ mparse_alloc(int options, enum mandoc_os os_e, const char *os_s)
}
curp->man->meta.first->tok = TOKEN_NONE;
curp->man->meta.os_e = os_e;
+ tag_alloc();
return curp;
}
@@ -678,6 +686,7 @@ mparse_reset(struct mparse *curp)
void
mparse_free(struct mparse *curp)
{
+ tag_free();
roffhash_free(curp->man->mdocmac);
roffhash_free(curp->man->manmac);
roff_man_free(curp->man);
diff --git a/usr.bin/mandoc/tag.c b/usr.bin/mandoc/tag.c
index 5c0854315dd..8bdf9943597 100644
--- a/usr.bin/mandoc/tag.c
+++ b/usr.bin/mandoc/tag.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tag.c,v 1.27 2020/01/20 10:29:31 schwarze Exp $ */
+/* $OpenBSD: tag.c,v 1.28 2020/03/13 00:31:05 schwarze Exp $ */
/*
* Copyright (c) 2015,2016,2018,2019,2020 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -13,132 +13,65 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Functions to tag syntax tree nodes.
+ * For internal use by mandoc(1) validation modules only.
*/
#include <sys/types.h>
#include <assert.h>
-#include <errno.h>
#include <limits.h>
-#include <signal.h>
#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <unistd.h>
#include "mandoc_aux.h"
#include "mandoc_ohash.h"
-#include "mandoc.h"
+#include "roff.h"
#include "tag.h"
struct tag_entry {
- size_t *lines;
- size_t maxlines;
- size_t nlines;
+ struct roff_node **nodes;
+ size_t maxnodes;
+ size_t nnodes;
int prio;
char s[];
};
-static void tag_signal(int) __attribute__((__noreturn__));
-
static struct ohash tag_data;
-static struct tag_files tag_files;
/*
- * Prepare for using a pager.
- * Not all pagers are capable of using a tag file,
- * but for simplicity, create it anyway.
+ * Set up the ohash table to collect nodes
+ * where various marked-up terms are documented.
*/
-struct tag_files *
-tag_init(char *tagname)
+void
+tag_alloc(void)
{
- struct sigaction sa;
- int ofd;
-
- ofd = -1;
- tag_files.tfd = -1;
- tag_files.tcpgid = -1;
- tag_files.tagname = tagname;
-
- /* Clean up when dying from a signal. */
-
- memset(&sa, 0, sizeof(sa));
- sigfillset(&sa.sa_mask);
- sa.sa_handler = tag_signal;
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
-
- /*
- * POSIX requires that a process calling tcsetpgrp(3)
- * from the background gets a SIGTTOU signal.
- * In that case, do not stop.
- */
-
- sa.sa_handler = SIG_IGN;
- sigaction(SIGTTOU, &sa, NULL);
-
- /* Save the original standard output for use by the pager. */
-
- if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) {
- mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
- goto fail;
- }
+ mandoc_ohash_init(&tag_data, 4, offsetof(struct tag_entry, s));
+}
- /* Create both temporary output files. */
+void
+tag_free(void)
+{
+ struct tag_entry *entry;
+ unsigned int slot;
- (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 ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) {
- mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
- "%s: %s", tag_files.tfn, strerror(errno));
- goto fail;
- }
- if (dup2(ofd, STDOUT_FILENO) == -1) {
- mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
- goto fail;
+ entry = ohash_first(&tag_data, &slot);
+ while (entry != NULL) {
+ free(entry->nodes);
+ free(entry);
+ entry = ohash_next(&tag_data, &slot);
}
- close(ofd);
-
- /*
- * Set up the ohash table to collect output line numbers
- * where various marked-up terms are documented.
- */
-
- mandoc_ohash_init(&tag_data, 4, offsetof(struct tag_entry, s));
- return &tag_files;
-
-fail:
- tag_unlink();
- if (ofd != -1)
- close(ofd);
- if (tag_files.ofd != -1)
- close(tag_files.ofd);
- if (tag_files.tfd != -1)
- close(tag_files.tfd);
- *tag_files.ofn = '\0';
- *tag_files.tfn = '\0';
- tag_files.ofd = -1;
- tag_files.tfd = -1;
- tag_files.tagname = NULL;
- return NULL;
+ ohash_delete(&tag_data);
}
/*
- * Set the line number where a term is defined,
+ * Set a node where a term is defined,
* unless it is already defined at a lower priority.
*/
void
-tag_put(const char *s, int prio, size_t line)
+tag_put(const char *s, int prio, struct roff_node *n)
{
struct tag_entry *entry;
const char *se;
@@ -146,11 +79,14 @@ tag_put(const char *s, int prio, size_t line)
unsigned int slot;
assert(prio <= TAG_FALLBACK);
- if (tag_files.tfd <= 0)
- return;
- if (s[0] == '\\' && (s[1] == '&' || s[1] == 'e'))
- s += 2;
+ if (s == NULL) {
+ if (n->child == NULL || n->child->type != ROFFT_TEXT)
+ return;
+ s = n->child->string;
+ if (s[0] == '\\' && (s[1] == '&' || s[1] == 'e'))
+ s += 2;
+ }
/*
* Skip whitespace and escapes and whatever follows,
@@ -168,131 +104,67 @@ tag_put(const char *s, int prio, size_t line)
slot = ohash_qlookupi(&tag_data, s, &se);
entry = ohash_find(&tag_data, slot);
- if (entry == NULL) {
-
- /* Build a new entry. */
+ /* Build a new entry. */
+ if (entry == NULL) {
entry = mandoc_malloc(sizeof(*entry) + len + 1);
memcpy(entry->s, s, len);
entry->s[len] = '\0';
- entry->lines = NULL;
- entry->maxlines = entry->nlines = 0;
+ entry->nodes = NULL;
+ entry->maxnodes = entry->nnodes = 0;
ohash_insert(&tag_data, slot, entry);
+ }
- } else {
-
- /*
- * Lower priority numbers take precedence,
- * but TAG_FALLBACK is special.
- * A tag with priority TAG_FALLBACK is only used
- * if the tag occurs exactly once.
- */
+ /*
+ * Lower priority numbers take precedence.
+ * If a better entry is already present, ignore the new one.
+ */
- if (prio == TAG_FALLBACK) {
- if (entry->prio == TAG_FALLBACK)
- entry->prio = TAG_DELETE;
+ else if (entry->prio < prio)
return;
- }
- /* A better entry is already present, ignore the new one. */
-
- if (entry->prio < prio)
- return;
+ /*
+ * If the existing entry is worse, clear it.
+ * In addition, a tag with priority TAG_FALLBACK
+ * is only used if the tag occurs exactly once.
+ */
- /* The existing entry is worse, clear it. */
+ else if (entry->prio > prio || prio == TAG_FALLBACK) {
+ while (entry->nnodes > 0)
+ entry->nodes[--entry->nnodes]->flags &= ~NODE_ID;
- if (entry->prio > prio)
- entry->nlines = 0;
+ if (prio == TAG_FALLBACK) {
+ entry->prio = TAG_DELETE;
+ return;
+ }
}
- /* Remember the new line. */
+ /* Remember the new node. */
- if (entry->maxlines == entry->nlines) {
- entry->maxlines += 4;
- entry->lines = mandoc_reallocarray(entry->lines,
- entry->maxlines, sizeof(*entry->lines));
+ if (entry->maxnodes == entry->nnodes) {
+ entry->maxnodes += 4;
+ entry->nodes = mandoc_reallocarray(entry->nodes,
+ entry->maxnodes, sizeof(*entry->nodes));
}
- entry->lines[entry->nlines++] = line;
+ entry->nodes[entry->nnodes++] = n;
entry->prio = prio;
-}
-
-/*
- * Write out the tags file using the previously collected
- * information and clear the ohash table while going along.
- */
-void
-tag_write(void)
-{
- FILE *stream;
- struct tag_entry *entry;
- size_t i;
- unsigned int slot;
- int empty;
-
- if (tag_files.tfd <= 0)
- return;
- if (tag_files.tagname != NULL && ohash_find(&tag_data,
- ohash_qlookup(&tag_data, tag_files.tagname)) == NULL) {
- mandoc_msg(MANDOCERR_TAG, 0, 0, "%s", tag_files.tagname);
- tag_files.tagname = NULL;
- }
- if ((stream = fdopen(tag_files.tfd, "w")) == NULL)
- mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
- empty = 1;
- entry = ohash_first(&tag_data, &slot);
- while (entry != NULL) {
- if (stream != NULL && entry->prio < TAG_DELETE) {
- for (i = 0; i < entry->nlines; i++) {
- fprintf(stream, "%s %s %zu\n",
- entry->s, tag_files.ofn, entry->lines[i]);
- empty = 0;
- }
- }
- free(entry->lines);
- free(entry);
- entry = ohash_next(&tag_data, &slot);
- }
- ohash_delete(&tag_data);
- if (stream != NULL)
- fclose(stream);
- else
- close(tag_files.tfd);
- tag_files.tfd = -1;
- if (empty) {
- unlink(tag_files.tfn);
- *tag_files.tfn = '\0';
+ n->flags |= NODE_ID;
+ if (n->child == NULL || n->child->string != s || *se != '\0') {
+ assert(n->string == NULL);
+ n->string = mandoc_strndup(s, len);
}
}
-void
-tag_unlink(void)
+enum tag_result
+tag_check(const char *test_tag)
{
- pid_t tc_pgid;
+ unsigned int slot;
- if (tag_files.tcpgid != -1) {
- tc_pgid = tcgetpgrp(tag_files.ofd);
- if (tc_pgid == tag_files.pager_pid ||
- tc_pgid == getpgid(0) ||
- getpgid(tc_pgid) == -1)
- (void)tcsetpgrp(tag_files.ofd, tag_files.tcpgid);
- }
- if (*tag_files.ofn != '\0')
- unlink(tag_files.ofn);
- if (*tag_files.tfn != '\0')
- unlink(tag_files.tfn);
-}
-
-static void
-tag_signal(int signum)
-{
- struct sigaction sa;
-
- tag_unlink();
- memset(&sa, 0, sizeof(sa));
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = SIG_DFL;
- sigaction(signum, &sa, NULL);
- kill(getpid(), signum);
- /* NOTREACHED */
- _exit(1);
+ if (ohash_first(&tag_data, &slot) == NULL)
+ return TAG_EMPTY;
+ else if (test_tag != NULL && ohash_find(&tag_data,
+ ohash_qlookup(&tag_data, test_tag)) == NULL)
+ return TAG_MISS;
+ else
+ return TAG_OK;
}
diff --git a/usr.bin/mandoc/tag.h b/usr.bin/mandoc/tag.h
index a4a4128eef0..494b72bb2ca 100644
--- a/usr.bin/mandoc/tag.h
+++ b/usr.bin/mandoc/tag.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tag.h,v 1.10 2020/01/20 10:29:31 schwarze Exp $ */
+/* $OpenBSD: tag.h,v 1.11 2020/03/13 00:31:05 schwarze Exp $ */
/*
* Copyright (c) 2015, 2018, 2019, 2020 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -13,6 +13,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Internal interfaces to tag syntax tree nodes.
+ * For use by mandoc(1) validation modules only.
*/
/*
@@ -25,19 +28,17 @@
#define TAG_FALLBACK (INT_MAX - 1) /* Tag only used if unique. */
#define TAG_DELETE (INT_MAX) /* Tag not used at all. */
-
-struct tag_files {
- char ofn[20];
- char tfn[20];
- char *tagname;
- int ofd;
- int tfd;
- pid_t tcpgid;
- pid_t pager_pid;
+/*
+ * Return values of tag_check().
+ */
+enum tag_result {
+ TAG_OK, /* Argument exists as a tag. */
+ TAG_MISS, /* Argument not found. */
+ TAG_EMPTY /* No tag exists at all. */
};
-struct tag_files *tag_init(char *);
-void tag_put(const char *, int, size_t);
-void tag_write(void);
-void tag_unlink(void);
+void tag_alloc(void);
+void tag_put(const char *, int, struct roff_node *);
+enum tag_result tag_check(const char *);
+void tag_free(void);
diff --git a/usr.bin/mandoc/term_tag.c b/usr.bin/mandoc/term_tag.c
new file mode 100644
index 00000000000..9a15b562036
--- /dev/null
+++ b/usr.bin/mandoc/term_tag.c
@@ -0,0 +1,204 @@
+/* $OpenBSD: term_tag.c,v 1.1 2020/03/13 00:31:05 schwarze Exp $ */
+/*
+ * Copyright (c) 2015,2016,2018,2019,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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Functions to write a ctags(1) file.
+ * For use by the mandoc(1) ASCII and UTF-8 formatters only.
+ */
+#include <sys/types.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mandoc.h"
+#include "roff.h"
+#include "tag.h"
+#include "term_tag.h"
+
+static void tag_signal(int) __attribute__((__noreturn__));
+
+static struct tag_files tag_files;
+
+
+/*
+ * Prepare for using a pager.
+ * Not all pagers are capable of using a tag file,
+ * but for simplicity, create it anyway.
+ */
+struct tag_files *
+term_tag_init(char *tagname)
+{
+ struct sigaction sa;
+ int ofd; /* In /tmp/, dup(2)ed to stdout. */
+ int tfd;
+
+ ofd = tfd = -1;
+ tag_files.tfs = NULL;
+ tag_files.tcpgid = -1;
+ tag_files.tagname = tagname;
+
+ /* Clean up when dying from a signal. */
+
+ memset(&sa, 0, sizeof(sa));
+ sigfillset(&sa.sa_mask);
+ sa.sa_handler = tag_signal;
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ /*
+ * POSIX requires that a process calling tcsetpgrp(3)
+ * from the background gets a SIGTTOU signal.
+ * In that case, do not stop.
+ */
+
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGTTOU, &sa, NULL);
+
+ /* Save the original standard output for use by the pager. */
+
+ if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) {
+ mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
+ goto fail;
+ }
+
+ /* 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 ((tfd = mkstemp(tag_files.tfn)) == -1) {
+ mandoc_msg(MANDOCERR_MKSTEMP, 0, 0,
+ "%s: %s", tag_files.tfn, strerror(errno));
+ goto fail;
+ }
+ if ((tag_files.tfs = fdopen(tfd, "w")) == NULL) {
+ mandoc_msg(MANDOCERR_FDOPEN, 0, 0, "%s", strerror(errno));
+ goto fail;
+ }
+ tfd = -1;
+ if (dup2(ofd, STDOUT_FILENO) == -1) {
+ mandoc_msg(MANDOCERR_DUP, 0, 0, "%s", strerror(errno));
+ goto fail;
+ }
+ close(ofd);
+ return &tag_files;
+
+fail:
+ term_tag_unlink();
+ if (ofd != -1)
+ close(ofd);
+ if (tfd != -1)
+ close(tfd);
+ if (tag_files.ofd != -1) {
+ close(tag_files.ofd);
+ tag_files.ofd = -1;
+ }
+ tag_files.tagname = NULL;
+ return NULL;
+}
+
+void
+term_tag_write(struct roff_node *n, size_t line)
+{
+ const char *cp;
+ int len;
+
+ if (tag_files.tfs == NULL)
+ return;
+ if (n->string == NULL)
+ n = n->child;
+ cp = n->string;
+ if (cp[0] == '\\' && (cp[1] == '&' || cp[1] == 'e'))
+ cp += 2;
+ len = strcspn(cp, " \t\\");
+ fprintf(tag_files.tfs, "%.*s %s %zu\n",
+ len, cp, tag_files.ofn, line);
+}
+
+void
+term_tag_finish(void)
+{
+ if (tag_files.tfs == NULL)
+ return;
+ fclose(tag_files.tfs);
+ tag_files.tfs = NULL;
+ switch (tag_check(tag_files.tagname)) {
+ case TAG_EMPTY:
+ unlink(tag_files.tfn);
+ *tag_files.tfn = '\0';
+ /* FALLTHROUGH */
+ case TAG_MISS:
+ if (tag_files.tagname == NULL)
+ break;
+ mandoc_msg(MANDOCERR_TAG, 0, 0, "%s", tag_files.tagname);
+ tag_files.tagname = NULL;
+ break;
+ case TAG_OK:
+ break;
+ }
+}
+
+void
+term_tag_unlink(void)
+{
+ pid_t tc_pgid;
+
+ if (tag_files.tcpgid != -1) {
+ tc_pgid = tcgetpgrp(tag_files.ofd);
+ if (tc_pgid == tag_files.pager_pid ||
+ tc_pgid == getpgid(0) ||
+ getpgid(tc_pgid) == -1)
+ (void)tcsetpgrp(tag_files.ofd, tag_files.tcpgid);
+ }
+ if (*tag_files.ofn != '\0') {
+ unlink(tag_files.ofn);
+ *tag_files.ofn = '\0';
+ }
+ if (*tag_files.tfn != '\0') {
+ unlink(tag_files.tfn);
+ *tag_files.tfn = '\0';
+ }
+ if (tag_files.tfs != NULL) {
+ fclose(tag_files.tfs);
+ tag_files.tfs = NULL;
+ }
+}
+
+static void
+tag_signal(int signum)
+{
+ struct sigaction sa;
+
+ term_tag_unlink();
+ memset(&sa, 0, sizeof(sa));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_DFL;
+ sigaction(signum, &sa, NULL);
+ kill(getpid(), signum);
+ /* NOTREACHED */
+ _exit(1);
+}
diff --git a/usr.bin/mandoc/term_tag.h b/usr.bin/mandoc/term_tag.h
new file mode 100644
index 00000000000..d1f31c4fba4
--- /dev/null
+++ b/usr.bin/mandoc/term_tag.h
@@ -0,0 +1,35 @@
+/* $OpenBSD: term_tag.h,v 1.1 2020/03/13 00:31:05 schwarze Exp $ */
+/*
+ * Copyright (c) 2015, 2018, 2019, 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
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Internal interfaces to write a ctags(1) file.
+ * For use by the mandoc(1) ASCII and UTF-8 formatters only.
+ */
+
+struct tag_files {
+ char ofn[20]; /* Output file name. */
+ char tfn[20]; /* Tag file name. */
+ char *tagname; /* Target specified with -O. */
+ FILE *tfs; /* Tag file object. */
+ int ofd; /* Original output file descriptor. */
+ pid_t tcpgid; /* Process group controlling the terminal. */
+ pid_t pager_pid; /* Process ID of the pager. */
+};
+
+
+struct tag_files *term_tag_init(char *);
+void term_tag_write(struct roff_node *, size_t);
+void term_tag_finish(void);
+void term_tag_unlink(void);
diff --git a/usr.bin/mandoc/tree.c b/usr.bin/mandoc/tree.c
index cc123ccf308..5d82f866056 100644
--- a/usr.bin/mandoc/tree.c
+++ b/usr.bin/mandoc/tree.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: tree.c,v 1.53 2020/02/27 21:38:27 schwarze Exp $ */
+/* $OpenBSD: tree.c,v 1.54 2020/03/13 00:31:05 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,6 +14,9 @@
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Formatting module to let mandoc(1) show
+ * a human readable representation of the syntax tree.
*/
#include <sys/types.h>
@@ -303,6 +306,11 @@ print_man(const struct roff_node *n, int indent)
putchar(')');
if (n->flags & NODE_EOS)
putchar('.');
+ if (n->flags & NODE_ID) {
+ printf(" ID");
+ if (n->string != NULL)
+ printf("=%s", n->string);
+ }
if (n->flags & NODE_NOFILL)
printf(" NOFILL");
putchar('\n');