| 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 | |