| Routines

28B2: THE 'LOOK-VARS' SUBROUTINE

Used by the routines at SAVE_ETC, CLASS_01, CLASS_04, S_LETTER and DIM. This subroutine is called whenever a search of the variables area or of the arguments of a DEF FN statement is required. The subroutine is entered with the system variable CH-ADD pointing to the first letter of the name of the variable whose location is being sought. The name will be in the program area or the work space. The subroutine initially builds up a discriminator byte, in the C register, that is based on the first letter of the variable's name. Bits 5 and 6 of this byte indicate the type of the variable that is being handled. The B register is used as a bit register to hold flags.
Output
C | Bits 0-4: Code of the variable's name (if executing)
C | Bit 5: Set if the variable is numeric, reset if it's a string
C | Bit 6: Set if the variable is simple, reset if it's an array
C | Bit 7: Set if checking syntax, reset if executing
HL | Address of the last letter of the variable's name (in the variables area, if found)
F | Carry flag reset if the variable already exists or if checking syntax
F | Zero flag reset if the variable is simple (not an array) and does not exist
LOOK_VARS | 28B2 | SET 6,(IY+$01) | Presume a numeric variable (set bit 6 of FLAGS).
| 28B6 | RST $18 | Get the first character into A.
| 28B7 | CALL ALPHA | Is it alphabetic?
| 28BA | JP NC,REPORT_C | Give an error report if it is not so.
| 28BD | PUSH HL | Save the pointer to the first letter.
| 28BE | AND $1F | Transfer bits 0 to 4 of the letter to the C register; bits 5 and 7 are always reset.
| 28C0 | LD C,A
| 28C1 | RST $20 | Get the second character into A.
| 28C2 | PUSH HL | Save this pointer also.
| 28C3 | CP "(" | Is the second character a '('?
| 28C5 | JR Z,V_RUN_SYN | Separate arrays of numbers.
| 28C7 | SET 6,C | Now set bit 6.
| 28C9 | CP "$" | Is the second character a '$'?
| 28CB | JR Z,V_STR_VAR | Separate all the strings.
| 28CD | SET 5,C | Now set bit 5.
| 28CF | CALL ALPHANUM | If the variable's name has only one character then jump forward.
| 28D2 | JR NC,V_TEST_FN
Now find the end character of a name that has more than one character.
V_CHAR | 28D4 | CALL ALPHANUM | Is the character alphanumeric?
| 28D7 | JR NC,V_RUN_SYN | Jump out of the loop when the end of the name is found.
| 28D9 | RES 6,C | Mark the discriminator byte.
| 28DB | RST $20 | Get the next character.
| 28DC | JR V_CHAR | Go back to test it.
Simple strings and arrays of strings require that bit 6 of FLAGS is reset.
V_STR_VAR | 28DE | RST $20 | Step CH-ADD past the '$'.
| 28DF | RES 6,(IY+$01) | Reset bit 6 of FLAGS to indicate a string.
If DEFADD-hi is non-zero, indicating that a 'function' (a 'FN') is being evaluated, and if in 'run-time', a search will be made of the arguments in the DEF FN statement.
V_TEST_FN | 28E3 | LD A,($5C0C) | Is DEFADD-hi zero?
| 28E6 | AND A
| 28E7 | JR Z,V_RUN_SYN | If so, jump forward.
| 28E9 | CALL SYNTAX_Z | In 'run-time'?
| 28EC | JP NZ,STK_F_ARG | If so, jump forward to search the DEF FN statement.
This entry point is used by the routine at STK_F_ARG. Otherwise (or if the variable was not found in the DEF FN statement) a search of variables area will be made, unless syntax is being checked.
V_RUN_SYN | 28EF | LD B,C | Copy the discriminator byte to the B register.
| 28F0 | CALL SYNTAX_Z | Jump forward if in 'run-time'.
| 28F3 | JR NZ,V_RUN
| 28F5 | LD A,C | Move the discriminator to A.
| 28F6 | AND $E0 | Drop the character code part.
| 28F8 | SET 7,A | Indicate syntax by setting bit 7.
| 28FA | LD C,A | Restore the discriminator.
| 28FB | JR V_SYNTAX | Jump forward to continue.
A BASIC line is being executed so make a search of the variables area.
V_RUN | 28FD | LD HL,($5C4B) | Pick up the VARS pointer.
Now enter a loop to consider the names of the existing variables.
V_EACH | 2900 | LD A,(HL) | The first letter of each existing variable.
| 2901 | AND $7F | Match on bits 0 to 6.
| 2903 | JR Z,V_80_BYTE | Jump when the '+80-byte' is reached.
| 2905 | CP C | The actual comparison.
| 2906 | JR NZ,V_NEXT | Jump forward if the first characters do not match.
| 2908 | RLA | Rotate A leftwards and then double it to test bits 5 and 6.
| 2909 | ADD A,A
| 290A | JP P,V_FOUND_2 | Strings and array variables.
| 290D | JR C,V_FOUND_2 | Simple numeric and FOR-NEXT variables.
Long names are required to be matched fully.
| 290F | POP DE | Take a copy of the pointer to the second character.
| 2910 | PUSH DE
| 2911 | PUSH HL | Save the first letter pointer.
V_MATCHES | 2912 | INC HL | Consider the next character.
V_SPACES | 2913 | LD A,(DE) | Fetch each character in turn.
| 2914 | INC DE | Point to the next character.
| 2915 | CP " " | Is the character a 'space'?
| 2917 | JR Z,V_SPACES | Ignore the spaces.
| 2919 | OR $20 | Set bit 5 so as to match lower and upper case letters.
| 291B | CP (HL) | Make the comparison.
| 291C | JR Z,V_MATCHES | Back for another character if it does match.
| 291E | OR $80 | Will it match with bit 7 set?
| 2920 | CP (HL) | Try it.
| 2921 | JR NZ,V_GET_PTR | Jump forward if the 'last characters' do not match.
| 2923 | LD A,(DE) | Check that the end of the name has been reached before jumping forward.
| 2924 | CALL ALPHANUM
| 2927 | JR NC,V_FOUND_1
In all cases where the names fail to match the HL register pair has to be made to point to the next variable in the variables area.
V_GET_PTR | 2929 | POP HL | Fetch the pointer.
V_NEXT | 292A | PUSH BC | Save B and C briefly.
| 292B | CALL NEXT_ONE | DE is made to point to the next variable.
| 292E | EX DE,HL | Switch the two pointers.
| 292F | POP BC | Get B and C back.
| 2930 | JR V_EACH | Go around the loop again.
Come here if no entry was found with the correct name.
V_80_BYTE | 2932 | SET 7,B | Signal 'variable not found'.
Come here if checking syntax.
V_SYNTAX | 2934 | POP DE | Drop the pointer to the second character.
| 2935 | RST $18 | Fetch the present character.
| 2936 | CP "(" | Is it a '('?
| 2938 | JR Z,V_PASS | Jump forward if so.
| 293A | SET 5,B | Indicate not dealing with an array and jump forward.
| 293C | JR V_END
Come here when an entry with the correct name was found.
V_FOUND_1 | 293E | POP DE | Drop the saved variable pointer.
V_FOUND_2 | 293F | POP DE | Drop the second character pointer.
| 2940 | POP DE | Drop the first letter pointer.
| 2941 | PUSH HL | Save the 'last' letter pointer.
| 2942 | RST $18 | Fetch the current character.
If the matching variable name has more than a single letter then the other characters must be passed over. Note: this appears to have been done already at V_CHAR.
V_PASS | 2943 | CALL ALPHANUM | Is it alphanumeric?
| 2946 | JR NC,V_END | Jump when the end of the name has been found.
| 2948 | RST $20 | Fetch the next character.
| 2949 | JR V_PASS | Go back and test it.
The exit-parameters are now set.
V_END | 294B | POP HL | HL holds the pointer to the letter of a short name or the 'last' character of a long name.
| 294C | RL B | Rotate the whole register.
| 294E | BIT 6,B | Specify the state of bit 6.
| 2950 | RET | Finished.
The exit-parameters for the subroutine can be summarised as follows. The system variable CH-ADD points to the first location after the name of the variable as it occurs in the BASIC line. When 'variable not found': The carry flag is set. The zero flag is set only when the search was for an array variable. The HL register pair points to the first letter of the name of the variable as it occurs in the BASIC line. When 'variable found': The carry flag is reset. The zero flag is set for both simple string variables and all array variables. The HL register pair points to the letter of a 'short' name, or the last character of a 'long' name, of the existing entry that was found in the variables area. In all cases bits 5 and 6 of the C register indicate the type of variable being handled. Bit 7 is the complement of the SYNTAX/RUN flag. But only when the subroutine is used in 'runtime' will bits 0 to 4 hold the code of the variable's letter. In syntax time the return is always made with the carry flag reset. The zero flag is set for arrays and reset for all other variables, except that a simple string name incorrectly followed by a '$' sets the zero flag and, in the case of SAVE "name" DATA a$(), passes syntax as well.