No, it isn't valid. What .if and .ie do is read one line, then decide whether it gets processed or skipped, depending on the condition. The real magic is in the \{ sequence, which is the only thing in the Roff language resembling a "multi-line" statement.
Troff, in a manner befitting a text processor, processes its input one line at a time. This is an important thing to wrap your head around, because it demystifies a lot of the syntax's "weirdness". Here's a dummy program to illustrate how \{ … \} get interpreted the same as everything else: once they're reached: .de BREAK ' \} ' ig } .. . .de IF ' if \\$1 \{' .. . .nf .IF 1 { 1. Foo 2. Bar .BREAK 3. Baz 4. Qux .} End Unless you remove the .BREAK line, the output will be: 1. Foo 2. Bar END On Tue, 1 Sep 2020 at 21:37, Tadziu Hoffmann <hoffm...@usm.uni-muenchen.de> wrote: > > > .if COND1 .ie COND2 xxx > > . el yyy > > > If this is considered working as designed, however, the > > documentation ought to mention the restriction. It currently > > implies the opposite, by saying the part after the condition > > in an .if request "is interpreted as though it was on a line > > by itself." Were the .ie in fact on a line by itself, groff > > wouldn't grumble about the .el. > > I think it is working as intended. "ie" pushes the result > of the conditional test onto a stack ("if" does not), to be > popped by a future "el". So if COND1 is true, that stack > contains the test result of COND2, which the "el" can use. > If COND1 is false, the "ie" is never executed, and the stack > remains empty, so "el" complains. > > Note that if there had been another "ie" before your program > fragment, then your "el" would be consuming its result. > So you can create some very interesting code this way. > > > The documentation should say that it "is interpreted as > though it was on a line by itself IF THE CONDITION IS TRUE". > If not, it is never executed (except perhaps macro expansions > that take place while the line is being read). > > > >