Mon 16 Mar 11:09:06 CET 2026
This commit is contained in:
parent
12b706d027
commit
7b00a51fba
157
src/var.c
Normal file
157
src/var.c
Normal 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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user