gbranden pushed a commit to branch master
in repository groff.

commit 0220f00c3c2e4dd2de1a9d63878334ce8872fb45
Author: G. Branden Robinson <[email protected]>
AuthorDate: Wed Mar 18 08:50:16 2026 -0500

    [troff]: Report category in warning diagnostics.
    
    When issuing warning diagnostic messages, report the warning category
    governing its emission.  Idea ripped off from GCC, which has been doing
    similarly for many years.
    
    * src/roff/troff/troff.h (enum warning_category): Add a `WARN_INVALID`
      enumeration constant with value zero, since we're extending the
      signatures of diagnostic functions to pass the warning category as a
      parameter.  Doing so has no meaning for non-warning diagnostics, but
      `do_error()` handles _all_ diagnostic messages, and so it must be
      prepared for this extra data.  This being C++98, we also don't have
      option types.
    
    * src/roff/troff/input.cpp (lookup_warning_by_bitset): New function
      looks up a bitset in the `warning_map` array and returns a pointer to
      a constant string naming the corresponding warning category.
    
      (do_error): Expect new parameter of type `warning_category`.  If the
      diagnostic is of type `WARNING`, look up the new parameter with
      `lookup_warning_by_bitset` and report it in the message to the user.
    
      (debug, warning, output_warning, error, fatal): Update to pass
      `do_error()` either the given warning category, or `WARN_INVALID` if
      the diagnostic is not a warning.
    
    * NEWS: Document this.
---
 ChangeLog                | 28 ++++++++++++++++++++++++++++
 NEWS                     |  4 ++++
 src/roff/troff/input.cpp | 25 ++++++++++++++++++++-----
 src/roff/troff/troff.h   |  3 +++
 4 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b7eb68ce1..f97c94e91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2026-03-18  G. Branden Robinson <[email protected]>
+
+       [troff]: When issuing warning diagnostic messages, report the
+       warning category governing its emission.  Idea ripped off from
+       GCC, which has been doing similarly for many years.
+
+       * src/roff/troff/troff.h (enum warning_category): Add a
+       `WARN_INVALID` enumeration constant with value zero, since we're
+       extending the signatures of diagnostic functions to pass the
+       warning category as a parameter.  Doing so has no meaning for
+       non-warning diagnostics, but `do_error()` handles _all_
+       diagnostic messages, and so it must be prepared for this extra
+       data.  This being C++98, we also don't have option types.
+
+       * src/roff/troff/input.cpp (lookup_warning_by_bitset): New
+       function looks up a bitset in the `warning_map` array and
+       returns a pointer to a constant string naming the corresponding
+       warning category.
+       (do_error): Expect new parameter of type `warning_category`.
+       If the diagnostic is of type `WARNING`, look up the new
+       parameter with `lookup_warning_by_bitset` and report it in the
+       message to the user.
+       (debug, warning, output_warning, error, fatal): Update to pass
+       `do_error()` either the given warning category, or
+       `WARN_INVALID` if the diagnostic is not a warning.
+
+       * NEWS: Document this.
+
 2026-03-18  G. Branden Robinson <[email protected]>
 
        [troff]: Trivially refactor.
diff --git a/NEWS b/NEWS
index 4a29775d7..e9c153903 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,10 @@ troff
    input that is non-idiomatic or likely to produce an unexpected result
    (or none at all), but is not invalid.
 
+*  When issuing warning diagnostic messages, GNU troff now reports the
+   warning category governing its emission.  This change is to make it
+   easier for users to select warnings of interest.
+
 Miscellaneous
 -------------
 
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index e52002251..63ff5b659 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -10636,6 +10636,14 @@ static const struct warning_selection {
   { "default", DEFAULT_WARNING_CATEGORY_SET },
 };
 
+static const char *lookup_warning_by_bitset(unsigned int bitset)
+{
+  for (unsigned int i = 0U; i < countof(warning_map); i++)
+    if (warning_map[i].bitset == bitset)
+      return warning_map[i].name;
+  return 0 /* nullptr */;
+}
+
 static unsigned int lookup_warning_by_name(const char *name)
 {
   for (unsigned int i = 0U; i < countof(warning_map); i++)
@@ -10686,6 +10694,7 @@ static void copy_mode_error(const char *format,
 enum error_type { DEBUG, WARNING, OUTPUT_WARNING, ERROR, FATAL };
 
 static void do_error(error_type type,
+                    warning_category wc,
                     const char *format,
                     const errarg &arg1,
                     const errarg &arg2,
@@ -10750,6 +10759,12 @@ static void do_error(error_type type,
     break;
   }
   errprint(format, arg1, arg2, arg3);
+  if (type == WARNING) {
+      const char *category_name = lookup_warning_by_bitset(wc);
+      assert(category_name != 0 /* nullptr */);
+      if (category_name != 0 /* nullptr */)
+       fprintf(stderr, " [-w %s]", category_name);
+  }
   fputc('\n', stderr);
   fflush(stderr);
   if (type == FATAL)
@@ -10762,7 +10777,7 @@ void debug(const char *format,
           const errarg &arg2,
           const errarg &arg3)
 {
-  do_error(DEBUG, format, arg1, arg2, arg3);
+  do_error(DEBUG, WARN_INVALID, format, arg1, arg2, arg3);
 }
 
 void warning(warning_category wc,
@@ -10772,7 +10787,7 @@ void warning(warning_category wc,
             const errarg &arg3)
 {
   if ((wc & desired_warnings) != 0U)
-    do_error(WARNING, format, arg1, arg2, arg3);
+    do_error(WARNING, wc, format, arg1, arg2, arg3);
 }
 
 void output_warning(warning_category wc,
@@ -10782,7 +10797,7 @@ void output_warning(warning_category wc,
                    const errarg &arg3)
 {
   if ((wc & desired_warnings) != 0U)
-    do_error(OUTPUT_WARNING, format, arg1, arg2, arg3);
+    do_error(OUTPUT_WARNING, wc, format, arg1, arg2, arg3);
 }
 
 void error(const char *format,
@@ -10790,7 +10805,7 @@ void error(const char *format,
           const errarg &arg2,
           const errarg &arg3)
 {
-  do_error(ERROR, format, arg1, arg2, arg3);
+  do_error(ERROR, WARN_INVALID, format, arg1, arg2, arg3);
 }
 
 void fatal(const char *format,
@@ -10798,7 +10813,7 @@ void fatal(const char *format,
           const errarg &arg2,
           const errarg &arg3)
 {
-  do_error(FATAL, format, arg1, arg2, arg3);
+  do_error(FATAL, WARN_INVALID, format, arg1, arg2, arg3);
 }
 
 void fatal_with_file_and_line(const char *filename, int lineno,
diff --git a/src/roff/troff/troff.h b/src/roff/troff/troff.h
index aa52e4b0a..e15f247e1 100644
--- a/src/roff/troff/troff.h
+++ b/src/roff/troff/troff.h
@@ -49,6 +49,9 @@ extern search_path *mac_path;
 #include "error.h"
 
 enum warning_category {
+  // This first item is so that diagnostic functions in "input.cpp" can
+  // have a consistent parameter list.  It feels a little clunky...
+  WARN_INVALID = 0,
   WARN_CHAR = 01,
   //WARN_NUMBER = 02, // withdrawn in groff 1.24
   WARN_BREAK = 04,

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

Reply via email to