diff --git a/src/opcodes.c b/src/opcodes.c index b713d7dd2762cd8c4156e10b82a77c6243ba45b3..6410fc05c27aa1291eca812320c2e4a521760874 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -74,14 +74,176 @@ void f_index() pop_stack(); } +void cast(struct lpc_string *s) +{ + INT32 i; + + i=compile_type_to_runtime_type(s); + + if(i != sp[-1].type) + { + if(i == T_MIXED) return; + + if(sp[-2].type == T_OBJECT) + { + push_string(describe_type(s)); + if(!sp[-2].u.object->prog) + error("Cast called on destructed object.\n"); + if(sp[-2].u.object->prog->lfuns[LFUN_CAST] == -1) + error("No cast method in object.\n"); + apply_lfun(sp[-2].u.object, LFUN_CAST, 1); + free_svalue(sp-2); + sp[-2]=sp[-1]; + sp--; + return; + } + + switch(i) + { + case T_MIXED: + break; + + case T_INT: + switch(sp[-1].type) + { + case T_FLOAT: + i=(int)(sp[-1].u.float_number); + break; + + case T_STRING: + i=strtol(sp[-1].u.string->str,0,0); + free_string(sp[-1].u.string); + break; + + default: + error("Cannot cast to int.\n"); + } + + sp[-1].type=T_INT; + sp[-1].u.integer=i; + break; + + case T_FLOAT: + { + FLOAT_TYPE f; + switch(sp[-1].type) + { + case T_INT: + f=(FLOAT_TYPE)(sp[-1].u.integer); + break; + + case T_STRING: + f=STRTOD(sp[-1].u.string->str,0); + free_string(sp[-1].u.string); + break; + + default: + error("Cannot cast to float.\n"); + f=0.0; + } + + sp[-1].type=T_FLOAT; + sp[-1].u.float_number=f; + break; + } + + case T_STRING: + { + char buf[200]; + switch(sp[-1].type) + { + case T_INT: + sprintf(buf,"%ld",(long)sp[-1].u.integer); + break; + + case T_FLOAT: + sprintf(buf,"%f",(double)sp[-1].u.float_number); + break; + + default: + error("Cannot cast to string.\n"); + } + + sp[-1].type=T_STRING; + sp[-1].u.string=make_shared_string(buf); + break; + } + + case T_OBJECT: + switch(sp[-1].type) + { + case T_STRING: + APPLY_MASTER("cast_to_object",1); + break; + + case T_FUNCTION: + sp[-1].type = T_OBJECT; + break; + } + break; + + case T_PROGRAM: + APPLY_MASTER("cast_to_program",1); + break; + + case T_FUNCTION: + { + INT32 i; + if(fp->current_object->prog) + error("Cast to function in destructed object.\n"); + i=find_shared_string_identifier(sp[-1].u.string,fp->current_object->prog); + free_string(sp[-1].u.string); + /* FIXME, check that it is a indeed a function */ + if(i==-1) + { + sp[-1].type=T_FUNCTION; + sp[-1].subtype=i; + sp[-1].u.object=fp->current_object; + fp->current_object->refs++; + }else{ + sp[-1].type=T_INT; + sp[-1].subtype=NUMBER_UNDEFINED; + sp[-1].u.integer=0; + } + break; + } + + } + } +} + void f_cast() { INT32 i; i=compile_type_to_runtime_type(sp[-1].u.string); - pop_stack(); - if(i != sp[-1].type) + + if(i != sp[-2].type) { + if(i == T_MIXED) + { + pop_stack(); + return; + } + + if(sp[-2].type == T_OBJECT) + { + struct lpc_string *s; + s=describe_type(sp[-1].u.string); + pop_stack(); + push_string(s); + if(!sp[-2].u.object->prog) + error("Cast called on destructed object.\n"); + if(sp[-2].u.object->prog->lfuns[LFUN_CAST] == -1) + error("No cast method in object.\n"); + apply_lfun(sp[-2].u.object, LFUN_CAST, 1); + free_svalue(sp-2); + sp[-2]=sp[-1]; + sp--; + return; + } + + pop_stack(); switch(i) { case T_MIXED: @@ -193,6 +355,8 @@ void f_cast() } } + }else{ + pop_stack(); } } @@ -493,10 +657,10 @@ static INT32 low_sscanf(INT32 num_arg) if(!contains_percent_percent) { - s=MEMMEM(end_str_start, - end_str_end-end_str_start, - input+eye, - input_len-eye); + s=my_memmem(end_str_start, + end_str_end-end_str_start, + input+eye, + input_len-eye); if(!s) return matches; eye=s-input; new_eye=eye+end_str_end-end_str_start; diff --git a/src/operators.c b/src/operators.c index 9227d3b05a3d182ce27ac7fa0a9d21d255b8dbce..ecbe77f120c0ff121854367be59e66e7b6a009ed 100644 --- a/src/operators.c +++ b/src/operators.c @@ -20,6 +20,8 @@ #include "add_efun.h" #include "peep.h" #include "lex.h" +#include "program.h" +#include "object.h" #define COMPARISON(ID,NAME,EXPR) \ void ID(INT32 args) \ @@ -31,9 +33,7 @@ void ID(INT32 args) \ error("Too few arguments to %s\n",NAME); \ i=EXPR; \ pop_n_elems(2); \ - sp->type=T_INT; \ - sp->u.integer=i; \ - sp++; \ + push_int(i); \ } COMPARISON(f_eq,"`==", is_eq(sp-2,sp-1)) @@ -44,6 +44,17 @@ COMPARISON(f_gt,"`>" , is_gt(sp-2,sp-1)) COMPARISON(f_ge,"`>=",!is_lt(sp-2,sp-1)) +#define CALL_OPERATOR(OP, args) \ + if(!sp[-args].u.object->prog) \ + error("Operator %s called in destructed object.\n",lfun_names[OP]); \ + if(sp[-args].u.object->prog->lfuns[OP] == -1) \ + error("No operator %s in object.\n",lfun_names[OP]); \ + apply_lfun(sp[-args].u.object, OP, args-1); \ + free_svalue(sp-2); \ + sp[-2]=sp[-1]; \ + sp--; + + void f_add(INT32 args) { INT32 e,size; @@ -60,6 +71,9 @@ void f_add(INT32 args) switch(sp[-args].type) { case T_OBJECT: + CALL_OPERATOR(LFUN_ADD,args); + return; + case T_PROGRAM: case T_FUNCTION: error("Bad argument 1 to summation\n"); @@ -338,11 +352,17 @@ static int float_promote() void o_subtract() { - if (sp[-2].type != sp[-1].type && !float_promote()) + if (sp[-2].type != sp[-1].type && + !float_promote() && + sp[-2].type != T_OBJECT) error("Subtract on different types.\n"); - switch(sp[-1].type) + switch(sp[-2].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_SUBTRACT,2); + break; + case T_ARRAY: { struct array *a; @@ -431,11 +451,16 @@ static int generate_minus(node *n) void o_and() { - if(sp[-1].type != sp[-2].type) + if(sp[-1].type != sp[-2].type && + sp[-2].type != T_OBJECT) error("Bitwise and on different types.\n"); switch(sp[-2].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_AND,2); + break; + case T_INT: sp--; sp[-1].u.integer &= sp[0].u.integer; @@ -479,7 +504,13 @@ void f_and(INT32 args) case 0: error("Too few arguments to `&\n"); case 1: return; case 2: o_and(); return; - default: while(--args > 0) o_and(); + default: + if(sp[-args].type == T_OBJECT) + { + CALL_OPERATOR(LFUN_AND, args); + }else{ + while(--args > 0) o_and(); + } } } @@ -503,11 +534,16 @@ static int generate_and(node *n) void o_or() { - if(sp[-1].type != sp[-2].type) + if(sp[-1].type != sp[-2].type && + sp[-2].type != T_OBJECT) error("Bitwise or on different types.\n"); switch(sp[-2].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_OR,2); + break; + case T_INT: sp--; sp[-1].u.integer |= sp[0].u.integer; @@ -552,7 +588,13 @@ void f_or(INT32 args) case 0: error("Too few arguments to `|\n"); case 1: return; case 2: o_or(); return; - default: while(--args > 0) o_or(); + default: + if(sp[-args].type==T_OBJECT) + { + CALL_OPERATOR(LFUN_OR, args); + } else { + while(--args > 0) o_or(); + } } } @@ -577,11 +619,16 @@ static int generate_or(node *n) void o_xor() { - if(sp[-1].type != sp[-2].type) + if(sp[-1].type != sp[-2].type && + sp[-2].type != T_OBJECT) error("Bitwise xor on different types.\n"); switch(sp[-2].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_XOR,2); + break; + case T_INT: sp--; sp[-1].u.integer ^= sp[0].u.integer; @@ -625,7 +672,13 @@ void f_xor(INT32 args) case 0: error("Too few arguments to `^\n"); case 1: return; case 2: o_xor(); return; - default: while(--args > 0) o_xor(); + default: + if(sp[-args].type==T_OBJECT) + { + CALL_OPERATOR(LFUN_XOR, args); + } else { + while(--args > 0) o_xor(); + } } } @@ -649,7 +702,16 @@ static int generate_xor(node *n) void o_lsh() { - if(sp[-2].type != T_INT) error("Bad argument 1 to <<\n"); + if(sp[-2].type != T_INT) + { + if(sp[-2].type == T_OBJECT) + { + CALL_OPERATOR(LFUN_LSH,2); + return; + } + + error("Bad argument 1 to <<\n"); + } if(sp[-1].type != T_INT) error("Bad argument 2 to <<\n"); sp--; sp[-1].u.integer = sp[-1].u.integer << sp->u.integer; @@ -675,7 +737,15 @@ static int generate_lsh(node *n) void o_rsh() { - if(sp[-2].type != T_INT) error("Bad argument 1 to >>\n"); + if(sp[-2].type != T_INT) + { + if(sp[-2].type == T_OBJECT) + { + CALL_OPERATOR(LFUN_RSH,2); + return; + } + error("Bad argument 1 to >>\n"); + } if(sp[-1].type != T_INT) error("Bad argument 2 to >>\n"); sp--; sp[-1].u.integer = sp[-1].u.integer >> sp->u.integer; @@ -740,6 +810,12 @@ void o_multiply() return; default: + if(sp[-2].type == T_OBJECT) + { + CALL_OPERATOR(LFUN_MULTIPLY,2); + return; + } + error("Bad arguments to multiply.\n"); } } @@ -751,7 +827,13 @@ void f_multiply(INT32 args) case 0: error("Too few arguments to `*\n"); case 1: return; case 2: o_multiply(); return; - default: while(--args > 0) o_multiply(); + default: + if(sp[-args].type==T_OBJECT) + { + CALL_OPERATOR(LFUN_MULTIPLY, args); + } else { + while(--args > 0) o_multiply(); + } } } @@ -775,11 +857,17 @@ static int generate_multiply(node *n) void o_divide() { - if(sp[-2].type!=sp[-1].type && !float_promote()) + if(sp[-2].type!=sp[-1].type && + !float_promote() && + sp[-2].type != T_OBJECT) error("Division on different types.\n"); switch(sp[-2].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_DIVIDE,2); + break; + case T_STRING: { struct array *ret; @@ -831,11 +919,17 @@ static int generate_divide(node *n) void o_mod() { - if(sp[-2].type != sp[-1].type && !float_promote()) + if(sp[-2].type != sp[-1].type && + !float_promote() && + sp[-2].type != T_OBJECT) error("Modulo on different types.\n"); - switch(sp[-1].type) + switch(sp[-2].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_MOD,2); + break; + case T_FLOAT: { FLOAT_TYPE foo; @@ -878,14 +972,28 @@ static int generate_mod(node *n) void o_not() { - if(sp[-1].type==T_INT) + switch(sp[-1].type) { + case T_INT: sp[-1].u.integer = !sp[-1].u.integer; - }else{ - pop_stack(); - sp->type=T_INT; - sp->u.integer=0; - sp++; + break; + + case T_FUNCTION: + case T_OBJECT: + if(IS_ZERO(sp-1)) + { + pop_stack(); + push_int(1); + }else{ + pop_stack(); + push_int(0); + } + break; + + default: + free_svalue(sp-1); + sp[-1].type=T_INT; + sp[-1].u.integer=0; } } @@ -910,6 +1018,10 @@ void o_compl() { switch(sp[-1].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_COMPL,1); + break; + case T_INT: sp[-1].u.integer = ~ sp[-1].u.integer; break; @@ -944,6 +1056,10 @@ void o_negate() { switch(sp[-1].type) { + case T_OBJECT: + CALL_OPERATOR(LFUN_SUBTRACT,1); + break; + case T_FLOAT: sp[-1].u.float_number=-sp[-1].u.float_number; return; @@ -1016,30 +1132,37 @@ void init_operators() { add_efun2("`==",f_eq,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); add_efun2("`!=",f_ne,"function(mixed,mixed:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); - add_efun2("`<", f_lt,"function(int|float,int|float:int)|function(string,string:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); - add_efun2("`<=",f_le,"function(int|float,int|float:int)|function(string,string:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); - add_efun2("`>", f_gt,"function(int|float,int|float:int)|function(string,string:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); - add_efun2("`>=",f_ge,"function(int|float,int|float:int)|function(string,string:int)",OPT_TRY_OPTIMIZE,0,generate_comparison); + add_efun2("`!",f_not,"function(mixed:int)",OPT_TRY_OPTIMIZE,0,generate_not); - add_efun2("`+",f_add,"function(int...:int)|!function(int...:mixed)&function(int|float...:float)|!function(int|float...:mixed)&function(string|int|float...:string)|function(array...:array)|function(mapping...:mapping)|function(list...:list)",OPT_TRY_OPTIMIZE,optimize_binary,generate_sum); +#define CMP_TYPE "function(object,mixed:int)|function(mixed,object:int)|function(int|float,int|float:int)|function(string,string:int)" + add_efun2("`<", f_lt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); + add_efun2("`<=",f_le,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); + add_efun2("`>", f_gt,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); + add_efun2("`>=",f_ge,CMP_TYPE,OPT_TRY_OPTIMIZE,0,generate_comparison); - add_efun2("`-",f_minus,"function(int:int)|function(float:float)|function(array,array:array)|function(mapping,mapping:mapping)|function(list,list:list)|function(float|int,float:float)|function(float,int:float)|function(int,int:int)|function(string,string:string)",OPT_TRY_OPTIMIZE,0,generate_minus); + add_efun2("`+",f_add,"function(object,mixed...:mixed)|function(int...:int)|!function(int...:mixed)&function(int|float...:float)|!function(int|float...:mixed)&function(string|int|float...:string)|function(array...:array)|function(mapping...:mapping)|function(list...:list)",OPT_TRY_OPTIMIZE,optimize_binary,generate_sum); - add_efun2("`&",f_and,"function(int...:int)|function(mapping...:mapping)|function(list...:list)|function(array...:array)",OPT_TRY_OPTIMIZE,optimize_binary,generate_and); + add_efun2("`-",f_minus,"function(object,mixed...:mixed)|function(int:int)|function(float:float)|function(array,array:array)|function(mapping,mapping:mapping)|function(list,list:list)|function(float|int,float:float)|function(float,int:float)|function(int,int:int)|function(string,string:string)",OPT_TRY_OPTIMIZE,0,generate_minus); - add_efun2("`|",f_or,"function(int...:int)|function(mapping...:mapping)|function(list...:list)|function(array...:array)",OPT_TRY_OPTIMIZE,optimize_binary,generate_or); +#define LOG_TYPE "function(object,mixed...:mixed)|function(int...:int)|function(mapping...:mapping)|function(list...:list)|function(array...:array)" - add_efun2("`^",f_xor,"function(int...:int)|function(mapping...:mapping)|function(list...:list)|function(array...:array)",OPT_TRY_OPTIMIZE,optimize_binary,generate_xor); + add_efun2("`&",f_and,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_and); - add_efun2("`<<",f_lsh,"function(int,int:int)",OPT_TRY_OPTIMIZE,0,generate_lsh); - add_efun2("`>>",f_rsh,"function(int,int:int)",OPT_TRY_OPTIMIZE,0,generate_rsh); + add_efun2("`|",f_or,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_or); - add_efun2("`*",f_multiply,"function(int...:int)|!function(int...:mixed)&function(float|int...:float)|function(string*,string:string)",OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply); + add_efun2("`^",f_xor,LOG_TYPE,OPT_TRY_OPTIMIZE,optimize_binary,generate_xor); - add_efun2("`/",f_divide,"function(int,int:int)|function(float|int,float:float)|function(float,int:float)|function(string,string:string*)",OPT_TRY_OPTIMIZE,0,generate_divide); - add_efun2("`%",f_mod,"function(int,int:int)|!function(int,int:mixed)&function(int|float,int|float:float)",OPT_TRY_OPTIMIZE,0,generate_mod); +#define SHIFT_TYPE "function(object,mixed:mixed)|function(int,int:int)" - add_efun2("`!",f_not,"function(mixed:int)",OPT_TRY_OPTIMIZE,0,generate_not); - add_efun2("`~",f_compl,"function(int:int)|function(float:float)",OPT_TRY_OPTIMIZE,0,generate_compl); + add_efun2("`<<",f_lsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_lsh); + add_efun2("`>>",f_rsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_rsh); + + add_efun2("`*",f_multiply,"function(object,mixed...:mixed)|function(int...:int)|!function(int...:mixed)&function(float|int...:float)|function(string*,string:string)",OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply); + + add_efun2("`/",f_divide,"function(object,mixed:mixed)|function(int,int:int)|function(float|int,float:float)|function(float,int:float)|function(string,string:string*)",OPT_TRY_OPTIMIZE,0,generate_divide); + + add_efun2("`%",f_mod,"function(object,mixed:mixed)|function(int,int:int)|!function(int,int:mixed)&function(int|float,int|float:float)",OPT_TRY_OPTIMIZE,0,generate_mod); + + add_efun2("`~",f_compl,"function(object:mixed)|function(int:int)|function(float:float)",OPT_TRY_OPTIMIZE,0,generate_compl); } diff --git a/src/svalue.c b/src/svalue.c index 300745e4c93a7d303b678e928235e0d2d14e041a..aa14b70353ed5f8a8c0b822cb511c38f4af48b95 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -15,6 +15,7 @@ #include "add_efun.h" #include "error.h" #include "dynamic_buffer.h" +#include "interpret.h" /* * This routine frees a short svalue given a pointer to it and @@ -330,6 +331,86 @@ void assign_short_svalue(union anything *to, } } +unsigned INT32 hash_svalue(struct svalue *s) +{ + unsigned INT32 q; + + check_type(s->type); + check_refs(s); + + switch(s->type) + { + case T_OBJECT: + if(!s->u.object->prog) + { + q=0; + break; + } + + if(s->u.object->prog->lfuns[LFUN___HASH] != -1) + { + safe_apply_low(s->u.object, s->u.object->prog->lfuns[LFUN___HASH], 0); + if(sp[-1].type == T_INT) + { + q=sp[-1].u.integer; + }else{ + q=0; + } + pop_stack(); + break; + } + + default: q=(unsigned INT32)s->u.refs >> 2; + case T_INT: q=s->u.integer; break; + case T_FLOAT: q=(unsigned INT32)(s->u.float_number * 16843009.0); break; + } + q+=q % 997; + q+=((q + s->type) * 9248339); + + return q; +} + +int svalue_is_true(struct svalue *s) +{ + unsigned INT32 q; + check_type(s->type); + check_refs(s); + + switch(s->type) + { + case T_INT: + if(s->u.integer) return 1; + return 0; + + case T_FUNCTION: + check_destructed(s); + if(sp[-1].type==T_INT) return 0; + return 1; + + case T_OBJECT: + check_destructed(s); + if(sp[-1].type==T_INT) return 0; + if(!s->u.object->prog) return 0; + + if(s->u.object->prog->lfuns[LFUN_NOT]!=-1) + { + safe_apply_low(s->u.object,s->u.object->prog->lfuns[LFUN_NOT],0); + if(sp[-1].type == T_INT && sp[-1].u.integer == 0) + { + pop_stack(); + return 1; + } else { + return 0; + } + } + + default: + return 1; + } + +} + + int is_eq(struct svalue *a, struct svalue *b) { check_type(a->type); @@ -340,11 +421,58 @@ int is_eq(struct svalue *a, struct svalue *b) check_destructed(a); check_destructed(b); - if (a->type != b->type) return 0; + if (a->type != b->type) + { + if(a->type == T_OBJECT) + { + if(a->u.object->prog->lfuns[LFUN_EQ] != -1) + { + a_is_obj: + assign_svalue_no_free(sp, b); + sp++; + apply_lfun(a->u.object, LFUN_EQ, 1); + if(IS_ZERO(sp-1)) + { + pop_stack(); + return 0; + }else{ + pop_stack(); + return 1; + } + } + } + + if(b->type == T_OBJECT) + { + if(b->u.object->prog->lfuns[LFUN_EQ] != -1) + { + b_is_obj: + assign_svalue_no_free(sp, a); + sp++; + apply_lfun(b->u.object, LFUN_EQ, 1); + if(IS_ZERO(sp-1)) + { + pop_stack(); + return 0; + }else{ + pop_stack(); + return 1; + } + } + } + + return 0; + } switch(a->type) { - case T_LIST: case T_OBJECT: + if(a->u.object->prog->lfuns[LFUN_EQ] != -1) + goto a_is_obj; + + if(b->u.object->prog->lfuns[LFUN_EQ] != -1) + goto b_is_obj; + + case T_LIST: case T_PROGRAM: case T_ARRAY: case T_MAPPING: @@ -444,7 +572,7 @@ int is_equal(struct svalue *a,struct svalue *b) return low_is_equal(a,b,0); } -int is_lt(const struct svalue *a,const struct svalue *b) +int is_lt(struct svalue *a,struct svalue *b) { check_type(a->type); check_type(b->type); @@ -459,10 +587,52 @@ int is_lt(const struct svalue *a,const struct svalue *b) if(a->type == T_INT && b->type==T_FLOAT) return (FLOAT_TYPE)a->u.integer < b->u.float_number; + if(a->type == T_OBJECT) + { + a_is_object: + if(!a->u.object->prog) + error("Comparison on destructed object.\n"); + if(a->u.object->prog->lfuns[LFUN_LT] == -1) + error("Object lacks '<\n"); + assign_svalue_no_free(sp, b); + sp++; + apply_lfun(a->u.object, LFUN_LT, 1); + if(IS_ZERO(sp-1)) + { + pop_stack(); + return 0; + }else{ + pop_stack(); + return 1; + } + } + + if(b->type == T_OBJECT) + { + if(!b->u.object->prog) + error("Comparison on destructed object.\n"); + if(b->u.object->prog->lfuns[LFUN_GT] == -1) + error("Object lacks '>\n"); + assign_svalue_no_free(sp, a); + sp++; + apply_lfun(b->u.object, LFUN_GT, 1); + if(IS_ZERO(sp-1)) + { + pop_stack(); + return 0; + }else{ + pop_stack(); + return 1; + } + } + error("Cannot compare different types.\n"); } switch(a->type) { + case T_OBJECT: + goto a_is_object; + default: error("Bad type to comparison.\n"); diff --git a/src/svalue.h b/src/svalue.h index 29c3e9b7efac0b1186b1a61610030b4a8183157f..4426fcc3eb7f966e6eaa4dced1cb8df55831075d 100644 --- a/src/svalue.h +++ b/src/svalue.h @@ -95,7 +95,7 @@ struct svalue #define NUMBER_DESTRUCTED 2 #define is_gt(a,b) is_lt(b,a) -#define IS_ZERO(X) ((X)->type==T_INT && (X)->u.integer==0) +#define IS_ZERO(X) ((X)->type==T_INT?(X)->u.integer==0:(1<<(X)->type)&(BIT_OBJECT|BIT_FUNCTION)?!svalue_is_true(X):0) #define check_destructed(S) \ do{ \ @@ -162,6 +162,8 @@ void assign_short_svalue_no_free(union anything *to, void assign_short_svalue(union anything *to, union anything *from, TYPE_T type); +unsigned INT32 hash_svalue(struct svalue *s); +int svalue_is_true(struct svalue *s); int is_eq(struct svalue *a, struct svalue *b); int low_is_equal(struct svalue *a, struct svalue *b, @@ -171,7 +173,7 @@ int low_short_is_equal(const union anything *a, TYPE_T type, struct processing *p); int is_equal(struct svalue *a,struct svalue *b); -int is_lt(const struct svalue *a,const struct svalue *b); +int is_lt(struct svalue *a,struct svalue *b); void describe_svalue(struct svalue *s,int indent,struct processing *p); void clear_svalues(struct svalue *s, INT32 num); void copy_svalues_recursively_no_free(struct svalue *to,