GT.M provides the error handling facilities described in the M standard. In addition, GT.M provides a number of extensions for error handling. Both are discussed in the following sections. The following table summarizes some of the tools, which are then described in more detail within the context of various techniques and examples.

Summary of GT.M Error-Handling Facilities

EXTENSION

EXPLANATION

OPEN/USE/CLOSE EXCEPTION

Provides a deviceparameter specifying an XECUTE string or entryref that GT.M invokes upon encountering a device-related exception condition.

MUMPS -list ZLINK :"-list"

Creates a listing file of all the errors detected by the compiler and detects syntax errors. Useful in the process of re-editing program to correct errors.

ZGoto

Provides for removing multiple levels from the M invocation stack.

ZMESSAGE

Creates or emulates arbitrary errors.

$STACK

Contains the current level of M execution stack depth.

$STACK()

Returns values describing aspects of the execution environment.

$ECODE

Contains a list of error codes for "active" errors; these are the errors that have occurred, but have not yet been cleared.

$ESTACK

Contains an integer count of M virtual machine stack levels that have been activated and not removed, since the last time $ESTACK was NEW'd.

$ETRAP

Contains a string value that GT.M invokes when an error occurs during routine execution.

$QUIT

Indicates whether the current block of code was called as an extrinsic function or a subroutine.

$ZCSTATUS

Holds the value of the status code for the last compilation performed by a ZCOMPILE, ZLINK or auto-ZLINK.

$ZEDIT

Holds the value of the status code for the last edit session invoked by a ZEDIT command.

$ZEOF

Holds the value '1' (TRUE) if the last READ on the current device reached end-of-file, otherwise holds a '0' (FALSE).

$ZERROR

Contains a string supplied by the application, typically one generated by the code specified in $ZYERROR.

$ZLEVEL

Contains current level of DO/EXECUTE nesting ($STACK+1).

$ZMESSAGE()

Translates a UNIX/GT.M condition code into text form.

$ZSTATUS

Contains the error condition code and location of last exception condition occurring during routine execution.

$ZTRAP

Contains an XECUTE string or entryref that GT.M invokes upon encountering an exception condition.

$ZYERROR

Contains an entryref to invoke when an error occurs; typically used to maintain $ZERROR.

The value of $ECODE is a string that may reflect multiple error conditions. As long as no error has occured, the value of $ECODE is equal to the empty string.

$ECODE contains a list of errors codes for "active" errors - the error conditions which are not yet resolved. If there are no active errors, $ECODE contains the empty string. The value of $ECODE can be SET.

The most recent error in $ECODE appears first, the oldest last. If the error is defined by the M standard, the code starts with an "M", GT.M error codes including those provided by OS services start with "Z", and application defined codes must start with "U". Every code is separated by a coma (,) and there is always a coma at the beginning and at the end of a list. GT.M provided codes are those reported in $ZSTATUS, interpreted by $ZMESSAGE() and recognized as arguments to ZMESSAGE command. When GT.M supplies a standard error code in $ECODE, it also supplies a corresponding 'Z' code.

[Note]Note

See “$ECode” for a detailed description of $ECODE.

Example (setting $ECODE):

SET $ECODE="" ;sets $ECODE to the empty string
SET $ECODE=",M20," ;an ANSI M standardized error code
SET $ECODE=",U14," ;user defined error code
SET $PIECE($ECODE,",",2)="Z3," ;insert a non-ANSI error code
SET $PIECE($ECODE,",",$LENGTH($ECODE,",")+1)="An..," ;append        

Standard Error processing affects the flow of control in the following manner. Detection of an error causes GOTO implicit sub-routine. When $ECODE="", the implicit subroutine is $ETRAP and QUIT:$QUIT "" QUIT. Otherwise the implicit subroutine is $ETRAP followed by TROLLBACK:$TLEVEL and then QUIT:$QUIT "" QUIT.

The QUIT command behaves in a special fashion while the value of $ECODE is non-empty. If a QUIT command is executed that returns control to a less nested level than the one where the error occurred, and the value of $ECODE is still non-empty, first all normal activity related to the QUIT command occurs (especially the unstacking of NEWed variables) and then the current value of $ETRAP is executed. Note that, if $ETRAP had been NEWed at the current or intervening level, the unstacked value of $ETRAP is executed.

SETting $ECODE to an invalid value is an error. SETting $ECODE to a valid error behaves like detection of error. SETting $ECODE="" does not cause a change in the flow, but effects $STACK(), subsequent $QUITs and errors.

[Note]Note

To force execution of an error trap or to flag a user-defined error ("U" errors), make the value of $ECODE non-empty:

SET $ECODE=",U13-User defined error trap,"

[Note]Note

The value of $ECODE provides information about errors that have occurred since the last time it was reset to an empty string. In addition to the information in this variable, more detailed information can be obtained from the intrinsic function $STACK. For more information, see the section on “$STack()”.

When you need to set up a stratified scheme where one level of subroutines use one error trap setting and another more nested subroutine uses a different one; the more nested subroutine must NEW $ETRAP. When $ETRAP is NEWed, its old value is saved and copied to the current value. A subsequent SET $ETRAP=<new-value> then establishes the error trapping code for the current execution level.

The QUIT command that reverts to the calling routine causes the NEWed values to be unstacked, including the one for $ETRAP.

If an error occurs while executing at the current execution level (or at an execution level farther from the initial base stack frame), GT.M executes the code from the current $ETRAP. Unless a GOTO or ZGOTO in $ETRAP or any code it invokes redirects the flow of execution, when the execution of the $ETRAP code completes, control reverts to the implicit QUIT command, which returns to the routine that invoked the code that encountered the error. At this time, the QUIT reinstates any prior value of $ETRAP.

While at the more nested execution level(s), if an error occurs, GT.M executes the code from the current $ETRAP. After the QUIT to a less nested level, GT.M invokes the code from the now current $ETRAP. The current $ETRAP may be different from the $ETRAP at the time of the error due to unstacking. This behavior continues until one of the following possible situations occur:

When dealing with stratified error trapping, it is important to be aware of two additional intrinsic variables: $STACK and $ESTACK. The values of both of these variables indicate the current execution level. The value of $STACK is an "absolute" value that counts from the start of the GT.M process, whereas the value of $ESTACK restarts at zero (0) each time $ESTACK is NEWed.

It is often beneficial to NEW both $ETRAP and $ESTACK a the same time.

If, at the time of any error, the value of $ZTRAP is non-empty, GT.M uses the $ZTRAP contents to direct execution of the next action.Refer to the $ZTRAP section in Chapter 8: “Intrinsic Special Variables.

By default, execution proceeds as if the next instruction to be executed were the first one on "the next line", and the code on that next line would be the same as the text in the value of $ZTRAP. Unless $ZTRAP or any code it invokes issues a GOTO or ZGOTO, after GT.M has executed the code in $ZTRAP, GT.M attempts to execute the line with the error again. When a value is assigned to $ZTRAP, the new value replaces the previous value. If the value of $ETRAP is a non-empty one, $ETRAP is implicitly NEWed, and the value of $ETRAP becomes equal to the empty string; this ensures that at most one of $ETRAP and $ZTRAP is not the empty string. If the environment variable gtm_ztrap_new evaluates to Boolean TRUE (case insensitive string "TRUE", or case insensitive string "YES", or a non-zero number), $ZTRAP is NEWed when $ZTRAP is SET; otherwise $ZTRAP is not stacked when it is SET.

Other than the default behavior, $ZTRAP settings are controlled by the environment variable gtm_ztrap_form as described in the following table.

Although the "adaptive" and "popadaptive" behaviors permit mixing of two behaviors based on the current value of $ZTRAP, the $ZTRAP behavior type is selected at process startup from gtm_ztrap_form and cannot be modified during the life of the process.

[Note]

Like $ZTRAP values, invocation of device EXCEPTION values, with the exception noted, follow the pattern specified by the current gtm_ztrap_form setting.

It is important to be aware of which of the trap mechanisms is in place to avoid unintended interactions, and aware of which conditions may cause a switch-over from one mode of error handling to the other.

When a SET command assigns a value to either $ZTRAP or $ETRAP, GT.M examines the value of the other error handling variable. If the other value is non-empty, GT.M executes an implicit NEW command that saves the current value of that variable, and then assigns that variable to the empty string, then makes the requested assignment effective.

For example, re-setting $ETRAP is internally processed as:

NEW:$LENGTH($ZTRAP) $ZTRAP $ETRAP SET $ETRAP=code        

Whereas, SET $ZTRAP=value is internally processed as:

NEW:$LENGTH($ETRAP) $ETRAP SET:$LENGTH($ETRAP)="" SET $ZTRAP=value

Note that, after saving the prior value, GT.M ensures the superseded $ETRAP or $ZTRAP implicitly gets the value of the empty string. As a result, at most one of the two error handling mechanisms can be effective at any given point in time.

If an error handling procedure was invoked through the $ETRAP method, and the value of $ECODE is non-empty when QUITing from the level of which the error occurred, the behavior is to transfer control to the error handler associated with the newly unstacked level. However, if the QUIT command at the end of error level happens to unstack a saved value of $ZTRAP (and thus cause the value of $ETRAP to become empty), the error handling mechanism switches from $ETRAP-based to $ZTRAP-based.

[Note]Note

At the end of an error handling procedure invoked through $ZTRAP, the value of $ECODE is not examined, and this value (if any) does not cause any transfer to another error handling procedure. However, if not cleared it may later trigger a $ETRAP unstacked by a QUIT.

Making a choice between the two mechanisms for error handling is mostly a matter of compatibility. If compatibility with existing GT.M code is important, and that code happens to use $ZTRAP, then $ZTRAP is the best effort choice. If compatibility with code written in MUMPS dialects from other vendors is important, then $ETRAP or a non-default form of $ZTRAP probably is the better choice.

When no pre-existing code exists that favors one mechanism, the features of the mechanisms themselves should be examined.

Almost any effect that can be achieved using one mechanism can also be achieved using the other. However, some effects are easier to achieve using one method, and some are easier using with the other.

If the mechanisms are mixed, or there is a desire to refer to $ECODE in an environment using $ZTRAP, it is recommended to have $ZTRAP error code SET $ECODE="" at some appropriate time, so that $ECODE does not become cluttered with errors that have been successfully handled.

[Note]Note

A device EXCEPTION gets control after a non-fatal device error and $ETRAP/$ZTRAP get control after other non-fatal errors.

With $ZTRAP: New $ZTRAP Set $ZTRAP=...

With $ETRAP: New $ETRAP Set $ETRAP=...

[Note]Note

In both cases, QUITting to a lower level may effectively make the other mechanism active.

With $ZTRAP: If $ZSTATUS[...

With $ETRAP: If $ECODE[...

[Note]Note

The value of $ZSTATUS reflects only the most recent error, while the value of $ECODE is the cumulative list of all errors since its value was explicitly set to empty. Both values are always maintained and can be used with either mechanism.

When GT.M encounters an error in the operation of an I/O device, GT.M executes the EXCEPTION deviceparameter for the OPEN/USE/CLOSE commands. An EXCEPTION deviceparameter specifies an action to take when an error occurs in the operation of an I/O device. The form of the EXCEPTION action is subject to the gtm_ztrap_form setting described for $ZTRAP, except that there is never any implicit popping with EXCEPTION actions. If a device has no current EXCEPTION, GT.M uses $ETRAP or $ZTRAP to handle an error from that device.

GT.M provides the option to:

An EXCEPTION based on an error for the device applies only to that device, and provides a specific error handler for a specific I/O device.

The CTRAP deviceparameter for USE establishes <CTRL-n> where 0<=n<=31 as an interrupting signal. When GT.M encounters <CTRL-n> with CTRAP enabled, GT.M executes the EXCEPTION deviceparamenter, or, $ETRAP or $ZTRAP if the device has no current EXCEPTION. <CTRL-C> is unique among <CTRL> characters, in that the OS recognizes it as an out-of-band signal and delivers it immediately; GT.M recognizes other <CTRL> character when they appear duing a READ.

Example:

GTM>ZPRINT ^EP12
EP12    WRITE !,"THIS IS ",$TEXT(+0)
        SET $ECODE="";this only affects $ETRAP
        SET $ETRAP="GOTO ET"
        ;N $ZT S $ZT="W !,"CAN'T TAKE RECIPROCAL OF 0"",*7"
        USE $P:(EXCEPTION="D BYE":CTRAP=$C(3))
        WRITE !,"TYPE <CTRL-C> TO STOP"
LOOP    FOR DO
        . READ !,"TYPE A NUMBER: ",X
        . WRITE ?20,"HAS RECIPROCAL OF: ",1/X
        . QUIT
ET      . WRITE !,"CAN'T TAKE RECIRPOCAL OF 0",*7
        . SET $ECODE=""
        QUIT
BYE     WRITE !,"YOU TYPED <CTRL-C> YOU MUST BE DONE!"
        USE $P:(EXCEPTION="":CTRAP="")
        WRITE !,"$ZSTATUS=",$ZSTATUS
        ZGOTO 1
GTM>DO ^EP12
THIS IS EP12
TYPE <CTRL-C> TO STOP
TYPE A NUMBER: 1 HAS RECIPROCAL OF: 1
TYPE A NUMBER: 2 HAS RECIRPOCAL OF: .5
TYPE A NUMBER: 3 HAS RECIPROCAL OF: .33333333333333
TYPE A NUMBER: 4 HAS RECIPROCAL OF: .25
TYPE A NUMBER: HAS RECIPROCAL OF:
CAN'T TAKE RECIPROCAL OF 0
TYPE A NUMBER:
YOU TYPED <CTRL-C> YOU MUST BE DONE!
$ZSTATUS=150372498,LOOP+1^EP12,%GTM-E-CTRAP,Character trap $C(3) encountered
GTM>

This routine prompts the user to enter a number at the terminal. If the user enters a zero, GT.M encounters an error and executes $ETRAP (or $ZTRAP). The action specified reports the error and returns to prompt the user to enter a number. With $ZTRAP, this is very straightforward. With $ETRAP, some care is required to get the code to resume at the proper place. The CTRAP deviceparameter establishes <CTRL-C> as a trap character. When GT.M encounters a <CTRL-C>, GT.M executes the EXCEPTION string whcih transfers control to the label BYE. At the label BYE, the routine terminates execution with an error message. Using the EXCEPTION deviceparameter with CTRAP generally simplifies $ETRAP or $ZTRAP handling.

$ZSTATUS allows the routine to find out which trap character GT.M encountered. When a routine has several character traps set, $ZSTATUS provides useful information for identifying which character triggered the trap, and thereby allows a custom response to a specific input.

loading table of contents...