It's much too hard to perform this analysis without the risk of throwing
this warning spuriously.  Paul Eggert reported a real-world use of
`ie`/`el` requests nested without the use of brace escape sequences in
his zic(8) man page that is structurally equivalent to the following
(with indentation added for clarity).

.ie \nA .tm register A is truthy
.el .ie t .tm in typesetter mode
.    el   .tm in terminal mode

Without brace escape sequences, the `skip_branch{}` function that
discards input corresponding to control flow branches not taken does not
reliably keep track of the nesting level.  So why not just make
`skip_branch()` more sophisticated to handle this case?  Because it
doesn't generalize.  What if the input changes the control character, or
uses the no-break control character?  What if the input has renamed the
`ie` request or invokes it through a macro?

* src/roff/troff/input.cpp: Drop this warning category from the
  `warning_table` global.

  (else_request): Stop throwing it.

* src/roff/troff/troff.h: Comment out its value in the `warning_type`
  enum.

Fixes <https://savannah.gnu.org/bugs/?65474>.  Thanks to Paul Eggert for
the report.

NEWS: Add item.
---
 ChangeLog                | 33 +++++++++++++++++++++++++++++++++
 NEWS                     |  8 ++++++++
 src/roff/troff/input.cpp |  5 +----
 src/roff/troff/troff.h   |  2 +-
 4 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2c0291e46..ad424369d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2024-04-05  G. Branden Robinson <g.branden.robin...@gmail.com>
+
+       [troff]: Retire "el" warning category.
+
+       It's much too hard to perform this analysis without the risk of
+       throwing this warning spuriously.  Paul Eggert reported a
+       real-world use of `ie`/`el` requests nested without the use of
+       brace escape sequences in his zic(8) man page that is
+       structurally equivalent to the following (with indentation added
+       for clarity).
+
+       .ie \nA .tm register A is truthy
+       .el .ie t .tm in typesetter mode
+       .    el   .tm in terminal mode
+
+       Without brace escape sequences, the `skip_branch{}` function
+       that discards input corresponding to control flow branches not
+       taken does not reliably keep track of the nesting level.  So why
+       not just make `skip_branch()` more sophisticated to handle this
+       case?  Because it doesn't generalize.  What if the input changes
+       the control character, or uses the no-break control character?
+       What if the input has renamed the `ie` request or invokes it
+       through a macro?
+
+       * src/roff/troff/input.cpp: Drop this warning category from the
+       `warning_table` global.
+       (else_request): Stop throwing it.
+       * src/roff/troff/troff.h: Comment out its value in the
+       `warning_type` enum.
+
+       Fixes <https://savannah.gnu.org/bugs/?65474>.  Thanks to Paul
+       Eggert for the report.
+
 2024-04-05  G. Branden Robinson <g.branden.robin...@gmail.com>
 
        * src/roff/troff/input.cpp (skip_branch): Handle a degenerate
diff --git a/NEWS b/NEWS
index 240cf1414..b941db9b1 100644
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,14 @@ o The `color`, `cp`, `linetabs`, and `vpt` requests now 
interpret
   with a register interpolation as an argument, the outcome agrees with
   an `if` test of the register's value.
 
+o The formatter no longer reports warnings in the "el" category.  There
+  was only one; it threw a warning diagnostic if enabled (which it was
+  not by default) if it inferred an imbalance between `ie` and `el`
+  requests.  Unfortunately it wasn't reliable and sometimes spuriously
+  issued these warnings, and making it perfectly reliable did not look
+  tractable.  We recommend using brace escape sequences `\{` and `\}` to
+  ensure that your control flow structures remain maintainable.
+
 o In nroff mode (in other words, when producing output for devices that
   claim to be terminals), the formatter now reports warning diagnostics
   regarding certain output problems using units of lines instead of
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 5c53217fc..db61117ea 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -6111,10 +6111,8 @@ static void if_request()
 
 static void else_request()
 {
-  if (if_else_stack.empty()) {
-    warning(WARN_EL, "unbalanced 'el' request");
+  if (if_else_stack.empty())
     skip_branch();
-  }
   else {
     bool predicate = if_else_stack.top();
     if_else_stack.pop();
@@ -8927,7 +8925,6 @@ static struct {
   { "range", WARN_RANGE },
   { "break", WARN_BREAK },
   { "delim", WARN_DELIM },
-  { "el", WARN_EL },
   { "scale", WARN_SCALE },
   { "number", WARN_NUMBER },
   { "syntax", WARN_SYNTAX },
diff --git a/src/roff/troff/troff.h b/src/roff/troff/troff.h
index e687464ce..c2f37a034 100644
--- a/src/roff/troff/troff.h
+++ b/src/roff/troff/troff.h
@@ -62,7 +62,7 @@ enum warning_type {
   WARN_NUMBER = 02,
   WARN_BREAK = 04,
   WARN_DELIM = 010,
-  WARN_EL = 020,
+  //WARN_EL = 020,
   WARN_SCALE = 040,
   WARN_RANGE = 0100,
   WARN_SYNTAX = 0200,
-- 
2.30.2

Attachment: signature.asc
Description: PGP signature

Reply via email to