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.


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

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 it is 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).

A common use of SIGNAL is to jump to an error handling routine when something goes wrong, so that the program can clean up and EXIT.

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.


SIGL variable

Whenever you jump to a label, a special variable named SIGL is set to the line number of the instruction from where you jumped (ie, the line number of the instruction containing the SIGNAL instruction).

Note: The SIGL variable is created by the REXX interpreter, which assigns it a value whenever you use SIGNAL to jump to a label. You should never name your own variable SIGL, but may reference this variable.

/* Jump to the label "Here" */
SIGNAL Here
EXIT

Here:
   /* Use the SIGL variable's value to tell from
    * which line we jumped.
    */
   SAY "Jumped to Here from line" SIGL