chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / BAS / src / s / basTalk
1 ;
2 ; basTalk.s
3 ;
4 ; Interface to BASIC's weird routines
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's BASIC Assembler Supplement.
12 ;
13 ; BAS is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
16 ; any later version.
17 ;
18 ; BAS is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 ; GNU General Public License for more details.
22 ;
23 ; You should have received a copy of the GNU General Public License
24 ; along with BAS.  If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27 ;----- Standard Header ------------------------------------------------------
28
29                 GET     libs:header
30                 GET     libs:swis
31
32                 GET     libs:stream
33
34 ;----- External dependencies ------------------------------------------------
35
36                 GET     sh.basicEnv
37                 GET     sh.messages
38                 GET     sh.string
39                 GET     sh.workspace
40
41 ;----- Main code ------------------------------------------------------------
42
43                 AREA    |BAS$$Code|,CODE,READONLY
44
45 ; --- bTalk_lvblnk ---
46 ;
47 ; On entry:     R0 == pointer to variable name to find (not tokenised)
48 ;
49 ; On exit:      R0 == address of lvalue
50 ;               R1 == type of lvalue
51 ;
52 ; Use:          Tries to locate the given BASIC variable.
53
54                 EXPORT  bTalk_lvblnk
55 bTalk_lvblnk    ROUT
56
57                 STMFD   R13!,{R0-R12,R14}       ;Save some registers
58
59                 ; --- Make sure name is tokenised ---
60
61                 BL      str_buffer              ;Get a string buffer nicely
62                 MOV     R2,R1                   ;This is the destination
63                 MOV     R11,R2                  ;Keep a pointer to it
64                 MOV     R1,R0                   ;Point to his source string
65                 BL      bTalk_match             ;Tokenise the variable name
66
67                 ; --- Find the lvalue ---
68
69                 LDR     R7,be__interface        ;Point to EIB
70                 LDR     R8,be__argp             ;Get argp pointer
71                 LDR     R12,be__line            ;Get line pointer
72                 MOV     R14,PC                  ;Set up return address
73                 ADD     PC,R7,#bEnv_lvblnk      ;Call BASIC's strange routine
74                 MOVNE   R1,R9                   ;Get variable type in R1
75                 ADDNE   R13,R13,#8              ;Don't keep R0, R1 saved
76                 LDMNEFD R13!,{R2-R12,PC}^       ;Return if found
77
78                 ; --- Complain about duff variable names ---
79
80 bTalk__badName  LDR     R12,[R13,#48]           ;Find workspace (good plan)
81                 LDR     R2,[R13,#0]             ;Point to the variable name
82                 ADRCSL  R0,msg_errBadLValue     ;If very bad, point to error
83                 ADRCCL  R0,msg_errVarNotFound   ;Otherwise say couldn't find
84                 BL      str_error               ;Build appropriate error
85                 SWI     OS_GenerateError        ;And report it nicely
86
87                 LTORG
88
89 ; --- bTalk_create ---
90 ;
91 ; On entry:     R0 == pointer to name of variable
92 ;
93 ; On exit:      R0 == address of variable lvalue
94 ;               R1 == type of variable created
95 ;
96 ; Use:          Creates a variable, if it doesn't already exist.  Otherwise
97 ;               a pointer to the existing variable is returned.
98
99                 EXPORT  bTalk_create
100 bTalk_create    ROUT
101
102                 STMFD   R13!,{R0-R12,R14}       ;Save too many registers
103
104                 ; --- Make sure name is tokenised ---
105
106                 BL      str_buffer              ;Get a string buffer nicely
107                 MOV     R2,R1                   ;This is the destination
108                 MOV     R11,R2                  ;Keep a pointer to it
109                 MOV     R1,R0                   ;Point to his source string
110                 BL      bTalk_match             ;Tokenise the variable name
111
112                 ; --- Find the lvalue ---
113
114                 LDR     R7,be__interface        ;Point to EIB
115                 LDR     R8,be__argp             ;Get argp pointer
116                 LDR     R12,be__line            ;Get line pointer
117                 MOV     R14,PC                  ;Set up return address
118                 ADD     PC,R7,#bEnv_lvblnk      ;Call BASIC's strange routine
119                 MOVNE   R1,R9                   ;Get variable type in R1
120                 ADDNE   R13,R13,#8              ;Don't keep R0, R1 saved
121                 LDMNEFD R13!,{R2-R12,PC}^       ;Return if found
122                 BCS     bTalk__badName          ;Contort rampantly on error
123
124                 ; --- Wasn't there -- try to create it ---
125
126                 MOV     R14,PC                  ;Set up return address
127                 ADD     PC,R7,#bEnv_create      ;Call CREATE routine
128                 MOV     R1,R9                   ;Get the variable type
129                 ADD     R13,R13,#8              ;Don't keep R0, R1 saved
130                 LDMFD   R13!,{R2-R12,PC}^       ;Return pristine variable
131
132                 LTORG
133
134 ; --- bTalk_store ---
135 ;
136 ; On entry:     R0 == lvalue in which to store
137 ;               R1 == type of lvalue
138 ;               R2 == (integer) value to store
139 ;
140 ; On exit:      --
141 ;
142 ; Use:          Stores an integer value in a BASIC variable.  The value is
143 ;               converted to floating point if required (without loss of
144 ;               precision).
145
146                 EXPORT  bTalk_store
147 bTalk_store     ROUT
148
149                 STMFD   R13!,{R0-R12,R14}       ;Save too many registers
150                 MOV     R4,R0                   ;Point to the lvalue
151                 MOV     R5,R1                   ;Get the lvalue's type
152                 MOV     R0,R2                   ;Put value in R0
153                 MOV     R9,#&40000000           ;It's an integer, Jim
154                 LDR     R7,be__interface        ;Find the EIB
155                 LDR     R8,be__argp             ;Get BASIC's workspace
156                 LDR     R12,be__line            ;Tell it which line we're on
157                 MOV     R14,PC                  ;Set up return address
158                 ADD     PC,R7,#bEnv_storea      ;Save the values away
159                 LDMFD   R13!,{R0-R12,PC}^       ;Return to caller
160
161                 LTORG
162
163 ; --- bTalk_load ---
164 ;
165 ; On entry:     R0 == address of lvalue
166 ;               R1 == type of lvalue
167 ;
168 ; On exit:      R2 == integer value of lvalue
169 ;
170 ; Use:          Loads an integer variable from an lvalue.
171
172                 EXPORT  bTalk_load
173 bTalk_load      ROUT
174
175                 STMFD   R13!,{R0,R1,R3-R12,R14} ;Save lots of registers
176
177                 ; --- Load value from register ---
178
179                 LDR     R8,be__argp             ;Load BASIC's workspace
180                 LDR     R7,be__interface        ;Find the EIB
181                 LDR     R12,be__line            ;And get the current LINE
182
183                 MOV     R9,R1                   ;Get the lvalue's type
184                 MOV     R14,PC                  ;Set up return address
185                 ADD     PC,R7,#bEnv_varind      ;Load the variable value
186                 TEQ     R9,#0                   ;Was it a string?
187                 BEQ     %80bTalk_load           ;Yes -- this is evil
188
189                 ; --- Now convert floating point to integer ---
190
191                 MOVMI   R14,PC                  ;Set up return address
192                 ADDMI   PC,R7,#bEnv_fix         ;And fix it into R0
193
194                 ; --- Return the value ---
195
196                 MOV     R2,R0                   ;Put value in R2 nicely
197                 LDMFD   R13!,{R0,R1,R3-R12,PC}^ ;Return to caller
198
199                 ; --- Silly user gave us a string ---
200
201 80bTalk_load    ADRL    R0,msg_errOddString     ;Point to error
202                 SWI     OS_GenerateError        ;And tell the world
203
204                 LTORG
205
206 ; --- bTalk_eval ---
207 ;
208 ; On entry:     R1 == pointer to a control-terminated string
209 ;
210 ; On exit:      R0 == value of expression
211 ;
212 ; Use:          Evaluates a BASIC expression.
213
214                 EXPORT  bTalk_eval
215 bTalk_eval      ROUT
216
217                 STMFD   R13!,{R1-R12,R14}       ;Save some registers
218                 MOV     R0,R1                   ;Look after string address
219                 BL      str_buffer              ;Get a string buffer
220                 MOV     R2,R1                   ;This is destination buffer
221                 MOV     R1,R0                   ;Point to source buffer
222                 BL      bTalk_match             ;Tokenise the string nicely
223
224                 ; --- Evaluate the expression ---
225
226                 LDR     R8,be__argp             ;Load BASIC's workspace
227                 LDR     R7,be__interface        ;Find the interface block
228                 LDR     R12,be__line            ;Load current LINE value
229                 MOV     R11,R2                  ;Point to tokenised expr
230                 STMFD   R13!,{R7}               ;Save environment pointer
231                 MOV     R14,PC                  ;Set up return address
232                 ADD     PC,R7,#bEnv_expr        ;Get BASIC to evaluate it
233                 LDMFD   R13!,{R7}               ;Restore environment pointer
234                 BEQ     %80bTalk_eval           ;If string, make an error
235
236                 MOVMI   R14,PC                  ;If floating point, fix it
237                 ADDMI   PC,R7,#bEnv_fix         ;To get an integer
238
239                 LDMFD   R13!,{R1-R12,PC}^       ;And return value to caller
240
241                 ; --- Expression gave us a string ---
242
243 80bTalk_eval    ADRL    R0,msg_errOddString     ;Point to error message
244                 SWI     OS_GenerateError        ;And raise an error nicely
245
246                 LTORG
247
248 ; --- bTalk_match ---
249 ;
250 ; On entry:     R1 == ctrl terminated string
251 ;               R2 == destination pointer
252 ;
253 ; On exit:      --
254 ;
255 ; Use:          Tokenises the given sting, and puts the result in the
256 ;               destination buffer given.
257
258                 EXPORT  bTalk_match
259 bTalk_match     ROUT
260
261                 STMFD   R13!,{R0-R5,R14}        ;Store some registers
262
263                 ; --- BASIC wants string CR terminated ---
264
265                 MOV     R3,R1                   ;Point to source string
266 00bTalk_match   LDRB    R14,[R3],#1             ;Load the next byte
267                 CMP     R14,#32                 ;Is this the end of it?
268                 BCS     %00bTalk_match          ;No -- go round again then
269                 MOV     R14,#13                 ;Want it CR terminated
270                 STRB    R14,[R3,#-1]            ;Save over terminator
271
272                 ; --- Get BASIC to do tokenising ---
273
274                 MOV     R3,#0                   ;Parse an lvalue
275                 MOV     R4,#0                   ;Without line numbers
276                 LDR     R5,be__interface        ;Get the EIB
277                 MOV     R14,PC                  ;Set up return address
278                 ADD     PC,R5,#bEnv_match       ;Call match routine
279                 LDMFD   R13!,{R0-R5,PC}^        ;Return with gleefulness
280
281                 LTORG
282
283 ;----- That's all, folks ----------------------------------------------------
284
285                 END