gbranden pushed a commit to branch master
in repository groff.

commit d68c68c2602b106736236124d9985ff3cf775ca0
Author: G. Branden Robinson <[email protected]>
AuthorDate: Tue May 19 19:11:18 2026 -0500

    [troff]: `pwh` request reports diversion traps.
    
    * src/roff/troff/div.h (class diversion): Declare new pure virtual
      member function `print_diversion_trap()` returning `void`.
    
      (class macro_diversion)
      (class top_level_diversion): Declare member function
      `print_diversion_trap()`.
    
    * src/roff/troff/div.cpp (macro_diversion::print_diversion_trap): New
      member function reports properties of a diversion trap if one exists.
    
      (top_level_diversion::print_diversion_trap): New member function
      throws assert(3)ion if called.  Internal logic should ensure that such
      a call is impossible.
    
      (print_traps_request): Call the `print_traps()` member function of
      `topdiv` (as before) only if it is the current diversion.  Otherwise,
      the current diversion is a macro diversion, so call its
      `print_diversion_trap()` member function.
    
    * doc/groff.texi.in (Diversion Traps, Debugging):
    * man/groff.7.man (Request short reference):
    * man/groff_diff.7.man (New requests): Document it.
    
    * src/roff/groff/tests/pwh-request-works.sh: Unit-test request.
    
    * src/roff/groff/groff.am (groff_TESTS): Run test.
    
    Fixes <https://savannah.gnu.org/bugs/?68358>.
---
 ChangeLog                                 | 28 ++++++++++
 doc/groff.texi.in                         | 19 +++++--
 man/groff.7.man                           |  9 +++-
 man/groff_diff.7.man                      | 12 +++--
 src/roff/groff/groff.am                   |  1 +
 src/roff/groff/tests/pwh-request-works.sh | 87 +++++++++++++++++++++++++++++++
 src/roff/troff/div.cpp                    | 21 +++++++-
 src/roff/troff/div.h                      |  3 ++
 8 files changed, 167 insertions(+), 13 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b1e70ef92..3d6185201 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2026-05-19  G. Branden Robinson <[email protected]>
+
+       * src/roff/troff/div.h (class diversion): Declare new pure
+       virtual member function `print_diversion_trap()` returning
+       `void`.
+       (class macro_diversion)
+       (class top_level_diversion): Declare member function
+       `print_diversion_trap()`.
+       * src/roff/troff/div.cpp
+       (macro_diversion::print_diversion_trap): New member function
+       reports properties of a diversion trap if one exists.
+       (top_level_diversion::print_diversion_trap): New member function
+       throws assert(3)ion if called.  Internal logic should ensure
+       that such a call is impossible.
+       (print_traps_request): Call the `print_traps()` member function
+       of `topdiv` (as before) only if it is the current diversion.
+       Otherwise, the current diversion is a macro diversion, so call
+       its `print_diversion_trap()` member function.
+
+       * doc/groff.texi.in (Diversion Traps, Debugging):
+       * man/groff.7.man (Request short reference):
+       * man/groff_diff.7.man (New requests): Document it.
+
+       * src/roff/groff/tests/pwh-request-works.sh: Unit-test request.
+       * src/roff/groff/groff.am (groff_TESTS): Run test.
+
+       Fixes <https://savannah.gnu.org/bugs/?68358>.
+
 2026-05-17  G. Branden Robinson <[email protected]>
 
        * src/roff/troff/input.cpp (char_list::get): De-optimize read
diff --git a/doc/groff.texi.in b/doc/groff.texi.in
index a59de62f4..fc73250ca 100644
--- a/doc/groff.texi.in
+++ b/doc/groff.texi.in
@@ -19542,6 +19542,10 @@ request.
 A diversion is not formatted in the context of a page, so it lacks page
 location traps; instead it can have a @dfn{diversion trap}.  There can
 exist at most one such vertical position trap per diversion.
+Use the
+@code{pwh}
+request to dump the properties of a diversion trap
+to the standard error stream.@footnote{@xref{Debugging}.}
 
 @Defreq {dt, [@Var{dist} @Var{name}]}
 @cindex @code{.t} register, and diversions
@@ -22593,16 +22597,23 @@ represents an empty list.
 @cindex listing page location traps (@code{pwh})
 @cindex traps, page location, dumping (@code{pwh})
 @cindex traps, page location, listing (@code{pwh})
-Report the names and positions of all page location traps to the
-standard error stream.  GNU @command{troff} reports empty slots in the
-list, where a trap had been planted but subsequently (re)moved, because
-they can affect the visibility of subsequently planted traps.
+If the top-level diversion is the current diversion,
+report the names and positions of all page location traps
+to the standard error stream.
+GNU
+@command{troff} @c GNU
+reports empty slots in the list,
+where a trap had been planted but subsequently (re)moved,
+because they can affect the visibility of subsequently planted traps.
 @c "because they can affect the priority of subsequently planted traps."
 @c XXX Is that right?  It's useful to print the empty slots, I think,
 @c but a trap planted in an "empty" slot with .wh will become active.
 @c The slot seems to act as an immobile dummy list head, but does not
 @c change the basic list semantics.  .wh plants a trap at the head of
 @c the trap list at a location, and .ch plants a trap at the tail.
+Otherwise,
+similarly report the name and position of the diversion trap,
+if any.
 @endDefreq
 
 @Defreq {fl, }
diff --git a/man/groff.7.man b/man/groff.7.man
index 3cfa5d4ff..e65b5d564 100644
--- a/man/groff.7.man
+++ b/man/groff.7.man
@@ -4968,8 +4968,13 @@ and its mode
 .
 .TPx
 .REQ .pwh
-Report names and positions of all page location traps to the standard
-error stream.
+If the top-level diversion is the current diversion,
+report the names and positions of all page location traps
+to the standard error stream.
+.
+Otherwise,
+similarly report the name and position of the diversion trap,
+if any.
 .
 .TPx
 .REQ .pvs
diff --git a/man/groff_diff.7.man b/man/groff_diff.7.man
index 38f9afc42..80edb721c 100644
--- a/man/groff_diff.7.man
+++ b/man/groff_diff.7.man
@@ -4181,18 +4181,20 @@ and its mode
 .
 .TP
 .B .pwh
-Report the names and vertical positions,
-in basic units,
-of all page location traps
+If the top-level diversion is the current diversion,
+report the names and positions of all page location traps
 to the standard error stream.
 .
 GNU
 .I troff \" GNU
 reports empty slots in the list,
-where a trap had been planted
-but subsequently (re)moved,
+where a trap had been planted but subsequently (re)moved,
 because they can affect the visibility of subsequently planted traps.
 .
+Otherwise,
+similarly report the name and position of the diversion trap,
+if any.
+.
 .
 .TP
 .BI .pvs \~\[+-]n
diff --git a/src/roff/groff/groff.am b/src/roff/groff/groff.am
index ce7362f4b..6175e1859 100644
--- a/src/roff/groff/groff.am
+++ b/src/roff/groff/groff.am
@@ -130,6 +130,7 @@ groff_TESTS = \
   src/roff/groff/tests/pnr-request-works.sh \
   src/roff/groff/tests/po-request-works.sh \
   src/roff/groff/tests/ps-device-smoke-test.sh \
+  src/roff/groff/tests/pwh-request-works.sh \
   src/roff/groff/tests/recognize-end-of-sentence.sh \
   src/roff/groff/tests/regression_savannah_56555.sh \
   src/roff/groff/tests/regression_savannah_58153.sh \
diff --git a/src/roff/groff/tests/pwh-request-works.sh 
b/src/roff/groff/tests/pwh-request-works.sh
new file mode 100755
index 000000000..52f412ef7
--- /dev/null
+++ b/src/roff/groff/tests/pwh-request-works.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copyright 2026 G. Branden Robinson
+#
+# This file is part of groff, the GNU roff typesetting system.
+#
+# groff is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# groff is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+groff="${abs_top_builddir:-.}/test-groff"
+
+fail=
+
+wail () {
+   echo "...FAILED"
+   fail=yes
+}
+
+input='.
+.de PAGE-LOCATION-TRAP
+.tm SPROING
+..
+.de DIVERSION-TRAP
+.tm BOING
+..
+.wh 10v PAGE-LOCATION-TRAP
+.pwh
+.di DIVERSION
+.tm inside diversion; reporting traps
+.pwh
+.tm setting diversion trap
+.dt 2v DIVERSION-TRAP
+.pwh
+.nf
+foo
+bar
+.tm diversion trap should have sprung; reporting traps
+.pwh
+.tm clearing diversion trap and reporting again
+.dt
+.pwh
+.di
+.tm outside diversion; reporting traps
+.pwh
+.'
+
+# Expected error stream output:
+#      1  PAGE-LOCATION-TRAP      120000
+#      2  inside diversion; reporting traps
+#      3  setting diversion trap
+#      4  DIVERSION-TRAP  24000
+#      5  BOING
+#      6  diversion trap should have sprung; reporting traps
+#      7  DIVERSION-TRAP  24000
+#      8  clearing diversion trap and reporting again
+#      9  outside diversion; reporting traps
+#     10  PAGE-LOCATION-TRAP      120000
+
+error=$(printf '%s\n' "$input" | "$groff" 2>&1 >/dev/null | nl -ba \
+    | tr '\t' ' ')
+echo "$error"
+
+echo "checking initial report of page location traps" >&2
+echo "$error" | grep -qx " *1 *PAGE-LOCATION-TRAP *[0-9]*" || wail
+
+echo "checking initial report of diversion trap" >&2
+echo "$error" | grep -qx " *4 *DIVERSION-TRAP *[0-9]*" || wail
+
+echo "checking subsequent report of diversion trap" >&2
+echo "$error" | grep -qx " *7 *DIVERSION-TRAP *[0-9]*" || wail
+
+echo "checking subsequent report of page location traps" >&2
+echo "$error" | grep -qx " *10 *PAGE-LOCATION-TRAP *[0-9]*" || wail
+
+test -z "$fail"
+
+# vim:set autoindent expandtab shiftwidth=4 tabstop=4 textwidth=72:
diff --git a/src/roff/troff/div.cpp b/src/roff/troff/div.cpp
index ceb383a18..555e1be22 100644
--- a/src/roff/troff/div.cpp
+++ b/src/roff/troff/div.cpp
@@ -1,5 +1,5 @@
 /* Copyright 1989-2020 Free Software Foundation, Inc.
-             2020-2025 G. Branden Robinson
+             2020-2026 G. Branden Robinson
 
 Written by James Clark ([email protected])
 
@@ -977,6 +977,14 @@ void macro_diversion::clear_diversion_trap()
   diversion_trap = NULL_SYMBOL;
 }
 
+void macro_diversion::print_diversion_trap()
+{
+  if (diversion_trap != NULL_SYMBOL)
+    errprint("%1\t%2\n", diversion_trap.contents(),
+            diversion_trap_pos.to_units());
+  fflush(stderr);
+}
+
 void top_level_diversion::set_diversion_trap(symbol, vunits)
 {
   error("cannot set diversion trap when not diverting output");
@@ -987,6 +995,12 @@ void top_level_diversion::clear_diversion_trap()
   error("cannot clear diversion trap when not diverting output");
 }
 
+void top_level_diversion::print_diversion_trap()
+{
+  assert(0 == "attempting to report diversion trap"
+             " of top-level diversion");
+}
+
 static void diversion_trap_request() // .dt
 {
   vunits n;
@@ -1025,7 +1039,10 @@ static void change_trap_request() // .ch
 
 static void print_traps_request() // .pwh
 {
-  topdiv->print_traps();
+  if (topdiv == curdiv)
+    topdiv->print_traps();
+  else
+    curdiv->print_diversion_trap();
   skip_line();
 }
 
diff --git a/src/roff/troff/div.h b/src/roff/troff/div.h
index c3257d2d9..bbc8c371a 100644
--- a/src/roff/troff/div.h
+++ b/src/roff/troff/div.h
@@ -62,6 +62,7 @@ public:
   const char *get_diversion_name() { return nm.contents(); }
   virtual void set_diversion_trap(symbol, vunits) = 0;
   virtual void clear_diversion_trap() = 0;
+  virtual void print_diversion_trap() = 0;
   virtual void copy_file(const char *filename) = 0;
 };
 
@@ -87,6 +88,7 @@ public:
   const char *get_next_trap_name();
   void set_diversion_trap(symbol, vunits);
   void clear_diversion_trap();
+  void print_diversion_trap();
   void copy_file(const char *filename);
 };
 
@@ -146,6 +148,7 @@ public:
   friend void page_offset();
   void set_diversion_trap(symbol, vunits);
   void clear_diversion_trap();
+  void print_diversion_trap();
   void set_last_page() { last_page_count = page_count; }
 };
 

_______________________________________________
groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit

Reply via email to