Using REXX Program Flow-Control Commands (99061)






This article was previously published under Q99061

SUMMARY

This article lists the program flow control capabilities of the REXX programming language and gives examples.

MORE INFORMATION

DISCLAIMER: This article is provided for users capable of developing programs with the information presented; it is not an extensive treatment of the language but rather a quick reference to aid someone in writing simple routines. Microsoft cannot support programming efforts beyond reproducing and submitting problems with the language implementation itself. If you need further assistance, consult REXX references such as "The REXX Language, A Practical Approach to Programming" by M. F. Cowlishaw, Prentice-Hall, Englewood Cliffs, 1985.

Examples are given at the bottom of the listing. Braces ({}) are used to indicate comments.

ARG var1 var2 var3 ... var20 { splits out the "command line parameters" passed to a subroutine using CALL (or a function call with multiple parameters, see example) and puts them into var1 through var20. }

CALL name var1 var2 ... var? { where name is a REXX label, built-in function or external routine and var1, etc. are parameters. Note that a built-in variable, RESULT, may be returned by CALL (see example) }.

CALL ON [ERROR|FAILURE|HALT|NOTREADY] NAME routine_to_call { When the specified condition occurs, control is transferred to the named routine. }

CALL OFF [ERROR|FAILURE|HALT|NOTREADY] { turns off the CALL ON for the specified condition }

DO n|var = start_value TO end_value |FOREVER ... END DO WHILE condition|UNTIL condition ... END { see the explanation and example in the basic article }

EXIT expression { Exit and abort the currently running program optionally returning expression. }

IF condition THEN action ELSE action { see the explanation and example in the basic article, 99060. }

ITERATE name { to the next cycle of the current loop (or the loop specified by name which is used in the DO name = _ TO _ line) thus bypassing the instructions from this point to the end of the loop for this iteration. }

LEAVE name { exit (end) the current loop or loop specified by name which is the variable used in the DO name = _ TO _ line. }

NOP { NO oPeration, a do-nothing place holder for situations where an instruction is required but no action is wanted. }

PROCEDURE [EXPOSE var1 var2] { this statement must appear after the colon identifying the subroutine name and either hides (without the EXPOSE keyword) or exposes variables inside the subroutine to the rest of the program. }

RETURN [expression] { returns control to the caller optionally supplying an expression as a result. }

SELECT; WHEN condition THEN action; .. OTHERWISE action; END { See the explanation in the introductory article, 99060, for this command. }

SIGNAL [OFF condition|ON condition label|label] { on the specified condition (if any) normal processing is terminated and transfer to label is done. SIGNAL OFF condition turns signaling off for that condition. Conditions are: ERROR, FAILURE (both the previous on command return), HALT (by external means), NOVALUE (use of an uninitialized variable) or SYNTAX (if REXX finds a source code syntax problem). }

Example: (An analysis follows; you are encouraged to extract the code below and run it. If you do, remember to include the beginning comment so that OS/2 ecognizes it as a REXX file.)
DO i = 1 TO 10
IF i = 5 THEN ITERATE
SELECT
   WHEN i = 1 THEN CALL rtn_a out words of order These are
   WHEN i > 3 THEN
      IF done = 'yes' THEN
         NOP
      ELSE
         DO
         CALL rtn_c
         SAY RESULT
         END
   OTHERWISE CALL routine_b
END
IF i = 4 THEN SAY "rtn_c's 'i = 5' didn't affect this loop"
SAY This is iteration i
IF i = 6 THEN
DO
z = function_a('arg1','arg2')
SAY z
END
IF i = 7 THEN SIGNAL early_exit
END
SAY Processing never gets here
early_exit:
SAY Left the routine before completion
EXIT

rtn_a:
ARG word1 word2 word3 word4 word5 word6
SAY word5 word2 word6 NO LONGER word1 word3 word4
RETURN

routine_b:
DO j = 1 TO 10
SAY This is pass j of iteration i
IF j = 2 THEN LEAVE
END
RETURN

rtn_c: PROCEDURE EXPOSE done
i = 5
SAY 'rtn_c set ' i ' to 5 but did not expose the variable'
done = 'yes'
RETURN 'Finished'

function_a:
PARSE ARG x , y
SAY x
SAY y
RETURN "This is a returned result"
				
Analysis (cycle by cycle):

The loop should theoretically cycle 10 times, but it will be interrupted (this is discussed later).

On cycle 1 rtn_a was CALLed from the SELECT statement which prevented either routine_b or rtn_c from being called. Although the CALL passed only one argument (which was the string "out words of order These are") the ARG command at the beginning of rtn_a split the string into its individual words allowing the SAY command just following it to rearrange them correctly and add the words "NO LONGER" before displaying the message. Once SELECT processing is done control passes to the statement after SELECT's END statement. Because "SAY This is iteration i" is the only unconditionally executed statement in the loop it is processed for each cycle.

On cycles 2 and 3 the OTHERWISE clause of the SELECT statement is executed, CALLing routine_b, which would have normally produced 10 "This is pass _ of iteration _" every time it was called, had it not been for the LEAVE command, which interrupted the loop on its second pass.

On cycle 4 the "WHEN i > 3 ..." condition is processed. Because the variable "done" is not yet set rtn_c is CALLed. Because of the "PROCEDURE EXPOSE done" clause, the assignment "i = 5" is hidden from the CALLing routine but "done" is exposed, allowing the IF test for it in the SELECT statement to function correctly. This can be seen by the processing of the statement "IF i = 4 THEN SAY "rtn_c's 'i = 5' didn't affect this loop"". Also note the SAY RESULT statement. This is a built-in variable which, if returned by the subroutine, is available after the CALL.

On cycle 5 the "IF i = 5 THEN ITERATE" causes the cycle to be skipped entirely, but allows following cycles to continue processing normally. Note that the "SAY This is iteration i" is not processed for cycle 5.

On cycle 6 the "WHEN i > 3 ..." option of the SELECT statement is again processed. However, since "done" was exposed in rtn_c, its value is now "yes" and the NOP command is processed. NOP was used so that a valid action was available for this condition. The "SAY This is iteration i" is again processed. Also note that function_a is called with two parameters separated by commas. The PARSE ARG x , y statement supplied them to function_a for use, when it was done it returned a result (required).

On cycle 7 the "IF i = 7 THEN SIGNAL early_exit" is processed, preventing the processing of the loop for cycles 8, 9 and 10. Since control is passed to early_exit: the line just above it:
   SAY Processing never gets here
				
is never encountered. Had the loop ended normally it would have been processed.

Modification Type: Major Last Reviewed: 7/30/2001
Keywords: KB99061