Error Handling in jBC Programs
jBASE provides several mechanisms to monitor, control and display runtime errors.
|Environment Variable||Error Message|
|JBASE_ERRMSG_DIVIDE_ZERO||Divide by zero !!-- ZERO returned|
|JBASE_ERRMSG_NON_NUMERIC||Non-numeric value -- ZERO USED|
|JBASE_ERRMSG_ZERO_USED||Invalid or uninitialised variable -- ZERO USED|
Setting this variable will log all error and runtime messages to the $JBCRELEASEDIR/tmp/jbase_error_trace file. Be aware that this will cause the jbase_error_trace file to grow very large if left to its own devices.
To redirect standard error to standard out in a jBC program set JBC_STDERR=1. This is useful with the EXECUTE statement for CAPTUREing output that would normally be sent to the screen.
This environment variable is used to specify an alternate error message file. See Advanced Error Message Tracking.
Most jBC (BASIC) I/O statements have built-in syntax to trap errors. This is implemented by specifying the SETTING and ON ERROR clauses. For example:
READ record FROM filevar, id SETTING errornumber ON ERROR CRT "READ failed with error number ":errornumber STOP END ELSE STOP 202,id ENDThe SYSTEM(0) function can also be used to determine the outcome of I/O options. Operations like READ and WRITE will return non-zero error numbers if the operation fails in some way. Tape statements, like READT and WRITET, will store the reason code if an error occurs.
ASSIGN 0 TO SYSTEM(0)
There are two files, jbcinit.err and jbcmesssages, underneath
JBCRELEASEDIR. The jbcinit.err file is used to build the jbcmessages
file. The jbcinit.err file contains extensive documentation on how to
add new and customize existing messages that display to the user. This is all
explained in detail
This section details how to track specific error messages.
The JBASE_ERRMSG_TRACE environment variable is message-agnostic. When it is set it logs all jBASE messages that are 'printable' (i.e. not marked 'NOPRINT') in the %JBCRELEASEDIR%\jbcmessages file. This can be problematic when all you want to do is log the occurrences of a few specific error messages. The log produced by JBASE_ERRMSG_TRACE will also not tell you what process produced the error, what time the error occurred, the port number, the username, etc.
For example, suppose we want to only log BASIC program errors that result from the 3 errors that are controlled by JBASE_ERRMSG_DIVIDE_ZERO, JBASE_ERRMSG_NON_NUMERIC and JBASE_ERRMSG_ZERO_USED. We don't want the program to drop to the debugger, nor do we want these error messages to display to the user. Setting JBASE_ERRMSG_TRACE=1 will certainly log these occurrences but they will be intermixed with all other messages making it difficult to determine what happened when.
The solution (details to follow) is to remove (unset) JBASE_ERRMSG_TRACE and place a POSTREAD trigger on your own version of the jbcmessages file. The trigger code will look for, and log, the 3 specific errors. Of course, you can add to this list as long as the error message is in the jbcmessages file.
There are two stages, Development and Implementation. The Development stage can be done at any time and will not affect the system in any way. The Implementation however must be done when there are no users on the system and no running jBASE processes.
1) Here is the trigger code.
It assumes the existence of a file called ERRORLOG, in which the errors
will be logged, and a different jbcmessages file. There are other things
that need to be done to allow the trigger to fire and we will get to those
2) The first task is to create a custom jbcmessages file and then modify specific messages in this new file. For this example, we will use a directory named C:\custom. We will also assume that JBCRELEASEDIR is set to C:\jbase5\5.2. Here are the steps:
a) Copy the following files to the C:\custom directory (DO NOT use the jBASE COPY command):
C:\jbase5\5.2\jbcinit.err C:\jbase5\5.2\jbcmessages]D C:\jbase5\5.2\jbcmessagesb) Open the C:\custom\jbcinit.err file with any editor, then locate the line that starts with the string ZERO_USED: and replace the string WARNING with the string NOPRINT on that line. Note that the ^ characters you see are up-arrows (shift+6 on the keyboard). Make the same change on the lines that start with DIVIDE_ZERO: and NON_NUMERIC:. The final lines must look EXACTLY like this.
cd C:\custom jmakeerr jbcinit.err (O TO: C:\custom\jbcmessages3) Create the ERRORLOG file (or whatever name you want to use, but if you change the name then you will then have to also change it in the trigger code). This is the file that the trigger will log the errors to rather than logging them to the jbase_error_trace file. The trigger code shows what information gets logged but you can, of course, add or remove elements as desired. Since the file is only going to contain 3 records it can be created with:
CREATE-FILE ERRORLOG 1 1
Feel free to create dictionary items as required.
Note: The ERRORLOG file must be available to your application so make sure that in is in HOME or is visible to JEDIFILEPATH.
Ensure that there are no users on the system and that there are no running jBASE processes.
Any environment variable changes must be set system-wide. The changes
should also be made in all remote.cmd (Windows) or .profile (Unix/Linux) files.
1) Compile the trigger code and catalog it so that it is available to your application. Remember to change the OPENs to reflect the locations and names of the files you are actually using.
Note: If you change the name of the trigger then remember to also change the name on the SUBROUTINE line.
2) Assign the trigger to your custom jbcmessages file:
CREATE-TRIGGER C:\custom\jbcmessages POSTREAD trackerrors3) Add (or change) the environment settings for the 3 error scenarios:
JBASE_ERRMSG_DIVIDE_ZERO=2 JBASE_ERRMSG_NON_NUMERIC=2 JBASE_ERRMSG_ZERO_USED=2Note: If the setting includes a bit mask value of 1 then the trigger will never fire because the jbcmessages file will never be read for that particular error condition.
JBCERRFILE=C:\custom\jbcmessagesNote: This setting is what actually activates the whole system.
0001 PROGRAM testerrors 0002 a = 1234 0003 b = 'xyz' 0004 CRT "Test1: use a non numeric --> ":a+b 0005 CRT "Test2: divide by 0 --> ":a/0 0006 CRT "Test3: invalid or uninitialised --> ":c ;* variable c was never assigned