Beginner

Control Flow in RPG

Learn conditionals, loops, and structured control flow in modern free-form RPG IV - IF/ELSE, SELECT, FOR, DOW, DOU, LEAVE, and ITER

Control flow determines the order in which a program’s statements run - which branches it takes and how many times it repeats a block of work. As a procedural, imperative language, RPG provides a familiar set of structured control-flow constructs: conditionals, multi-way selection, and several kinds of loops.

What makes RPG’s history interesting is that these constructs are relatively recent. The original 1959 language had no IF or DO statements at all - instead, it relied on the program cycle (an implicit read-process-write loop) and numbered indicators to drive branching. Structured programming constructs like IF/ENDIF and DO loops did not arrive until RPG III in 1978. Modern free-form RPG IV gives you clean, readable structured control flow while the old cycle still runs underneath for traditional file processing.

This tutorial uses fully free-form RPG (**FREE). You will learn how to write IF/ELSEIF/ELSE conditionals, multi-way SELECT groups, counted FOR loops, condition-driven DOW and DOU loops, and how to break out of or skip iterations with LEAVE and ITER. Every statement ends in a semicolon, and RPG remains case-insensitive throughout.

Conditionals: IF / ELSEIF / ELSE

The IF construct is the workhorse of RPG branching. It evaluates a condition and runs the matching block, closing with ENDIF. Optional ELSEIF clauses add more conditions, and ELSE handles everything else.

Create a file named control_flow_if.rpgle:

**FREE
dcl-s temp int(10) inz(72);
dcl-s msg varchar(50);

if temp > 80;
  msg = 'It is hot';
elseif temp >= 60;
  msg = 'It is comfortable';
else;
  msg = 'It is cold';
endif;

dsply msg;

*inlr = *on;

Key points:

  • The condition is a boolean expression; temp >= 60 uses the relational operators covered in the operators tutorial.
  • elseif is a single keyword (not else if) and you can chain as many as you need.
  • Every branch closes with a single endif.
  • RPG has no ternary operator (?:). Where other languages would write a conditional expression, RPG uses a full IF block or assigns inside the branches, as shown above.

Multi-Way Selection: SELECT / WHEN / OTHER

When you need to choose among several mutually exclusive cases, SELECT is clearer than a long IF/ELSEIF chain. It is RPG’s equivalent of a switch/case statement. Each WHEN holds a full boolean condition (not just a constant), the first matching WHEN runs, and OTHER is the catch-all. The group closes with ENDSL.

Create a file named control_flow_select.rpgle:

**FREE
dcl-s score int(10) inz(85);
dcl-s grade char(1);
dcl-s msg varchar(50);

select;
  when score >= 90;
    grade = 'A';
  when score >= 80;
    grade = 'B';
  when score >= 70;
    grade = 'C';
  other;
    grade = 'F';
endsl;

msg = 'Grade: ' + grade;
dsply msg;

*inlr = *on;

Key points:

  • Because each WHEN is a full condition, SELECT handles ranges and complex tests, not just equality.
  • Only the first matching WHEN executes - there is no fall-through, so no break is needed.
  • OTHER is optional; if no WHEN matches and there is no OTHER, the group simply does nothing.
  • With score = 85, the score >= 90 test fails and score >= 80 matches first, producing grade B.

Loops: FOR, DOW, and DOU

RPG offers three structured loops, each suited to a different situation.

  • FOR - a counted loop with a start, limit, and optional step (BY / DOWNTO). Use it when you know the iteration count.
  • DOW (Do While) - tests its condition before each pass; the body may run zero times.
  • DOU (Do Until) - tests its condition after each pass; the body always runs at least once.

All three close with ENDFOR (for FOR) or ENDDO (for DOW/DOU).

Create a file named control_flow_loops.rpgle:

**FREE
dcl-s i int(10);
dcl-s count int(10) inz(0);
dcl-s n int(10) inz(10);
dcl-s msg varchar(50);

// Counted FOR loop: 1 to 3
for i = 1 to 3;
  msg = 'FOR iteration ' + %char(i);
  dsply msg;
endfor;

// FOR counting down by 2: 6, 4, 2
for i = 6 downto 2 by 2;
  msg = 'Countdown ' + %char(i);
  dsply msg;
endfor;

// DOW: condition checked BEFORE each pass
dow count < 3;
  count += 1;
  msg = 'DOW count ' + %char(count);
  dsply msg;
enddo;

// DOU: body runs at least once, condition checked AFTER
dou n <= 8;
  n -= 1;
  msg = 'DOU n ' + %char(n);
  dsply msg;
enddo;

*inlr = *on;

Key points:

  • %char(i) converts the integer to its character form so it can be concatenated into the message and displayed.
  • FOR ... DOWNTO ... BY 2 decrements the index by 2 each pass.
  • count += 1 and n -= 1 use the compound-assignment operators from the operators tutorial.
  • The DOW body runs while count < 3 is true; the DOU body runs until n <= 8 becomes true.

Loop Control: LEAVE and ITER

Inside any loop you can change the normal flow with two operations:

  • LEAVE - immediately exits the innermost loop (like break in other languages).
  • ITER - skips the rest of the current pass and starts the next iteration (like continue).

Create a file named control_flow_iter.rpgle:

**FREE
dcl-s i int(10);
dcl-s msg varchar(50);

for i = 1 to 10;
  // Skip even numbers - jump to the next iteration
  if %rem(i:2) = 0;
    iter;
  endif;

  // Stop the loop entirely once we reach 7
  if i = 7;
    leave;
  endif;

  msg = 'Odd value: ' + %char(i);
  dsply msg;
endfor;

*inlr = *on;

Key points:

  • %rem(i:2) returns the remainder of i divided by 2; a result of 0 means i is even.
  • When i is even, ITER skips the dsply and moves to the next value.
  • When i reaches 7, LEAVE ends the loop before anything else runs, so 7, 8, 9, and 10 are never processed.
  • The loop therefore displays only the odd values 1, 3, and 5.

Running on IBM i

RPG requires an IBM i system. There is no open-source RPG compiler for Linux, macOS, or Windows, and no Docker image is available - so these examples cannot be containerized.

If you have access to an IBM i system, compile and run each program with CL (Control Language) commands. For example, to build and call control_flow_if.rpgle:

1
2
CRTBNDRPG PGM(MYLIB/CTLIF) SRCSTMF('/home/user/control_flow_if.rpgle')
CALL PGM(MYLIB/CTLIF)

Repeat with a different program name for each source file (for example CTLSEL, CTLLOOP, CTLITER). To get access to an IBM i for practice, see the options in the Hello World tutorial - the free public PUB400.COM system is a good starting point.

Expected Output

control_flow_if.rpgle (temperature 72 falls in the comfortable range):

It is comfortable

control_flow_select.rpgle (a score of 85 maps to grade B):

Grade: B

control_flow_loops.rpgle (the three loop types in sequence):

FOR iteration 1
FOR iteration 2
FOR iteration 3
Countdown 6
Countdown 4
Countdown 2
DOW count 1
DOW count 2
DOW count 3
DOU n 9
DOU n 8

control_flow_iter.rpgle (even values skipped, loop stops at 7):

Odd value: 1
Odd value: 3
Odd value: 5

On IBM i, each DSPLY shows its message interactively (press Enter to acknowledge) or writes it to the job log in batch mode, prefixed with DSPLY.

Key Concepts

  • IF / ELSEIF / ELSE / ENDIF provide standard structured conditionals; ELSEIF is one keyword and chains freely.
  • RPG has no ternary operator - use a full IF block or assign within branches instead of a conditional expression.
  • SELECT / WHEN / OTHER / ENDSL is RPG’s multi-way switch; each WHEN is a full condition, only the first match runs, and there is no fall-through.
  • FOR is the counted loop, supporting TO, DOWNTO, and a BY step; it replaced the older DO operation in modern free-form RPG.
  • DOW tests before the body (may run zero times); DOU tests after the body (always runs at least once).
  • LEAVE breaks out of the innermost loop and ITER skips to the next iteration.
  • Structured control flow is a later addition to RPG (RPG III, 1978); the original language relied on the implicit program cycle and numbered indicators for branching.
  • Conditions reuse RPG’s relational and logical operators, and statements always end with a semicolon in free-form syntax.

Running Today

All examples can be run using Docker:

docker pull none
Last updated:

Comments

Loading comments...

Leave a Comment

2000 characters remaining