BRK instruction to generate the error
Single byte error number (ERR)
Error message (like 'Mistake')
A zero byte to terminate the message
The first section of this chapter describes the default BRK handler in BASIC, and what normally happens when an error is generated. The subsequent sections detail the errors which BASIC can generate, and any recovery from them (if possible), so that they can be intercepted in a similar way to the methods used in chapters 7 to 9.
BASIC keeps an 'ON ERROR' pointer in locations &16,&17 in page zero, which is normally set to point to the default error handler (in the ROM). This pointer tells the BASIC BRK handler the location of a set of BASIC statements which will deal with the error.
BASIC resets it to point to the default error handler every time it enters immediate mode (either when it initialises, or when it has finished executing a program), or whenever an 'ON ERROR OFF' statement is executed. When an 'ON ERROR' statement is executed, this pointer will be pointed at the start of the statements on the rest of the line, so that these will be executed when an error occurs.
The other advantage that BASIC gains by using its own error handler, is that the error messages can be tokenised. This means that keywords which appear in error messages (like the 'RENUMBER' in 'RENUMBER space') only take up 1 byte. The 'REPORT' statement, which is used to print out the error message, will convert these tokens into the correct keyword and print them out fully (this uses the 'ptoken' ROM routine).
2 Turn TRACE off
3 Load the 'ON ERROR' pointer into PTRA, and start executing the statements making up the error handler by jumping to the 'Decode and execute command' entry. This executes the statements as if they had just been typed in as a command.
The default ERROR handler for BASIC1 reads:
REPORT:IF ERL<>0 PRINT" at line ";ERL; 0 PRINT : END
The BASIC2 BRK handler has been changed slightly from the BASIC1 version; it will not allow commands to be part of the error handler. This means that you can't do 'ON ERROR LIST' with BASIC2; but it does also stop 'ON ERROR 10' (which may have been mistyped for 'ON ERROR GOTO 10') which corrupts the program, giving a 'Bad program' error.
2 Turn TRACE off
3
4 Load the 'ON ERROR' pointer into PTRA, ready to execute it later.
5 Clear the BASIC stacks, and restore the D AT A pointer. This is done in BASIC1 in the 'Decode and execute command' routine.
6 Abandon the VDU queue (OSBYTE &DA). This is so that the first few characters of the error message to be printed will not be used as part of a multi-character VDU command (like VDU 19 or VDU 23).
7 Acknowledge an ESCAPE condition. In BASIC 1, this is done by the 'Decode and execute command' routine.
8 Set the OPT value to &FF (default)
9 Execute the BASIC statements of the error handler at PTRA, as if they are part of a program.
The default ERROR handler for BASIC2 reads:
REPORT:IF ERL PRINT" at Line ";ERL:END ELSE PRINT:END
Note that the 'REPORT' statement is slightly different for each BASIC: in BASIC1 a VDU 6 command is sent before the error message is printed; in BASIC2 the error message is just printed. This means that if a program turns the screen off using a VDU 21 command, in BASIC1 any error messages will be printed on the screen, but in BASIC2 it will not.
11.2 Numbered errors
The errors detailed in this section have error numbers associated with them, and can be trapped by the BASIC 'ON ERROR' statement.
These can be recognised easily by a BRK handler, as &FD,&FE will point at the error number when the BRK handler is entered. Chapters 7 to 9 show how some of these errors can be intercepted.
This error (and the 'No such variable' error) will be suppressed if 'OPT 0' or 'OPT 1' is used in the assembler (i.e. bit 1 of OPT is zero). In this case, a displacement of 0 will be used for the branch, and assembly will be allowed to continue. However, due to the way in which the test for this bit is carried out, the 'Out of range' error will only be suppressed if the OPT setting used is either 0 or 1. In BASIC2, setting bit 2 of the OPT value enables remote assembly (see section 1.6.1); so if this facility is being used, this error will not be suppressed.
This error is recoverable, so that assembly can continue, although recovery should only be attempted if remote assembly is being used (in BASIC2).
Error conditions: (BASIC2 only)
A (current OPT value) DIV 2
X mnemonic number
Y undefined
2 Bit 1 of the current OPT value (bit 0 of A) is 0
2 Set A to zero
3 JMP to &86A5 (BASIC2 only)
This will use a zero dispacement for the branch, and assembly will continue.
Error 2 - Byte
This error is generated by the assembler when a 2-byte value is used where only a single byte is allowed (the most significant 2 bytes of the 4-byte integer are ignored). The addressing modes which only allow a single byte are:
LDA #BB / Immediate
LDA (BB),Y / Post-indexed indirect
LDA (BB,X) / Pre-indexed indirect
Recovery should not normally be attempted from this error, as
potentially fatal mistakes in an assembler program may not be
spotted; however it is possible to recover and just use the LSB. of
the 2-byte word as the byte if required.
A MSB of the 16-bit value in IntA (non-zero)
X mnemonic number
Y undefined
This will use only the LSB of the 2-byte value as the byte for the instruction, and assembly will continue.
Error 3 - Index
This error is generated by the assembler if it finds an error in the syntax of any of the indexed addressing modes. The main causes of this are:
(a) The absence of an index in one of the indexed indirect modes. For example, 'LDA (&80)' will cause this error.
(b) A comma was found after the data, but no 'X' or 'Y' was found after the comma. For example, 'LDA &80,Z' will cause this error
(c) The wrong index register was used for this particular instruction. For example, 'LDY &80, Y' is not allowed.
A MSB of the 16-bit value in IntA (non-zero)
X mnemonic number
Y undefined
Error 4 - Mistake
This error is generated by BASIC when an equals sign, '=', is not found after the first item of an assignment statement.
The usual cause of this is the mis-typing of a keyword at the start of a statement. When BASIC attempts to interpret the statement, it does not find a keyword, so it assumes that the item is a variable. When it doesn't find the '=' after it, it generates a 'Mistake' error. By trapping this error, it is possible to add in new statements or commands to the language (see chapter 7).
There are, in fact, 5 slightly different causes of a 'Mistake':
(a) A non-existent, but valid, variable name was found at the start of a statemen.t, but the first non-space character after it was not a '='.
(b) An existing variable was found at the start of a statement, but the first non-space character after it was not a '='. This looks the same as (a) above, but a slightly different action is taken by the BASIC interpreter.
(c) A 'LET' followed by a valid variable name was found, but no '=' was found after the variable.
(d) A pseudo-varible (like 'HIMEM') was found at the start of a statement, but no '=' was found after it.
(e) A 'FOR' was found, followed by a valid variable name, but no '=' was found after the variable.
Note that if an invalid symbol is found at the start of a statement, and not a valid variable name, then a 'Syntax error' (error 16) will be generated instead.
Error conditions:
Error number: 4 'Mistake'
Stack contents: RTI information 3 bytes
Return address 2 bytes
(Return addr-(d) only 2 bytes)
PTRA: points to the character after the first
non-space character of the line.
PTRB: points to the character after the character
which was not an '='.
A the character which was not an '='
X undefined
Y PTRB offset- 1 (i.e. points at char in A)
2 The name at the start of the statement can be recognised as a new command or statement keyword. To attempt this, a pointer could be constructed which points at the character one before PTRA, and recognition attempted from there. See section 7.4 for more on recognising keywords.
2 Pull the 2 bytes of return address from the stack
3 If the first character of the statement was a pseudo-variable token (case (d)), then pull the other 2 bytes of return address from the stack. Normally a statement with a pseudo-variable at the start will not be recognised as a new command (unless one of the new keywords contains the token for it at the front), so this step does not need to be taken.
4 The action of the new statement can now be performed. This should be a call to the 'Check for end of statement' routine at &9810 (BASIC1) or &9857 (BASIC2), to set up the pointers ready to continue with the next statement.
5 Finally, after the action of the new statement has been completed, execution of the rest of the program can be continued with a JMP to &8B0C (BASIC1) or &8B9B (BASIC2). Alternatively, a restart of BASIC may be performed; this may be necessary if the program currently being run has been changed (by deleting a line, perhaps), as the syntax pointers may not point to the correct part of the program.
Note that pseudo-variables are not tokenised if followed by an alphanumeric character (see section 2.3. 1). This means that new commands may include these at the start of the new keyword ('TIMER',for example)
Error 6 - Type mismatch
This error is generated by BASIC if a string value was found where a number was expected, or a number was found where a string was expected. There are many ways that this error can be caused, including assigning a string to a number (and vice-versa) or giving the wrong type of argument to a function.
When inside a FN, the 6502 S register should be &F5 (the next available byte), and the contents of the stack should be:
&1F6 return addr to FN caller 2 bytes
&1F8 PTRB base MSB
&1F9 PTRB base LSB
&1FA PTRB offset
&1FB number of parameters
&1FC PTRA base MSB
&1FD PTRA base LSB
&1FE PTRA offset
&1FF Bottom: &A4 (FN token)
Note that the stack is 'upside down': the top of stack works downwards in page 1. Note also that the parameter values are stored on the BASIC STACK, rather than the 6502 stack.
Section 8.3 illustrates how this error can be used to throw away an overlayed FN when it exits, by substituting a different byte on the bottom of the 6502 stack when the FN is called.
A undefined
X copy of S (after TSX)
Y undefined
Recovery should only be attempted if:
1 The error number at (&FD) is 7
2 The condition of the stack due to which the error occurred can be determined.
To recover from the error:
1 Pull the 3 bytes of RTI information from the stack.
2 Evaluate the <numeric> or <string> following the '=', and check that it is at the end of the statement.
3 If we are in a FN (but it had been 'hidden' by changing the token at &1FF, for example) then executing an RTS will exit from the FN. The result of the FN should be in IntA, FPA, or StrA, with the result type stored in &27 (this is done automatically by the 'Get <numeric> or <string>' routine).
Note that the recovery performed in section 8.3 is more complex
than this, as it also has to throw away the FN from the STACK.
It is possible to recover from this error to allow strings to be assigned in page zero, but it is not possible to read from a page zero string that has 'got through' the $ range check. If the BASIC 'Get value of variable' routine discovers that the address of an indirected string is only a single byte (i.e. in page zero), it will interpret it as 'CHR$' instead. Thus, if this error is being recovered, 'PRINT $&70' will behave the same as 'PRINT CHR$&70' (although '$&70=A$' will place A$ at location &70 onwards). This mechanism does not appear to have any possible use in BBC BASIC, as it should not allow the address of strings to be less than &100. However, the BASIC on the Acorn ATOM used '$' with a single-byte number instead of 'CHR$', so it could be left over from this.
A 0
X undefined
Y undefined
Recovery should only be attempted if:
1 The error number at (&FD) is 7
To recover from the error:
1 Pull the 3 bytes of RTI information from the stack.
2
3 Clear the Z flag (this may have been done already), and set the C flag: this indicates that a valid string variable has been found (see 'Find variable' in section 10.5).
4 Execute an RTS instruction, to return to the code which called the 'Find variable routine'.
Error 10 - Bad DIM
This error is generated by BASIC if an error is encountered in a 'DIM' statement. The possible causes of this are:
(a) An attempt is made to re-dimension an array which already exists
(b) One of the dimensions of the array is either negative, or greater than &3FFF
(c) The total number of bytes required by the array is greater than &FFFF
(d) The size given to a 'reserve bytes' DIM is either less than - 1, or greater than &FFFE
(e) An invalid variable name is found as the DIM subject
See also error 11 - 'DIM space'.
Error 11 - DIM space
This error is generated by BASIC if there is not enough memory for the space required by a 'DIM' statement. This can be caused by:
(a) The new value of the HEAP pointer calculated for an array would be above the BASIC STACK, or would have 'wrapped round' the memory map
(a) The new value of the HEAP pointer calculated for a 'reserve bytes' DIM would be above the BASIC STACK; no test for wrap-round is made (so 'DIM A% &FFFE' will move the HEAP pointer down by 1 byte).
If the DIM statement runs out of memory while it is allocating space for the name of the array on the HEAP, then a 'No room' error will be produced instead.
This error can only be recovered if more space can be allocated somehow (by forcing a MODE change and shifting the STACK, perhaps). The two possible causes of this error, (a) and (b), must be recovered differently.
HEAP: If (a): points at 'offset' byte of array header
If (b): old value
A undefined
X MSB of new HEAP pointer
Y LSB of new HEAP pointer
C set
Recovery should only be attempted if:
1 The error number at (&FD) is 11 (&B)
2 The new HEAP pointer (in A,Y) is above the BASIC STACK pointer. If it is not, the HEAP pointer has wrapped round over the top of the memory, and recovery should be aborted.
3 The BASIC STACK can be shifted up out of the way, so that there is enough room for the new HEAP.
4 The STACK has not already been corrupted by the array header information. In case (a), the 'offset' byte pointed to by the old HEAP pointer gives the number of bytes already written on to the HEAP; if these would be above STACK, then the STACK has been corrupted. In case (b) there is no header information.
To recover from the error:
1 Pull the 3 bytes of RTI information from the 6502 stack.
2 Shift the BASIC STACK so that the STACK pointer is above the required new HEAP pointer (moving the HEAP would be more tricky, due to all the pointers which point into it).
3 Test if the pointer in locations &37 and &38 is equal to the pointer in locations &2 and &3: if it is, then the error is due to (a); otherwise it is due to (b).
4 If the error is due to (a), execute a JMP to &91A0 (BASIC1) or &91EB (BASIC2); if it was due to (b), execute a JMP to &90B5 (BASIC1) or &9108 (BASIC2).
The new HEAP value will be set, and the DIM statement will continue (the DIM' d area will also be cleared if it is for an array).
Error 12 - Not LOCAL
This error is generated by the BASIC 'LOCAL' statement if a FN or PROC is not currently being executed.
BASIC decides that a FN or PROC is not in progress, if the 6502 stack pointer is &FC or above. See section 5.3 for more on PROCs and FNs.
When inside a PROC, the 6502 S register should be &F5 (the next available byte), and the contents of the stack should be: 'Not LOCAL'
&1F6 return addr to PROC caller 2 bytes
&1F8 PTRB base MSB
&1F9 PTRB base LSB
&1FA PTRB offset
&1FB number of parameters
&1FC PTRA base MSB
&1FD PTRA base LSB
&1FE PTRA offset
&1FF Bottom: &F2 (PROC token)
Note that the stack is 'upside down': the 'top of stack' works downwards in page 1. Note also that the old parameter values are stored on the BASIC STACK, rather than the 6502 stack.
Section 8.3 illustrates interception of this error to remove an overlayed PROC from the STACK when it exits, by changing the token on the bottom of the stack when it is called.
A undefined
X copy of S (after TSX)
Y undefined
Recovery should only be attempted if:
1 The error number at (&FD) is 13
2 The condition of the stack which caused the error can be determined.
To recover from the error:
1 Pull the 3 bytes of RTI information from the stack.
2 Call the routine to 'Check end of statement at PTRA', at &9810 in BASIC1 or &9857 in BASIC2.
3 If we are in a PROC (but it had been 'hidden' by changing the token at &1FF, for example), executing an RTS will exit from the PROC. This could be done by JMPing to the 'Check end of statement' routine instead.
Error 14 - Array
This error is generated by the BASIC 'Find variable' routine. It will be caused either if an array name is referenced which has not already been dimensioned; or if the array referenced has fewer dimensions than the one in the original DIM statement (if it has more than the one in the DIM statement, a 'Missing )' error will be generated).
Error conditions
Error number: 14 'Array'
Stack contents: RTI information 3 bytes
undefined
A undefined
X undefined
Y undefined
This error is not recoverable.
In BASIC1, this error can also be caused if the '#' is missing after a statement or function which expects a file handle. BASIC2 has the new error 'Missing #' (error 45) for this condition.
Error 17 - Escape
This error is generated by the BASIC 'Check for end of statement' routine (or the last part of it, which tests the ESCAPE flag in &FF) if an ESCAPE condition is active (i.e. the ESCAPE key has been pressed).
If this error is to be recovered from (ignored), then the ESCAPE condition should be acknowledged with a call to OSBYTE &7E before continuing (or it could be just cleared by OSBYTE &7C). If this is not done, then the escape condition will still be active on return to the BASIC interpreter; and it will generate this error again at its earliest opportunity.
A better way of 'recovering' from this error is to disable the ESCAPE key, to prevent the error from being generated in the first place.
1 Pull the 3 bytes of RTI information from the stack.
2 Call OSBYTE &7E (or OSBYTE &7C) to acknowledge the ESCAPE condition.
3 Execute an RTS
Error 18 - Division by zero
This error is generated by the BASIC division routines if the divisor of the the attempted division is zero.
Error 20 - Too big
This error is generated by BASIC if an overflow occurs. This can be due to:
(a) A floating point number has overflowed after the end of a calculation. This is discovered by the 'Round and check for overflow' routine, before the floating point number is written out to memory (or to one of the temporary stores).
(b) An attempt was made to 'fix' (i.e. convert to integer) a number which would not fit into a 32-bit 2's complement integer.
Note that this error is not generated when two 32-bit integers are added or subtracted: if an overflow happens here, it will go undetected (try 'PRINT 2000000000+2000000000').
ASN(X) = ATN(X/SQR(1-X*X)) ACS(X) = PI/2 - ASN(X)
Error conditions
Error number: 21 '-ve root'
Stack contents: RTI information 3 bytes
undefined 21 22 '-ve root'
A undefined
X undefined
Y undefined
LOG(X) = LN(X)/LN(10)
(BASIC stores 1/LN(10) as a constant, and uses a multiply to convert the LN to a LOG.)
Error 23 - Accuracy lost
This error is generated by the BASIC SIN, COS, or TAN routines if the binary exponent of the floating point argument is &98 or greater. If it is, then at least 24 of the 32 bits in the mantissa make up the integer part of the number, leaving only 8 bits (or less) for the fractional part. This gives a resolution of worse than 1/256 (0.004) in the result from a SIN or COS (and all of this from the least significant byte).
The angle given to these trigonometric routines is reduced to the range 0 to PI/2 by subtracting a multiple of PI/2 from it. This does not introduce a significant amount of extra inaccuracy, as BASIC stores a more accurate (41 bits) - PI/2 as 2 separate numbers: a 'coarse' - PI/2, and an accurate adjustment to it.
A binary exponent of FPA
X undefined
Y undefined
A^B = EXP(B*LN(A))
Error conditions
Error number: 24 'Exp range'
Stack contents: RTI information 3 bytes
undefined
A undefined
X undefined
Y undefined
It is possible to recover from this error and perform the MODE change if the BASIC ST ACK can be preserved. This can be achieved by either shifting it to where the new HIMEM is, or (more simply) by leaving HIMEM where it was, and only allowing MODE changes which leave the bottom of screen memory higher than this. See section 9.1 for a 'Bad MODE' trap program.
&2A Prospective MODE number (LSB of IntA)
A undefined
X undefined
Y undefined
2 The bottom of the new MODE (found using OSBYTE &85) would not be below the top of the HEAP
3 The bottom of the new MODE would not be below TOP
4 The contents of the BASIC STACK can be preserved
2 Pull the 3 bytes of RTI information from the stack. Pull the MODE change character from the 6502 stack, and print it (using OSWRCH)
3 Get the new mode number from &2A, and send that to OSWRCH
4 Continue with the execution of the BASIC statements by making a JMP to the 'Continue execution' routine at &8B0C (BASIC1) or &8B9B (BASIC2).
This will allow a MODE change inside a FN or PROC, although HIMEM must be brought down below the bottom of the lowest MODE first. It will always allow a MODE change to a smaller mode. It should also be possible to allow mode changes to a larger mode without previously allocating the space, but that would involve shifting the BASIC ST ACK bodily, and repointing the STACK pointer.
Error 26 - No such variable
This error is generated by the BASIC 'Get <factor> or <string-factor>' routine if it tries to read the value of a variable which does 't exist. If the assembler is being used with an OPT value which has bit 1 cleared (i.e. OPT 0, 1, 4, 5), this error will be suppressed, and the current value of P% will be returned by the 'Get <factor>' routine instead. This error is suppressed if OPT 4 or 5 is used (unlike error 1 'Out of range').
By trapping this error it is possible to to add new functions to BASIC. Note, however, that the first character to be found after the name of the function must not be a '(', or BASIC will think that it is an array, and generate the 'Array' error instead (this is much more difficult to recover from). Bracketed expressions can be included after a new function, but the first '(' must be separated from the function name by a space.
&2C: type of the variable (if C=0)
(&37) points 1 before the start of the name
&39 length of the name (if C=0)
A undefined
X undefined
Y undefined
C 0=non-existent variable; 1=invalid name
Recovery should only be attempted if:
1 The error number at (&FD) is 26
2 The C flag is 0, signalling that a valid (but non-existent) variable name was found (unless you are trying to recognise a special symbol).
3 The name can be matched with the name of a new function. The length of the function name should be the same as that in &39 (if it is not, PTRB will have to be adjusted to point after the function name). Note that the first character of the name can be read by the sequence:
LDY #1 LDA (&37),Y
2 Pull the 3 bytes of RTI information from the stack.
3 Evaluate the function, and place the value in IntA, StrA, or FPA (depending on the type).
4 Load A with a byte which signals the type of the value of the function. This should be the last action performed before returning, as it sets the Z and N flags which will be tested by the code which is returned to. The type bytes are:
String: &00
Integer: &40
Real: &FF
5 Execute an RTS
This will return the value of the new function to the code which called the 'Get <factor> or <string-factor>' routine.
Error 27 - Missing )
This error is generated by BASIC if a closing bracket is expected, but none is found. This can either be caused by leaving off the ')', or by sending too many arguments to a function, or too many dimensions to an array.
Error 28 - Bad HEX
This error is generated by BASIC if the first character after an '&' was not a hexadecimal digit (i.e. 0 to 9, or A to F).
It is possible to recover from this error (if, for example, you want an '&' by itself to mean 0)
A 0
X Y
Y PTRB offset
1 Pull the 3 bytes of RTI information from the stack.
2 Load A with &40, to signal that the type of the result is an integer.
3 Execute an RTS
This will return 0 to the code which called the 'Get <factor> or <string-factor>' routine, if no HEX character followed the '&'.
Error 29 - No such FN/PROC
This error is generated by BASIC if an attempt is made to access a FN or PROC which is not defined inside the program. First, the FN/PROC handler tries to find it in the list on the HEAP; if it isn't found, it looks through the program for the definition; if it still does 't find it, this error is generated.
If this error is trapped, it is possible to overlay procedures and functions from disc, for example, and continue execution. Any routine which attempts to recover from this error should be very careful with the state of the 6502 stack, as the FN/PROC routine is in the middle of saving the information it needs to enable it to return properly at the end of the PROC or FN. See chapter 8 for more on overlaying FNs and PROCs.
A copy of &B (PTRA base LSB)
X undefined
Y 1
Recovery should only be attempted if:
1 The error number at (&FD) is 29
2 The FN or PROC can be overlayed (from disc, for example).
3 The FN or PROC is of the correct type (the token is held in location &1FF)
To recover from the error:
1 Pull the 3 bytes of RTI information from the stack.
2 Save PTRA base on the stack, by pushing the contents of &B followed by the contents of &C.
3 Load the FN or PROC to be overlayed, allocating space for it as necessary.
4 Restart the FN/PROC handler, to execute the FN or PROC.
There are two major alternative ways to re-start the FN/PROC handler:
(a) Set PTRA base (in &B,&C) to point to the first byte of the program section just overlayed (this will be the &0D usually at PAGE). Then JMP to &B149 (BASIC1) or &B11A (BASIC2). This will cause the 'Look for FN/ PROC in program' routine to search for the FN/PROC again, but this time starting from PTRA base, instead of PAGE. When the FN/PROC is found, it will be added to the list, and the main FN/PROC handler will be re-joined.
(b) Set PTRA base to point to the byte following the name of the defined PROC or FN in the overlayed section (this will be a '(' if any arguments are being used). Then JMP to &B223 (BASIC1) or &B1F4 (BASIC2). This directly rejoins the FN/PROC handler, without adding the name of the overlayed FN/PROC to the list.
Note that if (a) is being used, the same error may be generated again if the name is still not found; if (b) is being used, the name will not be tested (and does not even need to be in the file itself, as long as PTRA can still be set up to point to the character which would be after it).
Error 30 - Bad call
This error is generated by BASIC if no valid name is found after a PROC or FN token. Note that there can be no spaces between the FN or PROC token, and the name.
A undefined
X undefined
Y 2
A 0
X 0
Y undefined
Error 34 - FOR variable
This error is generated by the BASIC 'FOR' statement if there is no valid numeric variable after the FOR (i.e. either it is invalid, or it is a string variable). This variable can be an indirected variable (like '!X'), although single byte variables should not be used, as NEXT does not deal with them properly.
It is possible to recover from this error, to extend the FOR stack into the REPEAT stack area, for example. This should not normally be attempted, as any REPEAT statement will corrupt an extended FOR stack.
Error conditions
Error number: 35 'Too many FORs'
Stack contents RTI information 3 bytes
FOR stack: full
&26 &96 (or greater if already recovered)
Initial value already assigned to loop variable
A undefined
X undefined
Y copy of FOR stack pointer in &26
2 No REPEATs will be used in the program (or GOSUBs if the GOSUB stack area will be used as well).
3 The FOR stack pointer (in &26 and Y) is less than &BE (this gives room for 3 more entries). If the GOSUB stack area is to be used as well, the FOR stack pointer should be less than &F2 (this gives a total of 17 entries in the FOR stack).
2 JMP to &B7F5 (BASIC1) or &B7DA (BASIC2)
This will continue with the FOR statement, as though the FOR stack had not overflowed. The Y register should not be altered by the recovery routine, as it is used on return to the FOR handler.
Error 36 - no TO
This error is generated by the BASIC 'FOR' statement if the first non-space character after the initial value that the loop variable is to be set to, is not a 'TO' token. The initial value must be a <numeric>.
Recovery from this error is not easily possible, although it could be trapped to allow 'FOR lists'; i.e. a line of the form:
FOR I=1,3 TO 5,10
which would step through the loop with I taking the values 1,3,4,5, and 10. If this was to be implemented, a new 'NEXT' statement would have to be used for this type of 'FOR' (possibly trapped from the 'Mistake' error), as the normal NEXT would not handle it.
PTRB: points to the character after that in A
&26 FOR stack pointer
(&37) ddress of the loop variable
&39 type of the loop variable
A character after the initial value (not 'TO')
X undefined
Y copy of FOR stack pointer in &26
Recovery should only be attempted if:
1 The error number at (&FD) is 36
2 An alternative form of the 'FOR' statement can be used. Another NEXT should be used for this structure ('ENDFOR' ?), to handle the next value to be assigned to the loop variable.
2 Handle the new FOR structure, either using the FOR stack, or by creating a different stack. The address and type of the loop variable (i.e. its variable descriptor block) is already on the FOR stack.
3 If a FOR list is being used, the ENDFOR will have to look at the next item on the list; thus the current value of PTRB should be saved for it.
4 If the whole of the FOR list is to be parsed before the loop is entered, the 'Check for end of statement' routine at &9810 (BASIC1) or &9857 (BASIC2) should be called after the FOR list has been checked. Then the statements in the loop can be started with a JMP to the 'Continue execution' routine at &8B0C (BASIC1) or &8B9B (BASIC2).
5 If the FOR list is not to be parsed until the ENDFOR tries to use it, execution can be continued with a JMP to the 'Skip rest of line, and continue' routine at &8AED (BASIC1) or &8B7D (BASIC2). This will continue execution on the next program line (alternatively, the new FOR routine could just search for a ':', and continue from there).
Error 37 - Too many GOSUBs
This error is generated by the BASIC 'GOSUB' statement if there are already 26 GOSUBs on the GOSUB stack. See section 5.2 for more on GOSUBs.
Due to way that the GOSUB stack is stored (as 2 stacks, one after the other), it is not easily possible to recover this error and extend the stack in a similar manner to the FOR stack.
A undefined
X undefined
Y &1A (copy of location &25)
A undefined
X undefined
Y 0 (copy of GOSUB stack pointer in &25)
ON A#3 GOTO ...
A undefined
X non-space character after the <factor>
Y undefined
This error can be avoided by using an 'ELSE' clause after the GOTO or GOSUB list (such as 'ON I GOTO 20,30 ELSE END'), but in BASIC1 the 'GOTO' or 'GOSUB' token is left on the 6502 stack if the ELSE clause is executed. If this ELSE clause is executed inside a FN or PROC, the return from this FN or PROC will fail, as the return address will no longer be on the top of the stack. In BASIC2, this has been rectified, and the ELSE clause works correctly.
Error conditions
Error number: 40 'ON range'
Stack contents: RTI information 3
(token - BASIC1 only 1 byte 1
PTRA: points to the last part of the statement handled
A &0D
X undefined
Y offset from PTRA base to point end o line
This error could be recovered from if, for example, some sort of program overlaying mechanism is being used.
A undefined
X undefined
Y undefined
C 1
Recovery should only be attempted if:
1 The error number at (&FD) is 41
2 The line can be looked for in an alternative area (for example, in an overlayed program section)
2 Find the line in the alternative program section, and set the pointer at &3D,&3E to point 1 before the first byte of text of the line (i.e. to point to the length byte of the line). Care should be taken not to generate this error again, unless some flag is used to signal that this overlay has already been tried. If the line number is not found in the new section, and the error is generated again, this recovery routine will be called repeatedly, and the machine will 'hang up'.
3 When the line has been found, clear the carry flag (to signal that the line has been found), and execute an RTS.
This will return to the code which called the 'Evaluate and find line number' routine, which will then continue.
This error could be recovered, either if some sort of overlaying mechanism is being used, or perhaps by forcing a 'RESTORE' on an 'Out of DATA' error.
&1C,&1D: point after the last DATA item read
A undefined
X undefined
Y undefined
2 Either a RESTORE will be forced, or the DATA will be found in an alternative area
3 The DATA pointer in &1C,&1D does not still point at PAGE. If it does, there is no DATA in the program at all, and so forcing a RESTORE would have no effect.
2 Set PTRB to point to the area where the DATA will be X read from. This will be PAGE to force a RESTORE to the start of the program, or it will point to the new area if an overlay has been loaded.
3 Execute a JMP to &BB7 A (BASIC1) or &BB60 (BASIC2). This re-starts the 'Find next DATA item' routine looking from PTRB. If PTRB points at a comma or a 'DATA' token when the routine is re-started, then that routine will return to the READ statement handler, with PTRB pointing at the following DATA item.
Care should be taken that this recovery routine is not called again due to a failure to find any DATA in the new area. The DATA pointer could be used as a flag for this, by setting it to PAGE inside this recovery routine. If no DATA is found on return to the READ handler, then this error will be generated again, but with the DATA pointer still set to PAGE.
Error 43 - No REPEAT
This error is generated by the BASIC 'UNTIL' statement if the REPEAT stack is empty.
&24: 0 (REPEAT stack empty)
A undefined
X 0 (copy of REPEAT stack pointer in &24)
Y undefined
The REPEAT stack cannot be extended like the FOR stack, as it saves the MSB and LSB of the pointer in 2 stacks, 1 after the other. See section 5.5 for more on REPEAT loops.
A undefined
X &14 (copy of REPEAT stack pointer in &24)
Y undefined
Error number: 45 'Missing #'
Stack contents: RTI information
A character not a '#'
X undefined
Y undefined
11.3 Fatal errors
These errors cannot be trapped by the 'ON ERROR' statement. Some of them are just messages, with a JMP to immediate mode after the message has been printed; others have error number 0, which cannot be trapped (in BASIC 2).
Some of the errors in this section can still be intercepted by a BRK handler, although those that can be intercepted, will all have error number 0. This means that the error message string following the error number byte must be tested if the error is to be identified correctly.
If the program is OK, the 'Bad program' check routine resets TOP to the top of the program, and returns to the calling routine. The check is made when:
(a) A new program has been loaded (either by 'LOAD' or 'CHAIN').
(b) An 'OLD' statement has been executed
(c) A 'LIST' statement is about to be executed
(d) A 'RENUMBER' command is about to be executed
(e) An 'END' statement is executed. As an END statement is executed at the end of the default BASIC ERROR handler, this check will also be made whenever an error occurs.
See section 9.2 for a 'Bad program' salvage routine.
Failed at xxx
This message is printed by the 'RENUMBER' command if it finds any references to non-existent line numbers. This error cannot be trapped, but it will not abort the RENUMBERing of the program; it will just produce a list of the lines on which it found unresolved line number references.
This error, although 'fatal' to BASIC, could be recovered from if more memory could be allocated (by forcing a MODE change, perhaps).
&3B,&3C points to the first character to be inserted
A undefined
X undefined
Y undefined
Recovery should only be attempted if:
1 The error number at (&FD) is 0, followed by the string 'Line space', terminated by a zero byte.
2 HIMEM can be moved up from its present position, perhaps by a MODE change. If it can't be moved, then recovery should be aborted.
To recover from the error:
1 Pull the 3 bytes of RTI information from the stack
2 Change MODE to shift HIMEM to a higher value
3 Execute a JMP to &BC96 (BASIC1 or BASIC2 - the addresses coincide).
This will re-enter the routine to insert the line in the program. Note that if this recovery is attempted without moving HIMEM up, then this error will just be generated again, and the machine will 'hang up'.
No room
This error is generated by BASIC if an attempt is made to extend the HEAP above the STACK, or extend the STACK below the HEAP. In BASIC1, this is a message which is printed before a JMP to immediate mode (so it gives no line number); but in BASIC2 it is an error with error number 0.
In BASIC2 it is possible to trap this error, and recover from it under certain circumstances (providing some more memory can be found from somewhere); but in BASIC1 it does not go through the BRK handler, and so cannot be trapped.
The 'No room' error can be caused in one of 3 ways:
(a) An attempt was made to allocate space for a new variable information block on top of the HEAP. If this is the case, then the error is not recoverable, because the 'Allocate new information block' routine clears the space for the block before checking for a clash with the STACK: thus the contents of the STACK will be corrupted.
(b) An attempt was made to allocate space for a dynamic string on the HEAP. This error is recoverable, as a clash with the STACK is tested for before the string is written into the new area.
(c) An attempt was made to allocate space on the BASIC STACK. This error is also recoverable, because a clash with the HEAP is tested for before the item to be pushed is written into the allocated area.
These 3 different causes of a 'No room' must be handled differently, as they require different return conditions, and in the case of (a), recovery should not be attempted at all.
A 0
X 0
Y 1
C 1
If (b):
A undefined
X MSB of attempted new HEAP
Y LSB of attempted new HEAP
C 1
If (c):
A LSB of attempted new STACK (copy of location &4)
X undefined
Y MSB of attempted new STACK (copy of location &5)
C 0
2 The error was not caused by case (a). If the carry flag was clear when the BRK occurred (this should be tested from the RTI information on the 6502 stack) then it was due to case (c), and recovery is possible. Otherwise, if the X register is non-zero it was due to case (b), and recovery is also possible. If the carry flag was set, and the X register is zero, it was due to case (a), and recovery should be aborted.
To recover from the error:
1 Pull the 3 bytes of RTI information from the stack (the top byte was the 6502 status word when the BRK occurred, and the carry can be checked from there)
2 Allocate some more memory. This could either be done by forcing a mode change, or perhaps by throwing away any overlayed program sections which have been placed between HIMEM and the bottom of the screem. Both of these will involve shifting the STACK bodily, and pointing the STACK pointer (in &4,&5) at the bottom of the new ST ACK.
3 Check that the HEAP/STACK clash does not still exist: it may be that not enough memory could be cleared. If (c) is being dealt with, then the STACK and HEAP will be in the pointers already; but in case (b), the old HEAP pointer is in &2,&3 and the new one is in X (MSB) and Y (LSB).
4 If (c) is being dealt with, then simply executing an RTS will return to the code that called the 'Check for STACK/ HEAP clash' routine.
5 If (b) is being dealt with, then the 'Assign string' routine can be continued with a JMP to &8C6F (BASIC2 only). The new HEAP pointer must be in the X and Y registers as on entry (alternatively, if the new HEAP pointer is already set up by the recovery routine, a JMP can be made to &8C73 instead).
Trapping this routine, together with trapping the 'No such FN/ PROC' error (error 29), would give a very neat method of procedure and function overlaying. When a FN or PROC is not found in the program, the STACK can be shifted down and an overlay loaded from disc between HIMEM and the bottom of the screen; and when the computer runs out of memory and issues a 'No room' error, the overlay can be removed, and the STACK shifted up again.
RENUMBER space
When the RENUMBER statement is used, it creates a list of the old line numbers above TOP so that it can match up the GOTO and GOSUB references after the lines have been renumbered. This error is generated if there is not enough room between the TOP of the program and HIMEM to fit this list.
It is possible to recover from this error (if you really want to have all the lines in your program with the same line number).
A 0 if the interval = 0, non-zero if interval > 255
X undefined
Y undefined
This error should only be recovered if:
1 The error number at (&FD) is 0, followed by the string 'Silly', terminated by a zero byte.
To recover from the error:
1 Pull the 3 bytes of RTI information from the 6502 stack
2 Execute a JMP to &8F28 (BASIC1) or &8F8B (BASIC2)
This will continue with the AUTO or RENUMBER command,
ignoring any silly restrictions on the size of the interval.
Error number 0 'STOP'
Stack contents: RTI information 3 bytes
A undefined
X undefined
Y undefined