8FAE Execute next command line / program statement
Submitted by Steve Fewell
Description:
This routine has many entry points (depending on how the last statement finished and what needs to be done to tidy up
before the next statement can be executed. The entry points are listed between square brackets ([]).
Therefore, this routine may not necessarily be executed in the order described.
[&8FAE] Skip the rest of the line. This routine is called when a DATA keyword is found (as DATA statements are skipped
when reached and not executed (as the READ command controls how they are handled). It is also called when the DEF keyword
is found (as function and procedure definitions are not directly executed until they are called by an FN or PROC keyword).
This routine is also called when a REM keyword is found, to skip the rest of the line - as it is a comment line.
Additionally, this routine is also executed when a '*' command is found (the '*' command is first passed to the Operating
System OSCLI routine and then this routine skips the line - so that BASIC doesn't try to execute the '*' command.
The rest of the line is skipped as follows:
* Set A to #&0D (the end of line character - '<cr>').
* Set Y to the BASIC Text Pointer A offset (&0A) - 1.
* Keep incrementing Y and checking the character at BASIC Text pointer A (&0B-&0C) plus Y (offset) with the
character in A (the '<cr>' character) until the characters match.
* Call routine &9BBC to update the BASIC Text Pointer A address (to include the Y offset value) and to reset the offset
(&0A) to 1. (basically, this adds Y to the Text Pointer A address (&0B-&0C)).
[&8FBD] This routine checks whether the last character read (in A) is '<cr>', if it isn't then jump to &8FAE
to skip the rest of the line.
Now, we are at the end of the line (i.e. we have reached the '<cr>' character).
[&8FC1] If the BASIC Text pointer MSB address is #&07 then there are no more program lines to execute (as we were
executing a statement from the command line - and not from within a program), so jump to &8F86 to prompt for the next
command line input.
Set Y to #&01.
Load the next character (offset Y) from the BASIC text pointer A location.
If the character is negative (i.e. #&FF) then we have reached the end of the program, so jump to &8F86 to prompt
for the next command line input.
-
If the TRACE flag (location &20) is on (i.e. it's value is not zero), then:
- * Set IWA to the Line number (MSB byte (&2B) = the first byte at BASIC Text pointer A (offset 1) and the LSB byte (&2A)
- = the second byte at BASIC text pointer A location (offset 2)).
- * Call routine &9C4B to display the TRACE line number (in the IWA) on the screen.
[&8FDB] Set the BASIC Text pointer A offset (location &0A) to #&04 (i.e. the first character of the program
line - after the line number and line length).
Jump to &900D to execute the statement at the BASIC Text pointer A location.
[&8FEB] Check for special start statement characters '*', '=', 'EXT keyword' and '['
Set Y to the BASIC Text pointer A offset (location &0A) minus 1.
Load the character at the BASIC text pointer A location (plus offset - Y) (this should be the first character of the
BASIC statement).
If the character is '*' then jump to &8FA4 to execute the '*'-command.
If the character is '[' then set the OPT flag (location &28) to 3 (default setting) and jump to &8920 to begin
the assembly.
If the character is '=' then jump to &9060 to deal with returning from a function and setting the return variable's
value.
If the character is 'EXT keyword' then jump to &BE93 to execute the 'EXT =' statement. Note: In BASIC 2, it was not
possible to assign a file length (EXT) value, only to read the EXT value; therefore, only 1 BASIC token exists for the 'EXT'
keyword (unlike PTR, PAGE, LOMEM and HIMEM which have 2 keyword tokens, one for the setting of the value (where the keyword
occurs before the '='), and one for the reading of the value (where the keyword occurs after the '=')).
When BASIC version 4 was written, there was not enough spare BASIC Keyword token values to have two 'EXT' keywords
(one for 'EXT =' and the other for '= EXT'), so this workaround directly tests for the 'EXT' keyword appearing at the
start of a statement (along with the other special start statement characters '*', '[' and '=') in order to distinguish between
the reading of the EXT value and the writing of the EXT value. The EXT address in the keyword execution address table points to
the EXT read (=EXT) routine - this is used when the EXT keyword is not at the start of the BASIC program statement.
[&9000-&9048] Execute the BASIC statement
[&9000] Decrement the BASIC Text pointer A offset (location &0A).
[&9002] Call routine &9BA6 to check for the end of statement ('Syntax error' if ':', '<cr>' or 'ELSE' not found).
[&9005] Load the character pointed to by BASIC Text Pointer A.
If the character is not ':' then jump back to &8FBD to skip the rest of the program line and then proceed to execute
the statement on the next line.
[&900B] Set Y to the BASIC Text Pointer A offset (location &0A).
[&900D] Keep incrementing the BASIC Text Pointer A offset (location &0A) until we have found a non-space character.
This skips any spaces at the beginning of the BASIC Statement.
If the first non-space character is more than or equal to #&CF (PTR=, PAGE=,...,OSCLI), [i.e. it is not a Command
Line-only statement (e.g. OLD, NEW, RENUMBER, EDIT) or a middle of statement keyword (e.g. MID$, ELSE, AND, LEN), but a
valid keyword that can occur at the start of a program Statement], then:
[&9019] Jump to the keyword's execution address, as follows:
Multiply the character's ASCII Code by 2 & add the result to the base address &874D to form a pointer to the execution
address (LSB first, MSB next) of the required BASIC keyword. This resulting address is jumped to.
Example 1: Character = &CF [PTR= token] = 11001111 multiply by 2 = 10011110 (which is &9E in hex).
So, &874D + &9E = &87EB (The LSB of the execution address for the PTR= keyword (&87EC is the MSB of the address)).
Example 2: Character = &FF [OSCLI token] = 11111111 multiply by 2 = 11111110 (which is &FE in hex).
So, &874D + &FE = &884B (The LSB of the execution address for the OSCLI keyword (&884C is the MSB of the address)).
BASIC Keywords between 128 and 141 are not considered. as these Keywords are used in the middle of statements (and are not
functions), so the statements/expression handler will deal with these values. These keywords are as follows: AND, DIV, EOR,
MOD, OR, ERROR, LINE, OFF, STEP, SPC, TAB(, ELSE and THEN.
[&901E] Execute the BASIC Command line statement (which can include keywords OLD, NEW, AUTO, EDIT, etc...)
If the first/next non-space character on the command line is more than or equal to #&C6 ('AUTO') then jump back to &9019
to jump to the execution address for the BASIC keyword. This includes all BASIC statement start keywords (but not middle
of statement keywords like MID$, LEN, =PTR, AND, etc...).
Otherwise (the character is less than #&C6) continue to &9025 to check for a variable name.
[&9025] Check for variable name
If the character is less than #&CF then check whether it is a variable name as follows:
* Set BASIC Text pointer B location to the BASIC Text Pointer A location. (&19=&0B, &1A=&0C, &1B=Y)
* Call routine &9909 to evaluate a variable name at the BASIC text pointer B location.
* If routine &9909 returns with a value other than zero then jump to the LET keyword routine (address &904F).
to assign a value to the variable, as the variable was found and the address of the variable's value was found
-
* Otherwise, (routine &9909 returned zero) the variable is either invalid or hasn't been created yet, so:
- * Check the carry flag status (as returned by routine &9909). If carry is set then jump to &8FEB to
- check whether the BASIC statement begins with a special character ('*', '[', '=' or 'EXT keyword',
- and issue 'Syntax error' [via check end of statement routine &9BA6] if none of these special
- characters match the character at the start of the statement).
- * Store the BASIC text pointer B offset (in X) back to location &1B.
- * Call routine &9B86 to check whether the next non-space character after the variable name is an '=' character.
- If it isn't then issue the 'Mistake' error, as the variable assignment is not correct and a variable
- cannot appear at the start of a statement unless it is being assigned a value.
- * Otherwise, '=' was found sucessfully.
- * Call routine &9854 to add the new variable name to the variable pointer table.
- * If the variable type is a float (location &2C contains #&05) then set X to #&06; otherwise, set X to
- #&05. This specifies the amount of space to allocate for the variable's value.
- * Call routine &9883 to allocate space for the variable (and initialise it's value to zero/null).
- * Decrement the BASIC text pointer A offset (so that BASIC Text pointer A points to the first character of the
- variable name) and continue to the LET keyword routine to evaluate the variable name (again!) and
- assign the value specified after the '=' to the variable.
Disassembly for the Execute next command line / program statement routine
8FAE |
|
169 013 |
A9 0D |
LDA#&0D |
8FB0 |
|
164 010 |
A4 0A |
LDY &0A |
8FB2 |
|
136 |
88 |
DEY |
8FB3 |
|
200 |
C8 |
INY |
8FB4 |
|
209 011 |
D1 0B |
CMP (&0B),Y |
8FB6 |
|
208 251 |
D0 FB |
BNE -5 --> &8FB3 |
8FB8 |
|
032 188 155 |
20 BC 9B |
JSR &9BBC Update BASIC Text pointer A (Add offset value & then reset offset to 1) |
8FBB |
|
128 004 |
80 04 |
BRA 4 --> &8FC1 Process the next program line |
8FBD |
|
201 013 |
C9 0D |
CMP#&0D |
8FBF |
|
208 237 |
D0 ED |
BNE -19 --> &8FAE Skip the rest of the line and process the next program line |
8FC1 |
|
165 012 |
A5 0C |
LDA &0C |
8FC3 |
|
201 007 |
C9 07 |
CMP#&07 |
8FC5 |
|
240 191 |
F0 BF |
BEQ -65 --> &8F86 Read & execute command line input |
8FC7 |
|
160 001 |
A0 01 |
LDY#&01 |
8FC9 |
|
177 011 |
B1 0B |
LDA (&0B),Y |
8FCB |
0 |
048 185 |
30 B9 |
BMI -71 --> &8F86 Read & execute command line input |
8FCD |
|
166 032 |
A6 20 |
LDX &20 |
8FCF |
|
240 010 |
F0 0A |
BEQ 10 --> &8FDB |
8FD1 |
+ |
133 043 |
85 2B |
STA &2B |
8FD3 |
|
200 |
C8 |
INY |
8FD4 |
|
177 011 |
B1 0B |
LDA (&0B),Y |
8FD6 |
* |
133 042 |
85 2A |
STA &2A |
8FD8 |
K |
032 075 156 |
20 4B 9C |
JSR &9C4B Display current line number (IWA) on screen [if TRACE is on] |
8FDB |
|
160 004 |
A0 04 |
LDY#&04 |
8FDD |
|
132 010 |
84 0A |
STY &0A |
8FDF |
, |
128 044 |
80 2C |
BRA 44 --> &900D |
8FE1 |
|
169 003 |
A9 03 |
LDA#&03 |
8FE3 |
( |
133 040 |
85 28 |
STA &28 |
8FE5 |
L |
076 032 137 |
4C 20 89 |
JMP &8920 '[' Begin Assembly |
8FE8 |
L |
076 147 190 |
4C 93 BE |
JMP &BE93 EXT = |
8FEB |
|
164 010 |
A4 0A |
LDY &0A |
8FED |
|
136 |
88 |
DEY |
8FEE |
|
177 011 |
B1 0B |
LDA (&0B),Y |
8FF0 |
* |
201 042 |
C9 2A |
CMP#&2A |
8FF2 |
|
240 176 |
F0 B0 |
BEQ -80 --> &8FA4 '*'-Command |
8FF4 |
[ |
201 091 |
C9 5B |
CMP#&5B |
8FF6 |
|
240 233 |
F0 E9 |
BEQ -23 --> &8FE1 |
8FF8 |
|
201 162 |
C9 A2 |
CMP#&A2 |
8FFA |
|
240 236 |
F0 EC |
BEQ -20 --> &8FE8 |
8FFC |
= |
201 061 |
C9 3D |
CMP#&3D |
8FFE |
` |
240 096 |
F0 60 |
BEQ 96 --> &9060 '=' Return from Function Call (FN) |
9000 |
|
198 010 |
C6 0A |
DEC &0A |
9002 |
|
032 166 155 |
20 A6 9B |
JSR &9BA6 Check end of Statement |
9005 |
|
178 011 |
B2 0B |
LDA (&0B) |
9007 |
: |
201 058 |
C9 3A |
CMP#&3A |
9009 |
|
208 178 |
D0 B2 |
BNE -78 --> &8FBD Skip the rest of the line (until '<cr>' found) & process the next program line |
900B |
|
164 010 |
A4 0A |
LDY &0A |
900D |
|
230 010 |
E6 0A |
INC &0A |
900F |
|
177 011 |
B1 0B |
LDA (&0B),Y |
9011 |
|
201 032 |
C9 20 |
CMP#&20 |
9013 |
|
240 246 |
F0 F6 |
BEQ -10 --> &900B |
9015 |
|
201 207 |
C9 CF |
CMP#&CF |
9017 |
|
144 012 |
90 0C |
BCC 12 --> &9025 |
9019 |
|
010 |
0A |
ASL A |
901A |
|
170 |
AA |
TAX |
901B |
M |
124 077 135 |
7C 4D 87 |
JMP (&874D,X) |
901E |
|
032 224 142 |
20 E0 8E |
JSR &8EE0 Get next non-space character pointed to by Ptr A |
9021 |
|
201 198 |
C9 C6 |
CMP#&C6 |
9023 |
|
176 244 |
B0 F4 |
BCS -12 --> &9019 |
9025 |
|
166 011 |
A6 0B |
LDX &0B |
9027 |
|
134 025 |
86 19 |
STX &19 |
9029 |
|
166 012 |
A6 0C |
LDX &0C |
902B |
|
134 026 |
86 1A |
STX &1A |
902D |
|
132 027 |
84 1B |
STY &1B |
902F |
|
032 009 153 |
20 09 99 |
JSR &9909 Evaluate variable/array name & return the address of the value |
9032 |
|
208 027 |
D0 1B |
BNE 27 --> &904F Create variable (LET) |
9034 |
|
176 181 |
B0 B5 |
BCS -75 --> &8FEB |
9036 |
|
134 027 |
86 1B |
STX &1B |
9038 |
|
032 134 155 |
20 86 9B |
JSR &9B86 Check for '=' |
903B |
T |
032 084 152 |
20 54 98 |
JSR &9854 Create new variable name in variable pointer table |
903E |
|
162 005 |
A2 05 |
LDX#&05 |
9040 |
, |
228 044 |
E4 2C |
CPX &2C |
9042 |
|
208 001 |
D0 01 |
BNE 1 --> &9045 |
9044 |
|
232 |
E8 |
INX |
9045 |
|
032 131 152 |
20 83 98 |
JSR &9883 Allocate space for variable |
9048 |
|
198 010 |
C6 0A |
DEC &0A |
904A |
|
|
|
...LET keyword... |
Disassembly for 9B86 Check for '=' routine
9B86 |
|
032 213 142 |
20 D5 8E |
JSR &8ED5 Get next non-space character (PTR B) |
9B89 |
= |
201 061 |
C9 3D |
CMP#&3D |
9B8B |
|
208 211 |
D0 D3 |
BNE -45 --> Mistake error |
9B8D |
` |
096 |
60 |
RTS |
Or