From 7b00a51fba993487f96954a0769b0639dcbf1c97 Mon Sep 17 00:00:00 2001 From: sbosse Date: Mon, 16 Mar 2026 11:10:49 +0100 Subject: [PATCH] Mon 16 Mar 11:09:06 CET 2026 --- src/var.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/var.c diff --git a/src/var.c b/src/var.c new file mode 100644 index 0000000..c1c5968 --- /dev/null +++ b/src/var.c @@ -0,0 +1,157 @@ +#include "config.h" +#include "types.h" +#include "error.h" +#include "lexer.h" +#include "ops.h" +#include "reg.h" +#include "mem.h" +#include "printf.h" +#include "var.h" +#include "printf.h" +#include "str.h" +#include "log.h" + +extern int verbose; + +#if HASH_VAR>0 +/* + First character of variable name to heap address mapping +*/ +static address_t hashvar[26]; +#endif + +/* + Dual use: Allocates variable on heap or resolves address if exists already (and type and length is conforming) + +----------+ size -1 + | data+n | + | .. | + | data | <- addr + | length | + | name[] | <- top + ... + +----------+ 0 + + Scalar numbers occupy data field of var structure. + Number arrays extend data field by (n-1) fields. + Strings use data field + (n-4) following bytes. + Events are stored here just to get a string name space. Payload is name field (addr)! + Procs and funcs are stored here with data field containing the code address. + + Returns 0 if var is not found or wrong type or cannot be allocated. +*/ +address_t Allocate(mem_t *M,reg_t *R, char *name, var_type type, index_t length, var_t **var) { + index_t top; + var_t *v=NULL; + address_t addr=0; +#if DEBUG > 0 + log(LOGDEBUG1,"Allocate[%c:%d]? %s M[%d]\n",type,length,name,M->top); +#endif +#if HASH_VAR>0 + // check hash/lut candidate by first character look-up + if (hashvar[name[0]-'A']!=0) { + top=hashvar[name[0]-'A']; + v=(var_t*)(&M->data[top]); + if (string_cmp(name,v->name,0)) goto varfound; + } +#endif + top=M->top; + while (top<(M->size-1)) { + v=(var_t*)(&M->data[top]); + if (string_cmp(name,v->name,0)) break; + switch (v->type) { + case MEVENT: + case MVAR: + case MCONST: + top+=(var_s+(v->length-1)*number_s); + break; + case MSTRING: + top+=(var_s+v->length-1); + break; + // these use data as address field and + case MFUNC: // data: [address,args] + top+=number_s; + case MPROC: // data: [address] + top+=var_s; + break; +#if HAS_FUNC>0 + case MVARLOC: + top+=(var_s+(v->length-1)*number_s); +#endif + break; + } + v=NULL; + } +varfound: + if (v) { + // check type consistency C V F P E and length + switch (type) { + case MVAR: + case MCONST: +#if HAS_FUNC>0 + case MVARLOC: // frame pointer offset is stored in data field +#endif + if (v->type!=MVAR && v->type!=MVARLOC) + { /*R->error=EVAR;*/ return 0; } + if (length > 1 && v->length !=length) + { /*R->error=EVAR;*/ return 0; } + addr=(address_t)((char *)&v->data-(char*)M->data); + if (var) *var=v; +#if HASH_VAR>0 + hashvar[name[0]-'A']=top; +#endif + // (stack) data addr pointer of local variables are stored in data field + return addr; + break; + case MEVENT: + case MSTRING: + case MFUNC: // code address is stored in data field followed by nargs + case MPROC: // code address is stored in data field + if (length==1 && v->type!=type) + { /*R->error=EVAR;*/ return 0; } + else if (length>1 && (v->type!=type || (type==MSTRING?v->length:-v->length)!=length)) + { /*R->error=EVAR;*/ return 0; } + case MANY: // lookup only, no check + if (v->type!=MEVENT) addr=(address_t)((char *)&v->data-(char*)M->data); + else addr=(address_t)(&v->name[0]-(char*)M->data); + if (var) *var=v; +#if HASH_VAR>0 + hashvar[name[0]-'A']=top; +#endif + return addr; + break; + } + } else { + if (type==MANY) return 0; // only lookup + if (type==MEVENT) length=1; // pseudo string variable returning the name field as data address! + else if (type==MSTRING && length==0) length=DEFSTRINGLEN+1; + top=M->top-var_s-(length-1)*(type==MSTRING?1:number_s); + top=top+(top%MEMALIGN); + v=(var_t*)(&M->data[top]); + string_copy(v->name,name,0); + v->length=length; + v->type=type; + M->top=top; +#if HASH_VAR>0 + hashvar[name[0]-'A']=top; +#endif + } + // new allocation + if (type!=MEVENT) { + addr=(address_t)((char *)&v->data-(char*)M->data); + memset(&M->data[addr],0,length*(type==MSTRING?1:number_s)); + } else addr=(address_t)(&v->name[0]-(char*)M->data); +#if DEBUG > 0 + log(LOGDEBUG1,"Allocate[%c:%d]: %s top=%d addr(->)=%d (var_s=%d)\n",type,length,name,M->top,addr,var_s); +#endif +#if HAS_LOCK > 0 + LOCKDATA(v)=0; +#endif + if (var) *var=v; + return addr; +} + +void HeapInit() { +#if HASH_VAR>0 + memset(hashvar,0,sizeof(hashvar)); +#endif +}