URL: <https://savannah.gnu.org/bugs/?68430>
Summary: [PATCH] [troff] incorrectly handles right braces in
macro call arguments
Group: GNU roff
Submitter: gbranden
Submitted: Sun 07 Jun 2026 04:43:49 PM UTC
Category: Core
Severity: 3 - Normal
Item Group: Incorrect behaviour
Status: In Progress
Privacy: Public
Assigned to: gbranden
Open/Closed: Open
Discussion Lock: Unlocked
Planned Release: None
_______________________________________________________
Follow-up Comments:
-------------------------------------------------------
Date: Sun 07 Jun 2026 04:43:49 PM UTC By: G. Branden Robinson <gbranden>
In fixing one bug post-1.24.1, I introduced another.
ebf943aa66c3e54ddbed8e7ec0eccc6fc425b72c is the first bad commit
commit ebf943aa66c3e54ddbed8e7ec0eccc6fc425b72c
Author: G. Branden Robinson <[email protected]>
Date: Mon Apr 20 21:34:05 2026 -0500
[troff]: `\}` now terminates syntax items.
* src/roff/troff/token.h (token::is_terminator): Add `TOKEN_RIGHT_BRACE`
to the set of tokens that can terminate a sequence of nonterminal
symbols (such as the character sequence producing a *roff identifier,
transparent throughput argument, contents of a string definition, or
other string-like request argument like file names or system
commands).
Fixes <https://savannah.gnu.org/bugs/?68257>.
ChangeLog | 11 +++++++++++
src/roff/troff/token.h | 12 ++++++++++--
2 files changed, 21 insertions(+), 2 deletions(-)
That seemed to work as intended and I didn't notice any problems for a while.
But check this out.
$ cat /tmp/gbr5
.de aa
A
..
.de bb
.tm bb: I have \\n(.$ args
B \\$1 \\$2
..
.if 1 \{.aa
.bb\} Q\}Z
C
$ solaris10 nroff /tmp/gbr5 | cat -s
bb: I have 1 args
A B QZ C
$ heirloom nroff /tmp/gbr5 | cat -s
bb: I have 1 args
A B QZ C
$ dwb nroff /tmp/gbr5 | cat -s
bb: I have 1 args
A B QZ C
$ 9 nroff /tmp/gbr5 | cat -s
bb: I have 2 args
A B QZ C
$ ~/groff-1.24.1/bin/nroff /tmp/gbr5 | cat -s
bb: I have 1 args
A B QZ C
$ ~/groff-HEAD/bin/nroff /tmp/gbr5 | cat -s
bb: I have 0 args
A B
QZ C
So that's no good. Fortunately I have a fix:
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index d218847d5..89b53e60c 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -4755,6 +4755,24 @@ static void interpolate_macro_or_invoke_request(symbol
nm,
static void decode_macro_call_arguments(macro_iterator *mi)
{
+ // Discard right-brace escape sequences until hitting something else.
+ // Doing so enables us to ignore a newline that occurs right after a
+ // right-brace escape sequence. Nobody documents this, but it's what
+ // all AT&T-descended troffs do.
+ //
+ // Scenario:
+ // .de aa
+ // A
+ // ..
+ // .if 1 \{.aa\}
+ // B
+ //
+ // If we read the newline at the end of the macro definition and the
+ // newline at the end of the `if` control line adjacently, that's a
+ // blank line. No AT&T-descended troff acts that way, so we shouldn't
+ // either, and must discard one of the newlines.
+ while (tok.is_right_brace())
+ tok.next();
if (!tok.is_terminator()) {
node *n;
int c = read_character_in_copy_mode(&n);
Plan 9 troff is a funny case; I'll say more about that in bug #42675 and/or
the "Other Differences" section of our Texinfo manual and _groff_diff_(7) at
some point.
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?68430>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
signature.asc
Description: PGP signature
