groff
provides a looping construct: the while
request.
Its syntax matches the if
request.
.while
cond-expr anything ¶Evaluate the conditional expression cond-expr, and repeatedly
execute anything unless and until cond-expr evaluates false.
anything, which is often a conditional block, is referred to as
the while
request’s body.
.nr a 0 1 .while (\na < 9) \{\ \n+a, .\} \n+a ⇒ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
GNU troff
treats the body of a while
request similarly to
that of a de
request (albeit one not read in copy
mode94), but stores it under an internal name
and deletes it when the loop finishes. The operation of a macro
containing a while
request can slow significantly if the
while
body is large. Each time the macro is executed, the
while
body is parsed and stored again.
.de xxx . nr num 10 . while (\\n[num] > 0) \{\ . \" many lines of code . nr num -1 . \} ..
An often better solution—and one that is more portable, since
AT&T troff
lacked the while
request—is to
instead write a recursive macro. It will be parsed only
once.95
.de yyy . if (\\n[num] > 0) \{\ . \" many lines of code . nr num -1 . yyy . \} .. . .de xxx . nr num 10 . yyy ..
To prevent infinite loops, the default number of available recursion
levels is 1,000 or somewhat less.96 You can
disable this protective measure, or raise the limit, by setting the
slimit
register. See Debugging.
As noted above, if a while
body begins with a conditional block,
its closing brace must end an input line.
.if 1 \{\ . nr a 0 1 . while (\n[a] < 10) \{\ . nop \n+[a] .\}\} error→ unbalanced brace escape sequences
.break
¶Exit a while
loop. Do not confuse this request with a
typographical break or the br
request.
.continue
¶Skip the remainder of a while
loop’s body, immediately starting
the next iteration.