; ; basTalk.s ; ; Interface to BASIC's weird routines ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's BASIC Assembler Supplement. ; ; BAS is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; BAS is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with BAS. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard Header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sh.basicEnv GET sh.messages GET sh.string GET sh.workspace ;----- Main code ------------------------------------------------------------ AREA |BAS$$Code|,CODE,READONLY ; --- bTalk_lvblnk --- ; ; On entry: R0 == pointer to variable name to find (not tokenised) ; ; On exit: R0 == address of lvalue ; R1 == type of lvalue ; ; Use: Tries to locate the given BASIC variable. EXPORT bTalk_lvblnk bTalk_lvblnk ROUT STMFD R13!,{R0-R12,R14} ;Save some registers ; --- Make sure name is tokenised --- BL str_buffer ;Get a string buffer nicely MOV R2,R1 ;This is the destination MOV R11,R2 ;Keep a pointer to it MOV R1,R0 ;Point to his source string BL bTalk_match ;Tokenise the variable name ; --- Find the lvalue --- LDR R7,be__interface ;Point to EIB LDR R8,be__argp ;Get argp pointer LDR R12,be__line ;Get line pointer MOV R14,PC ;Set up return address ADD PC,R7,#bEnv_lvblnk ;Call BASIC's strange routine MOVNE R1,R9 ;Get variable type in R1 ADDNE R13,R13,#8 ;Don't keep R0, R1 saved LDMNEFD R13!,{R2-R12,PC}^ ;Return if found ; --- Complain about duff variable names --- bTalk__badName LDR R12,[R13,#48] ;Find workspace (good plan) LDR R2,[R13,#0] ;Point to the variable name ADRCSL R0,msg_errBadLValue ;If very bad, point to error ADRCCL R0,msg_errVarNotFound ;Otherwise say couldn't find BL str_error ;Build appropriate error SWI OS_GenerateError ;And report it nicely LTORG ; --- bTalk_create --- ; ; On entry: R0 == pointer to name of variable ; ; On exit: R0 == address of variable lvalue ; R1 == type of variable created ; ; Use: Creates a variable, if it doesn't already exist. Otherwise ; a pointer to the existing variable is returned. EXPORT bTalk_create bTalk_create ROUT STMFD R13!,{R0-R12,R14} ;Save too many registers ; --- Make sure name is tokenised --- BL str_buffer ;Get a string buffer nicely MOV R2,R1 ;This is the destination MOV R11,R2 ;Keep a pointer to it MOV R1,R0 ;Point to his source string BL bTalk_match ;Tokenise the variable name ; --- Find the lvalue --- LDR R7,be__interface ;Point to EIB LDR R8,be__argp ;Get argp pointer LDR R12,be__line ;Get line pointer MOV R14,PC ;Set up return address ADD PC,R7,#bEnv_lvblnk ;Call BASIC's strange routine MOVNE R1,R9 ;Get variable type in R1 ADDNE R13,R13,#8 ;Don't keep R0, R1 saved LDMNEFD R13!,{R2-R12,PC}^ ;Return if found BCS bTalk__badName ;Contort rampantly on error ; --- Wasn't there -- try to create it --- MOV R14,PC ;Set up return address ADD PC,R7,#bEnv_create ;Call CREATE routine MOV R1,R9 ;Get the variable type ADD R13,R13,#8 ;Don't keep R0, R1 saved LDMFD R13!,{R2-R12,PC}^ ;Return pristine variable LTORG ; --- bTalk_store --- ; ; On entry: R0 == lvalue in which to store ; R1 == type of lvalue ; R2 == (integer) value to store ; ; On exit: -- ; ; Use: Stores an integer value in a BASIC variable. The value is ; converted to floating point if required (without loss of ; precision). EXPORT bTalk_store bTalk_store ROUT STMFD R13!,{R0-R12,R14} ;Save too many registers MOV R4,R0 ;Point to the lvalue MOV R5,R1 ;Get the lvalue's type MOV R0,R2 ;Put value in R0 MOV R9,#&40000000 ;It's an integer, Jim LDR R7,be__interface ;Find the EIB LDR R8,be__argp ;Get BASIC's workspace LDR R12,be__line ;Tell it which line we're on MOV R14,PC ;Set up return address ADD PC,R7,#bEnv_storea ;Save the values away LDMFD R13!,{R0-R12,PC}^ ;Return to caller LTORG ; --- bTalk_load --- ; ; On entry: R0 == address of lvalue ; R1 == type of lvalue ; ; On exit: R2 == integer value of lvalue ; ; Use: Loads an integer variable from an lvalue. EXPORT bTalk_load bTalk_load ROUT STMFD R13!,{R0,R1,R3-R12,R14} ;Save lots of registers ; --- Load value from register --- LDR R8,be__argp ;Load BASIC's workspace LDR R7,be__interface ;Find the EIB LDR R12,be__line ;And get the current LINE MOV R9,R1 ;Get the lvalue's type MOV R14,PC ;Set up return address ADD PC,R7,#bEnv_varind ;Load the variable value TEQ R9,#0 ;Was it a string? BEQ %80bTalk_load ;Yes -- this is evil ; --- Now convert floating point to integer --- MOVMI R14,PC ;Set up return address ADDMI PC,R7,#bEnv_fix ;And fix it into R0 ; --- Return the value --- MOV R2,R0 ;Put value in R2 nicely LDMFD R13!,{R0,R1,R3-R12,PC}^ ;Return to caller ; --- Silly user gave us a string --- 80bTalk_load ADRL R0,msg_errOddString ;Point to error SWI OS_GenerateError ;And tell the world LTORG ; --- bTalk_eval --- ; ; On entry: R1 == pointer to a control-terminated string ; ; On exit: R0 == value of expression ; ; Use: Evaluates a BASIC expression. EXPORT bTalk_eval bTalk_eval ROUT STMFD R13!,{R1-R12,R14} ;Save some registers MOV R0,R1 ;Look after string address BL str_buffer ;Get a string buffer MOV R2,R1 ;This is destination buffer MOV R1,R0 ;Point to source buffer BL bTalk_match ;Tokenise the string nicely ; --- Evaluate the expression --- LDR R8,be__argp ;Load BASIC's workspace LDR R7,be__interface ;Find the interface block LDR R12,be__line ;Load current LINE value MOV R11,R2 ;Point to tokenised expr STMFD R13!,{R7} ;Save environment pointer MOV R14,PC ;Set up return address ADD PC,R7,#bEnv_expr ;Get BASIC to evaluate it LDMFD R13!,{R7} ;Restore environment pointer BEQ %80bTalk_eval ;If string, make an error MOVMI R14,PC ;If floating point, fix it ADDMI PC,R7,#bEnv_fix ;To get an integer LDMFD R13!,{R1-R12,PC}^ ;And return value to caller ; --- Expression gave us a string --- 80bTalk_eval ADRL R0,msg_errOddString ;Point to error message SWI OS_GenerateError ;And raise an error nicely LTORG ; --- bTalk_match --- ; ; On entry: R1 == ctrl terminated string ; R2 == destination pointer ; ; On exit: -- ; ; Use: Tokenises the given sting, and puts the result in the ; destination buffer given. EXPORT bTalk_match bTalk_match ROUT STMFD R13!,{R0-R5,R14} ;Store some registers ; --- BASIC wants string CR terminated --- MOV R3,R1 ;Point to source string 00bTalk_match LDRB R14,[R3],#1 ;Load the next byte CMP R14,#32 ;Is this the end of it? BCS %00bTalk_match ;No -- go round again then MOV R14,#13 ;Want it CR terminated STRB R14,[R3,#-1] ;Save over terminator ; --- Get BASIC to do tokenising --- MOV R3,#0 ;Parse an lvalue MOV R4,#0 ;Without line numbers LDR R5,be__interface ;Get the EIB MOV R14,PC ;Set up return address ADD PC,R5,#bEnv_match ;Call match routine LDMFD R13!,{R0-R5,PC}^ ;Return with gleefulness LTORG ;----- That's all, folks ---------------------------------------------------- END