ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
print.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
50/* <usermanual>
51@keyword PRINT
52
53@english
54
55The ''PRINT'' instruction displays information on the screen, starting from the current
56cursor position. An item or a list of items can follow the command. If any item is omitted,
57a blank line is printed. The list of items can consist of any group of strings, variables or constants.
58Each element in the list must be separated by either a semi-colon '';'' or a comma '',''.
59A semi-colon prints the data immediately after the previous value, whereas a comma first
60moves the cursor to the next ''TAB'' position on the screen.
61
62Normally the cursor will be advanced downwards by a single line after each ''PRINT''
63instruction. This can be suppressed by adding a separator after the print. As before, a semicolon
64will preserve the cursor position after the operation, and a comma will place the
65cursor to the next ''TAB'' stop before proceeding.
66
67All data printed to the screen is formatted by using the specific formatter for numbers,
68and "as is" for strings, while complex data will be printed out with an unique self descriptive string.
69 For the numeric data, the numbers are always translated into decimal system. Nothing is written
70 if parameter is omitted.
71
72Because the ''PRINT'' instruction prints with mono-spaced characters, there is a correlation between
73the number of characters printed and the number of columns those characters occupy. This ensures
74that each character uses only one column. You can use the ''SPC'' keyword to print after
75a specific number of spaces.
76
77It is also possible to put the output to a specific location. The ''PRINT @'' command is used
78to place output at a specified place on the screen. For this purpose the screen is divided
79into a ''SCREEN COLUMNS'' x ''SCREEN ROWS'' grid, giving a certain amount of positions.
80The expression after the ''@'' can be a number, a variable or an arithmetic expression, as
81long as the value is between ''0'' and ''((SCREEN COLUMNS*SCREEN ROWS)-1)''.
82
83Finally, note that the supplied string to print may contain control characters (clear
84screen, move cursor, and so on), which will be interpreted by the ''PRINT'' command.
85Since some targets give meaning to these characters, it is possible to omit
86this behavior by using the RAW keyword. This keyword will turn off interpretation for the
87expression that follows it, and turn it back on for the next one.
88
89@italian
90
91L'istruzione ''PRINT'' visualizza le informazioni sullo schermo, a partire dalla posizione attuale del
92cursore. Un elemento o un elenco di elementi può seguire il comando. Se un elemento viene omesso, viene
93stampata una riga vuota. L'elenco di elementi può essere costituito da qualsiasi gruppo di stringhe,
94variabili o costanti. Ogni elemento dell'elenco deve essere separato da un punto e virgola '';'' o da una
95virgola '',''. Un punto e virgola stampa i dati immediatamente dopo il valore precedente, mentre una virgola
96sposta prima il cursore alla posizione ''TAB'' successiva sullo schermo.
97
98Normalmente il cursore sarà portato verso il basso di una singola riga dopo ciascuna istruzione ''PRINT''.
99Questo può essere evitato aggiungendo un separatore dopo la stampa. Come prima, un punto e virgola manterrà
100la posizione del cursore dopo l'operazione e una virgola posizionerà il cursore al punto ''TAB'' successivo
101prima di procedere.
102
103Tutti i dati stampati sullo schermo vengono formattati utilizzando il formattatore specifico per i numeri
104e "così come sono" per le stringhe, mentre i dati complessi verranno stampati con una stringa di descrizione
105univoca e autoeplicativa. Per i dati numerici, i numeri sono sempre tradotti nel sistema decimale. Non viene scritto nulla
106se il parametro viene omesso.
107
108Poiché l'istruzione ''PRINT'' stampa con caratteri a spaziatura fissa, esiste una correlazione tra il
109numero di caratteri stampati e il numero di colonne occupate da tali caratteri. Ciò garantisce che ogni
110carattere utilizzi solo una colonna.
111
112È anche possibile collocare l'output in una posizione specifica. Il comando ''PRINT @'' viene utilizzato
113per posizionare l'output in un punto specificato sullo schermo. A questo scopo lo schermo è diviso
114in una griglia ''SCREEN COLUMNS'' x ''SCREEN ROWS'', fornendo un certo numero di posizioni.
115L'espressione dopo ''@'' può essere un numero, una variabile o un'espressione aritmetica, purché il
116valore sia compreso tra ''0'' e ''((SCREEN COLUMNS*SCREEN ROWS)-1)''.
117
118Infine, è da notare che la stringa fornita da stampare potrebbe presentare caratteri di controllo
119(di cancellazione schermo, di spostamento del cursore, e così via), che saranno interpretati
120dal comando ''PRINT''. Poiché alcuni target danno significato a questi caratteri, è
121possibile omettere questo comportamento usanto la parola chiave ''RAW''. Tale parola chiave
122disattiverà l'interpretazione per l'espressione che la segua, e la riattiverà alla
123successiva.
124
125@syntax PRINT [[RAW] expr] [; [[RAW]expr] [; ...] ... ]
126@syntax PRINT [[RAW] expr] [, [[RAW]expr] [, ...] ... ]
127@syntax PRINT @expr, [, [[RAW]expr] [, ...] ... ]
128
129@example PRINT "HELLO WORLD!"
130@example PRINT RAW "RAW";"NOT RAW";RAW "RAW"
131@example PRINT (a + b);" IS A SUM!";
132@example PRINT @100, "HELLO WORLD!"
133
134@usedInExample texts_print_01.bas
135@usedInExample texts_print_02.bas
136@usedInExample texts_print_04.bas
137
138@target all
139@verified
140</usermanual> */
141void print( Environment * _environment, char * _value, int _new_line, int _raw ) {
142
144
145 if ( _value ) {
146
147 Variable * value = variable_retrieve_or_define( _environment, _value, VT_DSTRING, 0 );
148
149 if ( value->type != VT_DSTRING && value->type != VT_STRING && value->type != VT_CHAR ) {
150 switch( VT_BITWIDTH( value->type ) ) {
151 case 32:
152 case 16:
153 case 8: {
154 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(temporary for PRINT)");
155 Variable * size = variable_temporary( _environment, VT_BYTE, "(temporary for PRINT)");
156 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
157 variable_store_string( _environment, tmp->name, " " );
158
159 cpu_dswrite( _environment, tmp->realName );
160
161 cpu_dsdescriptor( _environment, tmp->realName, address->realName, size->realName );
162
163 cpu_number_to_string( _environment, value->realName, address->realName, size->realName, VT_BITWIDTH( value->type ), VT_SIGNED( value->type ) );
164
165 cpu_dsresize( _environment, tmp->realName, size->realName );
166
167 value = tmp;
168
169 break;
170 }
171 case 1: {
172 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(temporary for PRINT)");
173 Variable * size = variable_temporary( _environment, VT_BYTE, "(temporary for PRINT)");
174 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
175 Variable * bcheck = variable_temporary( _environment, VT_BYTE, "(temporary for PRINT)");
176 Variable * zero = variable_temporary( _environment, VT_BYTE, "(temporary for PRINT)");
177 Variable * one = variable_temporary( _environment, VT_BYTE, "(temporary for PRINT)");
178
179 cpu_store_8bit( _environment, zero->realName, '0' );
180 cpu_store_8bit( _environment, one->realName, '1' );
181
182 variable_store_string( _environment, tmp->name, " " );
183 cpu_dswrite( _environment, tmp->realName );
184 cpu_dsdescriptor( _environment, tmp->realName, address->realName, size->realName );
185
187
188 char doneLabel[MAX_TEMPORARY_STORAGE]; sprintf( doneLabel, "%sdone", label );
189
190 outline0(" ; printing bit..." );
191 cpu_bit_check( _environment, value->realName, value->bitPosition, bcheck->realName, 8 );
192 cpu_compare_and_branch_8bit_const( _environment, bcheck->realName, 0, label, 1 );
193 cpu_move_8bit_indirect( _environment, one->realName, address->realName );
194 cpu_jump( _environment, doneLabel );
195 cpu_label( _environment, label );
196 cpu_move_8bit_indirect( _environment, zero->realName, address->realName );
197 cpu_label( _environment, doneLabel );
198
199 value = tmp;
200
201 break;
202 }
203 case 0:
204 switch( value->type ) {
205 case VT_NUMBER: {
206 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(temporary for PRINT)");
207 Variable * size = variable_temporary( _environment, VT_BYTE, "(temporary for PRINT)");
208 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
209
210 char * stringSpace = malloc( _environment->numberConfig.maxDigits + 1 );
211 memset( stringSpace, 0, _environment->numberConfig.maxDigits + 1 );
212 memset( stringSpace, 32, _environment->numberConfig.maxDigits );
213 variable_store_string( _environment, tmp->name, stringSpace );
214
215 cpu_dswrite( _environment, tmp->realName );
216
217 cpu_dsdescriptor( _environment, tmp->realName, address->realName, size->realName );
218
219 cpu_number_to_string( _environment, value->realName, address->realName, size->realName, _environment->numberConfig.maxBytes << 3, 1 );
220
221 cpu_dsresize( _environment, tmp->realName, size->realName );
222
223 value = tmp;
224
225 break;
226 }
227 case VT_FLOAT: {
228 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(temporary for PRINT)");
229 Variable * size = variable_temporary( _environment, VT_BYTE, "(temporary for PRINT)");
230 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
231
232 variable_store_string( _environment, tmp->name, " " );
233
234 cpu_dswrite( _environment, tmp->realName );
235
236 cpu_dsdescriptor( _environment, tmp->realName, address->realName, size->realName );
237
238 switch( value->precision ) {
239 case FT_FAST:
240 cpu_float_fast_to_string( _environment, value->realName, address->realName, size->realName );
241 break;
242 case FT_SINGLE:
243 cpu_float_single_to_string( _environment, value->realName, address->realName, size->realName );
244 break;
245 }
246
247 cpu_dsresize( _environment, tmp->realName, size->realName );
248
249 value = tmp;
250
251 break;
252 }
253 case VT_IMAGE: {
254 char bufferName[MAX_TEMPORARY_STORAGE];
255 sprintf(bufferName, "@image(%s)", value->name);
256 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
257 variable_store_string( _environment, tmp->name, bufferName );
258
259 value->usedImage = 1;
260
261 value = tmp;
262
263 break;
264 }
265 case VT_IMAGES: {
266 char bufferName[MAX_TEMPORARY_STORAGE];
267 sprintf(bufferName, "@images(%s)", value->name);
268 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
269 variable_store_string( _environment, tmp->name, bufferName );
270
271 value->usedImage = 1;
272
273 value = tmp;
274
275 break;
276 }
277 case VT_DOJOKA: {
278 Variable * dojokaHandle = variable_temporary( _environment, VT_DWORD, "(dojoka)");
279 cpu_mem_move_direct_size( _environment, value->realName, dojokaHandle->realName, 4 );
280 cpu_swap_8bit( _environment, dojokaHandle->realName, address_displacement( _environment, dojokaHandle->realName, "3" ) );
281 cpu_swap_8bit( _environment, address_displacement( _environment, dojokaHandle->realName, "1" ), address_displacement( _environment, dojokaHandle->realName, "2" ) );
282 print( _environment, variable_hex( _environment, dojokaHandle->name, 0 )->name, 0, _raw );
283 value = NULL;
284
285 break;
286 }
287 case VT_BUFFER: {
288 char bufferName[MAX_TEMPORARY_STORAGE];
289 sprintf(bufferName, "@buffer(%s)", value->name);
290 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
291 variable_store_string( _environment, tmp->name, bufferName );
292
293 value = tmp;
294
295 break;
296 }
297 case VT_TYPE: {
298 char bufferName[MAX_TEMPORARY_STORAGE];
299 sprintf(bufferName, "@type(%s)", value->name);
300 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
301 variable_store_string( _environment, tmp->name, bufferName );
302
303 value = tmp;
304
305 break;
306 }
307 case VT_SPRITE: {
308 char bufferName[MAX_TEMPORARY_STORAGE];
309 sprintf(bufferName, "@sprite(%s)", value->name);
310 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
311 variable_store_string( _environment, tmp->name, bufferName );
312
313 value = tmp;
314
315 break;
316 }
317 case VT_MSPRITE: {
318 char bufferName[MAX_TEMPORARY_STORAGE];
319 sprintf(bufferName, "@msprite(%s)", value->name);
320 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
321 variable_store_string( _environment, tmp->name, bufferName );
322
323 value = tmp;
324
325 break;
326 }
327 case VT_TILE: {
328 char bufferName[MAX_TEMPORARY_STORAGE];
329 sprintf(bufferName, "@tile(%s)", value->name);
330 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
331 variable_store_string( _environment, tmp->name, bufferName );
332
333 value = tmp;
334
335 break;
336 }
337 case VT_TILESET: {
338 char bufferName[MAX_TEMPORARY_STORAGE];
339 sprintf(bufferName, "@tileset(%s)", value->name);
340 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
341 variable_store_string( _environment, tmp->name, bufferName );
342
343 value->usedImage = 1;
344
345 value = tmp;
346
347 break;
348 }
349 case VT_TILEMAP: {
350 char bufferName[MAX_TEMPORARY_STORAGE];
351 sprintf(bufferName, "@tilemap(%s)", value->name);
352 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
353 variable_store_string( _environment, tmp->name, bufferName );
354
355 value->usedImage = 1;
356
357 value = tmp;
358
359 break;
360 }
361 case VT_TILES: {
362 char bufferName[MAX_TEMPORARY_STORAGE];
363 sprintf(bufferName, "@tiles(%s)", value->name);
364 Variable * tmp = variable_temporary( _environment, VT_DSTRING, "(temporary for PRINT)");
365 variable_store_string( _environment, tmp->name, bufferName );
366
367 value = tmp;
368
369 break;
370 }
371 default:
373 }
374 }
375 if ( value ) {
376 text_text( _environment, value->name, _raw );
377 cpu_dsfree( _environment, value->realName );
378 cpu_store_8bit( _environment, value->realName, 0 );
379 }
380 } else {
381 text_text( _environment, value->name, _raw );
382 }
383
384 }
385
386 if ( _new_line ) {
387 text_newline( _environment );
388 }
389
390}
391
398void print_tab( Environment * _environment, int _new_line ) {
399
400 text_tab( _environment );
401
402 if ( _new_line ) {
403 text_newline( _environment );
404 }
405
406}
407
413void print_question_mark( Environment * _environment ) {
414 text_question_mark( _environment );
415}
416
422void print_newline( Environment * _environment ) {
423 text_newline( _environment );
424}
425
void cpu_dsfree(Environment *_environment, char *_index)
Definition 6309.c:5917
void cpu_dsresize(Environment *_environment, char *_index, char *_resize)
Definition 6309.c:5937
void cpu_move_8bit_indirect(Environment *_environment, char *_source, char *_value)
Definition 6309.c:5239
void cpu_dswrite(Environment *_environment, char *_index)
Definition 6309.c:5927
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_number_to_string(Environment *_environment, char *_number, char *_string, char *_string_size, int _bits, int _signed)
Definition 6309.c:5688
void cpu_store_8bit(Environment *_environment, char *_destination, int _value)
CPU 6309: emit code to store 8 bit
Definition 6309.c:761
void cpu_swap_8bit(Environment *_environment, char *_left, char *_right)
Definition 6309.c:4451
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
void cpu_bit_check(Environment *_environment, char *_value, int _position, char *_result, int _bitwidth)
Definition 6309.c:5577
void cpu_float_single_to_string(Environment *_environment, char *_x, char *_string, char *_string_size)
Definition 6309.c:7023
void cpu_mem_move_direct_size(Environment *_environment, char *_source, char *_destination, int _size)
Definition 6309.c:4798
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
void cpu_float_fast_to_string(Environment *_environment, char *_x, char *_string, char *_string_size)
Definition 6309.c:7019
Variable * variable_retrieve_or_define(Environment *_environment, char *_name, VariableType _type, int _value)
Variable * variable_hex(Environment *_environment, char *_value, int _separator)
Emit code for = HEX( ... ).
Variable * variable_store_string(Environment *_environment, char *_destination, char *_value)
Store a string to a variable.
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
char * address_displacement(Environment *_environment, char *_address, char *_displacement)
int size
Definition _optimizer.c:678
void print_question_mark(Environment *_environment)
Emit code for print a single question mark.
Definition print.c:413
void print_tab(Environment *_environment, int _new_line)
Emit code for print a single TAB.
Definition print.c:398
void print_newline(Environment *_environment)
Emit code for print a single newline.
Definition print.c:422
void print(Environment *_environment, char *_value, int _new_line, int _raw)
Emit code for PRINT... instruction.
Definition print.c:141
NumberConfig numberConfig
Definition ugbc.h:2410
int maxBytes
Definition ugbc.h:2261
int maxDigits
Definition ugbc.h:2262
FloatTypePrecision precision
Definition ugbc.h:991
int bitPosition
Definition ugbc.h:1051
char * name
Definition ugbc.h:979
int usedImage
Definition ugbc.h:1220
VariableType type
Definition ugbc.h:988
char * realName
Definition ugbc.h:982
void text_tab(Environment *_environment)
Definition text.c:86
void text_text(Environment *_environment, char *_text, int _raw)
Definition text.c:41
void text_newline(Environment *_environment)
Definition text.c:51
void text_question_mark(Environment *_environment)
Definition text.c:134
void * malloc(YYSIZE_T)
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
#define VT_SIGNED(t)
Definition ugbc.h:618
struct _Variable Variable
Structure of a single variable.
#define CRITICAL_PRINT_UNSUPPORTED(v, t)
Definition ugbc.h:3487
struct _Environment Environment
Structure of compilation environment.
@ VT_DOJOKA
Definition ugbc.h:534
@ VT_TILE
Definition ugbc.h:504
@ VT_FLOAT
Definition ugbc.h:522
@ VT_NUMBER
Definition ugbc.h:549
@ VT_MSPRITE
Definition ugbc.h:531
@ VT_STRING
Definition ugbc.h:474
@ VT_TILEMAP
Definition ugbc.h:525
@ VT_TILES
Definition ugbc.h:507
@ VT_BYTE
Definition ugbc.h:450
@ VT_DWORD
Definition ugbc.h:460
@ VT_CHAR
Definition ugbc.h:498
@ VT_BUFFER
Definition ugbc.h:477
@ VT_SPRITE
Definition ugbc.h:501
@ VT_IMAGES
Definition ugbc.h:495
@ VT_TYPE
Definition ugbc.h:546
@ VT_ADDRESS
Definition ugbc.h:465
@ VT_TILESET
Definition ugbc.h:510
@ VT_DSTRING
Definition ugbc.h:483
@ VT_IMAGE
Definition ugbc.h:489
@ FT_FAST
Definition ugbc.h:854
@ FT_SINGLE
Definition ugbc.h:855
#define outline0(s)
Definition ugbc.h:4252
#define VT_BITWIDTH(t)
Definition ugbc.h:595
#define MAKE_LABEL
Definition ugbc.h:3351
char DATATYPE_AS_STRING[][16]