Hi Alex,

At 2024-02-16T01:44:36+0100, Alejandro Colomar wrote:
[...]
> here's [a warning] that I've only seen in -Tpdf.  It might be a bug in
> -Tpdf.

>       troff:man7/path_resolution.7:135: warning: macro 'and' not defined 
> (possibly missing space after 'an')
>       make: *** [share/mk/build/pdf/troff.mk:22: 
> .tmp/man/man7/path_resolution.7.pdf.set] Error 1
>       make: *** Deleting file '.tmp/man/man7/path_resolution.7.pdf.set'
> 
> Here's a small reproducer:
> 
>       alx@debian:~/tmp$ cat dot.man 
>       .TH dot 7 2024-02-16 dots-in-SS
>       .SH Foo
>       .SS . and ..
>       \&. and .. are special files.
>       alx@debian:~/tmp$ groff -man -Tutf8 dot.man >/dev/null
>       alx@debian:~/tmp$ groff -man -Tps dot.man >/dev/null
>       alx@debian:~/tmp$ groff -man -Tpdf dot.man >/dev/null
>       troff:dot.man:3: warning: macro 'and' not defined (possibly missing 
> space after 'an')

Yes, I can reproduce this with groff 1.23.0 and Git HEAD.

Try this patch.

diff --git a/tmac/pdf.tmac b/tmac/pdf.tmac
index 54175434f..fe12d35da 100644
--- a/tmac/pdf.tmac
+++ b/tmac/pdf.tmac
@@ -253,7 +253,7 @@ .de pdfbookmark
 .         tr \[em]-
 .         nf
 .         box pdf:clean
-.         nop \\$*
+.         nop \&\\$*
 .         fl
 .         box
 .         chop pdf:clean

I believe the problem happens because this `nop` request is taking place
inside a diversion (a "box" diversion, to be precise).  Consequently
when the diversion is later interpolated, it can include macro calls, so
the formatter recognizes the control character at the beginning of the
(interpolated) input line.  This causes the PDF bookmarks that are
automatically constructed from the (sub)section heading texts to be
susceptible to misinterpretation.  If you check the PDF generated from
your reproducer, you will see that the corresponding bookmark for the
subsection is absent.

The solution is to prevent a potential control character that starts the
(sub)section heading text from appearing at the beginning of the
(interpolated) input line.

Thus the dummy character prefix.

I'll review other groff macro packages for similar problems.  The
placement of a dummy character is not always necessary, so they'll need
to be checked on a case-by-case basis.

$ git grep 'nop.*\$\*' tmac
tmac/an.tmac:.    nop \&\\$*
tmac/doc.tmac:.    nop \*[doc-Fd-font]\$*
tmac/doc.tmac:.    nop \*[doc-Ft-font]\$*\c
tmac/mdoc/doc-common:.  nop \[em] \$*
tmac/pdf.tmac:. nop \!x X ps:exec [\\$* pdfmark
tmac/pdf.tmac:.         nop \&\\$*
tmac/pdf.tmac:.nop \!x X pdf: switchtopage \\$*
tmac/s.tmac:.   nop \&\\$*
tmac/www.tmac.in:.    \" was implemented via .nop \&\X^html:\\$*^ but
tmac/www.tmac.in:.  nop \X^html:\\$*^\c
tmac/www.tmac.in:.    nop \&\X^html</p>:\\$*^
tmac/www.tmac.in:.    nop \&\X^html<?p>:\\$*^
tmac/www.tmac.in:.    nop \&\X^math<?p>:\\$*^
tmac/www.tmac.in:.    nop \X^index:\\$*^

Regards,
Branden

Attachment: signature.asc
Description: PGP signature

Reply via email to