gbranden pushed a commit to branch master
in repository groff.

commit 88a864ffbd1e3691ea2f99212970e33e4b544909
Author: G. Branden Robinson <[email protected]>
AuthorDate: Wed Dec 3 17:40:39 2025 -0600

    [troff]: Fix Savannah #67711.
    
    Describe character (classes) better.  Character classes have one more
    property beyond their name, and lists of ranges and nested classes: a
    set of character flags that the formatter bitwise "or"s with any
    character members of the class (recursively).  However, the computation
    of flags applicable to a character has been done lazily almost from the
    time the character class feature was first implemented, presumably to
    keep a `cflags` request on a highly populated character class from
    taking a lot of time.  Improve the output of `pchar` accordingly.  When
    reporting properties of a character class, report the flags associated
    with it.  When reporting properties of a character, if it is a member of
    any class, compute its "effective" character flags and report them in
    distinction to its "inherent" character flags if they differ.  Then,
    revert the lazy computation of the effective character flags so that the
    `pchar` request has no visible effect on formatter state; we want this
    property for debugging documents, avoiding Heisenbugs.
    
    * roff/troff/charinfo.h (class charinfo): Declare new `describe_flags()`
      member function returning `void`.
    
    * src/roff/troff/input.cpp (charinfo::describe_flags): Refactor the
      tedious flags-to-English logic from `charinfo::dump_flags()` into this
      new member function, since we might need to perform this translation
      more than once when dumping a character's properties.
    
      (charinfo::describe_flags): Strip out flags-to-English translation as
      above.  For a character per se (not a class), report assigned
      character flags thereto as "inherent".  Then save them, do the lazy
      computation that normally occurs when formatting a character, report
      the combination as the "effective flags" if they differ, and restore
      the saved flags.
    
      (charinfo::dump): Call `dump_flags()` on character classes.
    
    Fixes <https://savannah.gnu.org/bugs/?67711>.  Thanks to Dave Kemper for
    prompting me to better understand this aspect of GNU troff's design.
---
 ChangeLog                 | 39 +++++++++++++++++++++++++++++++++++++++
 src/roff/troff/charinfo.h |  1 +
 src/roff/troff/input.cpp  | 23 ++++++++++++++++++++---
 3 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c486bbdd8..425c1f482 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2025-12-03  G. Branden Robinson <[email protected]>
+
+       [troff]: Describe character (classes) better.  Character classes
+       have one more property beyond their name, and lists of ranges
+       and nested classes: a set of character flags that the formatter
+       bitwise "or"s with any character members of the class
+       {recursively}.  However, the computation of flags applicable to
+       a character has been done lazily almost from the time the
+       character class feature was first implemented, presumably to
+       keep a `cflags` request on a highly populated character class
+       from taking a lot of time.  Improve the output of `pchar`
+       accordingly.  When reporting properties of a character class,
+       report the flags associated with it.  When reporting properties
+       of a character, if it is a member of any class, compute its
+       "effective" character flags and report them in distinction to
+       its "inherent" character flags if they differ.  Then, revert the
+       lazy computation of the effective character flags so that the
+       `pchar` request has no visible effect on formatter state; we
+       want this property for debugging documents, avoiding Heisenbugs.
+
+       * roff/troff/charinfo.h (class charinfo): Declare new
+       `describe_flags()` member function returning `void`.
+       * src/roff/troff/input.cpp (charinfo::describe_flags): Refactor
+       the tedious flags-to-English logic from `charinfo::dump_flags()`
+       into this new member function, since we might need to perform
+       this translation more than once when dumping a character's
+       properties.
+       (charinfo::describe_flags): Strip out flags-to-English
+       translation as above.  For a character per se (not a class),
+       report assigned character flags thereto as "inherent".  Then
+       save them, do the lazy computation that normally occurs when
+       formatting a character, report the combination as the "effective
+       flags" if they differ, and restore the saved flags.
+       (charinfo::dump): Call `dump_flags()` on character classes.
+
+       Fixes <https://savannah.gnu.org/bugs/?67711>.  Thanks to Dave
+       Kemper for prompting me to better understand this aspect of GNU
+       troff's design.
+
 2025-12-03  G. Branden Robinson <[email protected]>
 
        [troff]: Refactor.  Bust character flag dumping (a report to the
diff --git a/src/roff/troff/charinfo.h b/src/roff/troff/charinfo.h
index b58480032..c6995a1de 100644
--- a/src/roff/troff/charinfo.h
+++ b/src/roff/troff/charinfo.h
@@ -119,6 +119,7 @@ public:
   bool contains(int, bool = false);
   bool contains(symbol, bool = false);
   bool contains(charinfo *, bool = false);
+  void describe_flags();
   void dump_flags();
   void dump();
 };
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index f972a97b9..bef185ea1 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -10850,15 +10850,15 @@ bool charinfo::contains(charinfo *, bool)
   return false;
 }
 
-void charinfo::dump_flags()
+void charinfo::describe_flags()
 {
-  errprint("  flags: %1 (", flags);
   if (0U == flags)
-    errprint("none)\n");
+    errprint("(none)\n");
   else {
     char none[] = { '\0' };
     char comma[] = { ',', ' ', '\0' };
     char *separator = none;
+    errprint("(");
     if (flags & ENDS_SENTENCE) {
       errprint("%1ends sentence", separator);
       separator = comma;
@@ -10903,6 +10903,22 @@ void charinfo::dump_flags()
   }
 }
 
+void charinfo::dump_flags()
+{
+  errprint("  %1flags: %2 ", (is_class() ? "" : "inherent "), flags);
+  describe_flags();
+  if (!is_class()) {
+    // Report influence of membership in character classes, if any.
+    unsigned int saved_flags = flags;
+    get_flags();
+    if (flags != saved_flags) {
+      errprint("  effective flags: %1 ", flags);
+      describe_flags();
+      flags = saved_flags;
+    }
+  }
+}
+
 void charinfo::dump()
 {
   if (is_class()) {
@@ -10949,6 +10965,7 @@ void charinfo::dump()
     if (!has_nested_classes)
       errprint("(none)");
     errprint("\n");
+    dump_flags();
   }
   else {
     if (translation != 0 /* nullptr */)

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

Reply via email to