www.riscos.com Technical Support: |
|
By default, when the BASIC interpreter finds an error it halts execution of the program and prints an error message on the screen. Most errors are generated by incorrect programming, such as using a variable which has not had a value assigned to it. You have to correct this kind of error to make the program work. However, even if the syntax of the program is correct, errors can occur whilst it is being executed, because it cannot cope with the data it is given.
For example:
10 REPEAT 20 INPUT "Number",N 30 L = LOG(N) 40 PRINT "LOG of ";N" is ";L 50 UNTIL FALSE
This program takes a number from the keyboard and prints the logarithm of that number. If you type in a negative number, however, the program gives the message:
Logarithm range at line 30
The same thing happens if you type 0, or a character such as W, or a word such as TWELVE.
You may decide that you would like to trap such an error and print a message to tell the user what he or she has done wrong instead of having the program end abruptly. You can do this using the ON ERROR statement.
For example:
5 ON ERROR PROCerror 10 REPEAT 20 INPUT "Number",N 30 L = LOG(N) 40 PRINT "LOG of ";N" is ";L 50 UNTIL FALSE 60 END 100 DEFPROCerror 110 IF ERR=22 THEN 120 PRINT "The number must be greater than 0" 130 ELSE REPORT 140 PRINT " at line ";ERL 150 END 160 ENDIF 170 ENDPROC
The ON ERROR statement can be followed by a series of statements given on the same line. In many cases, it is more convenient to follow it with a call to an error handling procedure, as in the example above, which can then be as complex as you like.
When an error occurs, BASIC passes control to the first statement on the ON ERROR line, as if it jumped there using a GOTO. It will 'forget' about any loops or procedures that were active when the error occurred, as if the program had been re-started. Of course, the values of all the variables and so on will still be intact.
Each error has an error number associated with it. When a particular error occurs, its number is placed in a variable called ERR (these numbers are guaranteed to remain the same). A full list of error numbers is given in Appendix C: Error messages.
In the example above, the error handling procedure tests for error 22 which is the Logarithm range error. If it was this error which occurred, it is dealt with appropriately. If a different error occurred, the program executes the REPORT instruction which prints out the error message and then prints the number of the line where the error occurred which is given in the function ERL. Then it executes the END to end the execution of the program. Trapping all errors is not necessarily a good idea since you then would not be able to press Esc, which is treated as an error, to stop the program.
If a program contains more than one ON ERROR statement, the most recently executed one is used when an error occurs.
Error handling can be turned off, and BASIC's default handler restored, at any stage in the program using the instruction ON ERROR OFF.
In addition to the error messages that the interpreter itself generates when it discovers a mistake in the program, you can cause your own errors. This can be useful when, for example, you find a mistake in the user's input data and want to notify the user through your standard error handler. To generate an error, use the statement:
The errnum expression is a number which will be passed to the error handler via the ERR function, as usual. The errstring is accessible to the error handler through the REPORT statement and REPORT$ function. ERL will be set to the line number at which the ERROR statement was executed.
If you use 0 as the error number, the error will be a 'fatal' one. As with built-in errors with that number, it cannot be trapped by using ON ERROR.
An example of the use of ERROR is:
1000 ch=OPENIN(f$) 1010 IF ch=0 THEN ERROR 214,"File '"+f$+"' not found"
If an error occurs in a program, you may wish to leave BASIC altogether and pass the error back to the program that called BASIC in the first place. You can do this using the ERROR EXT statement. Its syntax is very similar to ERROR, described above. If you say:
ERROR EXT 0,"Can't find template file"
then BASIC will quit and the error message and number will be passed back to the error handler of the program that called BASIC (e.g. the RISC OS Supervisor prompt or error box).
BASIC's default error handler uses this form of the ERROR statement if the program being executed was called from a command of the form
*BASIC -quit filename
(A BASIC program filename typed as a * command will behave like this.) When BASIC is called like this, it loads and executes the program stored in filename, and then QUITs automatically when the program terminates. In addition, the function QUIT will return TRUE instead of FALSE, as it usually does. This is used in BASIC's default error handler, which reads as follows:
TRACE OFF IF QUIT THEN ERROR EXT ERR,REPORT$ ELSE RESTORE !(HIMEM-4)=@% : REM save current @% @%=&900 : REM print line numbers as integers REPORT IF ERL THEN PRINT " at line "ERL ELSE PRINT @%=!(HIMEM-4) : REM restore @% END ENDIF
When an error occurs, the ON ERROR command can be used to deal with it. BASIC, however, forgets all about what it was doing at the time the error happened. For example, if it was in the middle of a FOR NEXT loop or executing a procedure, it is not possible to jump back to the place the error occurred and carry on as though nothing had happened.
The ON ERROR LOCAL command can be used to get around this problem. This command traps errors which occur inside an individual procedure or function and then continues executing within the procedure or function rather than jumping back to the top level. For example:
10 PROCcalculate(100) 20 END 100 DEFPROCcalculate(A) 110 LOCAL I 120 LOCAL ERROR 130 FOR I = -15 TO 15 140 ON ERROR LOCAL PRINT"Infinite Result":NEXT I:ENDPROC 150 PRINT A / I 160 NEXT I 180 ENDPROC
Local error handlers can be used in any loops, not just inside procedures and functions.
Normally, when one ON ERROR or ON ERROR LOCAL statement is used, all previous ON ERROR statements are forgotten about. It is possible, however, to use one error handler and then restore the previous one. To do this, use the instruction LOCAL ERROR to store the old error handler, and RESTORE ERROR to activate it again.
For example:
1 ON ERROR PRINT "Error ";REPORT$;:END 10 PROCcalculate(100) 15 this line will give an error !!! 20 END 100 DEFPROCcalculate(A) 110 LOCAL I 120 LOCAL ERROR 130 FOR I = -15 TO 15 140 ON ERROR LOCAL PRINT"Infinite Result":NEXT I:ENDPROC 150 PRINT A / I 160 NEXT I 170 RESTORE ERROR 180 ENDPROC
This shows that the local error handler is in force during the procedure, but that the original one set up by the first line of the program is restored when the PROC has finished.
Strictly speaking, the RESTORE ERROR is not required here because it is done automatically when the ENDPROC is reached. RESTORE ERROR is also executed automatically at the end of a user-defined function. However, if you set up a local error handler in a loop at the top level, then you would need to use it explicitly.
For example:
100 LOCAL ERROR 110 WHILE ... 120 ON ERROR LOCAL ... 130 ... 140 ENDWHILE 150 RESTORE ERROR 160 ...
A program may contain errors which cause it to behave differently from the way you intended. In these circumstances, you may wish to watch more closely how the program is being executed.
One option you have available is to place a STOP statement at a particular point in the program. When this line is reached, execution of the program stops and you can then investigate the values assigned to any of its variables using the PRINT statement or LVAR command.
Another option is to use the TRACE facility. The standard trace prints the BASIC line numbers in the order these lines are executed, thus showing the path being taken through the program. This can be invoked by typing
TRACE ON
To trace only those lines with a line number below 1000, for example, type
TRACE 1000
Alternatively you may trace procedures and functions only as follows:
TRACE PROC
You can also trace both at once if you wish by typing
TRACE 1000 : TRACE PROC
Tracing can be performed in single-step mode where the computer stops after each line or procedure call and waits for a key to be pressed before continuing. Single-step tracing can be invoked by typing
TRACE STEP ON
to stop after every line traced, or
TRACE STEP n
to trace all lines below n and stop after each one, or
TRACE STEP PROC
to stop after every procedure call.
Instead of having TRACE output displayed on the screen, you can send it to a file. To do this, type
TRACE TO filename
This means that you have a permanent record of the path taken through your program.
Any TRACE option affects all programs which are subsequently run until tracing is turned off by
TRACE OFF
or until an error occurs.
Because TRACE is a statement, you can also use it from within a program. Thus if you know that a program is going wrong within a particular procedure, you could insert a TRACE ON statement at the start of the procedure, and a TRACE OFF just before the ENDPROC. That way, trace information will only be produced while the procedure is executing.