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/

Attachment: signature.asc
Description: PGP signature

Reply via email to