ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
read_data.c
Go to the documentation of this file.
1/*****************************************************************************
2 * ugBASIC - an isomorphic BASIC language compiler for retrocomputers *
3 *****************************************************************************
4 * Copyright 2021-2026 Marco Spedaletti (asimov@mclink.it)
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *----------------------------------------------------------------------------
18 * Concesso in licenza secondo i termini della Licenza Apache, versione 2.0
19 * (la "Licenza"); è proibito usare questo file se non in conformità alla
20 * Licenza. Una copia della Licenza è disponibile all'indirizzo:
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Se non richiesto dalla legislazione vigente o concordato per iscritto,
25 * il software distribuito nei termini della Licenza è distribuito
26 * "COSÌ COM'È", SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO, esplicite o
27 * implicite. Consultare la Licenza per il testo specifico che regola le
28 * autorizzazioni e le limitazioni previste dalla medesima.
29 ****************************************************************************/
30
31/****************************************************************************
32 * INCLUDE SECTION
33 ****************************************************************************/
34
35#include "../../ugbc.h"
36
37/****************************************************************************
38 * CODE SECTION
39 ****************************************************************************/
40
41extern char DATATYPE_AS_STRING[][16];
42
43static void read_data_safe( Environment * _environment, char * _variable ) {
44
45 _environment->dataNeeded = 1;
46
48
49 char typeMismatchDuringReadLabel[MAX_TEMPORARY_STORAGE]; sprintf( typeMismatchDuringReadLabel, "%stm", label );
50 char doneReadLabel[MAX_TEMPORARY_STORAGE]; sprintf( doneReadLabel, "%sdone", label );
51 char completeReadLabel[MAX_TEMPORARY_STORAGE]; sprintf( completeReadLabel, "%scm", label );
52 char byteReadLabel[MAX_TEMPORARY_STORAGE]; sprintf( byteReadLabel, "%sby", label );
53 char wordReadLabel[MAX_TEMPORARY_STORAGE]; sprintf( wordReadLabel, "%swo", label );
54 char dwordReadLabel[MAX_TEMPORARY_STORAGE]; sprintf( dwordReadLabel, "%sdw", label );
55 char stringReadLabel[MAX_TEMPORARY_STORAGE]; sprintf( stringReadLabel, "%sst", label );
56
57 Variable * variable = NULL;
58
59 if ( variable_exists( _environment, _variable ) ) {
60 variable = variable_retrieve( _environment, _variable );
61 } else {
62 variable = variable_define( _environment, _variable, _environment->defaultVariableType, 0 );
63 }
64
65#if defined(__c64reu__)
66 Variable * databank = variable_retrieve( _environment, "DATABANK" );
67#endif
68 Variable * dataptr = variable_retrieve( _environment, "DATAPTR" );
69 Variable * dataptre = NULL;
70 Variable * datatype = variable_temporary( _environment, VT_BYTE, "(type)" );
71
72 VariableType type = variable->type;
73
74 if ( type == VT_DSTRING ) {
75 type = VT_STRING;
76 }
77
78#if defined(__c64reu__)
79 dataptre = variable_retrieve( _environment, "DATAPTRE" );
80#else
81 dataptre = variable_temporary( _environment, VT_ADDRESS, "(dataptre)" );
82 cpu_addressof_16bit( _environment, "DATAPTRE", dataptre->realName );
83#endif
84 cpu_compare_16bit( _environment, dataptr->realName, dataptre->realName, datatype->realName, 1 );
85 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, 0xff, doneReadLabel, 1 );
86
87#if defined(__c64reu__)
88 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, datatype->name, 1 );
89#else
90 cpu_move_8bit_indirect2( _environment, dataptr->realName, datatype->realName );
91#endif
92
93 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, type, typeMismatchDuringReadLabel, 0 );
94
95 switch( VT_BITWIDTH( variable->type ) ) {
96 case 32:
97 cpu_inc_16bit( _environment, dataptr->realName );
98#if defined(__c64reu__)
99 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, variable->name, 4 );
100#else
101 cpu_move_32bit_indirect2( _environment, dataptr->realName, variable->realName );
102#endif
103 cpu_inc_16bit( _environment, dataptr->realName );
104 cpu_inc_16bit( _environment, dataptr->realName );
105 cpu_inc_16bit( _environment, dataptr->realName );
106 cpu_inc_16bit( _environment, dataptr->realName );
107 break;
108 case 16:
109 cpu_inc_16bit( _environment, dataptr->realName );
110#if defined(__c64reu__)
111 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, variable->name, 2 );
112#else
113 cpu_move_16bit_indirect2( _environment, dataptr->realName, variable->realName );
114#endif
115 cpu_inc_16bit( _environment, dataptr->realName );
116 cpu_inc_16bit( _environment, dataptr->realName );
117 break;
118 case 8:
119 cpu_inc_16bit( _environment, dataptr->realName );
120#if defined(__c64reu__)
121 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, variable->name, 1 );
122#else
123 cpu_move_8bit_indirect2( _environment, dataptr->realName, variable->realName );
124#endif
125 cpu_inc_16bit( _environment, dataptr->realName );
126 break;
127 case 1:
129 break;
130 case 0:
131 switch( variable->type ) {
132 case VT_DSTRING: {
133 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(address)" );
134 Variable * size = variable_temporary( _environment, VT_BYTE, "(size)" );
135 cpu_inc_16bit( _environment, dataptr->realName );
136#if defined(__c64reu__)
137 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, size->name, 1 );
138#else
139 cpu_move_8bit_indirect2( _environment, dataptr->realName, size->realName );
140#endif
141 cpu_inc_16bit( _environment, dataptr->realName );
142 cpu_dsfree( _environment, variable->realName );
143 cpu_dsalloc( _environment, size->realName, variable->realName );
144 cpu_dsdescriptor( _environment, variable->realName, address->realName, size->realName );
145#if defined(__c64reu__)
146 bank_read_vars( _environment, databank->name, dataptr->name, address->name, size->name );
147#else
148 cpu_mem_move( _environment, dataptr->realName, address->realName, size->realName );
149#endif
150 cpu_math_add_16bit_with_8bit( _environment, dataptr->realName, size->realName, dataptr->realName );
151 break;
152 }
153 case VT_TYPE: {
154 Field * field = variable->typeType->first;
155 while( field ) {
156 Variable * data = variable_temporary( _environment, field->type, "(data)");
157 read_data_safe( _environment, data->name );
158 variable_move_type( _environment, variable->name, field->name, data->name );
159 field = field->next;
160 }
161 break;
162 }
163 default:
165 }
166 break;
167 }
168
169 cpu_jump( _environment, doneReadLabel );
170
171 cpu_label( _environment, typeMismatchDuringReadLabel );
172
173 if ( variable->type != VT_DSTRING && variable->type != VT_TYPE ) {
174
175 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, VT_BYTE, byteReadLabel, 1 );
176 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, VT_SBYTE, byteReadLabel, 1 );
177
178 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, VT_WORD, wordReadLabel, 1 );
179 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, VT_SWORD, wordReadLabel, 1 );
180
181 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, VT_DWORD, dwordReadLabel, 1 );
182 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, VT_SDWORD, dwordReadLabel, 1 );
183
184 cpu_compare_and_branch_8bit_const( _environment, datatype->realName, VT_STRING, stringReadLabel, 1 );
185
186 cpu_jump( _environment, doneReadLabel );
187
188 cpu_label( _environment, dwordReadLabel );
189
190 Variable * data32 = variable_temporary( _environment, VT_SIGNED( variable->type ) ? VT_SDWORD : VT_DWORD, "(data)" );
191
192 cpu_inc_16bit( _environment, dataptr->realName );
193#if defined(__c64reu__)
194 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, data32->name, 4 );
195#else
196 cpu_move_32bit_indirect2( _environment, dataptr->realName, data32->realName );
197#endif
198 cpu_inc_16bit( _environment, dataptr->realName );
199 cpu_inc_16bit( _environment, dataptr->realName );
200 cpu_inc_16bit( _environment, dataptr->realName );
201 cpu_inc_16bit( _environment, dataptr->realName );
202
203 variable_move( _environment, data32->name, variable->name );
204
205 cpu_jump( _environment, completeReadLabel );
206
207 cpu_label( _environment, wordReadLabel );
208
209 Variable * data16 = variable_temporary( _environment, VT_SIGNED( variable->type ) ? VT_SWORD : VT_WORD, "(data)" );
210
211 cpu_inc_16bit( _environment, dataptr->realName );
212#if defined(__c64reu__)
213 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, data16->name, 2 );
214#else
215 cpu_move_16bit_indirect2( _environment, dataptr->realName, data16->realName );
216#endif
217 cpu_inc_16bit( _environment, dataptr->realName );
218 cpu_inc_16bit( _environment, dataptr->realName );
219
220 variable_move( _environment, data16->name, variable->name );
221
222 cpu_jump( _environment, completeReadLabel );
223
224 cpu_label( _environment, byteReadLabel );
225
226 Variable * data8 = variable_temporary( _environment, VT_SIGNED( variable->type ) ? VT_SBYTE : VT_BYTE, "(data)" );
227
228 cpu_inc_16bit( _environment, dataptr->realName );
229#if defined(__c64reu__)
230 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, data8->name, 1 );
231#else
232 cpu_move_8bit_indirect2( _environment, dataptr->realName, data8->realName );
233#endif
234 cpu_inc_16bit( _environment, dataptr->realName );
235
236 variable_move( _environment, data8->name, variable->name );
237
238 cpu_jump( _environment, completeReadLabel );
239
240 cpu_label( _environment, stringReadLabel );
241 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(address)" );
242 Variable * size = variable_temporary( _environment, VT_BYTE, "(size)" );
243 cpu_inc_16bit( _environment, dataptr->realName );
244#if defined(__c64reu__)
245 bank_read_vars_direct_size( _environment, databank->name, dataptr->name, size->name, 1 );
246#else
247 cpu_move_8bit_indirect2( _environment, dataptr->realName, size->realName );
248#endif
249 cpu_inc_16bit( _environment, dataptr->realName );
250 cpu_dsfree( _environment, variable->realName );
251 cpu_dsalloc( _environment, size->realName, variable->realName );
252 cpu_dsdescriptor( _environment, variable->realName, address->realName, size->realName );
253#if defined(__c64reu__)
254 bank_read_vars( _environment, databank->name, dataptr->name, address->name, size->name );
255#else
256 cpu_mem_move( _environment, dataptr->realName, address->realName, size->realName );
257#endif
258 cpu_math_add_16bit_with_8bit( _environment, dataptr->realName, size->realName, dataptr->realName );
259 cpu_jump( _environment, doneReadLabel );
260
261 cpu_label( _environment, completeReadLabel );
262
263 }
264
265 cpu_label( _environment, doneReadLabel );
266
267}
268
269static void read_data_unsafe_common( Environment * _environment, char * _variable ) {
270
272
273 Variable * variable;
274 if ( variable_exists( _environment, _variable ) ) {
275 variable = variable_retrieve( _environment, _variable );
276 } else {
277 variable = variable_define( _environment, _variable, _environment->defaultVariableType, 0 );
278 }
279
280 read_data_unsafe( _environment, _variable );
281
282}
283
290/* <usermanual>
291@keyword READ
292
293@english
294
295The ''READ'' is used for reading constant values from ''DATA'' lines into the
296given variables. This command is able to read more constants at once with a
297variable list separated by commas.
298
299If using the wrong type of variable (for example read a character string into a
300numerical variable like float or integer), the variable will be untouched.
301Such behavior can be prevented by generally using a variable of the same type
302like the ''DATA AS'' used.
303
304With a value that falls outside the expected range of a ''READ'' variable,
305e.g. the value is outside the range of an integer, ugBASIC will implicitly
306convert it, with a precision lost, but only if ''SAFE'' keyword is used.
307If more constants are read than values
308exist in ''DATA'' lines, garbare will be read. It can be avoided by using
309''SAFE'' keyword or using ''READ END'' function. Using ''SAFE'' the
310variable will not be touched if last value is already read.
311
312A succeeding ''READ'' searches for the first ''DATA'' statement where the
313''DATA'' read pointer is adjusted to.
314
315@italian
316
317Il comando ''READ'' viene utilizzato per leggere valori costanti dalle righe ''DATA''
318nelle variabili indicate. Questo comando è in grado di leggere più costanti
319contemporaneamente con un elenco di variabili separate da virgole.
320
321Se si utilizza il tipo sbagliato di variabile (ad esempio leggere una stringa di caratteri
322in una variabile numerica come float o intero), la variabile non verrà modificata.
323Tale comportamento può essere evitato utilizzando generalmente una variabile dello stesso
324tipo di quello indicato nel ''DATA AS''.
325
326Con un valore che non rientra nell'intervallo previsto di una variabile ''READ'', ad es.
327il valore non è compreso nell'intervallo di un numero intero, ugBASIC lo convertirà
328implicitamente, perdendo precisione, ma solo se si usa la parola chiave ''SAFE''.
329Se vengono lette più costanti di quanti siano i
330valori presenti nelle righe ''DATA'', verranno lette. Può essere evitato utilizzando la
331parola chiave ''SAFE'' o utilizzando la funzione ''READ END''. Utilizzando ''SAFE''
332la variabile non verrà toccata se l'ultimo valore è stato già letto.
333
334Un ''READ'' successivo cerca la prima istruzione ''DATA'' su cui è regolato il puntatore di
335lettura di ''DATA''.
336
337@syntax READ var
338
339@example READ nextStep
340
341@usedInExample data_example_01.bas
342@usedInExample data_example_02.bas
343@usedInExample data_example_03.bas
344
345@target all
346@verified
347</usermanual> */
348void read_data( Environment * _environment, char * _variable, int _safe ) {
349
350 _environment->readDataUsed = 1;
351
352 if ( _safe ) {
353 read_data_safe( _environment, _variable );
354 } else {
355 read_data_unsafe_common( _environment, _variable );
356 }
357
358}
359
void cpu_move_32bit_indirect2(Environment *_environment, char *_value, char *_source)
Definition 6309.c:5398
void cpu_dsfree(Environment *_environment, char *_index)
Definition 6309.c:5917
void cpu_math_add_16bit_with_8bit(Environment *_environment, char *_source, char *_destination, char *_other)
Definition 6309.c:1708
void cpu_mem_move(Environment *_environment, char *_source, char *_destination, char *_size)
Definition 6309.c:4692
void cpu_addressof_16bit(Environment *_environment, char *_source, char *_destination)
Definition 6309.c:1485
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_move_16bit_indirect2(Environment *_environment, char *_value, char *_source)
Definition 6309.c:5352
void cpu_dsalloc(Environment *_environment, char *_size, char *_index)
Definition 6309.c:5895
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
void cpu_move_8bit_indirect2(Environment *_environment, char *_value, char *_source)
Definition 6309.c:5294
void cpu_inc_16bit(Environment *_environment, char *_variable)
Definition 6309.c:4565
void cpu_compare_16bit(Environment *_environment, char *_source, char *_destination, char *_other, int _positive)
CPU 6309: emit code to compare two 16 bit values
Definition 6309.c:1523
void cpu_dsdescriptor(Environment *_environment, char *_index, char *_address, char *_size)
Definition 6309.c:5977
void cpu_compare_and_branch_8bit_const(Environment *_environment, char *_source, int _destination, char *_label, int _positive)
CPU 6309: emit code to compare two 8 bit values and jump if they are equal/different
Definition 6309.c:876
Variable * variable_retrieve(Environment *_environment, char *_name)
int variable_exists(Environment *_environment, char *_name)
Variable * variable_move(Environment *_environment, char *_source, char *_destination)
Store the value of a variable inside another variable by converting it.
Variable * variable_define(Environment *_environment, char *_name, VariableType _type, int _value)
Define a variable for the program.
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
void variable_move_type(Environment *_environment, char *_type, char *_field, char *_value)
int size
Definition _optimizer.c:678
void read_data_unsafe(Environment *_environment, char *_variable)
void bank_read_vars_direct_size(Environment *_environment, char *_bank, char *_address1, char *_address2, int _size)
Definition bank_read.c:169
void bank_read_vars(Environment *_environment, char *_bank, char *_address1, char *_address2, char *_size)
Emit ASM code for instruction BANK READ ....
Definition bank_read.c:107
void read_data(Environment *_environment, char *_variable, int _safe)
Emit code for READ instruction.
Definition read_data.c:348
VariableType defaultVariableType
Definition ugbc.h:2956
int dataNeeded
Definition ugbc.h:2557
int readDataUsed
Definition ugbc.h:2578
char * name
Definition ugbc.h:1231
VariableType type
Definition ugbc.h:1233
struct _Field * next
Definition ugbc.h:1237
struct _Field * first
Definition ugbc.h:1247
char * name
Definition ugbc.h:979
VariableType type
Definition ugbc.h:988
struct _Type * typeType
Definition ugbc.h:1222
char * realName
Definition ugbc.h:982
#define CRITICAL_READ_DATA_TYPE_NOT_SUPPORTED(v, t)
Definition ugbc.h:3678
struct _Field Field
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
#define VT_SIGNED(t)
Definition ugbc.h:618
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
@ VT_WORD
Definition ugbc.h:455
@ VT_SDWORD
Definition ugbc.h:462
@ VT_STRING
Definition ugbc.h:474
@ VT_SWORD
Definition ugbc.h:457
@ VT_BYTE
Definition ugbc.h:450
@ VT_DWORD
Definition ugbc.h:460
@ VT_SBYTE
Definition ugbc.h:452
@ VT_TYPE
Definition ugbc.h:546
@ VT_ADDRESS
Definition ugbc.h:465
@ VT_DSTRING
Definition ugbc.h:483
enum _VariableType VariableType
Type of variables.
#define VT_BITWIDTH(t)
Definition ugbc.h:595
#define MAKE_LABEL
Definition ugbc.h:3351
char DATATYPE_AS_STRING[][16]