* src/roff/troff/input.cpp (is_char_usable_as_delimiter): Revise: return
  `true` for Control+A (default leader character) through Control+I
  (default tab character) plus Control+L (form feed) and DEL.
  Restructure: because this function is "hot"--it gets hit over 4.6
  million times in a groff build--arrange the most expected case of
  delimiter (a valid printable character) on the "straight-line" path,
  assuming a forward branch is not taken.
---
 ChangeLog                | 11 ++++++
 src/roff/troff/input.cpp | 76 ++++++++++++++++++++++++++--------------
 2 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5fcd2a5eb..4ca07b1de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2026-10-25  G. Branden Robinson <[email protected]>
+
+       * src/roff/troff/input.cpp (is_char_usable_as_delimiter): Revise
+       and restructure.  Revise: return `true` for Control+A (default
+       leader character) through Control+I (default tab character) plus
+       Control+L (form feed) and DEL.  Restructure: because this
+       function is "hot"--it gets hit over 4.6 million times in a groff
+       build--arrange the most expected case of delimiter (a valid
+       printable character) on the "straight-line" path, assuming a
+       forward branch is not taken.
+
 2026-10-25  G. Branden Robinson <[email protected]>
 
        [troff]: Fix Savannah #68832.
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 28747aaee..98e39f1ed 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -2968,35 +2968,57 @@ bool token::operator!=(const token &t)
 // doesn't tokenize it) and accepts a user-specified delimiter.
 static bool is_char_usable_as_delimiter(int c)
 {
-  // Reject all characters that can validly begin a numeric expression.
+  if (csprint(c))
+    // Reject all characters that can validly begin a numeric expression.
+    switch (c) {
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+    case '+':
+    case '-':
+    // Several characters are valid in a numeric expression only
+    // _non-initially_, and so are not ambiguous.  We present them here
+    // as documentation.
+    // case '/':
+    // case '*':
+    // case '%':
+    // case '<':
+    // case '>':
+    // case '=':
+    // case '&':
+    // case ':':
+    case '(':
+    // case ')':
+    case '.':
+    case '|':
+      return false;
+    default:
+      return true;
+    }
   switch (c) {
-  case '0':
-  case '1':
-  case '2':
-  case '3':
-  case '4':
-  case '5':
-  case '6':
-  case '7':
-  case '8':
-  case '9':
-  case '+':
-  case '-':
-  // case '/':
-  // case '*':
-  // case '%':
-  // case '<':
-  // case '>':
-  // case '=':
-  // case '&':
-  // case ':':
-  case '(':
-  // case ')':
-  case '.':
-  case '|':
-    return false;
-  default:
+  // Accept Control+A (default leader character) through Control+I
+  // (default tab character) plus Control+L (form feed) and DEL.
+  case 1:
+  case 2:
+  case 3:
+  case 4:
+  case 5:
+  case 6:
+  case 7:
+  case 8:
+  case 9:
+  case 12:
+  case 127:
     return true;
+  default:
+    return false;
   }
 }
 
-- 
2.39.5

Attachment: signature.asc
Description: PGP signature

Reply via email to