1 | // This file is part of SmallBASIC |
2 | // |
3 | // SmallBASIC Code & Variable Manager. |
4 | // |
5 | // This program is distributed under the terms of the GPL v2.0 or later |
6 | // Download the GNU Public License (GPL) from www.gnu.org |
7 | // |
8 | // Copyright(C) 2000 Nicholas Christopoulos |
9 | |
10 | /** |
11 | * @defgroup var Variables |
12 | */ |
13 | /** |
14 | * @defgroup exec Executor |
15 | */ |
16 | /** |
17 | * @ingroup var |
18 | * @page var_12_2001 Var API (Dec 2001) |
19 | * |
20 | * @code |
21 | * Use these routines |
22 | * |
23 | * Memory free/alloc is contolled inside these functions |
24 | * The only thing that you must care of, is when you declare local var_t elements |
25 | * |
26 | * Auto-type-convertion is controlled inside these functions, |
27 | * So if you want a string value of an integer you just do strcpy(buf,v_getstr(&myvar)); |
28 | * or a numeric value of a string R = v_getreal(&myvar); |
29 | * |
30 | * Using variables on code: |
31 | * |
32 | * void myfunc() { // using them in stack |
33 | * var_t myvar; |
34 | * v_init(&myvar); // DO NOT FORGET THIS! local variables are had random data |
35 | * ... |
36 | * v_setstr(&myvar, "Hello, world"); |
37 | * ... |
38 | * v_set(&myvar, &another_var); // copy variables (LET myvar = another_var) |
39 | * ... |
40 | * v_setint(&myvar, 0x100); // Variable will be cleared automatically |
41 | * ... |
42 | * v_free(&myvar); |
43 | * } |
44 | * |
45 | * void myfunc() { // using dynamic memory |
46 | * var_t *myvar_p; |
47 | * |
48 | * myvar_p = v_new(); // create a new variable |
49 | * ... |
50 | * v_setstr(myvar_p, "Hello, world"); |
51 | * ... |
52 | * v_setint(myvar_p, 0x100); // Variable will be cleared automatically |
53 | * ... |
54 | * v_free(myvar_p); // clear variable's data |
55 | * v_detach(myvar_p); // free the variable |
56 | * } |
57 | * |
58 | * @endcode |
59 | */ |
60 | |
61 | #if !defined(_sb_cvm_h) |
62 | #define _sb_cvm_h |
63 | |
64 | #include "common/sys.h" |
65 | |
66 | /* |
67 | * predefined system variables - index |
68 | */ |
69 | #define SYSVAR_SBVER 0 /**< system variable, SBVER @ingroup var */ |
70 | #define SYSVAR_PI 1 /**< system variable, PI @ingroup var */ |
71 | #define SYSVAR_XMAX 2 /**< system variable, XMAX @ingroup var */ |
72 | #define SYSVAR_YMAX 3 /**< system variable, YMAX @ingroup var */ |
73 | #define SYSVAR_TRUE 4 /**< system variable, TRUE @ingroup var */ |
74 | #define SYSVAR_FALSE 5 /**< system variable, FALSE @ingroup var */ |
75 | #define SYSVAR_CWD 6 /**< system variable, CWD$ @ingroup var */ |
76 | #define SYSVAR_HOME 7 /**< system variable, HOME$ @ingroup var */ |
77 | #define SYSVAR_COMMAND 8 /**< system variable, COMMAND$ @ingroup var */ |
78 | #define SYSVAR_X 9 /**< system variable, X @ingroup var */ |
79 | #define SYSVAR_Y 10 /**< system variable, Y @ingroup var */ |
80 | #define SYSVAR_SELF 11 /**< system variable, SELF @ingroup var */ |
81 | #define SYSVAR_NONE 12 /**< system variable, NONE @ingroup var */ |
82 | #define SYSVAR_MAXINT 13 /**< system variable, INTMAX @ingroup var */ |
83 | #define SYSVAR_COUNT 14 |
84 | |
85 | #if defined(__cplusplus) |
86 | extern "C" { |
87 | #endif |
88 | |
89 | /* |
90 | * label |
91 | */ |
92 | typedef struct lab_s { |
93 | bcip_t ip; |
94 | } lab_t; |
95 | |
96 | /** |
97 | * @ingroup exec |
98 | * @struct stknode_s |
99 | * |
100 | * EXECUTOR's STACK NODE |
101 | */ |
102 | typedef struct stknode_s { |
103 | union { |
104 | /** |
105 | * FOR-TO-NEXT |
106 | */ |
107 | struct { |
108 | var_t *var_ptr; /**< 'FOR' variable */ |
109 | var_t *arr_ptr; /**< FOR-IN array-variable */ |
110 | var_t *str_ptr; /**< FOR-IN string variable */ |
111 | bcip_t to_expr_ip; /**< IP of 'TO' expression */ |
112 | bcip_t step_expr_ip; /**< IP of 'STEP' expression (FOR-IN = current element) */ |
113 | bcip_t jump_ip; /**< code block IP */ |
114 | bcip_t exit_ip; /**< EXIT command IP to go */ |
115 | code_t subtype; /**< kwTO | kwIN */ |
116 | byte flags; /**< ... */ |
117 | } vfor; |
118 | |
119 | /** |
120 | * REPEAT/WHILE |
121 | */ |
122 | struct { |
123 | bcip_t exit_ip; /**< EXIT command IP to go */ |
124 | } vloop; |
125 | |
126 | /** |
127 | * IF/ELIF |
128 | */ |
129 | struct { |
130 | bcip_t lcond; /**< result of the last condition */ |
131 | } vif; |
132 | |
133 | /** |
134 | * SELECT CASE |
135 | */ |
136 | struct { |
137 | var_t *var_ptr; |
138 | byte flags; |
139 | } vcase; |
140 | |
141 | /** |
142 | * GOSUB |
143 | */ |
144 | struct { |
145 | bcip_t ret_ip; /**< return ip */ |
146 | } vgosub; |
147 | |
148 | /** |
149 | * CALL UDP/F |
150 | */ |
151 | struct { |
152 | var_t *retvar; /**< return-variable data */ |
153 | bcip_t ret_ip; /**< return ip */ |
154 | bid_t rvid; /**< return-variable ID */ |
155 | int task_id; /**< task_id or -1 (this task) */ |
156 | uint16_t pcount; /**< number of parameters */ |
157 | } vcall; |
158 | |
159 | /** |
160 | * Create dynamic variable (LOCAL or PARAMETER) |
161 | */ |
162 | struct { |
163 | var_t *vptr; /**< previous variable */ |
164 | bid_t vid; /**< variable index in tvar */ |
165 | } vdvar; |
166 | |
167 | /** |
168 | * parameter (CALL UDP/F) |
169 | */ |
170 | struct { |
171 | var_t *res; /**< variable pointer (for BYVAL this is a clone) */ |
172 | uint16_t vcheck; /**< checks (1=BYVAL ONLY, 3=BYVAL|BYREF, 2=BYREF ONLY) */ |
173 | } param; |
174 | |
175 | /** |
176 | * try/catch |
177 | */ |
178 | struct { |
179 | bcip_t catch_ip; |
180 | } vtry; |
181 | |
182 | struct { |
183 | var_t *catch_var; |
184 | } vcatch; |
185 | } x; |
186 | |
187 | int line; /** line number of current execution **/ |
188 | code_t type; /**< type of node (keyword id, i.e. kwGOSUB, kwFOR, etc) */ |
189 | } stknode_t; |
190 | |
191 | /** |
192 | * @ingroup var |
193 | * |
194 | * intialises the var pool |
195 | */ |
196 | void v_init_pool(void); |
197 | |
198 | /** |
199 | * @ingroup var |
200 | * |
201 | * free pooled var |
202 | */ |
203 | void v_pool_free(var_t *var); |
204 | |
205 | /** |
206 | * < returns the integer value of variable v |
207 | * @ingroup var |
208 | */ |
209 | #define v_getint(v) v_igetval((v)) |
210 | |
211 | /** |
212 | * < returns the real value of variable v |
213 | * @ingroup var |
214 | */ |
215 | #define v_getreal(v) v_getval((v)) |
216 | |
217 | /** |
218 | * @ingroup var |
219 | * |
220 | * creates an system image object |
221 | * |
222 | * @param v is the variable |
223 | */ |
224 | void v_create_image(var_p_t var); |
225 | |
226 | /** |
227 | * @ingroup var |
228 | * |
229 | * creates an system form object |
230 | * |
231 | * @param v is the variable |
232 | */ |
233 | void v_create_form(var_p_t var); |
234 | |
235 | /** |
236 | * @ingroup var |
237 | * |
238 | * creates an system window object |
239 | * |
240 | * @param v is the variable |
241 | */ |
242 | void v_create_window(var_p_t var); |
243 | |
244 | /** |
245 | * @ingroup exec |
246 | * |
247 | * skips over the label |
248 | * |
249 | * @param label_id |
250 | */ |
251 | void code_jump_label(uint16_t label_id); // IP <- LABEL_IP_TABLE[label_id] |
252 | |
253 | /** |
254 | * @ingroup exec |
255 | * |
256 | * skips to the specified address |
257 | * |
258 | * @param newip |
259 | */ |
260 | #define code_jump(newip) prog_ip=(newip) /**< IP <- NewIP @ingroup exec */ |
261 | |
262 | /** |
263 | * @ingroup exec |
264 | * |
265 | * stores a node to stack |
266 | * |
267 | * @param node the stack node |
268 | */ |
269 | stknode_t *code_push(code_t type); |
270 | |
271 | /** |
272 | * @ingroup exec |
273 | * |
274 | * restores the topmost node from stack |
275 | * |
276 | * @param node the stack node |
277 | */ |
278 | void code_pop(stknode_t *node, int expected_type); |
279 | |
280 | /** |
281 | * @ingroup exec |
282 | * |
283 | * POPs and frees the topmost node from stack and returns the node type |
284 | * |
285 | */ |
286 | int code_pop_and_free(); |
287 | |
288 | /** |
289 | * @ingroup exec |
290 | * |
291 | * returns the node at the top of the stack. does not change the stack. |
292 | * |
293 | */ |
294 | stknode_t *code_stackpeek(); |
295 | |
296 | /** |
297 | * @ingroup var |
298 | * |
299 | * Returns the varptr of the next variable. if the variable is an array |
300 | * returns the element ptr |
301 | */ |
302 | #define code_getvarptr() code_getvarptr_parens(0) |
303 | |
304 | #define code_peek() prog_source[prog_ip] /**< R(byte) <- Code[IP] @ingroup exec */ |
305 | #define code_getnext() prog_source[prog_ip++] /**< R(byte) <- Code[IP]; IP ++; @ingroup exec */ |
306 | |
307 | #define code_skipnext() prog_ip++ /**< IP ++; @ingroup exec */ |
308 | #define code_skipnext16() prog_ip+=2 /**< IP += 2; @ingroup exec */ |
309 | #define code_skipnext32() prog_ip+=4 /**< IP += 4; @ingroup exec */ |
310 | |
311 | #if defined(CPU_BIGENDIAN) |
312 | #define code_getnext16() (prog_ip+=2, (prog_source[prog_ip-2]<<8)|prog_source[prog_ip-1]) |
313 | #define code_peeknext16() ((prog_source[prog_ip]<<8)|prog_source[prog_ip+1]) |
314 | #define code_peek16(o) ((prog_source[(o)]<<8)|prog_source[(o)+1]) |
315 | #define code_peek32(o) (((bcip_t)code_peek16((o)) << 16) + (bcip_t)code_peek16((o)+2)) |
316 | #else |
317 | #define code_getnext16() (*((uint16_t *)(prog_source+(prog_ip+=2)-2))) |
318 | #define code_peeknext16() (*((uint16_t *)(prog_source+prog_ip))) |
319 | #define code_peek16(o) (*((uint16_t *)(prog_source+(o)))) |
320 | #define code_peek32(o) (*((uint32_t *)(prog_source+(o)))) |
321 | #endif |
322 | |
323 | #define code_skipopr() code_skipnext16() /**< skip operator @ingroup exec */ |
324 | #define code_skipsep() code_skipnext16() /**< skip separator @ingroup exec */ |
325 | /**< returns the separator and advance (IP) to next command @ingroup exec */ |
326 | #define code_getsep() (prog_ip ++, prog_source[prog_ip++]) |
327 | #define code_peeksep() (prog_source[prog_ip+1]) |
328 | |
329 | #define code_getaddr() code_getnext32() /**< get address value and advance @ingroup exec */ |
330 | #define code_skipaddr() code_skipnext32() /**< skip address field @ingroup exec */ |
331 | #define code_getstrlen() code_getnext32() /**< get strlen (kwTYPE_STR) and advance @ingroup exec */ |
332 | #define code_peekaddr(i) code_peek32((i)) /**< peek address field at offset i @ingroup exec */ |
333 | |
334 | /** |
335 | * @ingroup var |
336 | * @page sysvar System variables |
337 | * @code |
338 | * System variables (osname, osver, bpp, xmax, etc) |
339 | * |
340 | * The variables must be defined |
341 | * a) here (see in first lines) - (variable's index) |
342 | * b) in scan.c (variable's name) |
343 | * c) in brun.c or device.c (variable's value) |
344 | * |
345 | * DO NOT LOSE THE ORDER |
346 | * @endcode |
347 | */ |
348 | |
349 | /** |
350 | * @ingroup var |
351 | * |
352 | * sets an integer value to a system variable (constant) |
353 | * |
354 | * @param index is the system variable's index |
355 | * @param val the value |
356 | */ |
357 | void setsysvar_int(int index, var_int_t val); |
358 | |
359 | /** |
360 | * @ingroup var |
361 | * |
362 | * sets a double value to a system variable (constant) |
363 | * |
364 | * @param index is the system variable's index |
365 | * @param val the value |
366 | */ |
367 | void setsysvar_num(int index, var_num_t val); |
368 | |
369 | /** |
370 | * @ingroup var |
371 | * |
372 | * sets a string value to a system variable (constant) |
373 | * |
374 | * @param index is the system variable's index |
375 | * @param val the value |
376 | */ |
377 | void setsysvar_str(int index, const char *value); |
378 | |
379 | /* |
380 | * in eval.c |
381 | */ |
382 | var_num_t *mat_toc(var_t *v, int32_t *rows, int32_t *cols); |
383 | |
384 | void mat_tov(var_t *v, var_num_t *m, int32_t rows, int32_t cols, |
385 | int protect_col1); |
386 | |
387 | #if defined(__cplusplus) |
388 | } |
389 | #endif |
390 | |
391 | #endif |
392 | |