5.23.5 while

groff provides a looping construct: the while request. Its syntax matches the if request.

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
Request: .break

Exit a while loop. Do not confuse this request with a typographical break or the br request.

Request: .continue

Skip the remainder of a while loop’s body, immediately starting the next iteration.