A HALT condition happens when the person running your script wants to manually abort your script, or some add-on Function you call in a DLL wants your script to abort.

REXX's default handling for the HALT condition is to display some information, and then end your script right there. The information displayed includes the line number and the actual line in your script where the condition was raised, the name of the script, and a message indicating that the script was aborted.

But if you trap the HALT condition, then such default handling doesn't happen. Instead, REXX calls your own HALT handler (instead of displaying a message, and terminating your script).


HALT error/signal numbers

Whenever a HALT condition is raised, an error number, and a signal number, is associated with that instance of the condition being raised. If a HALT condition is raised within your script, then the error number will be 4, and the signal number can be any numeric value, within the range 1 to 65535, that tells you why the HALT condition was raised. There are three defined numbers -- 2 (the person using your script wants to manually abort), 15 (the operating system wants your script to close down), and 1 (ie, a UNIX signal not used on Windows).

Your handler can use the CONDITION() built-in function's 'E' option to fetch the error and signal numbers associated with a given instance of that condition. CONDITION('E') will return the two numbers separated by a dot. For example, 4.2 will be returned for the user trying to manually abort your script.

A signal number may have a matching name (ie, some string that identifies the signal being given to your script). There are 3 defined signal names for signal numbers 2, 15, and 1 respectively -- 'SIGINT', 'SIGTERM', and 'SIGHUP'. Your handler can use CONDITION()'s 'D' option to fetch signal name. If there is no matching name, then the signal number is returned.

Some add-on Function that you call in a DLL may also raise HALT. This function may specify some other signal number/name. Consult the documentation with that function for meanings of other names/numbers. If a function doesn't provide a matching signal name, then CONDITION('D') simply returns the signal number.


Trapping HALT in a child script

The Reginald interpreter allows you to trap HALT in any child script you call (as well as any other child script that the first child calls), if that script doesn't trap HALT for itself. Your script must use a CATCH HALT instruction where you call the child script. If HALT is then raised within the child script, the child script will abort on the line where HALT occurs, and Reginald will raise HALT in your script (on the line where you called the script). In this case, CONDITION('E') returns an error number of 65 (instead of 4) to indicate that it was a child script (as opposed to your script) that received a HALT signal. CONDITION('D') will return an error message that reports the name of the child script in which HALT was raised, the line number where it occurred in the child script, and the signal's name.

What this means is that, if a child script doesn't handle HALT for itself, you can force that child script to be aborted and have that HALT automatically reported back to you by REXX.

Here is an example handler that would differentiate between HALT raised in your script versus another script that you called:

/* Here you would have more instructions. If the person
 * running the script presses CTRL and C keys while
 * these instructions are executing, REXX jumps to the
 * CATCH HALT
 */
DO FOREVER
END
EXIT

CATCH HALT
   PARSE VALUE CONDITION('E') WITH error '.' sub
   IF error = 65 THEN SAY "Untrapped HALT in a script we called"
   IF sub = 2 THEN SAY "User wants to abort"
   ELSE IF sub = 15 THEN SAY "Operating system wants to close down"
   ELSE SAY "Other type of HALT =" sub
   RETURN

You can use the "PARSE SOURCE" and "SAY" REXX instructions, and the ERRORTEXT() and CONDITION() built-in functions to duplicate the default handling for HALT condition, as so:

/* Handler for HALT that duplicates the default handling */
CATCH HALT

   /* Get the error and sub-error numbers */
   PARSE VALUE CONDITION('E') WITH error '.' sub

   /* Was NOTREADY raised in a child script we called? */
   IF error == '65' THEN DO

      /* Yes it was. Parse the child script's name, the
       * line number in that script where HALT was
       * raised, and the signal name.
       */
      PARSE VALUE CONDITION('D') WITH . '"' scriptname '"' . 'line ' linenum ': ' sig
      SAY 'ERROR 4.'||sig 'in "'||scriptname||'" at line' linenum
      SAY ERRORTEXT(4||'.'||sig)
   END

   ELSE DO
      linenum = CONDITION('L')
      SAY "    " linenum "+++" SOURCELINE(linenum)
      PARSE SOURCE . . scriptname
      SAY 'ERROR' CONDITION('E') 'in "'||scriptname||'" at line' linenum
      SAY ERRORTEXT(CONDITION('E'))
   END

   RETURN
Note: Reginald's CONDITION() function has an additional option. CONDITION('M') will present a pop-up message box containing an appropriate message, the name of the script in which HALT was raised, the source line and line number upon which HALT was raised, and a Help button to bring up a help page. This is preferable to trying to create your own message to present to the person running your script, since the online help may be supplied by the entity raising HALT.
CATCH HALT
   /* A preferable way to display a HALT message. */
   CONDITION('M')
   RETURN