bugGNU roff - Bugs: bug #45502, [troff] .if, .ie, .el parsing...

 
 

bug #45502: [troff] .if, .ie, .el parsing incompatible with Unix V7, DWB, and Heirloom Doctools troff

Submitter:  Carsten Kunze <carstenkunze>
Submitted:  Thu 09 Jul 2015 03:26:27 PM UTC
   
 
Category:  Core Severity:  3 - Normal
Item Group:  Incorrect behaviour Status:  Fixed
Privacy:  Public Assigned to:  gbranden
Open/Closed:  Closed Planned Release:  1.24.0
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Sat 13 Apr 2024 09:56:12 PM UTC, comment #19: 


commit 1381d6a3471b88ec3d2a8aa601836531e0b3a9eb
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
Date:   Fri Apr 5 09:17:14 2024 -0500

    src/roff/troff/input.cpp: Fix Savannah #45502.

    * src/roff/troff/input.cpp (skip_branch): Handle control flow branches
      consisting only of a newline correctly when skipping them--actually
      skip them, as AT&T troff does.  A newline after the `el` request, or
      after the conditional expression of an `if`, `ie`, or `while` request,
      is not "nothing"; if the branch is taken, it puts a newline on the
      output, and if it is not taken, it should neither affect output nor be
      _syntactically_ ignored on the pretense that the next input line was
      actually part of the branch.

    Fixes <https://savannah.gnu.org/bugs/?45502>.  Problem likely goes back
    to groff's origin.  (You could always avoid it with brace escape
    sequences, which might explain why it seemed to cause little
    consternation.)  Thanks to Carsten Kunze for the report and to Dave
    Kemper for the code review.

commit ac042bfcd0eabe586790f4d424091466cf426768
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
Date:   Thu Apr 4 23:54:17 2024 -0500

    [troff]: Regression-test Savannah #45502.

    Test fails at this commit.


G. Branden Robinson <gbranden>
Group administrator
Sun 07 Apr 2024 07:10:01 AM UTC, comment #18: 

comment #17:

> comment #16:
> > Sometimes I don't evaluate the truth value of a proposition
> > until I've inspected the machine that interprets it.  😅
>
> "Trust, but verify," as they say (though the second step seems to render the first moot).


You won't get far in a quest for cogent reasoning from the ultimate source of that quite... ;-)


> > Any spaces between the condition and the beginning of anything are skipped over.


> >
> > Without too much of a head tilt, I can interpret this as
> > implying that such spaces can be omitted in the first place.
>
> I have no trouble reading that as saying the spaces are optional.  I have more trouble reading it as the branch also being optional.


The branch is only optional in the sense that it is interpreted contingently upon the truth value of the conditional expression before it, or, in the case of `el`, the inversion of the truth value of the conditional expression in the counterpart `ie` request.

In this aspect, however, *roff is well within common programming language practice.

An important insight might be that the human reader of *roff has to remember to stop and interpret the conditional expression immediately once it is complete.  Remember that even spaces are not allowed inside a conditional expression, except, in GNU troff within parentheses.  As soon as that expression's truth can be decided, you must do so immediately.  Do not pass go.  Do not collect a space or newline for pleasant, spread-out readability.

(Where *roff is unusual with control flow handling is that you can "defer" the "else" branch of an "if-else" structure, and "spring" it long after many other unconditional operations). 

> I concede that you're more creative at abusing the parser than I am.


My hand was forced by the demands of composing documentation.


> > I think GNU troff's historical behavior
> > here is an ugly and unintended syntactical extension.
>
> I'd argue that at this stage, intention is largely irrelevant.  Groff has a 30-year history of working one way, and AT&T troff a 50-year one of working a different way.  Now it's a question of which set of users' historical use of this mostly undocumented feature you want to break.


I think few groff documents are likely to trip over this.

1.  If you want


super\c
.if 1
tanker


...then GNU troff has offered `nop` since groff 1.17.

2.  If you want


super\c
.if \n[want-split-compund-nouns]
tanker


...then you probably wrote a comment explaining your cleverness, and it would then work the same way as AT&T troff.

3.  If you want


super\c
.ie \n[want-hyphenated-compund-nouns] -\c
.el
tanker


...then you didn't notice an issue or a discrepancy between AT&T and GNU _roff_s, because here, the newline isn't silently discarded.

That is one reason I am so confident that GNU troff's behavior here is unintended, and a bug.  It should have pushed the newline terminating the conditional expression back onto the input stream, and it didn't.


> > He simply didn't write enough test cases for his formatter, saith I.
>
> What is the sound of no jaws hitting the floor?


Lost in the din of applause from brachial single amputees...

> > I think matching AT&T troff behavior here produces a more consistent grammar.
>
> I'm not sure you've made this case, but I'll take it on faith, you having examined the grammar in far more depth than I.
>
> > Yes, it will be less comfortable for people who read all
> > languages in the expectation that they are C.
>
> C cares very little where newlines occur, while anyone who's spent more than five minutes writing roff code knows that it's on the opposite end of that spectrum.  So visitors from the C-side will pretty quickly toss out their C ideas of a line of code.  Thus I don't think that's actually a problem for this issue.


I'm glad to hear it, because that means it should not constitute a site of resistance to my proposed bug fix.

> (The more insidious case of bug #59434 issue will give C coders far more ulcers.)


That, I submit, is a matter of the warning diagnostic promising more than it could deliver.

> > The branch portion of a control flow request in *roff is read
> > as if it were on an input line by itself.
>
> A phrase which is not always true; it's at the heart of the bug #59434 complaint, and in one of the emails linked from there (http://lists.gnu.org/r/groff/2020-09/msg00001.html), Tadziu proposed an amendment to make it truer.


I keep striving to get you to decouple your notion of how the formatter decides which branch of a conditional it will interpret from your notion of how the conditionals are nested for the purpose of the "unbalanced 'el' request" diagnostic.  Why?

*Because the formatter itself handles these separately.*

G. Branden Robinson <gbranden>
Group administrator
Sun 07 Apr 2024 05:51:07 AM UTC, comment #17: 

comment #16:

> Sometimes I don't evaluate the truth value of a proposition
> until I've inspected the machine that interprets it.  😅


"Trust, but verify," as they say (though the second step seems to render the first moot).

> You are using "predicate" in the sentential sense; I am
> using it in the (formally) logical sense.


Right, sorry for the ambiguity.


> Any spaces between the condition and the beginning of anything are skipped over.


>
> Without too much of a head tilt, I can interpret this as
> implying that such spaces can be omitted in the first place.


I have no trouble reading that as saying the spaces are optional.  I have more trouble reading it as the branch also being optional.

But, as this thread has covered, that did work in Ye Troffe Of Olde, and as you note, there might even have been a use for it:

> There are indeed more straightforward ways to skin that
> particular cat.  But the foregoing is not insane as I read
> CSTR #54.


I concede that you're more creative at abusing the parser than I am.  (I also never noticed the similar "supertanker" example in the manual until you pointed it out.)

> I think GNU troff's historical behavior
> here is an ugly and unintended syntactical extension.


I'd argue that at this stage, intention is largely irrelevant.  Groff has a 30-year history of working one way, and AT&T troff a 50-year one of working a different way.  Now it's a question of which set of users' historical use of this mostly undocumented feature you want to break.

> He simply didn't write enough test cases for his formatter, saith I.


What is the sound of no jaws hitting the floor?

> I think matching AT&T troff behavior here produces a more consistent grammar.


I'm not sure you've made this case, but I'll take it on faith, you having examined the grammar in far more depth than I.

> Yes, it will be less comfortable for people who read all
> languages in the expectation that they are C.


C cares very little where newlines occur, while anyone who's spent more than five minutes writing roff code knows that it's on the opposite end of that spectrum.  So visitors from the C-side will pretty quickly toss out their C ideas of a line of code.  Thus I don't think that's actually a problem for this issue.  (The more insidious case of bug #59434 issue will give C coders far more ulcers.)

> The branch portion of a control flow request in *roff is read
> as if it were on an input line by itself.


A phrase which is not always true; it's at the heart of the bug #59434 complaint, and in one of the emails linked from there (http://lists.gnu.org/r/groff/2020-09/msg00001.html), Tadziu proposed an amendment to make it truer.

Dave <barx>
Group Member
Fri 05 Apr 2024 11:24:17 PM UTC, comment #16: 

comment #15:

> comment #12:
> > Wow, it's actually GNU troff that aggressively reads through
> > the newline.
>
> That was Carsten's original complaint.


Sometimes I don't evaluate the truth value of a proposition until I've inspected the machine that interprets it.  😅

> I reiterate my question of comment #2: "Does strictly enforcing the V7 Unix troff syntax offer any compatibility benefit?  That is, are there correctly formed historical constructions that would be parsed incorrectly under groff as a result of this change?"


We obviously have several models thereof in this ticket's history.

Whether/how those correspond to *roff documents written in anger in the past 50 years, I'm sorry I cannot say.
 

> I realize this would be parsed differently:
>
> .if 0
> A
>
> But you have to squint pretty hard to see this as a "correctly formed historical construction": although AT&T troff allowed an empty .if predicate,


There is a terminological hazard here.  You are using "predicate" in the sentential sense; I am using it in the (formally) logical sense.

What is empty in your example above, in the terminology I am employing, is the "branch".  And, strictly, even that is not empty under AT&T troff grammar as implemented.  The branch, which is never taken due to the false predicate, is a bare newline.

But, yes, the interpretation of the above differs between AT&T and GNU _troff_s to date.

> CSTR#54 section 16 does not specify this as legal syntax,


It does say:


Any spaces between the condition and the beginning of anything are skipped over.


Without too much of a head tilt, I can interpret this as implying that such spaces can be omitted in the first place.  The traditional parsing then shakes out.

> and it has no practical application.


I disagree here too.  It's possible someone might want to conditionally apply a word break.


.nr AP 1 \" use AP Style Guide recommendations
.\" ...
Be sure to check your voice\c
.if \n(AP
mail.


There are indeed more straightforward ways to skin that particular cat.  But the foregoing is not insane as I read CSTR #54.
 

> If this ever appears in any code intended for AT&T troff, it's probably the result of a coder who began writing a conditional then got distracted by a squirrel.


Probably.  I think in practice what GNU troff users have likely done is add brace escape sequences until (1) they got the desired output and (2) the formatter quit mewling at them with "unbalanced `el` request" diagnostics.

> In the GNU age, on the other hand, coders might have written the above deliberately, noticing that it worked despite not being strictly documented.  And it's worked for at least two decades, and possibly all the way back to the Clarkian era.
>
> So it seems to me this proposal breaks back GNU compatibility to achieve fealty to an AT&T construction that offered no real-world application.  Might a better solution be to document the difference as a GNU syntactical extension?


Now that I've gone through the logic and measured the behavior of multiple implementations, I think GNU troff's historical behavior here is an ugly and unintended syntactical extension.

I would point you to the following source comment from Clark.

https://git.savannah.gnu.org/cgit/groff.git/tree/troff/input.c?h=1.02#n3746

Since he intended to admit the input


#if 0\{


(observe the absence of a trailing backslash escaping the newline)

I find it implausible that he didn't mean to handle the same input without the brace escape sequence.

He simply didn't write enough test cases for his formatter, saith I.

I think matching AT&T troff behavior here produces a more consistent grammar.  Yes, it will be less comfortable for people who read all languages in the expectation that they are C.

The branch portion of a control flow request in *roff is read as if it were on an input line by itself.

G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 04:48:00 PM UTC, comment #15: 

comment #12:

> Wow, it's actually GNU troff that aggressively reads through
> the newline.


That was Carsten's original complaint.

comment #14:

> That last version of the exhibit is now the basis of the
> regression test, which passes (along with our other 202 tests)
> with this simple patch.


I reiterate my question of comment #2: "Does strictly enforcing the V7 Unix troff syntax offer any compatibility benefit?  That is, are there correctly formed historical constructions that would be parsed incorrectly under groff as a result of this change?"

I realize this would be parsed differently:

.if 0
A

But you have to squint pretty hard to see this as a "correctly formed historical construction": although AT&T troff allowed an empty .if predicate, CSTR#54 section 16 does not specify this as legal syntax, and it has no practical application.  If this ever appears in any code intended for AT&T troff, it's probably the result of a coder who began writing a conditional then got distracted by a squirrel.

In the GNU age, on the other hand, coders might have written the above deliberately, noticing that it worked despite not being strictly documented.  And it's worked for at least two decades, and possibly all the way back to the Clarkian era.

So it seems to me this proposal breaks back GNU compatibility to achieve fealty to an AT&T construction that offered no real-world application.  Might a better solution be to document the difference as a GNU syntactical extension?

Dave <barx>
Group Member
Fri 05 Apr 2024 02:27:41 PM UTC, comment #14: 

That last version of the exhibit is now the basis of the regression test, which passes (along with our other 202 tests) with this simple patch.  I discarded most of what is shown in comment #6.


diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index cac51d1a6..5c53217fc 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -5880,6 +5880,10 @@ static void troff_request()

 static void skip_branch()
 {
+  if (tok.is_newline()) {
+    tok.next();
+    return;
+  }
   int level = 0;
   // ensure that ".if 0\{" works as expected
   if (tok.is_left_brace())


G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 01:59:05 PM UTC, comment #13: 

I have a better exhibit.


$ cat EXPERIMENTS/truncated-if4.roff
.nm 1
@
.if 0
A
.if !0
B
.ie 0
C
.el
D
E
.pl \n(nlu
$ cd ~/heirloom/
$ ./bin/nroff truncated-if4.roff
  1 @ A

  2 B C

  3 D E
$ cd ~/dwb
$ DWBHOME=. ./bin/nroff truncated-if4.roff
  1 @ A

  2 B C

  3 D E
$ ~/groff-stable/bin/nroff EXPERIMENTS/truncated-if4.roff
  1 @

  2 B

  3 D E


G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 12:52:31 PM UTC, comment #12: 

Wow, it's actually GNU troff that aggressively reads through the newline.  I wasn't expecting that.


$ cat EXPERIMENTS/truncated-if4.roff
.if 0
A
.if !0
B
.ie 0
C
.el
D
.pl \n(nlu
$ ~/groff-stable/bin/nroff EXPERIMENTS/truncated-if4.roff

B

D
$ cd ~/heirloom/
$ ./bin/nroff truncated-if4.roff
A

B C

D
$ DWBHOME=. ./bin/nroff truncated-if4.roff
A

B C

D


So as the groff mailing list's own version of Colonel "Bat" Guano would say, GNU troff is behaving here like some kind of "deviated prevert" [sic].

I reckon we can make it boring and conventional without much effort.

G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 12:34:57 PM UTC, comment #11: 

comment #7:

> comment #6:
> >    If an `el` request or the
> >    conditional expression of an `if` or `ie` request is followed
> >    immediately by a newline, then (A) if in AT&T compatibility
> >    mode, ignore the newline character as AT&T troff did
>
> This description doesn't seem to match AT&T behavior.  "Ignore the newline character" implies, to me, that AT&T troff processed
>
> .if 1
> .tm true
>
> as if it were written
>
> .if 1 .tm true
>
> But in fact AT&T troff processes it as if it were
>
> .if 1 .do-nothing
> .tm true
>
> So AT&T troff is in essence ignoring the .if request...which is what's written next in the commit message, for NON-compatibility mode:
>
> >    (B) otherwise, emit a warning in
> >    category `el` and ignore the request.
>
> Are these descriptions backwards, or is my understanding?


I'm not sure.  I don't think this is baked yet.  I need to check two more things.

1.  What happens if these conditionals have false predicates?  I'm only doing that in one place ("startlingly"), but it's not startling if the request turns into a no-op.  And if that's the case then I may not need to do things different for compatibility mode after all, but just fix an ancient groff bug.

2.  Is a newline immediately after the conditional really ignored by AT&T troff, or does it put a break on the output same as any other newline?  If the latter, does that depend on whether the predicate is true?

So, no, I don't have it.  Not yet.  But I'm on the scent.

G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 12:31:07 PM UTC, comment #10: 


comment #9:

> That was a stale comment.  I had included checks `|| tok.is_eof()` while developing this, but backed them out.  Will fix.  (If I don't end up putting the checks back in light of comment #8.)


I meant comment #7.

G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 12:30:26 PM UTC, comment #9: 

comment #8:

> comment #6:
> >   GNU troff treats a newline and EOF equivalently in this case.
>
> Also I don't get how that's possible.  GNU troff treats a newline at the end of an .if condition as an implied join with the following line.  If EOF instead of newline appears here, there's no following line to join.


That was a stale comment.  I had included checks `|| tok.is_eof()` while developing this, but backed them out.  Will fix.  (If I don't end up putting the checks back in light of comment #8.)

G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 08:13:42 AM UTC, comment #8: 

comment #6:

>   GNU troff treats a newline and EOF equivalently in this case.


Also I don't get how that's possible.  GNU troff treats a newline at the end of an .if condition as an implied join with the following line.  If EOF instead of newline appears here, there's no following line to join.

Dave <barx>
Group Member
Fri 05 Apr 2024 07:51:48 AM UTC, comment #7: 

comment #6:

>    If an `el` request or the
>    conditional expression of an `if` or `ie` request is followed
>    immediately by a newline, then (A) if in AT&T compatibility
>    mode, ignore the newline character as AT&T troff did


This description doesn't seem to match AT&T behavior.  "Ignore the newline character" implies, to me, that AT&T troff processed

.if 1
.tm true

as if it were written

.if 1 .tm true

But in fact AT&T troff processes it as if it were

.if 1 .do-nothing
.tm true

So AT&T troff is in essence ignoring the .if request...which is what's written next in the commit message, for NON-compatibility mode:

>    (B) otherwise, emit a warning in
>    category `el` and ignore the request.


Are these descriptions backwards, or is my understanding?

Dave <barx>
Group Member
Fri 05 Apr 2024 05:20:28 AM UTC, comment #6: 

I think I have it.


$ git log --patch src/roff
commit 06c4b5704193d4a3afc03132eb552c897f0ae029 (HEAD -> master)
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
Date:   Thu Apr 4 23:51:56 2024 -0500

    [troff]: Fix Savannah #45502.

    * src/roff/troff/input.cpp: Alter handling of degenerate or ambiguous
      control flow requests.

      (skip_alternative, begin_alternative): If an `el` request or the
      conditional expression of an `if` or `ie` request is followed
      immediately by a newline, then (A) if in AT&T compatibility mode,
      ignore the newline character as AT&T troff did (but issue an error
      message regarding the ambiguity); (B) otherwise, emit a warning in
      category `el` and ignore the _request_.

    Fixes <https://savannah.gnu.org/bugs/?45502>.  Thanks to Carsten Kunze
    for the report.

    GNU troff treats a newline and EOF equivalently in this case.  This
    detail is not specified by CSTR #54.

    "Any spaces between the condition and the beginning of anything are
    skipped over."

    DWB 3.3 and Heirloom Doctools troff handle EOF here differently from GNU
    troff and from each other.

    ANNOUNCE: Acknowledge Carsten.

diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 2d5dc4980..30db343b9 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -5880,6 +5880,17 @@ static void troff_request()

 static void skip_alternative()
 {
+  if (tok.is_newline()) {
+    if (compatible_flag) {
+      error("ambiguous branch in control flow; rewrite to append"
+           " control or text line, or end line with escape character");
+      return;
+    }
+    else {
+      warning(WARN_EL, "ignoring empty branch in control flow");
+      tok.next();
+    }
+  }
   int level = 0;
   // ensure that ".if 0\{" works as expected
   if (tok.is_left_brace())
@@ -5922,6 +5933,17 @@ static void skip_alternative()

 static void begin_alternative()
 {
+  if (tok.is_newline()) {
+    if (compatible_flag) {
+      error("ambiguous branch in control flow; rewrite to append"
+           " control or text line, or end line with escape character");
+      tok.next();
+    }
+    else {
+      warning(WARN_EL, "ignoring empty branch in control flow");
+      return;
+    }
+  }
   while (tok.is_space() || tok.is_left_brace())
     tok.next();
 }
diff --git a/src/roff/troff/troff.1.man b/src/roff/troff/troff.1.man
index 3d81f980c..f0d36f1ea 100644
--- a/src/roff/troff/troff.1.man
+++ b/src/roff/troff/troff.1.man
@@ -606,11 +606,19 @@ .SH Warnings
 .
 .TP
 .BR el "\t16"
-The
+An
 .B el
 request was encountered with no prior corresponding
 .B ie
-request.
+request;
+or an
+.B el
+request or the conditional expression of an
+.B if
+of
+.B ie
+request was followed immediately by a newline,
+making the control flow ambiguous.
 .
 .
 .TP

commit 5d5834a8dfefe363805617f4e5e1e18626058b83
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
Date:   Thu Apr 4 23:54:17 2024 -0500

    [troff]: Regression-test Savannah #45502.

    Test fails at this commit.

diff --git a/src/roff/groff/groff.am b/src/roff/groff/groff.am
index 5c7ed2f3b..0ce7601eb 100644
--- a/src/roff/groff/groff.am
+++ b/src/roff/groff/groff.am
@@ -42,6 +42,7 @@ groff_TESTS = \
   src/roff/groff/tests/backslash-exclamation-early-does-not-fail.sh \
   src/roff/groff/tests/break_zero-length_output_line_sanely.sh \
   src/roff/groff/tests/cf-request-early-does-not-fail.sh \
+  src/roff/groff/tests/degenerate-control-flow-works.sh \
   src/roff/groff/tests/detect-evil-link-time-optimizer.sh \
   src/roff/groff/tests/device-request-works.sh \
   src/roff/groff/tests/device_control_escapes_express_basic_latin.sh \
diff --git a/src/roff/groff/tests/degenerate-control-flow-works.sh b/src/roff/groff/tests/degenerate-control-flow-works.sh
new file mode 100755
index 000000000..8eb0881e2
--- /dev/null
+++ b/src/roff/groff/tests/degenerate-control-flow-works.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is part of groff.
+#
+# groff is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# groff is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+groff="${abs_top_builddir:-.}/test-groff"
+
+fail=
+
+wail () {
+  echo ...FAILED >&2
+  fail=YES
+}
+
+input='.if 1
+.tm true
+.if !0
+.tm also true
+.ie 0
+.tm startlingly, but AT&T compatibly, true
+.el
+.tm unsurprisingly false'
+
+output=$(echo "$input" | "$groff" -W el -T ascii 2>&1)
+echo "$output"
+
+echo "checking GNU troff truncated control flow request semantics" >&2
+echo "$output" | sed -n 1p | grep -qx 'true' || wail
+echo "$output" | sed -n 2p | grep -q 'also true' || wail
+echo "$output" | sed -n 3p | grep -q 'unsurprisingly' || wail
+! echo "$output" | grep -q 'startlingly' || wail
+
+output=$(echo "$input" | "$groff" -CE -T ascii 2>&1)
+echo "$output"
+
+echo "checking AT&T troff truncated control flow request semantics" >&2
+echo "$output" | sed -n 1p | grep -qx 'true' || wail
+echo "$output" | sed -n 2p | grep -q 'also true' || wail
+echo "$output" | sed -n 3p | grep -q 'startlingly' || wail
+echo "$output" | sed -n 4p | grep -q 'unsurprisingly' || wail
+
+test -z "$fail"
+
+# vim:set autoindent expandtab shiftwidth=2 tabstop=2 textwidth=72:


G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 02:54:17 AM UTC, comment #5: 

Taking a stab at this.

It does not appear that anyone relies on the silent discard of a newline immediately after the conditional expression.

I'm inclined to honor but error about it in compatibility mode (following the "\s36" precedent), and error and ignore otherwise (and document this parsing difference, of course).

G. Branden Robinson <gbranden>
Group administrator
Fri 05 Apr 2024 01:53:07 AM UTC, comment #4: 

Input:


$ cat truncated-if.roff
.if 1
.tm true
.if !0
.tm also true
.ie 0
.tm startlingly true
.el
.tm unsurprisingly false
.pl \n(nlu


Output (Unix V7 nroff, DWB 3.3 nroff, Heirloom Doctools nroff):


$ nroff truncated-if.roff

true

also true
startlingly true

unsurprisingly false
$


Output (groff):


$ nroff EXPERIMENTS/truncated-if.roff
true
also true
unsurprisingly false



$


G. Branden Robinson <gbranden>
Group administrator
Wed 12 May 2021 08:16:03 PM UTC, comment #3: 

FWIW, when this was brought up on the email list at the time (http://lists.gnu.org/archive/html/groff/2015-07/msg00012.html) it elicited no responses.

Dave <barx>
Group Member
Tue 11 May 2021 11:40:04 PM UTC, comment #2: 

Does strictly enforcing the V7 Unix troff syntax offer any compatibility benefit?  That is, are there correctly formed historical constructions that would be parsed incorrectly under groff as a result of this change?

I ask because changing groff's behavior 30 years on (assuming this behavior dates to groff 1.0) also poses back-compatibility concerns for those authors (perhaps unwittingly) taking advantage of this undocumented syntactical relaxation.

Maybe the right solution is to document this as a GNU extension to traditional troff syntax.  As long as it breaks no valid historical documents, it seems a pretty clear-cut case of DWIM.

Dave <barx>
Group Member
Tue 16 Mar 2021 02:29:47 AM UTC, comment #1: 

Confirmed.

Output from V7 Unix nroff and Heirloom Doctools 191015 troff is as Carsten's example of correct output, with added newlines (maybe Savannah stripped them)?


$ pdp11

PDP-11 simulator V3.8-1
sim> set cpu 11/45
Disabling XQ
sim> set tto 7b
sim> att rl unix_v7_rl.dsk
sim> boot rl
@boot
New Boot, known devices are hp ht rk rl rp tm vt
: rl(0,0)rl2unix
mem = 177856
# Restricted rights: Use, duplication, or disclosure
is subject to restrictions stated in your contract with
Western Electric Company, Inc.
Thu Sep 22 05:50:28 EDT 1988

login: dmr
$ cat > carsten.roff
.pl 5
.de A
. ie \\$1
. tm \\$1: true
. el
. tm \\$1: false
..
.A 0
.A 1
$ nroff carsten.roff
0: true

0: false

1: true
1: false



$


G. Branden Robinson <gbranden>
Group administrator
Thu 09 Jul 2015 03:26:27 PM UTC, original submission:  

Specification:  The conditionally processed commands or text need to follow ".if expr", ".ie expr", and ".el" separated by space on the same line (i.e. .ie <expr> <anything>).

Wrong behaviour:  If ".if expr", ".ie expr", or ".el" is followed by nothing on a line the next line is executed conditionally.

This is not compliant with the specified syntax and leads to documents where this wrong syntax is not noticed (since it works).

Example:

.pl 5
.de A
. ie \\$1
. tm \\$1: true
. el
. tm \\$1: false
..
.A 0
.A 1

The output is

0: false
1: true

whereas the expected (stderr) output would be

0: true
0: false
1: true
1: false

Since the .ie and .el statements have a wrong syntax the following line needs to be processed unconditionally.

Additionally a warning could be output for the lines with wrong syntax.

Carsten Kunze <carstenkunze>
Group Member

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by barx (Posted a comment)
  • -email is unavailable- added by gbranden (Posted a comment)
  • -email is unavailable- added by carstenkunze (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2024-04-13 gbranden StatusIn Progress Fixed
        Open/ClosedOpen Closed
        Planned ReleaseNone 1.24.0
    2024-04-05 gbranden StatusConfirmed In Progress
        Assigned toNone gbranden
    2024-04-05 gbranden Summary.if, .ie, .el parsing incompatible with V7 Unix &amp; Heirloom troff [troff] .if, .ie, .el parsing incompatible with Unix V7, DWB, and Heirloom Doctools troff
    2021-05-14 barx CategoryNone Core
    2021-03-16 gbranden StatusNone Confirmed
        Summary.if, .ie, .el syntax issue .if, .ie, .el parsing incompatible with V7 Unix & Heirloom troff

    Back to the top

    Powered by Savane 3.13-d3ae.
    Corresponding source code