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)
86extern "C" {
87#endif
88
89/*
90 * label
91 */
92typedef 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 */
102typedef 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 */
196void v_init_pool(void);
197
198/**
199 * @ingroup var
200 *
201 * free pooled var
202 */
203void 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 */
224void 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 */
233void 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 */
242void v_create_window(var_p_t var);
243
244/**
245 * @ingroup exec
246 *
247 * skips over the label
248 *
249 * @param label_id
250 */
251void 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 */
269stknode_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 */
278void 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 */
286int 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 */
294stknode_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 */
357void 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 */
367void 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 */
377void setsysvar_str(int index, const char *value);
378
379/*
380 * in eval.c
381 */
382var_num_t *mat_toc(var_t *v, int32_t *rows, int32_t *cols);
383
384void 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