Next: , Previous: , Up: Conditionals and Loops   [Contents][Index]


5.23.4 Conditional Blocks

It is frequently desirable for a control structure to govern more than one request, macro call, text line, or combination of the foregoing. The opening and closing brace escape sequences \{ and \} define such groups. These conditional blocks can furthermore be nested.

Brace escape sequences outside of control structures have no meaning (but can be used as delimiters) and produce no output.254

Escape sequence: \{
Escape sequence: \}

\{ begins a conditional block; it must appear (after optional spaces and tabs) immediately subsequent to the conditional expression of an if, ie, or while request,255 or as the argument to an el request.

\} ends a conditional block and should appear on an input line with other occurrences of itself as necessary to match \{ sequences. It can be preceded by a control character, spaces, and tabs. Input after any quantity of opening brace escape sequences \} on the same line is processed only if all of the preceding conditions to which they correspond are true. Further, a closing brace escape sequence \} closing the body of a while request must be the last such escape sequence on an input line.

Caution: Input lines using \{ often end with \RET, especially in macros that consist primarily of control lines. Forgetting to use \RET on an input line after \{ is a common source of error.

We might write the following in a page header macro. If we delete \RET, the header will carry an unwanted extra empty line (except on page 1).

.if (\\n[%] != 1) \{\
.  ie ((\\n[%] % 2) = 0) .tl \\*[even-numbered-page-title]
.  el                    .tl \\*[odd-numbered-page-title]
.\}

Let us take a closer look at how conditional blocks nest.

A
.if 0 \{ B
C
D
\}E
F
    ⇒ A F
N
.if 1 \{ O
.  if 0 \{ P
Q
R\} S\} T
U
    ⇒ N O U
.ie 1 \{\
.  ds a abc\}def
a="\*a"
.el ghi
    ⇒ a="abcdef"

The above behavior may challenge the intuition; it was implemented to retain compatibility with AT&T troff. A right-brace escape sequence governs flow of control this way: if a branch is not taken, then the closing brace that closes a conditional block causes the formatter to ignore the entire input line on which it appears for all purposes except matching braces.

For clarity, it is idiomatic to end input lines with \{ (followed by \RET if appropriate), and to precede \} on an input line with nothing more than a control character, spaces, tabs, and other instances of itself.

We can use ie, el, and conditional blocks to simulate the multi-way “switch” or “case” control structures of other languages. The following example is adapted from the groff man package. Indentation is used to clarify the logic.

.\" Simulate switch/case in roff.
.      ie '\\$2'1' .ds title General Commands\"
.el \{.ie '\\$2'2' .ds title System Calls\"
.el \{.ie '\\$2'3' .ds title Library Functions\"
.el \{.ie '\\$2'4' .ds title Kernel Interfaces\"
.el \{.ie '\\$2'5' .ds title File Formats\"
.el \{.ie '\\$2'6' .ds title Games\"
.el \{.ie '\\$2'7' .ds title Miscellaneous Information\"
.el \{.ie '\\$2'8' .ds title System Management\"
.el \{.ie '\\$2'9' .ds title Kernel Development\"
.el                .ds title \" empty
.\}\}\}\}\}\}\}\}

Next: , Previous: , Up: Conditionals and Loops   [Contents][Index]