ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
on_gosub.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
50/* <usermanual>
51@keyword ON...GOSUB
52
53@english
54This command is used to force a unconditional jump with returning to a pre-defined position when a
55specific expression is calculated. The choice is done against several positions,
56and it depends on what value is held by the expression at the time it is spotted.
57
58To work properly, the expression must have a value from 1 up to the number of
59the highest possible destination. If the expression has a value of 0 or
60greater than the highest possibile destination, no jump will be performed.
61
62@italian
63Questo comando viene utilizzato per forzare un salto incondizionato a una
64posizione predefinita (con ritorno), calcolata da un'espressione. La scelta è tra le posizioni
65elencate, e dipende dal valore dell'espressione al momento in cui viene
66calcolata.
67
68Per funzionare correttamente, l'espressione deve avere un valore compreso
69tra 1 e il numero di destinazioni. Se l'espressione ha un valore di 0 o
70maggiore della destinazione più alta possibile, non sarà eseguito alcun salto.
71
72@syntax ON expression GOSUB label1[, label2 [, ... ] ]
73
74@example ON level GOSUB level1, level2, level3
75@usedInExample control_by_expression_01.bas
76
77@target all
78</usermanual> */
79void on_gosub( Environment * _environment, char * _expression ) {
80
82
83 Variable * expression = variable_retrieve( _environment, _expression );
84
85 char newLabel[MAX_TEMPORARY_STORAGE]; sprintf(newLabel, "gosub%d", UNIQUE_ID );
86
87 Conditional * conditional = malloc( sizeof( Conditional ) );
88 conditional->label = strdup( newLabel );
89 conditional->type = CT_ON_GOSUB;
90 conditional->expression = variable_cast( _environment, expression->name, expression->type );
91 conditional->expression->locked = 1;
92 conditional->index = 1;
93 conditional->next = _environment->conditionals;
94 _environment->conditionals = conditional;
95
96}
97
107void on_gosub_index( Environment * _environment, char * _label ) {
108
109 Conditional * conditional = _environment->conditionals;
110
111 if ( ! conditional ) {
112 CRITICAL_INTERNAL_ERROR("on_gosub_index called out of order (1)");
113 }
114
115 if ( conditional->type != CT_ON_GOSUB ) {
116 CRITICAL_INTERNAL_ERROR("on_gosub_index called out of order (2)");
117 }
118
119 char realLabel[MAX_TEMPORARY_STORAGE];
120 if (strcmp(_label, "q" ) == 0 && _environment->vestigialConfig.rchack_ostra_1172 ) {
121 sprintf( realLabel, "lbl%s", _label );
122 } else {
123 strcpy( realLabel, _label );
124 }
125 label_referred_define_named( _environment, realLabel );
126
127 Variable * index = variable_resident( _environment, VT_BYTE, "(index)");
128
129 variable_store( _environment, index->name, conditional->index );
130
131 Variable * expression = variable_retrieve( _environment, conditional->expression->name );
132
133 char newLabel[MAX_TEMPORARY_STORAGE]; sprintf(newLabel, "%s%d", conditional->label, (conditional->index+1) );
134
135 cpu_bveq( _environment, variable_compare( _environment, expression->name, index->name )->realName, newLabel );
136
137 cpu_call( _environment, realLabel );
138
139 char newLabel2[MAX_TEMPORARY_STORAGE]; sprintf(newLabel2, "%sfinal", conditional->label );
140
141 cpu_jump( _environment, newLabel2 );
142
143 cpu_label( _environment, newLabel );
144
145 ++conditional->index;
146
147};
148
158void on_gosub_number( Environment * _environment, int _number ) {
159
160 label_referred_define_numeric( _environment, _number );
161
162 char label[MAX_TEMPORARY_STORAGE]; sprintf( label, "_linenumber%d", _number );
163
164 on_gosub_index( _environment, label );
165
166};
167
168
177void on_gosub_end( Environment * _environment ) {
178
179 Conditional * conditional = _environment->conditionals;
180
181 if ( ! conditional ) {
182 CRITICAL_INTERNAL_ERROR("on_gosub_end called out of order (1)");
183 }
184
185 if ( conditional->type != CT_ON_GOSUB ) {
186 CRITICAL_INTERNAL_ERROR("on_gosub_end called out of order (2)");
187 }
188
189 char newLabel2[MAX_TEMPORARY_STORAGE]; sprintf(newLabel2, "%sfinal", conditional->label );
190
191 cpu_label( _environment, newLabel2 );
192
193 _environment->conditionals->expression->locked = 0;
194
195 _environment->conditionals = _environment->conditionals->next;
196
197};
void cpu_bveq(Environment *_environment, char *_value, char *_label)
Definition 6309.c:334
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_call(Environment *_environment, char *_label)
Definition 6309.c:3755
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
Variable * variable_retrieve(Environment *_environment, char *_name)
void label_referred_define_named(Environment *_environment, char *_label)
Variable * variable_resident(Environment *_environment, VariableType _type, char *_meaning)
void label_referred_define_numeric(Environment *_environment, int _label)
Variable * variable_cast(Environment *_environment, char *_source, VariableType _type)
Cast a variable from a type to another.
Variable * variable_compare(Environment *_environment, char *_source, char *_destination)
Compare two variable and return the result of comparation.
Variable * variable_store(Environment *_environment, char *_destination, unsigned int _value)
Store a direct value to a variable.
void on_gosub(Environment *_environment, char *_expression)
Emit ASM code for ON ... GOSUB ....
Definition on_gosub.c:79
void on_gosub_index(Environment *_environment, char *_label)
Emit ASM code for ... (of ON ... GOSUB ...).
Definition on_gosub.c:107
void on_gosub_number(Environment *_environment, int _number)
Emit ASM code for ... (of ON ... GOSUB ...).
Definition on_gosub.c:158
void on_gosub_end(Environment *_environment)
Emit ASM code for ... (of ON ... GOSUB ...).
Definition on_gosub.c:177
struct _Conditional * next
Definition ugbc.h:1378
int index
Definition ugbc.h:1372
ConditionalType type
Definition ugbc.h:1363
char * label
Definition ugbc.h:1366
Variable * expression
Definition ugbc.h:1369
Conditional * conditionals
Definition ugbc.h:2664
VestigialConfig vestigialConfig
Definition ugbc.h:2442
int locked
Definition ugbc.h:1009
char * name
Definition ugbc.h:979
char * realName
Definition ugbc.h:982
char rchack_ostra_1172
Definition ugbc.h:2020
void * malloc(YYSIZE_T)
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
@ CT_ON_GOSUB
Definition ugbc.h:1342
#define UNIQUE_ID
Definition ugbc.h:3349
struct _Variable Variable
Structure of a single variable.
#define CRITICAL_INTERNAL_ERROR(v)
Definition ugbc.h:3443
struct _Environment Environment
Structure of compilation environment.
@ VT_BYTE
Definition ugbc.h:450
struct _Conditional Conditional
Structure of a single conditional jump.
#define MAKE_LABEL
Definition ugbc.h:3351