RPGLE Control-Flow Opcodes Reference

This page is a lookup for the RPGLE opcodes that decide which statements run and how often: the conditions, the select group, the loops, the loop exits and the monitor group. For each one it gives the free-form syntax, how it behaves, and a short example.

It is not a tutorial. Each section links to the lesson that teaches the topic, and the full list of opcodes by family is in the RPGLE Opcode Reference. File-reading loops use the operations in the RPGLE File I/O Opcodes Reference.

All examples are free-form RPGLE.

Control-flow opcodes at a glance

OpcodeFree-form syntaxUse it to
ifif condition; … endif;Run statements when a condition is true
elseif, elseelseif condition; and else;Add alternative branches to an if
selectselect; or select expression;Start a group of mutually exclusive choices
whenwhen condition;Run one branch of a select group
when-is, when-inwhen-is value;, when-in list;Compare the select expression to a value or a list
otherother;Run when no when was true
dowdow condition; … enddo;Repeat while a condition is true, testing first
doudou condition; … enddo;Repeat until a condition is true, testing last
forfor index = start {by n} to or downto limit;Repeat a counted number of times
for-eachfor-each item in array; … endfor;Visit each item of an array, %list, %split, %subarr or enumeration
leaveleave;Exit the innermost loop
iteriter;Skip to the next pass of the innermost loop
returnreturn {expression};Return to the caller
monitormonitor; … on-error ...; … endmon;Handle run-time errors in a block

A condition is an expression that gives true or false, and it can use and, or and not. end can replace any specific end statement such as endif or enddo, but the specific form is easier to read.

IF, ELSEIF and ELSE

if runs its statements when the condition is true. elseif tests another condition only when the earlier ones were false, and else runs when none was true. Only one branch runs.

dcl-s qty int(10) inz(75);
dcl-s tier char(6);

if qty >= 100;
  tier = 'LARGE';
elseif qty >= 50;
  tier = 'MEDIUM';
else;
  tier = 'SMALL';
endif;

Lesson: RPGLE IF, ELSE and ELSEIF Decisions.

SELECT, WHEN and OTHER

A select group runs the first when whose condition is true, then continues after endsl. If no when is true, the other block runs, if there is one. Without an other block, nothing runs.

dcl-s code char(1) inz('B');
dcl-s label char(10);

select;
  when code = 'A';
    label = 'ACTIVE';
  when code = 'B' or code = 'C';
    label = 'BLOCKED';
  other;
    label = 'UNKNOWN';
endsl;

Give select an expression to compare it with values. when-is tests for equality, and when-in tests membership in a list. The expression is evaluated once, when select starts.

dcl-s role char(10) inz('MANAGER');
dcl-s level int(10);

select role;
  when-is 'OWNER';
    level = 3;
  when-is 'MANAGER';
    level = 2;
  when-in %list('REGULAR' : 'NEW');
    level = 1;
  other;
    level = 0;
endsl;

Lesson: RPGLE SELECT and WHEN Logic.

DOW and DOU

dow tests its condition before each pass, so the body can run zero times. dou tests after each pass, so the body always runs at least once.

dcl-s n int(10) inz(0);

dow n < 3;
  n += 1;
enddo;
dcl-s tries int(10) inz(0);

dou tries >= 3;
  tries += 1;
enddo;

The condition in each case is for staying in the loop (dow) or for leaving it (dou). Whatever the loop tests must change inside the body, or the loop never ends. Lessons: RPGLE DOW Loops and RPGLE DOU Loops.

FOR

for counts. It sets the index to the start value, tests it against the limit, runs the body, then adds the increment, which is 1 unless you give by. to counts up and downto counts down. The by and to clauses can be written in either order.

dcl-s i int(10);
dcl-s total int(10) inz(0);

for i = 1 to 5;
  total += i;                  // 15 at the end
endfor;

for i = 10 downto 0 by 5;
  total += i;                  // 10, 5, then 0
endfor;

Declare the index separately, because for cannot declare it. It must be large enough to hold one more than the limit, since the loop ends when the index passes the limit. The limit is evaluated on every pass, so put an expensive expression in a variable first. Lesson: RPGLE DO Loops.

FOR-EACH

for-each visits every item of an array, a %list, a %split, a %subarr or an enumeration. Each item is assigned to the variable named first, and the group ends with endfor. The variable must have a type compatible with the items, and it cannot be an array.

dcl-s names char(8) dim(3);
dcl-s name char(8);
dcl-s seen int(10) inz(0);

names(1) = 'Ann';
names(2) = 'Bob';
names(3) = 'Cy';

for-each name in names;
  seen += 1;                   // 3 passes
endfor;

Use for instead when you need the index.

LEAVE and ITER

Both act on the innermost loop only. leave jumps to the statement after the loop’s end. iter jumps to the end statement of the loop, so the next pass starts at once. In a for loop, iter still adds the increment, but leave does not.

dcl-s i int(10);
dcl-s sum int(10) inz(0);

for i = 1 to 10;
  if i = 3;
    iter;                      // skip 3
  endif;
  if i = 6;
    leave;                     // stop before 6
  endif;
  sum += i;                    // 1 + 2 + 4 + 5 = 12
endfor;

leave and iter are not allowed outside a loop. Lesson: RPGLE LEAVE, ITER and Loop Control.

RETURN

return ends the current program or procedure and goes back to the caller. In a procedure that returns a value, return gives the value, and the procedure must reach a return before its end, or an exception is signalled to the caller.

dcl-proc doubled;
  dcl-pi *n int(10);
    value int(10) const;
  end-pi;
  return value * 2;
end-proc;

In a cycle-main program, return ends the program normally only when *inlr is on. Otherwise it returns to the caller and keeps its data for the next call.

MONITOR and ON-ERROR

monitor starts a group whose run-time errors are handled by on-error blocks that follow it. The first matching on-error runs, and the program continues after endmon. With no list, on-error handles all program and file errors. You can also name a status code, *program, *file or *all.

dcl-s text varchar(10) inz('Hi');
dcl-s part varchar(10);

monitor;
  part = %subst(text : 1 : 5);
on-error;
  part = '*ERR';
endmon;

Put specific status codes before *all, because only the first matching block is used. Errors inside an on-error block are not handled by that monitor. Lesson: Error Handling in RPG.

Which one to use

SituationUse
One test, one or two outcomesif, with else
Several exclusive conditionsselect with when
One value compared with manyselect with when-is or when-in
Repeat while something is true, possibly neverdow
Repeat at least once, until something is truedou
A known number of passes, or a counterfor
Every item of an array or listfor-each
Stop a loop earlyleave
Skip the rest of one passiter
Recover from a run-time errormonitor and on-error

Common mistakes

  • Using dow when the body must run once, or dou when it must be able to run zero times.
  • A loop whose condition never changes, so it never ends.
  • Expecting leave to exit all nested loops. It exits one level.
  • A for index that is too small to hold the limit plus one.
  • Several when conditions that overlap, where only the first one runs.
  • Putting *all before a specific status code in a monitor group.

FAQ

What is the difference between DOW and DOU?

dow checks the condition first and may not run at all. dou checks it at the end, so the body runs at least once.

Does SELECT run every true WHEN?

No. It runs the first true when and then continues after endsl.

Is there a FOR EACH loop in RPGLE?

Yes. for-each item in array; visits each item of an array, %list, %split, %subarr or enumeration, as shown above. Use for when you need the index.

Summary

  • Use if and select to choose, dow, dou, for and for-each to repeat, leave and iter to change a loop, return to go back to the caller, and monitor to handle errors.
  • dow may run zero times and dou always runs once.
  • leave and iter affect only the innermost loop.
  • For the whole set of opcodes by family, see the RPGLE Opcode Reference.

Leave a Comment

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

Scroll to Top