The execution of an S procedure can be controlled via control flow commands. These can be used to build command sequences that are executed subject to a condition (IF blocks), and loops (WHILE, REPEAT-UNTIL and FOR blocks); both are similar to those used in higher-level programming languages. Each of these conditional or repetitive command sequences begins and ends with a specific command:
/IF (condition) / "then-command sequence" /END-IF /WHILE (condition) / "loop body" /END-WHILE /REPEAT / "loop body, executed at least once" /UNTIL (condition) /FOR variable = valuelist, CONDITION = (condition) / "loop body" /END-FOR
The control structures may be nested in any order since each is identified unequivocally by its start and end commands. The IF block may contain additional queries of other conditions and/or an ELSE branch:
/IF (condition-1) / "commands executed ..." / "... if condition-1 is TRUE" /ELSE-IF (condition-2) / "... if condition-1 is FALSE but condition-2 is TRUE" / " (any number of ELSE-IF is possible" /ELSE / "... if none of the conditions was fullfilled" /END-IF
For further clarity, the beginning and end of a block can be identified by tags, whose correspondence will be checked by SDF-P:
/&* This command sequence removes all trailing blanks from /&* a string variable TEXT. TEXT should contain at least /&* one character that is not equal to ' '. /BLANKS-OFF: WHILE (SUBSTR(TEXT,LENGTH(TEXT),1) == ' ') / TEXT = SUBSTR(TEXT,1,LENGTH(TEXT) - 1) "truncate one byte" /END-WHILE BLANKS-OFF
Such tags can be referenced by the EXIT-BLOCK command in order to exit an enclosing block before reaching its end. By referencing the tag of an enclosing loop, the CYCLE command can be used to initiate the next loop pass although the loop body has not yet been completely executed.
A BEGIN block resembles a loop in that it encompasses a command sequence, but it cannot influence the sequence of command execution. In conjunction with an EXIT-BLOCK, a BEGIN block can, for instance, be used to exit from a procedure section prematurely subject to certain conditions:
/DAILYTASK: BEGIN-BLOCK / "Tasks to be performed daily" / IF (DAY() == 'SAT' OR DAY() == 'SUN') / EXIT-BLOCK DAILYTASK / END-IF / "Tasks to be performed on weekdays only" / IF (SUBSTR(DATE(),9,2) <> '01') / EXIT-BLOCK DAILYTASK / END-IF / "Tasks to be performed only on the first day of the month" /END-BLOCK DAILYTASK
This may improve the clarity of the procedure structure as compared with numerous nested IF blocks.
Those programmers who wish to continue using GOTO despite the command’s bad reputation will appreciate the fact that this command has been implemented as well; the branch destination should be specified as a tag prefixed to the destination command:
/IF (...); GOTO CLEANUP; END-IF /"further commands" /CLEANUP: DELETE-FILE ...
Note that the usual restrictions apply (e.g. no GOTO to enter a block).