#include "config.h"
#include "object.h"
#include "instr.h"
#include "interp.h"
#include "interface.h"
#include "globals.h"
#include "cache.h"
#include "operproto.h"
#define FNS_HASH_SIZE 16
struct fns_hash_item {
struct proto *parent;
struct fns *func;
};
struct fns_hash_item fns_hash_table[FNS_HASH_SIZE];
void clear_fns_hash() {
int loop;
loop=0;
while (loop<FNS_HASH_SIZE)
fns_hash_table[loop++].parent=NULL;
}
struct fns *hash_find_fns(char *name, struct object *obj) {
int index;
index=obj->parent->proto_obj->refno%FNS_HASH_SIZE;
if (fns_hash_table[index].parent==obj->parent)
return fns_hash_table[index].func;
fns_hash_table[index].parent=obj->parent;
return fns_hash_table[index].func=find_fns(name,obj);
}
int s_iterate(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var *arglist,*old_locals;
struct fns *tmp_fns;
struct var_stack *arg_stack;
long num_args,loop;
struct var tmp;
char *name;
struct object *curr_obj,*avoid1,*avoid2;
unsigned int old_num_locals;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num<4) return 1;
num_args=tmp.value.num-4;
if (num_args)
arglist=MALLOC(sizeof(struct var)*num_args);
else
arglist=NULL;
loop=0;
while (loop<num_args) {
if (pop(&tmp,rts,obj)) {
while (loop>0)
clear_var(&(arglist[--loop]));
if (arglist) FREE(arglist);
return 1;
}
arglist[loop].type=tmp.type;
switch (tmp.type) {
case INTEGER:
arglist[loop].value.integer=tmp.value.integer;
break;
case STRING:
arglist[loop].value.string=tmp.value.string;
break;
case OBJECT:
arglist[loop].value.objptr=tmp.value.objptr;
break;
default:
clear_var(&tmp);
arglist[loop].type=INTEGER;
arglist[loop].value.integer=0;
}
tmp.type=INTEGER;
tmp.value.integer=0;
loop++;
}
if (pop(&tmp,rts,obj)) {
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
if (tmp.type!=STRING) {
clear_var(&tmp);
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
name=tmp.value.string;
if (pop(&tmp,rts,obj)) {
FREE(name);
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
if (tmp.type==INTEGER && tmp.value.integer==0) {
tmp.type=OBJECT;
tmp.value.objptr=NULL;
}
if (tmp.type!=OBJECT) {
clear_var(&tmp);
FREE(name);
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
avoid1=tmp.value.objptr;
if (pop(&tmp,rts,obj)) {
FREE(name);
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
if (tmp.type==INTEGER && tmp.value.integer==0) {
tmp.type=OBJECT;
tmp.value.objptr=NULL;
}
if (tmp.type!=OBJECT) {
clear_var(&tmp);
FREE(name);
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
avoid2=tmp.value.objptr;
if (pop(&tmp,rts,obj)) {
FREE(name);
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
if (tmp.type==INTEGER && tmp.value.integer==0) {
tmp.type=OBJECT;
tmp.value.objptr=NULL;
}
if (tmp.type!=OBJECT) {
clear_var(&tmp);
FREE(name);
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
return 1;
}
curr_obj=tmp.value.objptr;
old_locals=locals;
old_num_locals=num_locals;
clear_fns_hash();
while (curr_obj) {
if (curr_obj!=avoid1 && curr_obj!=avoid2) {
tmp_fns=hash_find_fns(name,curr_obj);
if (tmp_fns) if (tmp_fns->is_static) tmp_fns=NULL;
if (tmp_fns) {
arg_stack=NULL;
loop=num_args;
while (loop-->0)
push(&(arglist[loop]),&arg_stack);
tmp.type=NUM_ARGS;
tmp.value.num=num_args;
push(&tmp,&arg_stack);
interp(obj,curr_obj,player,&arg_stack,tmp_fns);
free_stack(&arg_stack);
}
}
curr_obj=curr_obj->next_object;
}
locals=old_locals;
num_locals=old_num_locals;
loop=0;
while (loop<num_args) clear_var(&(arglist[loop++]));
if (arglist) FREE(arglist);
tmp.type=INTEGER;
tmp.value.integer=0;
push(&tmp,rts);
return 0;
}
int s_next_who(struct object *caller, struct object *obj, struct object
*player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=NUM_ARGS) {
clear_var(&tmp);
return 1;
}
if (tmp.value.num>1) return 1;
if (tmp.value.num) {
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type==INTEGER && tmp.value.integer==0) {
tmp.type=OBJECT;
tmp.value.objptr=NULL;
}
if (tmp.type!=OBJECT) {
clear_var(&tmp);
return 1;
}
} else {
tmp.type=OBJECT;
tmp.value.objptr=NULL;
}
tmp.value.objptr=next_who(tmp.value.objptr);
if (!tmp.value.objptr) {
tmp.type=INTEGER;
tmp.value.integer=0;
}
push(&tmp,rts);
return 0;
}