The DO statement gives Easytrieve programs a controlled loop - a way to repeat the same block of logic many times without copying the code. It comes in two forms that look almost identical but behave differently at the edges: DO WHILE and DO UNTIL. Both repeat a group of statements based on a conditional expression, and both must be closed with an END-DO. The crucial difference is when the condition is checked. DO WHILE checks the condition at the top of the loop, before the body runs, which means the body can execute zero times if the condition is already false. DO UNTIL checks the condition at the bottom, after the body has run, which guarantees the body runs at least once. That single distinction decides which form is correct for a given task, and getting it wrong is a classic source of off-by-one bugs. Easytrieve deliberately keeps the loop model simple: there is no counted DO n TIMES form, so counting loops are built by initializing a counter, testing it in the DO condition, and incrementing it inside the body. This tutorial walks through both forms with worked examples, explains the conditional expressions DO accepts, shows how to nest loops, and highlights the infinite-loop pitfalls that trip up beginners. By the end you will know exactly which form to reach for and how to write a loop that always terminates.
123456789{WHILE} DO { } conditional-expression {UNTIL} statement-1 ... statement-n END-DO
You pick either WHILE or UNTIL - the braces in the syntax mean the choice is mandatory. After the keyword comes a conditional expression, the same kind of test you would write on an IF statement. Between the DO line and END-DO you place the statements to repeat, called the loop body. END-DO is required: every DO must have a matching END-DO, and the compiler rejects the program if one is missing.
DO WHILE evaluates the condition before executing the body. If the condition is true, the body runs and control branches back to test the condition again. The loop continues as long as the condition stays true. As soon as the condition is false, control jumps to the first statement after END-DO. Because the test happens first, a DO WHILE whose condition is false at the very start executes its body zero times - the loop is completely skipped. This makes DO WHILE the right choice when it is valid, and sometimes necessary, to do nothing.
123456JOB INPUT PERSNL NAME DO-EX-1 CTR = 0 DO WHILE CTR LT 10 CTR = CTR + 1 ** Logic ** END-DO
Here CTR starts at 0. The condition CTR LT 10 (CTR less than 10) is tested first; while it holds, the body increments CTR and does its work. When CTR reaches 10 the condition is false and the loop ends, so the body runs exactly ten times. Notice the counter is both initialized before the loop and incremented inside it - that is what makes the loop terminate.
DO UNTIL runs the body first, then evaluates the condition. If the condition is false the loop repeats; when the condition becomes true, control passes to the statement after END-DO. Because the body executes before the first test, DO UNTIL always runs at least once - even if the exit condition is already true when the loop is entered. Use DO UNTIL when the work inside must happen at least one time regardless of the starting state.
123456JOB INPUT PERSNL NAME DO-EX-2 CTR = 0 DO UNTIL CTR GE 10 CTR = CTR + 1 ** Logic ** END-DO
This loop increments CTR once, then checks whether CTR is greater than or equal to 10. It keeps going until that test is true, again giving ten passes. The logic looks similar to the WHILE version because both counters run 0 through 10, but the mental model is reversed: WHILE says "keep going while there is more to do", UNTIL says "keep going until the goal is reached".
| Aspect | DO WHILE | DO UNTIL |
|---|---|---|
| When condition is tested | At the top, before the body | At the bottom, after the body |
| Minimum executions | Zero | One |
| Loops while | Condition is TRUE | Condition is FALSE (until it becomes true) |
| Use when | Body may need to be skipped entirely | Body must run at least once |
| Terminator | END-DO | END-DO |
The condition on a DO uses the same relational operators as IF. You compare a field to another field, a literal, or an arithmetic expression using operators such as EQ or =, NE, LT or <, LE or <=, GT or >, and GE or >=. You can combine several tests with AND and OR, and use parentheses to group them. This lets a loop exit on more than one condition at once, such as stopping when a counter overflows or a sentinel value appears.
1234567DO UNTIL (W20-STRIP-COUNT > 30) + OR (W20-OUT-COUNT > 20) IF W20-STRIP-CHAR(W20-STRIP-COUNT) ALPHABETIC W20-OUT-COUNT = W20-OUT-COUNT + 1 END-IF W20-STRIP-COUNT = W20-STRIP-COUNT + 1 END-DO
This loop stops as soon as either counter passes its limit. The plus sign at the end of the first line is the Easytrieve continuation character, letting a long condition span two source lines.
You can put one DO loop inside another. Each loop keeps its own condition and its own END-DO, and the inner loop runs completely for every single pass of the outer loop. Nested loops are the standard way to process grids, tables of tables, or every combination of two ranges.
1234567891011JOB INPUT NULL NAME MYPROG DO WHILE COUNT-1 LT 10 COUNT-1 = COUNT-1 + 1 COUNT-2 = 0 DO WHILE COUNT-2 < 10 COUNT-2 = COUNT-2 + 1 RESULT = COUNT-1 * COUNT-2 DISPLAY 'COUNT-1= ' COUNT-1 ' COUNT-2= ' COUNT-2 + ' RESULT= ' RESULT END-DO END-DO
The outer loop advances COUNT-1 from 1 to 10. For each value the inner loop resets COUNT-2 to 0 and counts it up to 10, printing the product. Resetting COUNT-2 at the top of every outer pass is essential - forget it and the inner loop only runs the first time.
A DO loop only ends when its condition changes. If the body never moves the control variable toward the exit, the condition never flips and the program loops forever, eventually abending on a time limit. Three rules prevent this: initialize the control variable before the loop, test it in the DO condition, and change it inside the body on every path. When a loop has multiple exit conditions, make sure at least one of them is guaranteed to be reached.
Older Easytrieve code sometimes built loops with LABEL and GOTO instead of DO. The DO construct is strongly preferred because the loop boundary is explicit (DO to END-DO), the exit condition is stated up front, and there is no risk of jumping into the middle of a block. Reserve GOTO for special early-exit cases such as GOTO JOB to skip to the next record, and use DO for genuine repetition.
A DO loop is like being told "keep clapping". DO WHILE is the careful teacher who checks first: "Do you still have energy? Yes? Then clap once more" - and if you were already tired you would not clap at all. DO UNTIL is the teacher who says "Clap once, now are we done? No? Clap again" - so you always clap at least one time. END-DO is the teacher saying "okay, stop now". And if the teacher forgets to ever ask if you are done, you would clap forever - that is an infinite loop.
1. What are the two forms of the Easytrieve DO statement?
2. How many times can a DO WHILE loop execute if the condition is false at the start?
3. Why does DO UNTIL always execute its body at least once?
4. What statement terminates a DO loop?
5. What is the most common cause of an infinite DO loop?