A NOVALUE condition happens when a variable is used without first having been explicitly assigned a value.

The default handling for the NOVALUE condition is to ignore it. So for example, assume the following script:

/* DROP "MyVar" and then reference it */
DROP MyVar
SAY MyVar
This displays MYVAR since the value of a variable is its name upper-cased, when it has not yet been assigned a value.

But if you would like to be informed when you're referencing a variable that has not yet been given a value, then you can trap the NOVALUE condition. Consider the following script:

/* DROP "MyVar" and reference it */
DROP MyVar
SAY MyVar
EXIT

CATCH NOVALUE
   SAY 'MyVar was not assigned a value'
When REXX gets to the line SAY MyVar, it notices that MyVar does not have a value, and you have trapped NOVALUE. So, instead of executing the SAY instruction, REXX jumps to the label MyHandler.

Your handler can use the CONDITION() built-in function's 'D' option to fetch the name of the variable whose value has not been set. For example:

/* DROP "MyVar" and reference it */
DROP MyVar
SAY MyVar
EXIT

CATCH NOVALUE
   SAY CONDITION('D') 'was not assigned a value'

Note: Reginald's CONDITION() function has an additional option. CONDITION('M') will present a pop-up message box containing a message about the variable not being assigned a value, the name of the script in which NOVALUE was raised, the source line and line number upon which NOVALUE was raised, and a Help button to bring up a help page for that error. This is preferable to trying to create your own message to present to the person running your script.

When a NOVALUE condition is raised as a result of your script referencing a variable that has not yet been given a value, CONDITION('E') returns an error number of 66.


Trapping NOVALUE in a child script

The Reginald interpreter allows you to trap NOVALUE raised in any child script you call (as well as any other child script that the first child calls), if that script doesn't trap NOVALUE for itself.

Your script must use a CATCH NOVALUE instruction where you call the child script. If NOVALUE is then raised by the child script, the child script will abort on the line where NOVALUE occurs, and Reginald will raise NOVALUE in your script (on the line where you called the script). In this case, CONDITION('E') returns an error number of 65 to indicate that it was a child script (as opposed to your script) that tried to use the value of a variable that hasn't yet been assigned a value. CONDITION('D') will return an error message that reports the name of the child script in which NOVALUE was raised, the line number where it occurred in the child script, and the name of the variable that was used.

What this means is that, using the CATCH NOVALUE, if a child script doesn't handle NOVALUE for itself, you can force that child script to be aborted as soon as it tries to use the value of a variable that hasn't yet been assigned a value, and have that error automatically reported back to you by REXX.

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

CATCH NOVALUE
   IF CONDITION('E') == '65' THEN DO

      PARSE VALUE CONDITION('D') WITH . '"' scriptname '"' . 'line ' linenum ': ' varname

      /* CONDITION('M') is preferable to this SAY. */
      SAY 'The variable named "'|| varname ||'" in "'|| scriptname ||'" was not assigned a value at line' linenum
   END

   ELSE
      /* CONDITION('M') is preferable to this SAY. */
      SAY CONDITION('D') 'was not assigned a value at line' CONDITION('L')

Environment variables queried with VALUE()

Finally, a NOVALUE condition can be raised as a result of your script trying to fetch the value of an environment variable which has not been given a value. In this case, CONDITION('E') returns an error number of 80.5. (This is a Reginald-only feature). This may happen if you use the VALUE() or GETENV() built-ins.

Your handler can use CONDITION()'s 'D' option to fetch the name of the environment variable whose value has not been set.