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.