Mon 16 Mar 11:09:06 CET 2026

This commit is contained in:
sbosse 2026-03-16 11:10:49 +01:00
parent 12b706d027
commit 7b00a51fba

157
src/var.c Normal file
View File

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