URL: <https://savannah.gnu.org/bugs/?68816>
Summary: [PATCH] [troff] add `.pi` register permitting
inspection of output pipeline
Group: GNU roff
Submitter: gbranden
Submitted: Thu 22 Oct 2026 02:50:08 PM UTC
Category: Formatter
Severity: 2 - Minor
Item Group: Feature change
Status: In Progress
Privacy: Public
Assigned to: gbranden
Open/Closed: Open
Discussion Lock: Unlocked
Planned Release: None
_______________________________________________________
Follow-up Comments:
-------------------------------------------------------
Date: Thu 22 Oct 2026 02:50:08 PM UTC By: G. Branden Robinson <gbranden>
Troubleshooting bug #68815 was more tedious than it needed to be.
To see the pipeline constructed by one or more `pi` requests required one to
fire up a symbolic debugger on a running `troff` process and to print the
global variable `pipe_command`.
A guiding principle of my work on the formatter has been that the user should
not have to fire up a debugger to observe aspects of the program's state that
are closely related to to its feature set.
I've already implemented this, and it has coverage in a test.
commit 3c1efd17bd1d4fac01aecc6ec44c65df848c9a2a
Author: G. Branden Robinson <[email protected]>
Date: Wed Oct 21 23:10:21 2026 -0500
[troff]: Implement new `.pi` register.
[troff]: Implement `.pi` register for orthogonality and to make the
output filtration pipeline readily inspectable.
* src/roff/troff/input.cpp (pipe_command_reg): New file-local class
handles dynamically computed data. (The class `readonly_text_reg` is
not appropriate because it has _static_ contents that are computed
once only, at formatter startup. The global `pipe_command` is
populated, and can be updated, by the input stream--until output
commences).
(pipe_command_reg::get_string): Member function returns `pipe_command`
contents (a C string).
* doc/groff.texi.in (Host System Service Access):
* man/groff.7.man.in (Read-only registers):
* man/groff_diff.7.man (New register): Document it.
diff --git a/doc/groff.texi.in b/doc/groff.texi.in
index 6d64dde5a..0ab7be4af 100644
--- a/doc/groff.texi.in
+++ b/doc/groff.texi.in
@@ -22150,7 +22150,8 @@
.ex
@endExample
-@Defreq {pi, [@code{"}]@Var{command}}
+@DefreqList {pi, [@code{"}]@Var{command}}
+@DefregListEndx {.pi}
Use
the formatter's device-independent output
as the input to the commands specified in
@@ -22167,17 +22168,17 @@
@code{pi}
requests construct a multi-stage pipeline
in the same order as the formatter encounters the requests.
-Thus,
+The read-only register
+@code{.pi}
+interpolates the configured pipeline.
@Example
.pi foo
.pi bar
+.pnr .pi
+ @error{} .pi foo|bar
@endExample
-@noindent
-is the same as
-@w{@samp{.pi foo | bar}}.
-
@code{pi}
must be invoked before
GNU
diff --git a/man/groff.7.man.in b/man/groff.7.man.in
index aa5be873f..9d80bc727 100644
--- a/man/groff.7.man.in
+++ b/man/groff.7.man.in
@@ -8016,6 +8016,12 @@ .SS "Read-only registers"
Page ejection is in progress (Boolean-valued).
.
.TP
+.REG .pi
+Pipeline configured by
+.B pi
+requests.
+.
+.TP
.REG .pn
Number of the next page.
.
diff --git a/man/groff_diff.7.man b/man/groff_diff.7.man
index ceafada9c..c70020d10 100644
--- a/man/groff_diff.7.man
+++ b/man/groff_diff.7.man
@@ -5418,6 +5418,13 @@ .SS "New registers"
.
.
.TP
+.B \[rs]n[.pi]
+Interpolate the pipeline configured by
+.B pi
+requests.
+.
+.
+.TP
.B \[rs]n[.pn]
Interpolate next page number
(either that set by
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 53d27229e..13f6a4558 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -9567,6 +9567,16 @@ const char
*enclosing_want_att_compat_reg::get_string()
: want_att_compat_stack.top());
}
+class pipe_command_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *pipe_command_reg::get_string()
+{
+ return pipe_command;
+}
+
class readonly_text_register : public reg {
const char *s;
public:
@@ -10621,6 +10631,7 @@ void init_input_requests()
register_dictionary.define(".g", new readonly_text_register(1));
register_dictionary.define(".H", new readonly_register(&hresolution));
register_dictionary.define(".O", new
readonly_register(&suppression_level));
+ register_dictionary.define(".pi", new pipe_command_reg);
register_dictionary.define(".R", new readonly_text_register(INT_MAX));
register_dictionary.define(".U", new
readonly_boolean_register(&want_unsafe_requests));
register_dictionary.define(".V", new readonly_register(&vresolution));
commit 8f54c928f2f908567be152527d40fb8d926eb403
Author: G. Branden Robinson <[email protected]>
Date: Wed Oct 21 22:20:35 2026 -0500
[groff]: Test use of multiple `pi` requests.
* src/roff/groff/tests/pi-request-works.sh: Add test of multiple
pipeline command construction. Dump new `.pi` register while we're at
it.
diff --git a/src/roff/groff/tests/pi-request-works.sh
b/src/roff/groff/tests/pi-request-works.sh
index a85b04d7f..1c9823695 100755
--- a/src/roff/groff/tests/pi-request-works.sh
+++ b/src/roff/groff/tests/pi-request-works.sh
@@ -31,6 +31,12 @@ output=$(printf '.pi sed s/^/#/\nhello\n' | "$groff" -UZ)
|| wail
echo "$output"
echo "$output" | grep -Eqx '^#t *hello'
+echo "checking that multiple 'pi' requests work" >&2
+output=$(printf '.pi sed s/^/#/\n.pi sed s/^#/##/\n.pnr .pi\nhello\n' \
+ | "$groff" -UZ) || wail
+echo "$output"
+echo "$output" | grep -Eqx '^##t *hello'
+
echo "checking that parser returns to correct state after 'pi'" >&2
output=$(printf '.pi cat\n.tm goodbye\n' \
| "$groff" -UZ 2>&1 > /dev/null) || wail
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?68816>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
signature.asc
Description: PGP signature
