The Pascal/MT+ system supports three types of run-time checking: range, exception, and input/output.
The default condition of the system is that range checks are disabled and exception checks are enabled. I/O checks are disabled because the routine which handles I/O errors is not part of PASLIB but in source code to be modified by the user to suit his / her own needs.
The general philosophy is that error checks and error routines will set boolean flags. These boolean flags along with an error code will be loaded onto the stack and the built-in routine @ERR is called with these two parameters. The @ERR routine will then test the boolean parameter. If it is false then no error has occurred and the @ERR routine will exit back to the compiled code and execution continues. if it is true the @ERR routine take appropriate action as described in the following sections.
Listed below are the error numbers passed to the @ERR routine:
Value | Meaning |
---|---|
1 | Divide by 0 check |
2 | Heap overflow check (unused, see below) |
3 | String overflow check (unused, see below) |
4 | Array and subrange check |
5 | Floating point underflow |
6 | Floating point overflow |
7 | 9511 transcendental error |
Range checking is performed on array subscripts and on subrange assignments. It is not performed when READing into a subrange variable. When range checking is enabled the compiler generates calls to @CHK for each array subscript and subrange assignment. The @CHK routine leaves a boolean on the stack and the error code number 4, and the compiler generates calls to @ERR after the @CHK call. If range checking is enabled @ERR prints a message and asks whether to continue or abort. If range checking is disabled and an array subscript falls outside the valid range, unpredictable results will occur. For subrange assignments the value will be truncated at the byte level.
Exception checking is performed on integer and real number divide by 0, real number underflow and overflow, and string overflow. It is enabled by default. In the current release $X- does not turn off exception checking. When exception checking is enabled the compiler will load the error flags (zero divide, string overflow, real number underflow and overflow) as needed and call the @ERR routine after each operation which would set the flags. If a floating point underflow occurs, 0.0 is returned but no message is printed by @ERR. If a floating point overflow occurs, a message is printed and a large number is returned. Divide by zero results in a maximum value being returned, heap overflow does nothing and string overflow truncates.
It is possible for the user to write an @ERR routine to be used instead of the system routine. The user should declare the routine as:
PROCEDURE @ERR(ERROR:BOOLEAN; ERRNUM:INTEGER);
The routine will be called, as mentioned above, each time an error check is needed and this routine should check the ERROR variable and exit if it is FALSE. The user may decide the appropriate action if the value is true. To use your @ERR routine instead of the routine contained in PASLIB, link your own routine ahead of PASLIB to resolve the references to @ERR. The values of ERRNUM are as shown at the beginning of this chapter.
The run-time routine, @BDOS, does not perform any I/O error handling except to return the CP/M error code in IORESULT for the user to check. An alternative @BDOS routine is found in XBDOS.SRC on the distribution disk. When this XBDOS calls the BDOS with the CP/M I/O functions 15, 16, 21, and 22 (OPEN or RESET, CLOSE, WRITE or PUT, and REWRITE, respectively); it generates a call to IOERR passing it the CP/M function call number. The IOERR routine, found in IOERR.SRC, may be altered to handle these I/O errrors as the user desires.
To use the I/O error handling code, compile both IOERR.SRC and XBDOS.SRC. The relocatable files that result may be built into a library using the file named IOCHK.BLD on the distribution disk as input to LIB/MT+. This creates a library called IOCHK.ERL which must be linked before PASLIB and cannot be searched because all references to @BDOS are generated by PASLIB. See the section in Chapter 2 on using the librarian.
@BDOS need not be declared external because all references to @BDOS are generated by PASLIB. Also, all references to IOERR are generated by @BDOS so IOERR is not declared as external.