[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Warnings of dangling .el with bracket-less nesting
From: |
G. Branden Robinson |
Subject: |
Re: Warnings of dangling .el with bracket-less nesting |
Date: |
Sun, 21 Mar 2021 12:22:39 +1100 |
User-agent: |
NeoMutt/20180716 |
Hi, Tadziu!
At 2021-03-20T17:03:52+0100, Tadziu Hoffmann wrote:
>
> > > in spite of the warnings. Are the warnings a bug?
>
> > It seems so. Would you be willing to file this report
> > as a Savannah ticket?
>
> Do not remove the warnings. They are not a bug.
Thank you for this writeup. It is quite clear and consistent with my
study of the code last fall[1]. (Nevertheless, I didn't completely
understand it, and that, combined with a bias from the older report of
Savannah #45502 I had recently reviewed, led me to fear we had yet
another incompatibility on our hands.)
I'd like to keep #60260 open as a documentation issue and adapt your
explanation into an addition to the Texinfo manual. Is that okay with
you .if/.ie/.el are a matter of recurring confusion.
> Here is how .ie and .el work:
>
> * .ie evaluates its condition "c" and pushes "not(c)" onto a
> stack. Then, if "c" is true, it executes the rest of the
> line, otherwise it simply discards it.
>
> * .el pops a value "z" from the stack. If "z" is true, it
> executes the rest of the line, otherwise it discards it.
Yes; specifically, this stack is called "if_else_stack" in the source.
> Now consider again the code
>
> .de mymac
> .ie '\\$1'a' CASE a
> .el .ie '\\$1'b' CASE b
> .el .ie '\\$1'c' CASE c
> .el CASE z
> ..
>
> and imagine calling this as
>
> .mymac a
>
> Then, step by step, this is what happens:
>
> 1) First line: the condition evaluates to "true", so .ie
> pushes "false" onto the stack. The stack now contains one
> item. "CASE a" is output, since the condition was "true".
>
> 2) Second line: .el pops the previously pushed value "false"
> off the stack. The stack is now empty. Since "false"
> was popped, the rest of the line is discarded.
>
> 3) Third line: .el tries to pop a value off the stack,
> but the stack is empty, therefore a warning is printed.
> Since no "true" was popped, the rest of the line is
> discarded.
>
> 4) Fourth line: .el tries to pop a value off the stack,
> but the stack is still empty, therefore a warning is
> printed. Since no "true" was popped, the rest of the
> line is discarded.
>
> So, superficially it might appear as if the code were doing the
> right thing. But now imagine that .mymac was called as part of
> a larger .ie branch. THEN THOSE TWO .el REQUESTS WILL POP VALUES
> FROM THE STACK THAT MOST PROBABLY WERE NOT INTENDED FOR THEM.
My first attempt to contrive this situation (attached) did not succeed
in provoking such bad behavior, but I think you have a valid point.
> With no warnings to indicate that the logic of .mymac was flawed
> when called in isolation, imagine the frustration of trying to
> debug the behavior of troff in that larger context under the
> (wrong) assumption that .mymac was in fact correct.
I would add that we should add an exhibit of a right way to do what is
desired, since *roff has no C-like "switch" or Lisp-like "cond".
.de My
. tm --- mymac called with '\\$1' ---
. ie '\\$1'a' .tm CASE a
. el \{\
. ie '\\$1'b' .tm CASE b
. el \{\
. ie '\\$1'c' .tm CASE c
. el \{\
. tm Got something else (\\$1)
. \}\}\}
..
.My a
.My b
.My c
.My d
A recursive descent parser for anything but a trivial language in *roff
would be quite a spectacle of nesting, wouldn't it?
Regards,
Branden
avera-mod.roff
Description: Troff document
signature.asc
Description: PGP signature