History log of /openbsd-current/usr.bin/mandoc/tag.c
Revision (<<< Hide revision tags) (Show revision tags >>>) Date Author Comments
# 1.38 24-Nov-2023 schwarze

1. Do not put ASCII_HYPH (0x1c) into the tag file.
That happened when tagging a string containing '-' on an input text line,
most commonly in man(7) .TP next line scope.
2. Do not let "\-" end the tag.
In both cases, translate ASCII_HYPH and "\-" to plain '-' for output.
For example, this improves handling of unbound.conf(5).

These two bugs were found thanks to a posting by weerd@.


Revision tags: OPENBSD_7_2_BASE OPENBSD_7_3_BASE OPENBSD_7_4_BASE
# 1.37 26-Apr-2022 schwarze

If a node is tagged explicitly, skip implicit tagging for that node.
Apart from making sense in the first place, this fixes an assertion
failure that happened when the calculated implicit tag did not match
the string value of the first child of the node,

Bug found by tb@ using afl(1).


Revision tags: OPENBSD_6_7_BASE OPENBSD_6_8_BASE OPENBSD_6_9_BASE OPENBSD_7_0_BASE OPENBSD_7_1_BASE
# 1.36 19-Apr-2020 schwarze

When .Bd, .D1, or .Dl is tagged, attach the permalink
to the first few letters, similar to what was earlier done for .Pp.


# 1.35 18-Apr-2020 schwarze

When a .Tg is attached to a paragraph, attach the permalink
to the first word, or the first few words if they are short.


# 1.34 08-Apr-2020 schwarze

Use a separate node->tag attribute rather than abusing the node->string
attribute for the purpose. No functional change intended.
The purpose is to make it possible to later attach tags to text nodes.


# 1.33 07-Apr-2020 schwarze

Separate the place to put the <a href> permalink (now marked
with NODE_HREF) from the target element of the link (still marked
with NODE_ID). In many cases, use this to move the target to the
beginning of the paragraph, such that readers don't get dropped
into the middle of a sentence.


# 1.32 03-Apr-2020 schwarze

#include <stdint.h> because that is needed before #include <ohash.h>;
fixing a build failure of mandoc-portable on Arch Linux
reported by Stephen Gregoratto <dev at sgregoratto dot me>.


# 1.31 02-Apr-2020 schwarze

When the last file formatted yielded no tags, the tags file got
deleted before starting the pager, even when earlier input files
had written to it; thanks to weerd@ for reporting that bug.

Since we now generate tags for section headers, we almost always
generate at least some. Consequently, while fixing the above bug,
simplify the code by never deleting the tags file before the pager
exits, not even in the rare case that the file happens to be empty.
Hence, this patch is -75 +63 LOC even though it fixes two bugs.

While deleting the output files belongs after exit from the pager,
closing them should be done before it is started. Collect the
related code, which was scattered in various places, to where
it belongs, in a dedicated function in the term_tag.c module.
As a side benefit, never fclose(2) stdout, only dup2(2) to it.

Similarly, when the -O tag argument wasn't found in the last file
formatted, there was a complaint about "no such tag" even when the
argument did occur in earlier files. Fix that by looking for a
matching tag after every formatted file rather than just once at
the very end. Given that command line arguments aren't properties
of the file(s) being formatted, that check is a job for the main
program, not for the formatters, so while fixing the check, move
it from term_tag.c to main.c.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.37 26-Apr-2022 schwarze

If a node is tagged explicitly, skip implicit tagging for that node.
Apart from making sense in the first place, this fixes an assertion
failure that happened when the calculated implicit tag did not match
the string value of the first child of the node,

Bug found by tb@ using afl(1).


Revision tags: OPENBSD_6_7_BASE OPENBSD_6_8_BASE OPENBSD_6_9_BASE OPENBSD_7_0_BASE OPENBSD_7_1_BASE
# 1.36 19-Apr-2020 schwarze

When .Bd, .D1, or .Dl is tagged, attach the permalink
to the first few letters, similar to what was earlier done for .Pp.


# 1.35 18-Apr-2020 schwarze

When a .Tg is attached to a paragraph, attach the permalink
to the first word, or the first few words if they are short.


# 1.34 08-Apr-2020 schwarze

Use a separate node->tag attribute rather than abusing the node->string
attribute for the purpose. No functional change intended.
The purpose is to make it possible to later attach tags to text nodes.


# 1.33 07-Apr-2020 schwarze

Separate the place to put the <a href> permalink (now marked
with NODE_HREF) from the target element of the link (still marked
with NODE_ID). In many cases, use this to move the target to the
beginning of the paragraph, such that readers don't get dropped
into the middle of a sentence.


# 1.32 03-Apr-2020 schwarze

#include <stdint.h> because that is needed before #include <ohash.h>;
fixing a build failure of mandoc-portable on Arch Linux
reported by Stephen Gregoratto <dev at sgregoratto dot me>.


# 1.31 02-Apr-2020 schwarze

When the last file formatted yielded no tags, the tags file got
deleted before starting the pager, even when earlier input files
had written to it; thanks to weerd@ for reporting that bug.

Since we now generate tags for section headers, we almost always
generate at least some. Consequently, while fixing the above bug,
simplify the code by never deleting the tags file before the pager
exits, not even in the rare case that the file happens to be empty.
Hence, this patch is -75 +63 LOC even though it fixes two bugs.

While deleting the output files belongs after exit from the pager,
closing them should be done before it is started. Collect the
related code, which was scattered in various places, to where
it belongs, in a dedicated function in the term_tag.c module.
As a side benefit, never fclose(2) stdout, only dup2(2) to it.

Similarly, when the -O tag argument wasn't found in the last file
formatted, there was a complaint about "no such tag" even when the
argument did occur in earlier files. Fix that by looking for a
matching tag after every formatted file rather than just once at
the very end. Given that command line arguments aren't properties
of the file(s) being formatted, that check is a job for the main
program, not for the formatters, so while fixing the check, move
it from term_tag.c to main.c.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.36 19-Apr-2020 schwarze

When .Bd, .D1, or .Dl is tagged, attach the permalink
to the first few letters, similar to what was earlier done for .Pp.


# 1.35 18-Apr-2020 schwarze

When a .Tg is attached to a paragraph, attach the permalink
to the first word, or the first few words if they are short.


# 1.34 08-Apr-2020 schwarze

Use a separate node->tag attribute rather than abusing the node->string
attribute for the purpose. No functional change intended.
The purpose is to make it possible to later attach tags to text nodes.


# 1.33 07-Apr-2020 schwarze

Separate the place to put the <a href> permalink (now marked
with NODE_HREF) from the target element of the link (still marked
with NODE_ID). In many cases, use this to move the target to the
beginning of the paragraph, such that readers don't get dropped
into the middle of a sentence.


# 1.32 03-Apr-2020 schwarze

#include <stdint.h> because that is needed before #include <ohash.h>;
fixing a build failure of mandoc-portable on Arch Linux
reported by Stephen Gregoratto <dev at sgregoratto dot me>.


# 1.31 02-Apr-2020 schwarze

When the last file formatted yielded no tags, the tags file got
deleted before starting the pager, even when earlier input files
had written to it; thanks to weerd@ for reporting that bug.

Since we now generate tags for section headers, we almost always
generate at least some. Consequently, while fixing the above bug,
simplify the code by never deleting the tags file before the pager
exits, not even in the rare case that the file happens to be empty.
Hence, this patch is -75 +63 LOC even though it fixes two bugs.

While deleting the output files belongs after exit from the pager,
closing them should be done before it is started. Collect the
related code, which was scattered in various places, to where
it belongs, in a dedicated function in the term_tag.c module.
As a side benefit, never fclose(2) stdout, only dup2(2) to it.

Similarly, when the -O tag argument wasn't found in the last file
formatted, there was a complaint about "no such tag" even when the
argument did occur in earlier files. Fix that by looking for a
matching tag after every formatted file rather than just once at
the very end. Given that command line arguments aren't properties
of the file(s) being formatted, that check is a job for the main
program, not for the formatters, so while fixing the check, move
it from term_tag.c to main.c.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.35 18-Apr-2020 schwarze

When a .Tg is attached to a paragraph, attach the permalink
to the first word, or the first few words if they are short.


# 1.34 08-Apr-2020 schwarze

Use a separate node->tag attribute rather than abusing the node->string
attribute for the purpose. No functional change intended.
The purpose is to make it possible to later attach tags to text nodes.


# 1.33 07-Apr-2020 schwarze

Separate the place to put the <a href> permalink (now marked
with NODE_HREF) from the target element of the link (still marked
with NODE_ID). In many cases, use this to move the target to the
beginning of the paragraph, such that readers don't get dropped
into the middle of a sentence.


# 1.32 03-Apr-2020 schwarze

#include <stdint.h> because that is needed before #include <ohash.h>;
fixing a build failure of mandoc-portable on Arch Linux
reported by Stephen Gregoratto <dev at sgregoratto dot me>.


# 1.31 02-Apr-2020 schwarze

When the last file formatted yielded no tags, the tags file got
deleted before starting the pager, even when earlier input files
had written to it; thanks to weerd@ for reporting that bug.

Since we now generate tags for section headers, we almost always
generate at least some. Consequently, while fixing the above bug,
simplify the code by never deleting the tags file before the pager
exits, not even in the rare case that the file happens to be empty.
Hence, this patch is -75 +63 LOC even though it fixes two bugs.

While deleting the output files belongs after exit from the pager,
closing them should be done before it is started. Collect the
related code, which was scattered in various places, to where
it belongs, in a dedicated function in the term_tag.c module.
As a side benefit, never fclose(2) stdout, only dup2(2) to it.

Similarly, when the -O tag argument wasn't found in the last file
formatted, there was a complaint about "no such tag" even when the
argument did occur in earlier files. Fix that by looking for a
matching tag after every formatted file rather than just once at
the very end. Given that command line arguments aren't properties
of the file(s) being formatted, that check is a job for the main
program, not for the formatters, so while fixing the check, move
it from term_tag.c to main.c.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.34 08-Apr-2020 schwarze

Use a separate node->tag attribute rather than abusing the node->string
attribute for the purpose. No functional change intended.
The purpose is to make it possible to later attach tags to text nodes.


# 1.33 07-Apr-2020 schwarze

Separate the place to put the <a href> permalink (now marked
with NODE_HREF) from the target element of the link (still marked
with NODE_ID). In many cases, use this to move the target to the
beginning of the paragraph, such that readers don't get dropped
into the middle of a sentence.


# 1.32 03-Apr-2020 schwarze

#include <stdint.h> because that is needed before #include <ohash.h>;
fixing a build failure of mandoc-portable on Arch Linux
reported by Stephen Gregoratto <dev at sgregoratto dot me>.


# 1.31 02-Apr-2020 schwarze

When the last file formatted yielded no tags, the tags file got
deleted before starting the pager, even when earlier input files
had written to it; thanks to weerd@ for reporting that bug.

Since we now generate tags for section headers, we almost always
generate at least some. Consequently, while fixing the above bug,
simplify the code by never deleting the tags file before the pager
exits, not even in the rare case that the file happens to be empty.
Hence, this patch is -75 +63 LOC even though it fixes two bugs.

While deleting the output files belongs after exit from the pager,
closing them should be done before it is started. Collect the
related code, which was scattered in various places, to where
it belongs, in a dedicated function in the term_tag.c module.
As a side benefit, never fclose(2) stdout, only dup2(2) to it.

Similarly, when the -O tag argument wasn't found in the last file
formatted, there was a complaint about "no such tag" even when the
argument did occur in earlier files. Fix that by looking for a
matching tag after every formatted file rather than just once at
the very end. Given that command line arguments aren't properties
of the file(s) being formatted, that check is a job for the main
program, not for the formatters, so while fixing the check, move
it from term_tag.c to main.c.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.33 07-Apr-2020 schwarze

Separate the place to put the <a href> permalink (now marked
with NODE_HREF) from the target element of the link (still marked
with NODE_ID). In many cases, use this to move the target to the
beginning of the paragraph, such that readers don't get dropped
into the middle of a sentence.


# 1.32 03-Apr-2020 schwarze

#include <stdint.h> because that is needed before #include <ohash.h>;
fixing a build failure of mandoc-portable on Arch Linux
reported by Stephen Gregoratto <dev at sgregoratto dot me>.


# 1.31 02-Apr-2020 schwarze

When the last file formatted yielded no tags, the tags file got
deleted before starting the pager, even when earlier input files
had written to it; thanks to weerd@ for reporting that bug.

Since we now generate tags for section headers, we almost always
generate at least some. Consequently, while fixing the above bug,
simplify the code by never deleting the tags file before the pager
exits, not even in the rare case that the file happens to be empty.
Hence, this patch is -75 +63 LOC even though it fixes two bugs.

While deleting the output files belongs after exit from the pager,
closing them should be done before it is started. Collect the
related code, which was scattered in various places, to where
it belongs, in a dedicated function in the term_tag.c module.
As a side benefit, never fclose(2) stdout, only dup2(2) to it.

Similarly, when the -O tag argument wasn't found in the last file
formatted, there was a complaint about "no such tag" even when the
argument did occur in earlier files. Fix that by looking for a
matching tag after every formatted file rather than just once at
the very end. Given that command line arguments aren't properties
of the file(s) being formatted, that check is a job for the main
program, not for the formatters, so while fixing the check, move
it from term_tag.c to main.c.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.32 03-Apr-2020 schwarze

#include <stdint.h> because that is needed before #include <ohash.h>;
fixing a build failure of mandoc-portable on Arch Linux
reported by Stephen Gregoratto <dev at sgregoratto dot me>.


# 1.31 02-Apr-2020 schwarze

When the last file formatted yielded no tags, the tags file got
deleted before starting the pager, even when earlier input files
had written to it; thanks to weerd@ for reporting that bug.

Since we now generate tags for section headers, we almost always
generate at least some. Consequently, while fixing the above bug,
simplify the code by never deleting the tags file before the pager
exits, not even in the rare case that the file happens to be empty.
Hence, this patch is -75 +63 LOC even though it fixes two bugs.

While deleting the output files belongs after exit from the pager,
closing them should be done before it is started. Collect the
related code, which was scattered in various places, to where
it belongs, in a dedicated function in the term_tag.c module.
As a side benefit, never fclose(2) stdout, only dup2(2) to it.

Similarly, when the -O tag argument wasn't found in the last file
formatted, there was a complaint about "no such tag" even when the
argument did occur in earlier files. Fix that by looking for a
matching tag after every formatted file rather than just once at
the very end. Given that command line arguments aren't properties
of the file(s) being formatted, that check is a job for the main
program, not for the formatters, so while fixing the check, move
it from term_tag.c to main.c.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.30 21-Mar-2020 schwarze

When setting automatic tags, skip initial hyphens and minus signs,
bringing the behaviour for mdoc(7) closer to what is already done
for man(7).
Triggered by the observation of kn@ that automatic tagging didn't
work very well for find(1) primaries.
OK kn@


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.29 13-Mar-2020 schwarze

Properly reset the validation part of the tagging module between files.
This fixes a crash in makewhatis(8) encountered by naddy@.
I'm very sorry for the disruption of the build.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.28 13-Mar-2020 schwarze

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.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.27 20-Jan-2020 schwarze

Make the code more readable by introducing
symbolic constants for tagging priorities.
This review also made me find a minor bug: do not upgrade
TAG_FALLBACK to TAG_WEAK when there is trailing whitespace.


# 1.26 19-Jan-2020 schwarze

Introduce a new mdoc(7) macro .Tg ("tag") to explicitly mark a place
as defining a term. Please only use it when automatic tagging does
not work. Manual page authors will not be required to add the new
macro; using it remains optional. HTML output is still rudimentary
in this version and will be polished later.

Thanks to kn@ for reminding me that i have been considering since
BSDCan 2014 whether something like this might be useful. Given
that possibilities of making automatic tagging better are running
out and there are still several situations where automatic tagging
cannot do the job, i think the time is now ripe.

Feedback and no objection from millert@; OK espie@ inoguchi@ kn@.


Revision tags: OPENBSD_6_6_BASE
# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.25 27-Jul-2019 schwarze

Move two more output state variables into the new struct outstate.
Also, move setting of tag_files.tagname into tag_init().
No functional change.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.24 22-Jul-2019 schwarze

Slowly start implementing tagging support for man(7) pages, even
though it is obvious that this can never become as good as for
mdoc(7) pages. As a first step, tag alphabetic arguments of .IP
macros, which are often used for lists of options and keywords.

Try "man -O tag=g as" to get the point.

Thanks to Leah Neukirchen for recently reminding me that exploring
how much can be done in this respect may be worthwhile: it is likely
to slightly improve usability while adding only small amounts of
relatively straightforward code.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.23 19-Jul-2019 schwarze

If no tags were generated at all, unlink(2) the empty tags file as
soon the condition can be detected and do not pass it to less(1).
This may happen for man(7) pages, for preformatted pages, and for
very simple pages like true(1). The main benefit is that :t inside
less(1) yields the clearer diagnostic message "No tags file" rather
than the mildly confusing "No such tag in tags file": the latter
might encourage further, futile attempts to jump to other tags.

Improvement suggested by Leah Neukirchen <leah at vuxu dot org>
from The Void.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.22 10-Jul-2019 schwarze

Some time ago, i simplified mandoc_msg() such that it can be used
everywhere and not only in the parsers.
For more uniform messages, use it at more places instead of err(3),
in particular in the main program.
While here, integrate a few trivial functions called at exactly one
place into the main option parser, and let a few more functions use
the normal convention of returning 0 for success and -1 for error.


Revision tags: OPENBSD_6_5_BASE
# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.21 22-Nov-2018 schwarze

In -T locale (the default), -T ascii, and -T utf8 mode, provide a new
output option -O tag[=term] to move right to the definition of "term" when
opening the manual page in a pager, effectively porting the -T html
fragment name feature - https://man.openbsd.org/ksh#ulimit - to the
terminal. Try:

$ man -O tag uvm_sysctl
$ man -O tag=ulimit ksh
$ man -O tag 3 compress

Feature development triggered by a question from kn@. Klemens also
tested, provided feedback that resulted in improvements, and provided
an OK.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.20 23-Oct-2018 schwarze

The ctags(1) file format uses whitespace as a field delimiter, and
there is no escaping mechanism, so tags cannot contain whitespace.
Consequently, we used to simply not tag macro arguments containing
space characters. Instead, let's tag the first word, unless there
is a proper match for that word somewhere else. For example, this
makes ":tquery" work in ntpd.conf(5).

Feature suggested by kn@, who also thinks the implementation looks
reasonable and works in his testing.


Revision tags: OPENBSD_6_3_BASE OPENBSD_6_4_BASE
# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


# 1.19 08-Feb-2018 tb

Invalidate the tag_files.tfd after fclose(3)ing the stram associated with
it. In main assert that the tfd was actually invalidated. This avoids
closing an invalid fd.

ok deraadt on earlier version, tweak & ok schwarze


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.


Revision tags: OPENBSD_6_1_BASE OPENBSD_6_2_BASE
# 1.18 09-Feb-2017 schwarze

Be consistent in protecting __attribute__ attributes with __;
from Christos Zoulas <christos @ NetBSD>.


# 1.17 09-Jan-2017 schwarze

Use stdout rather than stdin for controlling the terminal
such that "cat foo.mdoc | man -l" works.
Issue reported by Christian Neukirchen <chneukirchen at gmail dot com>
and also tested by him on Void Linux with both glibc and musl.
The patch makes sense to millert@.


# 1.16 08-Nov-2016 schwarze

implement tag priority 0, which will tag only keys that appear as
tag candidates exactly once, and use it for .Em and .Sy;
written on the TGV Toulouse-Paris


# 1.15 08-Nov-2016 schwarze

skip leading \& and \e in tags


# 1.14 08-Nov-2016 schwarze

support more than one tag entry for the same search term;
general idea discussed with bcook@ during l2k16


Revision tags: OPENBSD_6_0_BASE
# 1.13 20-Jul-2016 schwarze

tag_signal() is dead; from LLVM via Christos Zoulas


# 1.12 08-Jul-2016 schwarze

POSIX requires that a process calling tcsetpgrp(3) from the background
gets a SIGTTOU signal. In that case, do not stop.
Portability issue found while testing on commercial Solaris 9/10/11.
Thanks to opencsw.org for providing me with a testing environment.


Revision tags: OPENBSD_5_9_BASE
# 1.11 20-Nov-2015 schwarze

Fix multiple issues regarding process group and signal mask handling
found by tb@ and millert@; parts of the code, in particular in tag.c,
by millert@; OK millert@.


# 1.10 13-Oct-2015 schwarze

Reduce the amount of code by moving the three copies of the ohash
callback functions into one common place, preparing for the use of
ohash for some additional purposes. No functional change.


# 1.9 11-Oct-2015 schwarze

Drop tags containing a blank character:
They don't work, they break other tags in weird ways, and even
if they could be made to work, they would be mostly useless.
Issue reported by naddy@, thanks.


# 1.8 06-Oct-2015 schwarze

modernize style: "return" is not a function; ok cmp(1)


# 1.7 29-Aug-2015 schwarze

Portability: including <ohash.h> requires including <stdint.h> before.
Noticed by Svyatoslav Mishyn <juef and openmailbox dot org>, Crux Linux.


Revision tags: OPENBSD_5_8_BASE
# 1.6 28-Jul-2015 schwarze

Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.


# 1.5 25-Jul-2015 schwarze

Simplify and make tag_put() more efficient by integrating tag_get()
into it and by only handling NUL-terminated strings.
Minus 25 lines of code, no functional change.


# 1.4 25-Jul-2015 schwarze

basic support for tag priorities; written at YYC


# 1.3 21-Jul-2015 schwarze

When creation of the temporary tags file fails, call the pager
without the -T option, because otherwise the pager won't even start.
Fixing a bug reported by jca@.

While here, shorten the code by two lines
and delete one internal interface function.


# 1.2 18-Jul-2015 schwarze

clean up the temporary file when the process dies from a signal


# 1.1 17-Jul-2015 schwarze

Initial, still somewhat experimental implementation to leverage
less(1) -T and :t ctags(1)-like functionality to jump to the
definitions of various terms inside manual pages.
To be polished in the tree, so bear with me and report issues.

Technically, if less(1) is used as a pager, information is collected
by the mdoc(7) terminal formatter, first stored using the ohash
library, then ultimately written to a temporary file which is passed
to less via -T. No change intended for other output formatters or
when running without a pager.

Based on an idea from Kristaps using feedback from many, in particular
phessler@ nicm@ millert@ halex@ doug@ kspillner@ deraadt@.