#include "config.h"
#include "object.h"
#include "construct.h"
#include "instr.h"
#include "operproto.h"
#include "operdefine.h"
#include "globals.h"
#include "cache.h"
int comma_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp;
if (pop(&tmp,rts,obj)) return 1;
clear_var(&tmp);
if (pop(&tmp,rts,obj)) return 1;
pushnocopy(&tmp,rts);
return 0;
}
int eq_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp1,tmp2;
int loop;
struct ref_list *tmpref;
if (pop(&tmp2,rts,obj)) return 1;
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
return 1;
}
if (tmp1.type!=GLOBAL_L_VALUE && tmp1.type!=LOCAL_L_VALUE) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (tmp1.value.l_value.size!=1) {
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp2,obj)) return 1;
if (tmp1.type==GLOBAL_L_VALUE) {
obj->obj_state=DIRTY;
if (tmp2.type==OBJECT) {
load_data(tmp2.value.objptr);
tmp2.value.objptr->obj_state=DIRTY;
tmpref=MALLOC(sizeof(struct ref_list));
tmpref->ref_obj=obj;
tmpref->ref_num=tmp1.value.l_value.ref;
tmpref->next=tmp2.value.objptr->refd_by;
tmp2.value.objptr->refd_by=tmpref;
}
clear_global_var(obj,tmp1.value.l_value.ref);
obj->globals[tmp1.value.l_value.ref]=tmp2;
} else {
clear_var(&(locals[tmp1.value.l_value.ref]));
locals[tmp1.value.l_value.ref]=tmp2;
}
push(&tmp2,rts);
return 0;
}
EQ_INT_OPER(intaddeq, += )
int pleq_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp1,tmp2;
char *tmpstr;
int tmp2_not_int;
if (pop(&tmp2,rts,obj)) return 1;
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
return 1;
}
if (tmp1.type!=GLOBAL_L_VALUE && tmp1.type!=LOCAL_L_VALUE) {
clear_var(&tmp2);
clear_var(&tmp1);
return 1;
}
if (tmp1.value.l_value.size!=1) {
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp2,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (tmp1.type==GLOBAL_L_VALUE) {
if (tmp2.type==INTEGER && obj->globals[tmp1.value.l_value.ref].type==
INTEGER) {
push(&tmp1,rts);
push(&tmp2,rts);
return intaddeq(caller,obj,player,rts);
}
if (tmp2.type==INTEGER && tmp2.value.integer==0) {
tmp2.type=STRING;
tmp2.value.string=copy_string("");
}
if (tmp2.type==STRING) {
if (obj->globals[tmp1.value.l_value.ref].type==INTEGER && obj->globals
[tmp1.value.l_value.ref].value.integer==0) {
obj->globals[tmp1.value.l_value.ref].type=STRING;
obj->globals[tmp1.value.l_value.ref].value.string=copy_string("");
}
}
if (tmp2.type!=STRING || obj->globals[tmp1.value.l_value.ref].type!=
STRING) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
tmpstr=MALLOC(strlen(obj->globals[tmp1.value.l_value.ref].value.string)+
strlen(tmp2.value.string)+1);
strcat(strcpy(tmpstr,obj->globals[tmp1.value.l_value.ref].value.string),
tmp2.value.string);
clear_global_var(obj,tmp1.value.l_value.ref);
obj->globals[tmp1.value.l_value.ref].type=STRING;
obj->globals[tmp1.value.l_value.ref].value.string=tmpstr;
obj->obj_state=DIRTY;
} else {
if (tmp2.type==INTEGER && locals[tmp1.value.l_value.ref].type==INTEGER) {
push(&tmp1,rts);
push(&tmp2,rts);
return intaddeq(caller,obj,player,rts);
}
if (tmp2.type==INTEGER && tmp2.value.integer==0) {
tmp2.type=STRING;
tmp2.value.string=copy_string("");
}
if (tmp2.type==STRING) {
if (locals[tmp1.value.l_value.ref].type==INTEGER && locals[tmp1.value.
l_value.ref].value.integer==0) {
locals[tmp1.value.l_value.ref].type=STRING;
locals[tmp1.value.l_value.ref].value.string=copy_string("");
}
}
if (tmp2.type!=STRING || locals[tmp1.value.l_value.ref].type!=
STRING) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
tmpstr=MALLOC(strlen(locals[tmp1.value.l_value.ref].value.string)+
strlen(tmp2.value.string)+1);
strcat(strcpy(tmpstr,locals[tmp1.value.l_value.ref].value.string),
tmp2.value.string);
clear_var(&(locals[tmp1.value.l_value.ref]));
locals[tmp1.value.l_value.ref].type=STRING;
locals[tmp1.value.l_value.ref].value.string=tmpstr;
}
clear_var(&tmp1);
clear_var(&tmp2);
tmp1.type=STRING;
tmp1.value.string=tmpstr;
push(&tmp1,rts);
return 0;
}
int cond_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
return 0;
}
int or_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp1,tmp2;
int t1,t2;
if (pop(&tmp2,rts,obj)) return 1;
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp1,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp2,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
t1=!(tmp1.type==INTEGER && tmp1.value.integer==0);
t2=!(tmp2.type==INTEGER && tmp2.value.integer==0);
clear_var(&tmp1);
clear_var(&tmp2);
tmp1.type=INTEGER;
tmp1.value.integer=(t1 || t2);
push(&tmp1,rts);
return 0;
}
int and_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp1,tmp2;
int t1,t2;
if (pop(&tmp2,rts,obj)) return 1;
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp1,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp2,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
t1=!(tmp1.type==INTEGER && tmp1.value.integer==0);
t2=!(tmp2.type==INTEGER && tmp2.value.integer==0);
clear_var(&tmp1);
clear_var(&tmp2);
tmp1.type=INTEGER;
tmp1.value.integer=(t1 && t2);
push (&tmp1,rts);
return 0;
}
int condeq_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp1,tmp2;
int result;
if (pop(&tmp2,rts,obj)) return 1;
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp1,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp2,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (tmp1.type==STRING && tmp2.type==STRING) {
result=(!strcmp(tmp1.value.string,tmp2.value.string));
clear_var(&tmp1);
clear_var(&tmp2);
tmp1.type=INTEGER;
tmp1.value.integer=result;
push(&tmp1,rts);
return 0;
}
result=(tmp1.type==tmp2.type && ((tmp1.type==INTEGER &&
tmp1.value.integer==tmp2.value.integer) || (tmp1.type==OBJECT &&
tmp1.value.objptr==tmp2.value.objptr)));
clear_var(&tmp1);
clear_var(&tmp2);
tmp1.type=INTEGER;
tmp1.value.integer=result;
push(&tmp1,rts);
return 0;
}
int noteq_oper(struct object *caller,struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp;
if (condeq_oper(caller,obj,player,rts)) return 1;
if (pop(&tmp,rts,obj)) return 1;
if (tmp.type!=INTEGER) {
clear_var(&tmp);
return 1;
}
tmp.value.integer=!(tmp.value.integer);
push(&tmp,rts);
return 0;
}
BI_INT_OPER(intadd, + )
int add_oper(struct object *caller, struct object *obj,
struct object *player, struct var_stack **rts) {
struct var tmp1,tmp2;
char *tmpstr;
if (pop(&tmp2,rts,obj)) return 1;
if (pop(&tmp1,rts,obj)) {
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp1,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (resolve_var(&tmp2,obj)) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
if (tmp1.type==INTEGER && tmp2.type==INTEGER) {
push(&tmp1,rts);
push(&tmp2,rts);
return intadd(caller,obj,player,rts);
}
if (tmp1.type==INTEGER && tmp1.value.integer==0) {
tmp1.type=STRING;
tmp1.value.string=copy_string("");
}
if (tmp2.type==INTEGER && tmp2.value.integer==0) {
tmp2.type=STRING;
tmp2.value.string=copy_string("");
}
if (tmp2.type!=STRING || tmp1.type!=STRING) {
clear_var(&tmp1);
clear_var(&tmp2);
return 1;
}
tmpstr=MALLOC(strlen(tmp1.value.string)+strlen(tmp2.value.string)+1);
strcat(strcpy(tmpstr,tmp1.value.string),tmp2.value.string);
clear_var(&tmp1);
clear_var(&tmp2);
tmp1.type=STRING;
tmp1.value.string=tmpstr;
pushnocopy(&tmp1,rts);
return 0;
}