A label is used to mark a place in your REXX script. A label name can be any legal variable name. In order to indicate a label, you put a colon : immediately after the label. Here we have a label named RightHere:, marking a SAY instruction.
RightHere: SAY "This instruction has a label"
The label could optionally be put on a separate line (ie, above the instruction that it marks). Also, the label may be indented.

Note: Labels are not case-sensitive. So, 'RightHere' is the same as 'RIGHTHERE'.

Note: It is legal to have the same label name in two different places in a script, but REXX ignores the second instance, and will use only the first instance. Reginald has a 'LABELCHECK' option that will cause a SYNTAX error (with error number 47.2) if there is a duplicate label in your script. This option can be used to detect unintentional, duplicate labels. The LABELCHECK option is automatically set in any REXX object script.


Jumping to a label

The SIGNAL instruction allows you to jump to a label somewhere within your script. You specify the label name after the SIGNAL keyword. REXX jumps to the instruction following that label, and resumes executing instructions at that place.

/* Terminate the script before the last line, if the user answers YES */
SAY "Do you want to terminate before printing the word 'Hello'?"
PULL answer
IF answer == "YES" THEN SIGNAL Here
SAY "Hello"
Here:
EXIT
You can alternately use the SIGNAL VALUE instruction, followed by some expression that is evaluated to determine the label. For example, here we store the name of the desired label in a variable named "Jump", and then use SIGNAL VALUE to jump there.
SAY "Do you want to print 'Hello'?"
PULL answer
IF answer == "YES" THEN Jump = "PrintHello"
ELSE Jump = "SkipPrint"
SIGNAL VALUE Jump
PrintHello:
SAY "Hello"
SkipPrint:
EXIT

A potential problem

If you use SIGNAL within a loop or SELECT group, to jump to a label outside of that loop or SELECT group, then you effectively jump out of (ie, terminate) the loop or SELECT group itself. But, even if you jump to a label within the loop, that loop may terminate prematurely.

Consider the following example:

count = 1

/* Loop 5 times */
DO 5

   /* Skip displaying count when it is 3 */
   IF count = 3 THEN SIGNAL Skip

   /* Display count */
   SAY count

Skip:
   /* Increment count */
   count = count + 1

/* Next iteration */
END

SAY 'DONE'
You may think that the above would display the following:
1
2
4
5
DONE
But, it actually displays the following:
1
2
DONE
Why? Because as soon as REXX encounters a SIGNAL instruction, it terminates any loops that are executing. This means that, after we SIGNAL to "Skip", the END instruction never jumps back to do another loop, even though we haven't finished 5 iterations yet. For this reason, you should be very careful using SIGNAL. We could instead rewrite our code like so to eliminate SIGNAL:
count = 1

/* Loop 5 times */
DO 5

   /* Skip displaying count when it is 3 */
   IF count \= 3 THEN SAY count

   /* Increment count */
   count = count + 1

/* Next iteration */
END

SAY 'DONE'
Now we do get the expected results of:
1
2
4
5
DONE
It should be noted that if you use SIGNAL in some subroutine or function you write in REXX, it doesn't terminate the loops in the caller. So, if you're in a loop and you call some subroutine that uses SIGNAL, that won't terminate the loop (although it may terminate another loop inside of the subroutine).

If you need to end a loop, you should use the LEAVE keyword instead of using SIGNAL to jump outside of the loop. So too, the ITERATE keyword can be used to skip part of a loop, instead of using SIGNAL to jump past part of the loop. One limitation of LEAVE/ITERATE is that you can use them only in conjunction with a loop that has some sort of loop variable -- not a DO WHILE, DO UNTIL, nor DO FOREVER loop. Alternately, Reginald supports using the RAISE instruction to raise a condition, and you can then use the CATCH instruction to determine the point where you want to unwind to. Besides choosing exactly where to unwind, you also can utilize FINALLY instructions to do cleanup in loops that you unwind.


Checking if a label exists

If you wish to know whether a label exists, use the EXISTS function.