gbranden pushed a commit to branch master
in repository groff.

commit 8ab3666cf4540cb41ae6350fb10d6ff1d0d3ec8f
Author: G. Branden Robinson <[email protected]>
AuthorDate: Sun Dec 21 10:14:33 2025 -0600

    [troff]: Fix Savannah #67842.
    
    Split `TOKEN_SPECIAL_CHAR` token type into two, leaving the existing one
    for `\(` and `\[` escape sequences, and creating a new
    `TOKEN_DELIMITED_SPECIAL_CHAR` for the delimited `\C` escape sequence.
    
    * src/roff/troff/token.h (class token): Add new
      `TOKEN_DELIMITED_SPECIAL_CHAR` enumeration constant.
    
      (token::is_special_character, token::is_any_character): Return `true`
      for both new and old token types.
    
    * src/roff/troff/input.cpp (token::next) <C>: Tokenize `C` escape
      sequence as `TOKEN_DELIMITED_SPECIAL_CHAR`.
    
      (token::is_usable_as_delimiter): Reject `TOKEN_DELIMITED_SPECIAL_CHAR`
      as a delimiter.
    
      (token::operator==, token::description, process_input_stack)
      (token::get_charinfo, token::add_to_zero_width_node_list)
      (token::process): Treat new token type the same as the old one.
    
    Fixes <https://savannah.gnu.org/bugs/?67842>.  Problem appears to date
    back to groff's birth.
---
 ChangeLog                | 22 ++++++++++++++++++++++
 src/roff/troff/input.cpp | 11 +++++++++--
 src/roff/troff/token.h   | 10 +++++++---
 3 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7e75df0c0..e6efdaafc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2025-12-21  G. Branden Robinson <[email protected]>
+
+       [troff]: Split `TOKEN_SPECIAL_CHAR` token type into two, leaving
+       the existing one for `\(` and `\[` escape sequences, and
+       creating a new `TOKEN_DELIMITED_SPECIAL_CHAR` for the delimited
+       `\C` escape sequence.
+
+       * src/roff/troff/token.h (class token): Add new
+       `TOKEN_DELIMITED_SPECIAL_CHAR` enumeration constant.
+       (token::is_special_character, token::is_any_character): Return
+       `true` for both new and old token types.
+       * src/roff/troff/input.cpp (token::next) <C>: Tokenize `C`
+       escape sequence as `TOKEN_DELIMITED_SPECIAL_CHAR`.
+       (token::is_usable_as_delimiter): Reject
+       `TOKEN_DELIMITED_SPECIAL_CHAR` as a delimiter.
+       (token::operator==, token::description, process_input_stack)
+       (token::get_charinfo, token::add_to_zero_width_node_list)
+       (token::process): Treat new token type the same as the old one.
+
+       Fixes <https://savannah.gnu.org/bugs/?67842>.  Problem appears
+       to date back to groff's birth.
+
 2025-12-21  G. Branden Robinson <[email protected]>
 
        * src/roff/groff/tests/check-delimiter-validity.sh: Add
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index b26d608dc..597f055da 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -2459,7 +2459,7 @@ void token::next()
        nm = read_delimited_identifier();
        if (nm.is_null())
          break;
-       type = TOKEN_SPECIAL_CHAR;
+       type = TOKEN_DELIMITED_SPECIAL_CHAR;
        return;
       case 'd':
        type = TOKEN_NODE;
@@ -2789,6 +2789,7 @@ bool token::operator==(const token &t)
   case TOKEN_CHAR:
     return c == t.c;
   case TOKEN_SPECIAL_CHAR:
+  case TOKEN_DELIMITED_SPECIAL_CHAR:
     return nm == t.nm;
   case TOKEN_INDEXED_CHAR:
     return val == t.val;
@@ -2958,6 +2959,7 @@ bool token::is_usable_as_delimiter(bool report_error,
   case TOKEN_STRETCHABLE_SPACE:
   case TOKEN_UNSTRETCHABLE_SPACE:
   case TOKEN_DELIMITED_HORIZONTAL_MOTION:
+  case TOKEN_DELIMITED_SPECIAL_CHAR:
   case TOKEN_NEWLINE:
   case TOKEN_EOF:
     if (report_error)
@@ -3038,6 +3040,7 @@ const char *token::description()
   case TOKEN_SPACE:
     return "a space";
   case TOKEN_SPECIAL_CHAR:
+  case TOKEN_DELIMITED_SPECIAL_CHAR:
     // We normally use apostrophes for quotation in diagnostic messages,
     // but many special character names contain them.  Fall back to
     // double quotes if this one does.  A user-defined special character
@@ -3713,6 +3716,7 @@ void process_input_stack()
       }
     case token::TOKEN_INDEXED_CHAR:
     case token::TOKEN_SPECIAL_CHAR:
+    case token::TOKEN_DELIMITED_SPECIAL_CHAR:
       if (curenv->get_was_line_interrupted())
        warning(WARN_SYNTAX, "ignoring %1 on input line after output"
                " line continuation escape sequence",
@@ -8871,7 +8875,8 @@ charinfo *token::get_charinfo(bool required, bool 
suppress_creation)
 {
   if (TOKEN_CHAR == type)
     return charset_table[c];
-  if (TOKEN_SPECIAL_CHAR == type)
+  if ((TOKEN_SPECIAL_CHAR == type)
+      || (TOKEN_DELIMITED_SPECIAL_CHAR == type))
     return lookup_charinfo(nm, suppress_creation);
   if (TOKEN_INDEXED_CHAR == type)
     return get_charinfo_by_index(val, suppress_creation);
@@ -8955,6 +8960,7 @@ bool token::add_to_zero_width_node_list(node **pp)
                         curenv->get_fill_color());
     break;
   case TOKEN_SPECIAL_CHAR:
+  case TOKEN_DELIMITED_SPECIAL_CHAR:
     *pp = (*pp)->add_char(lookup_charinfo(nm), curenv, &w, &s);
     break;
   case TOKEN_STRETCHABLE_SPACE:
@@ -9053,6 +9059,7 @@ void token::process()
     curenv->space();
     break;
   case TOKEN_SPECIAL_CHAR:
+  case TOKEN_DELIMITED_SPECIAL_CHAR:
     // Optimize `curenv->add_char(get_charinfo())` for token type.
     curenv->add_char(lookup_charinfo(nm));
     break;
diff --git a/src/roff/troff/token.h b/src/roff/troff/token.h
index f38d6b5b6..b3a7c39fb 100644
--- a/src/roff/troff/token.h
+++ b/src/roff/troff/token.h
@@ -45,6 +45,7 @@ class token {
     TOKEN_BEGIN_TRAP,
     TOKEN_CHAR,                        // ordinary character
     TOKEN_DELIMITED_HORIZONTAL_MOTION, // \h
+    TOKEN_DELIMITED_SPECIAL_CHAR,      // \C
     TOKEN_DUMMY,               // dummy character: \&
     TOKEN_EMPTY,               // this is the initial value
     TOKEN_END_TRAP,
@@ -64,7 +65,7 @@ class token {
     TOKEN_REQUEST,
     TOKEN_RIGHT_BRACE,         // \}
     TOKEN_SPACE,               // ' ' -- ordinary space
-    TOKEN_SPECIAL_CHAR,                // \(, \[, \C
+    TOKEN_SPECIAL_CHAR,                // \(, \[
     TOKEN_SPREAD,              // \p -- break and spread output line
     TOKEN_STRETCHABLE_SPACE,   // \~
     TOKEN_TAB,                 // ^I
@@ -188,7 +189,8 @@ inline bool token::is_horizontal_motion()
 
 inline bool token::is_special_character()
 {
-  return (TOKEN_SPECIAL_CHAR == type);
+  return ((TOKEN_SPECIAL_CHAR == type)
+         || (TOKEN_DELIMITED_SPECIAL_CHAR == type));
 }
 
 inline int token::nspaces()
@@ -218,7 +220,9 @@ inline unsigned char token::ch()
 
 inline bool token::is_any_character()
 {
-  return ((TOKEN_CHAR == type) || (TOKEN_SPECIAL_CHAR == type)
+  return ((TOKEN_CHAR == type)
+         || (TOKEN_SPECIAL_CHAR == type)
+         || (TOKEN_DELIMITED_SPECIAL_CHAR == type)
          || (TOKEN_INDEXED_CHAR == type));
 }
 

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

Reply via email to