groff
[Top][All Lists]
Advanced

[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

Attachment: avera-mod.roff
Description: Troff document

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]