Hi Doug,

At 2026-08-31T23:18:58-0400, Douglas McIlroy wrote:
> groff -ms does not diagnose nested .KS keeps. An inner keep is
> useless, because if it triggers, the containing keep will include a
> page break, contrary to intent.
> 
> There's nothing inherently wrong about a useless feature, but a stray
> .KS (as distinct from a nested one) like this
> .KS
> ...
> .KS
> ...
> .KE
> can lead to the diagnostic "diversion open while ejecting a page." A
> diagnostic for a .KS within a keep would be clearer.

True; it seems to be a recurring pain point on this mailing list.

https://lists.gnu.org/archive/html/groff/2015-10/msg00051.html
https://lists.gnu.org/archive/html/groff/2007-07/msg00018.html

What do you think of the following patch from my Git working copy?

diff --git a/tmac/s.tmac b/tmac/s.tmac
index 92a664a9a..bff83c009 100644
--- a/tmac/s.tmac
+++ b/tmac/s.tmac
@@ -834,7 +834,8 @@ .de pg*footer
 .de pg@super-eject
 .br
 .if !'\\n(.z'' \{\
-.      ds @msg diversion open while ejecting page\"
+.      ds @msg diversion open while ejecting page;\"
+.      as @msg " possible .KS/.KF/.KE mismatch\"
 .      as @msg " (last file seen: \\*[@last-file-seen])\"
 .      @error-recover \\*[@msg]
 .      rm @msg
@@ -1047,9 +1048,15 @@ .de fn@print-sep
 .\" ******** module kp ********
 .\" ***************************
 .\" Keeps.
+.nr kp*in-static-keep 0
 .de KS
 .br
-.di kp@div
+.ie \\n[kp*in-static-keep] .@error ignoring .\\$0: \
+cannot nest static keeps
+.el \{\
+.      nr kp*in-static-keep 1
+.      di kp@div
+.\}
 ..
 .de KF
 .if !'\\n(.z'' .@error-recover .KF while diversion open
@@ -1062,9 +1069,12 @@ .de KF
 ..
 .de KE
 .nr kp*did-closure-succeed 0
-.if '\\n(.z'kp@div'  .kp*end
+.if '\\n(.z'kp@div'  \{\
+.      kp*end
+.      nr kp*in-static-keep 0
+.\}
 .if '\\n(.z'kp@fdiv' .kp*fend
-.if !\\n[kp*did-closure-succeed] .@error .KE without .KS or .KF
+.if !\\n[kp*did-closure-succeed] .@error .KE without (valid) .KS or .KF
 .rr kp*did-closure-succeed
 ..
 .de @div-end!kp@div

Here it is in action.

$ printf '.LP\nHello,\n.KS\nDoug!\n' | ./build/test-groff -ms -T ascii | cat -s
s.tmac: error: diversion open while ejecting page; possible .KS/.KF/.KE 
mismatch (last file seen: <standard input>) (recovering)

Hello,
Doug!

$ printf '.LP\nHello,\n.KS\nDoug!\n.KE\n' | ./build/test-groff -ms -T ascii | 
cat -s

Hello,
Doug!

$ printf '.LP\nHello,\n.KS\nDoug!\n.KS\n.KE\n' | ./build/test-groff -ms -T 
ascii | cat -s
s.tmac:<standard input>:5: error: ignoring .KS: cannot nest static keeps

Hello,
Doug!

$ printf '.LP\nHello,\n.KS\nDoug!\n.KS\n.KE\n.KE\n' | ./build/test-groff -ms -T 
ascii | cat -s
s.tmac:<standard input>:5: error: ignoring .KS: cannot nest static keeps
s.tmac:<standard input>:7: error: .KE without (valid) .KS or .KF

Hello,
Doug!

With luck, the foregoing fixes <https://savannah.gnu.org/bugs/?64466>.

Dave, what do you think?

> It seems that nested .KF keeps should be OK.

That's never yet been implemented.

Any volunteers?  :)

Regards,
Branden

Attachment: signature.asc
Description: PGP signature

  • nested keeps Douglas McIlroy
    • Re: nested keeps G. Branden Robinson

Reply via email to