#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; }