RPGLE DOW Loops Explained

Some repetition is naturally check-first: keep reading while more records remain, keep processing while a queue is not empty, keep retrying while a resource stays unavailable. In every one of these cases, the correct behavior on the very first pass depends on a condition that must be checked before any work happens at all — including the possibility that the work should not happen even once. RPGLE’s DOW operation code expresses exactly that kind of repetition: it repeats a controlled group while an expression is true, checking that expression before the body ever runs.12

This tutorial focuses on that single, pre-test form. It assumes you already understand counted DO repetition and keeps the contrast with post-test DOU brief and conceptual, since that timing difference was already introduced when DOU was covered.

Quick Summary

  • Write a pre-test group as dow indicator-expression; ... enddo;.1
  • The expression is evaluated before the body executes, both on entry and again at ENDDO. Repetition continues while the expression is true and stops once it becomes false.1
  • Because the check happens before the body, a DOW group can execute zero times if the expression is already false the first time it is reached.1
  • ENDDO marks the end of the group and is where RPG returns control so the condition can be re-evaluated before another pass.2
  • Use DOW when the business rule is “check first, then work only if the check passes” — not when the work must always happen at least once.
  • The loop can only stop if something the body does changes the outcome of the condition. A condition that never changes and starts true produces an infinite loop.
  • Trace the very first check by hand, especially when the condition might already be false before entry, to confirm zero iterations is the intended outcome.

Reader Prerequisites

You should already be comfortable with counted repetition from RPGLE DO Loops Explained (ARTICLE-068), including the index, limit, body, and ENDDO vocabulary. This tutorial reuses that vocabulary and replaces the numeric range with a condition checked before every pass, including the first.

The wider learning sequence is collected in RPGLE for Beginners: A Practical IBM i Learning Path (ARTICLE-046).

Learning Outcomes

After reading, you should be able to:

  1. State what DOW means and when its condition is evaluated relative to the body.
  2. Explain why a DOW group can execute zero times.
  3. Trace a counter-based DOW loop and a state/sentinel-driven DOW loop, including the boundary where the condition starts false.
  4. Recognize the infinite-loop risk created by a condition whose state the body never updates.
  5. Choose DOW only when “check first, then work only if true” actually matches the business rule.

Why Pre-Test Repetition Exists

Some tasks are naturally check-first: process records while more remain, keep retrying while a connection is still down, keep looping while a balance is positive. For that family, the check is not an afterthought performed once work has already started — it is the gate that decides whether work should start at all. If the gate is already closed the first time the program reaches it, the correct behavior is to do nothing and move on.

DOW matches that check-first shape directly. The body is guarded by an entry test the same way it is guarded on every later pass; RPG asks “is this still true” before it will run the body even once.1 This makes DOW the natural fit for read-and-process loops, availability checks, and any task where “there might be nothing to do” is a normal, expected outcome rather than an edge case.

Educational illustration showing a work item reaching a checkpoint first, then either passing through one processing stage and looping back for another check, or exiting immediately when the condition is not satisfied on the first check.
Pre-Test Repetition: Check First, Process If True

Anatomy of an RPGLE DOW Loop

Here is the smallest complete pre-test example:

dcl-s attemptLimit int(10) inz(5);
dcl-s attemptCount int(10) inz(0);

dow attemptCount < attemptLimit;
  attemptCount += 1;
  dsply ('Attempt ' + %char(attemptCount));
enddo;

The parts have distinct responsibilities:

PartExampleResponsibility
While-conditionattemptCount < attemptLimitIndicator-valued expression evaluated before the body, on every pass including the first
BodyattemptCount += 1; dsply ...Work performed only when the condition is currently true, including the state the condition depends on
Terminatorenddo;Closes the group; RPG returns here so the condition can be re-evaluated before another pass

IBM documents DOW as controlling a group of operations performed only while the expression in the condition is true, with ENDDO as its matching end operation.12 The variable names above and the recommendation to keep the condition’s state visible in the body are teaching and readability guidance, not compiler requirements.

Flow diagram of a pre-test RPGLE DOW group: initialize the state the condition depends on, evaluate the DOW condition before the body -- a false result skips the body entirely and continues after ENDDO, a true result executes the body, updates that state, and returns to re-evaluate the condition.
Pre-test DOW control flow based on IBM-documented DOW and ENDDO semantics; not compiler internals.

How the Loop Progresses

Trace basic-dow-loop.rpgle one state at a time, starting with attemptCount at 0 and attemptLimit at 5:

MomentattemptCountWhat happens
Enter DOW0Check 0 < 5 — true; proceed to the body
First body execution0 → 1Increment, then display “Attempt 1”
Return to DOW check11 < 5 is true; repeat
……Passes 2 through 4 follow the same pattern
Fifth body execution4 → 5Increment, then display “Attempt 5”
Return to DOW check55 < 5 is false; continue after the group

The critical detail is the very first row: RPG checks attemptCount < attemptLimit before the body ever runs, exactly the same way it checks on every later pass. There is no special “first time” exemption — the condition sits at the top of the group, not at ENDDO, so it always governs entry.12 This is conceptual source-level behavior; the diagram and trace do not claim anything about compiler internals or generated machine instructions.

Counter-Based DOW Example

basic-dow-loop.rpgle is the example traced above. It stops as soon as attemptCount reaches attemptLimit, giving exactly five displayed attempts. The pattern — initialize a counter, check before working, do work, advance the counter — looks similar to counted DO, but the stopping question is phrased as a condition rather than a range, and the check controls entry to the work rather than following it.

The Pre-Test Boundary: Zero Iterations

The most important boundary case for DOW is not an off-by-one count; it is what happens when the while-condition is already false before the loop is ever entered. dow-zero-iteration-boundary.rpgle makes this visible:

dcl-s remainingItems int(10) inz(0);
dcl-s iterationsRun int(10) inz(0);

dow remainingItems > 0;
  iterationsRun += 1;
  remainingItems -= 1;
  dsply ('Iteration ' + %char(iterationsRun) + ' remaining ' + %char(remainingItems));
enddo;

dsply ('Total iterations ' + %char(iterationsRun));

remainingItems starts at 0, which already fails remainingItems > 0. A reader who expects a loop to always do something at least once might predict one iteration by habit. The intended, documentation-based result is iterationsRun = 0: the body never runs, because DOW tests the condition before the first pass and finds it already false.1 Confirming this boundary by hand, with a deliberately “nothing to do” starting value, is the fastest way to catch a mistaken assumption carried over from a post-test loop.

State/Sentinel-Driven DOW Example

Not every DOW condition is a simple counter comparison. readable-dow-processing.rpgle models a small connection-retry sequence where the continue-question combines a not-yet-successful flag with a maximum-attempts safeguard, both checked before every attempt:

dow not connectionEstablished and connectionAttemptNumber < maxConnectionAttempts;
  connectionAttemptNumber += 1;
  connectionEstablished = (connectionAttemptNumber = maxConnectionAttempts);

  dsply ('Connection attempt ' + %char(connectionAttemptNumber));
enddo;

With maxConnectionAttempts set to 3, the loop tries at most three times and stops as soon as connectionEstablished turns on. If connectionEstablished had already been *on before the loop started, the loop would run zero times — there would be nothing left to do. This is a common shape for real retry logic — a state flag for “do we still need to try” combined with a count-based safeguard so the loop cannot run forever even if the flag never turns on. Both variables are updated inside the body, and the updated values are what the next DOW check reads before allowing another pass.

All three members in this tutorial are documentation-reviewed; not compiled or run on IBM i in this workspace. Their traced values follow from initialized values and documented DOW/ENDDO behavior, not captured runtime output.

Common Mistakes

Forgetting to update the state the condition depends on. If nothing in the body changes the value(s) the DOW condition reads, and the condition starts true, it can never become false, and the loop repeats forever. This is the single most consequential DOW mistake — always identify which variable(s) the while-condition reads and confirm the body writes to at least one of them on every pass.

Assuming DOW always runs at least once. As dow-zero-iteration-boundary.rpgle shows, the body can execute zero times when the condition is already false on entry. Code that depends on the body running once unconditionally belongs in a post-test structure, not DOW.

Using DOW when a numeric range is already known. If the real stopping rule is “repeat exactly N times,” counted DO states that directly; reaching for a condition to express a known count adds an extra place for the count to drift.

Relying on a single flag with no safeguard. A pure success flag with no maximum-attempts guard can loop forever if success never arrives for a legitimate reason, such as a permanently unreachable resource. Combining a state flag with a bounded count, as in the retry example, keeps the loop safely terminating.

Hiding the condition’s state far from the loop. If the variables read by the DOW condition are updated deep inside a long body, a reader cannot quickly confirm the loop terminates or predict whether the next pass will even happen.

Confusing an attempt count with a success count. connectionAttemptNumber counts tries, not successes. Naming each state variable for exactly what it counts avoids reusing one variable for two different questions.

Readability Guidance

The following are editorial recommendations, not compiler requirements:

  • Name every variable the while-condition reads for what it represents (attemptCount, remainingItems, connectionEstablished) rather than reusing a generic flag across unrelated loops.
  • Keep the statement that updates the condition’s state close to the top or bottom of the body, not buried in unrelated work.
  • When a condition combines a state flag with a safeguard count, write both in one line so a reader sees the full continue-rule at a glance.
  • Comment the intended maximum number of passes when a safeguard count exists, so a future reader knows it is a safety limit, not an arbitrary number.
  • Treat a zero-iteration outcome as a normal, expected result worth a brief trace, not a bug to explain away.

IBM defines what DOW and ENDDO do.12 These naming and layout choices are maintainability guidance from this tutorial.

Choosing the Right Loop Structure

Choose a structure by asking what governs completion and when the check belongs:

QuestionAppropriate direction
“Repeat for these numeric positions”Counted DO — ARTICLE-068
“Run at least once, then stop when a condition becomes true”DOU — ARTICLE-069
“Run only while a condition is true, and skip entirely if it starts false”DOW — this article

DOW differs from DOU in exactly one respect that matters here: DOW tests its condition before the body, so it can skip the body entirely on the first pass. DOU cannot skip the first pass, because its condition lives at ENDDO, after the body.6 Detailed LEAVE, ITER, nested loops, arrays, and file-reading loops remain outside this tutorial’s scope.

FAQ

Does a DOW loop check its condition before the first pass, or can it run zero times?

Yes to both. The condition is evaluated before the body on every pass, including the first, so the body can execute zero times if the condition is already false when the loop is reached.1

What happens if the condition’s state never changes and starts true?

The condition never becomes false, and the loop repeats indefinitely. Confirm that some statement in the body writes to every variable the while-condition reads.

Is DOW the right choice for reading records until end of file?

Often yes, if “check for more records, then read only if some remain” matches your actual sequence. Verify the intended timing before choosing DOW over a post-test structure, since some read patterns are naturally do-first instead.

Can the while-condition combine more than one thing, like a flag and a count?

Yes. readable-dow-processing.rpgle combines a not-yet-successful flag with a maximum-attempts count using and, which is ordinary indicator-expression logic, not a special DOW feature.1

Were these examples tested on IBM i?

No. They are documentation-reviewed against IBM i 7.5 and 7.4 references, but were not compiled or run on IBM i in this workspace.

Key Takeaways

  • A pre-test RPGLE DOW group repeats a body while an expression is true, checked before the body runs, both on entry and again at ENDDO.12
  • The body can execute zero times if the condition is already false the first time it is reached.
  • The loop can only terminate if the body updates the state the condition depends on.
  • Combine a state flag with a bounded safeguard count when “success” alone might never arrive.
  • Choose DO for known numeric ranges and DOU when the work must always happen at least once before any check.
  • Treat descriptive naming, visible state updates, and hand-tracing as editorial guidance rather than IBM compiler requirements.

Continue Your Learning

  1. Pillar: RPGLE for Beginners: A Practical IBM i Learning Path (ARTICLE-046)
  2. Prerequisite: RPGLE DO Loops Explained (ARTICLE-068)
  3. Related: RPGLE DOU Loops Explained (ARTICLE-069)
  4. Current: RPGLE DOW Loops Explained (ARTICLE-070)
  5. Recommended next: RPGLE LEAVE, ITER, and Loop Control (ARTICLE-071)

ARTICLE-071 and ARTICLE-072 are named from the canonical registry but remain unlinked until publishable repository routes exist.

IBM Evidence Used

The IBM i 7.5 DOW reference is the primary source for pre-test timing, the zero-iteration possibility, and condition evaluation before the body.1 The matching ENDDO reference supports how the group closes and returns control for re-evaluation.2 IBM’s structured-programming overview supplies the broader grouping context shared with counted DO and DOU.3

The IBM i 7.4 DOW and ENDDO topics were cross-checked for the same operation model.45 No publication date is assigned to any IBM Docs page. Recommendations about naming, state-update discipline, safeguard counts, and hand-tracing are editorial guidance; they are not represented as IBM compiler rules.

References


  1. IBM, DOW (Do While), IBM i 7.5, accessed 2026-09-13. ↩↩↩↩↩↩↩↩↩↩↩↩↩

  2. IBM, ENDDO (End Do), IBM i 7.5, accessed 2026-09-13. ↩↩↩↩↩↩↩

  3. IBM, Structured Programming Operations, IBM i 7.5, accessed 2026-09-13. ↩

  4. IBM, DOW (Do While), IBM i 7.4, accessed 2026-09-13. ↩

  5. IBM, ENDDO (End Do), IBM i 7.4, accessed 2026-09-13. ↩

  6. IBM, DOU (Do Until), IBM i 7.5, accessed 2026-09-13. ↩

References

  1. DOW (Do While) — IBM
  2. ENDDO (End Do) — IBM
  3. DOU (Do Until) — IBM
  4. Structured Programming Operations — IBM
  5. DOW (Do While) — IBM
  6. ENDDO (End Do) — IBM



Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top