/* construct.c */
#include "config.h"
#include "object.h"
#include "instr.h"
#include "construct.h"
#include "globals.h"
#include "cache.h"
int is_legal(char *name) {
int x,len;
len=strlen(name);
if (!len || len>14) return 0;
if (*name=='.') return 0;
x=0;
while (x<len) {
if (!(isgraph(name[x])) || name[x]=='/' || name[x]=='#')
return 0;
x++;
}
return 1;
}
void free_gst(struct var_tab *gst) {
struct var_tab *curr_var,*next_var;
struct array_size *curr_array,*next_array;
curr_var=gst;
while (curr_var) {
next_var=curr_var->next;
curr_array=curr_var->array;
while (curr_array) {
next_array=curr_array->next;
FREE(curr_array);
curr_array=next_array;
}
FREE(curr_var->name);
FREE(curr_var);
curr_var=next_var;
}
}
void free_code(struct code *the_code) {
struct fns *next,*curr;
unsigned int x;
if (!the_code) return;
next=the_code->func_list;
while (next) {
curr=next;
next=curr->next;
x=0;
while (x<curr->num_instr) {
clear_var(&(curr->code[x]));
x++;
}
if (curr->code)
FREE(curr->code);
FREE(curr->funcname);
FREE(curr);
}
free_gst(the_code->gst);
FREE(the_code);
}
char *copy_string(char *s) {
return strcpy((char *) MALLOC(strlen(s)+1),s);
}
void push(struct var *data, struct var_stack **rts) {
struct var_stack *tmp;
tmp=MALLOC(sizeof(struct var_stack));
tmp->data.type=data->type;
switch (data->type) {
case STRING:
case FUNC_NAME:
tmp->data.value.string=copy_string(data->value.string);
break;
case INTEGER:
tmp->data.value.integer=data->value.integer;
break;
case OBJECT:
tmp->data.value.objptr=data->value.objptr;
break;
case ASM_INSTR:
tmp->data.value.instruction=data->value.instruction;
break;
case GLOBAL_L_VALUE:
case LOCAL_L_VALUE:
tmp->data.value.l_value.ref=data->value.l_value.ref;
tmp->data.value.l_value.size=data->value.l_value.size;
break;
case FUNC_CALL:
tmp->data.value.func_call=data->value.func_call;
break;
default:
tmp->data.value.num=data->value.num;
break;
}
tmp->next=*rts;
*rts=tmp;
}
void pushnocopy(struct var *data, struct var_stack **rts) {
struct var_stack *tmp;
tmp=MALLOC(sizeof(struct var_stack));
tmp->data.type=data->type;
switch (data->type) {
case STRING:
case FUNC_NAME:
tmp->data.value.string=data->value.string;
break;
case INTEGER:
tmp->data.value.integer=data->value.integer;
break;
case OBJECT:
tmp->data.value.objptr=data->value.objptr;
break;
case ASM_INSTR:
tmp->data.value.instruction=data->value.instruction;
break;
case GLOBAL_L_VALUE:
case LOCAL_L_VALUE:
tmp->data.value.l_value.ref=data->value.l_value.ref;
tmp->data.value.l_value.size=data->value.l_value.size;
break;
case FUNC_CALL:
tmp->data.value.func_call=data->value.func_call;
break;
default:
tmp->data.value.num=data->value.num;
break;
}
tmp->next=*rts;
*rts=tmp;
}
int resolve_var(struct var *data, struct object *obj) {
if (data->type==GLOBAL_L_VALUE) {
if (data->value.l_value.size!=1)
return 1;
if (data->value.l_value.ref>=obj->parent->funcs->num_globals)
return 1;
data->type=obj->globals[data->value.l_value.ref].type;
switch (data->type) {
case INTEGER:
data->value.integer=obj->globals[data->value.l_value.ref].value.integer;
break;
case STRING:
data->value.string=copy_string(obj->globals[data->value.l_value.ref].
value.string);
break;
case OBJECT:
data->value.objptr=obj->globals[data->value.l_value.ref].value.objptr;
break;
default:
return 1;
break;
}
} else
if (data->type==LOCAL_L_VALUE) {
if (data->value.l_value.size!=1)
return 1;
if (data->value.l_value.ref>=num_locals)
return 1;
data->type=locals[data->value.l_value.ref].type;
switch (data->type) {
case INTEGER:
data->value.integer=locals[data->value.l_value.ref].value.integer;
break;
case STRING:
data->value.string=copy_string(locals[data->value.l_value.ref].
value.string);
break;
case OBJECT:
data->value.objptr=locals[data->value.l_value.ref].value.objptr;
break;
default:
return 1;
break;
}
}
return 0;
}
int popint(struct var *data, struct var_stack **rts, struct object *obj) {
struct var tmp;
int size,base;
struct var_stack *ptr;
ptr=*rts;
if (ptr==NULL) return 1;
*rts=ptr->next;
data->type=ptr->data.type;
switch (ptr->data.type) {
case INTEGER:
data->value.integer=ptr->data.value.integer;
break;
case STRING:
case FUNC_NAME:
data->value.string=ptr->data.value.string;
break;
case OBJECT:
data->value.objptr=ptr->data.value.objptr;
break;
case ASM_INSTR:
data->value.instruction=ptr->data.value.instruction;
break;
case GLOBAL_L_VALUE:
case LOCAL_L_VALUE:
data->value.l_value.ref=ptr->data.value.l_value.ref;
data->value.l_value.size=ptr->data.value.l_value.size;
break;
case FUNC_CALL:
data->value.func_call=ptr->data.value.func_call;
break;
case LOCAL_REF:
case GLOBAL_REF:
if (popint(&tmp,rts,obj)) {
FREE(ptr);
return 1;
}
data->value.l_value.size=tmp.value.integer;
if (popint(&tmp,rts,obj)) {
FREE(ptr);
return 1;
}
data->value.l_value.ref=tmp.value.integer;
if (data->type==LOCAL_REF) {
if (data->value.l_value.ref>=num_locals) {
FREE(ptr);
return 1;
}
data->type=LOCAL_L_VALUE;
} else {
if (data->value.l_value.ref>=obj->parent->funcs->num_globals) {
FREE(ptr);
return 1;
}
data->type=GLOBAL_L_VALUE;
}
break;
default:
data->value.num=ptr->data.value.num;
break;
}
if (data->type==LOCAL_L_VALUE || data->type==GLOBAL_L_VALUE)
if (data->value.l_value.size!=1) {
FREE(ptr);
return 1;
}
if (resolve_var(data,obj)) {
clear_var(data);
FREE(ptr);
return 1;
}
if (data->type!=INTEGER) {
clear_var(data);
FREE(ptr);
return 1;
}
FREE(ptr);
return 0;
}
int pop(struct var *data, struct var_stack **rts, struct object *obj) {
struct var tmp;
int size,base;
struct var_stack *ptr;
ptr=*rts;
if (ptr==NULL) return 1;
*rts=ptr->next;
data->type=ptr->data.type;
switch (ptr->data.type) {
case INTEGER:
data->value.integer=ptr->data.value.integer;
break;
case STRING:
case FUNC_NAME:
data->value.string=ptr->data.value.string;
break;
case OBJECT:
data->value.objptr=ptr->data.value.objptr;
break;
case ASM_INSTR:
data->value.instruction=ptr->data.value.instruction;
break;
case GLOBAL_L_VALUE:
case LOCAL_L_VALUE:
data->value.l_value.ref=ptr->data.value.l_value.ref;
data->value.l_value.size=ptr->data.value.l_value.size;
break;
case FUNC_CALL:
data->value.func_call=ptr->data.value.func_call;
break;
case LOCAL_REF:
case GLOBAL_REF:
if (popint(&tmp,rts,obj)) {
FREE(ptr);
return 1;
}
data->value.l_value.size=tmp.value.integer;
if (popint(&tmp,rts,obj)) {
FREE(ptr);
return 1;
}
data->value.l_value.ref=tmp.value.integer;
if (data->type==LOCAL_REF) {
if (data->value.l_value.ref>=num_locals) {
FREE(ptr);
return 1;
}
data->type=LOCAL_L_VALUE;
} else {
if (data->value.l_value.ref>=obj->parent->funcs->num_globals) {
FREE(ptr);
return 1;
}
data->type=GLOBAL_L_VALUE;
}
break;
default:
data->value.num=ptr->data.value.num;
break;
}
if (data->type==LOCAL_L_VALUE || data->type==GLOBAL_L_VALUE)
if (data->value.l_value.size!=1) {
FREE(ptr);
return 1;
}
FREE(ptr);
return 0;
}
void free_stack(struct var_stack **rts) {
struct var_stack *next;
next=*rts;
while (next) {
next=(*rts)->next;
if ((*rts)->data.type==STRING || (*rts)->data.type==FUNC_NAME)
FREE((*rts)->data.value.string);
FREE(*rts);
*rts=next;
}
}
void clear_var(struct var *data) {
if (data->type==STRING || data->type==FUNC_NAME)
FREE(data->value.string);
data->type=INTEGER;
data->value.integer=0;
}
void clear_global_var(struct object *obj, unsigned int ref) {
struct ref_list *next,*curr;
if (ref>=obj->parent->funcs->num_globals)
return;
obj->obj_state=DIRTY;
if (obj->globals[ref].type==STRING || obj->globals[ref].type==FUNC_NAME)
FREE(obj->globals[ref].value.string);
if (obj->globals[ref].type==OBJECT) {
load_data(obj->globals[ref].value.objptr);
obj->globals[ref].value.objptr->obj_state=DIRTY;
next=obj->globals[ref].value.objptr->refd_by;
if (next)
if (next->ref_obj==obj && next->ref_num==ref) {
obj->globals[ref].value.objptr->refd_by=next->next;
FREE(next);
} else
while (next)
if (next->ref_obj==obj && next->ref_num==ref) {
curr->next=next->next;
FREE(next);
next=NULL;
} else {
curr=next;
next=curr->next;
}
}
obj->globals[ref].type=INTEGER;
obj->globals[ref].value.integer=0;
}
void copy_var(struct var *dest, struct var *src) {
dest->type=src->type;
switch (src->type) {
case INTEGER:
dest->value.integer=src->value.integer;
break;
case STRING:
case FUNC_NAME:
dest->value.string=copy_string(src->value.string);
break;
case OBJECT:
dest->value.objptr=src->value.objptr;
break;
case ASM_INSTR:
dest->value.instruction=src->value.instruction;
break;
case GLOBAL_L_VALUE:
case LOCAL_L_VALUE:
dest->value.l_value.ref=src->value.l_value.ref;
dest->value.l_value.size=src->value.l_value.size;
break;
default:
dest->value.num=src->value.num;
break;
}
}
struct var_stack *gen_stack(struct var_stack **rts, struct object *obj) {
struct var_stack *tmp,*stack1;
unsigned long arg_count;
stack1=*rts;
tmp=*rts;
if (!tmp) return NULL;
arg_count=tmp->data.value.num;
while (arg_count && tmp->next) {
tmp=tmp->next;
arg_count--;
if (resolve_var(&(tmp->data),obj))
return NULL;
}
if (arg_count) return NULL;
*rts=tmp->next;
tmp->next=NULL;
return stack1;
}
struct var_stack *gen_stack_noresolve(struct var_stack **rts,
struct object *obj) {
struct var_stack *tmp,*stack1;
unsigned long arg_count;
stack1=*rts;
tmp=*rts;
if (!tmp) return NULL;
arg_count=tmp->data.value.num;
while (arg_count && tmp->next) {
tmp=tmp->next;
arg_count--;
}
if (arg_count) return NULL;
*rts=tmp->next;
tmp->next=NULL;
return stack1;
}