X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fcalc.c;h=f88ab30ad7f708801019ae6fa8ecc05d38cd04b3;hp=f701b5a3fca9388227de8943c42f222861263b8f;hb=224b0dc90c463f236a978f41c66c2f2b565038b5;hpb=c264e2866e9d509e4ed73e2542e80d4c7fb0a92b diff --git a/src/calc.c b/src/calc.c index f701b5a..f88ab30 100644 --- a/src/calc.c +++ b/src/calc.c @@ -1,123 +1,129 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "php.h" -#include "php_psi.h" -#include "parser.h" -#include "calc.h" - -static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val *res) { - impl_val *ref, *tmp = NULL; - - switch (exp->t) { - case PSI_T_NUMBER: - switch (is_numeric_string(exp->u.numb, strlen(exp->u.numb), (zend_long *) res, (double *) res, 0)) { - case IS_LONG: - return PSI_T_INT64; - case IS_DOUBLE: - return PSI_T_DOUBLE; - } - break; +/******************************************************************************* + Copyright (c) 2016, Michael Wallner . + All rights reserved. - case PSI_T_NSNAME: - switch (exp->u.cnst->type->type) { - case PSI_T_INT: - res->i64 = zend_get_constant_str(exp->u.cnst->name, strlen(exp->u.cnst->name))->value.lval; - return PSI_T_INT64; - case PSI_T_FLOAT: - res->dval = zend_get_constant_str(exp->u.cnst->name, strlen(exp->u.cnst->name))->value.dval; - return PSI_T_DOUBLE; - default: - return 0; - } - break; + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - case PSI_T_ENUM: - return psi_calc_num_exp(exp->u.enm->num ?: &exp->u.enm->inc, NULL, res); - break; + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. - case PSI_T_NAME: - if (strct) { - ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp); - } else { - ref = exp->u.dvar->arg->let; - } - switch (real_decl_type(exp->u.dvar->arg->type)->type) { - case PSI_T_INT8: - case PSI_T_UINT8: - case PSI_T_INT16: - case PSI_T_UINT16: - case PSI_T_INT32: - case PSI_T_UINT32: - case PSI_T_INT64: - case PSI_T_UINT64: - memcpy(res, deref_impl_val(ref, exp->u.dvar), sizeof(*res)); - if (tmp) { - free(tmp); - } - return real_decl_type(exp->u.dvar->arg->type)->type; + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ - case PSI_T_FLOAT: - case PSI_T_DOUBLE: - memcpy(res, deref_impl_val(ref, exp->u.dvar), sizeof(*res)); - if (tmp) { - free(tmp); - } - return real_decl_type(exp->u.dvar->arg->type)->type; +#include "php_psi_stdinc.h" +#include - EMPTY_SWITCH_DEFAULT_CASE(); - } - break; +#include "token.h" +#include "calc.h" - EMPTY_SWITCH_DEFAULT_CASE(); - } - return 0; +#define PSI_CALC_CAST_SET(in_type, in_val, op, out_val, out_var) \ +switch (in_type) { \ +case PSI_T_INT8: (out_val)->out_var op (in_val)->i8; break; \ +case PSI_T_UINT8: (out_val)->out_var op (in_val)->u8; break; \ +case PSI_T_INT16: (out_val)->out_var op (in_val)->i16; break; \ +case PSI_T_UINT16: (out_val)->out_var op (in_val)->u16; break; \ +case PSI_T_INT32: (out_val)->out_var op (in_val)->i32; break; \ +case PSI_T_UINT32: (out_val)->out_var op (in_val)->u32; break; \ +case PSI_T_INT64: (out_val)->out_var op (in_val)->i64; break; \ +case PSI_T_UINT64: (out_val)->out_var op (in_val)->u64; break; \ +case PSI_T_FLOAT: (out_val)->out_var op (in_val)->fval; break; \ +case PSI_T_DOUBLE: (out_val)->out_var op (in_val)->dval; break; \ +case PSI_T_LONG_DOUBLE: (out_val)->out_var op (in_val)->ldval; break; \ +default: \ + assert(0); \ } -int psi_calc_num_exp(num_exp *exp, impl_val *strct, impl_val *res) { - impl_val num = {0}; - int num_type = psi_calc_num_exp_value(exp, strct, &num); - - if (exp->operand) { - impl_val tmp = {0}; - int tmp_type = psi_calc_num_exp(exp->operand, strct, &tmp); - - return exp->calculator(num_type, &num, tmp_type, &tmp, res); - } +#define PSI_CALC_CAST(in_type, in_val, op, out_type, out_val) \ +switch (out_type) { \ +case PSI_T_INT8: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i8) break; \ +case PSI_T_UINT8: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u8) break; \ +case PSI_T_INT16: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i16) break; \ +case PSI_T_UINT16: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u16) break; \ +case PSI_T_INT32: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i32) break; \ +case PSI_T_UINT32: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u32) break; \ +case PSI_T_INT64: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, i64) break; \ +case PSI_T_UINT64: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, u64) break; \ +case PSI_T_FLOAT: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, fval) break; \ +case PSI_T_DOUBLE: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, dval) break; \ +case PSI_T_LONG_DOUBLE: PSI_CALC_CAST_SET(in_type, in_val, op, out_val, ldval) break; \ +default: \ + assert(0); \ +} - memcpy(res, &num, sizeof(*res)); - return num_type; +#define PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, out_var) \ +switch (in_type) { \ +case PSI_T_INT8: (out_val)->out_var op (in_val)->i8; break; \ +case PSI_T_UINT8: (out_val)->out_var op (in_val)->u8; break; \ +case PSI_T_INT16: (out_val)->out_var op (in_val)->i16; break; \ +case PSI_T_UINT16: (out_val)->out_var op (in_val)->u16; break; \ +case PSI_T_INT32: (out_val)->out_var op (in_val)->i32; break; \ +case PSI_T_UINT32: (out_val)->out_var op (in_val)->u32; break; \ +case PSI_T_INT64: (out_val)->out_var op (in_val)->i64; break; \ +case PSI_T_UINT64: (out_val)->out_var op (in_val)->u64; break; \ +default: \ + assert(0); \ +} +#define PSI_CALC_CAST_INT(in_type, in_val, op, out_type, out_val) \ +switch (out_type) { \ +case PSI_T_INT8: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i8) break; \ +case PSI_T_UINT8: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u8) break; \ +case PSI_T_INT16: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i16) break; \ +case PSI_T_UINT16: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u16) break; \ +case PSI_T_INT32: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i32) break; \ +case PSI_T_UINT32: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u32) break; \ +case PSI_T_INT64: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, i64) break; \ +case PSI_T_UINT64: PSI_CALC_CAST_SET_INT(in_type, in_val, op, out_val, u64) break; \ +default: \ + assert(0); \ } -#define PRIfval "f" -#define PRIdval "lf" -#define PRIldval "Lf" +void psi_calc_cast(token_t in_type, impl_val *in_val, token_t out_type, impl_val *out_val) +{ + PSI_CALC_CAST(in_type, in_val, =, out_type, out_val) +} +#if 0 #define PSI_CALC_OP(var) do { \ const char *fmt = "calc %" PRI##var ", %" PRI##var ": %" PRI##var "\n"; \ res->var = PSI_CALC(v1->var, v2->var); \ - if (!res->var) fprintf(stderr, fmt, v1->var, v2->var, res->var); \ + if (!res->var && (v1->var || v2->var)) fprintf(stderr, fmt, v1->var, v2->var, res->var); \ } while (0) #define PSI_CALC_OP2(vres, var1, var2) do { \ const char *fmt = "calc %" PRI##var1 ", %" PRI##var2 ": %" PRI##vres "\n"; \ res->vres = PSI_CALC(v1->var1, v2->var2); \ - if (!res->vres) fprintf(stderr, fmt, v1->var1, v2->var2, res->vres); \ + if (!res->vres && (v1->var1 || v2->var2)) fprintf(stderr, fmt, v1->var1, v2->var2, res->vres); \ } while(0) +#else +#define PSI_CALC_OP(var) res->var = PSI_CALC(v1->var, v2->var) +#define PSI_CALC_OP2(vres, var1, var2) res->vres = PSI_CALC(v1->var1, v2->var2) +#endif #ifdef HAVE_LONG_DOUBLE -#define PSI_CALC_NO_LD -#define PSI_CALC_OP_LD PSI_CALC_OP(ldval) -#define PSI_CALC_OP2_LD2(var1) PSI_CALC_OP2(ldval, var1, ldval) -#define PSI_CALC_OP2_LD1(var2) PSI_CALC_OP2(ldval, ldval, var2) +# define PSI_CALC_NO_LD +# define PSI_CALC_OP_LD PSI_CALC_OP(ldval) +# define PSI_CALC_OP2_LD2(var1) PSI_CALC_OP2(ldval, var1, ldval) +# define PSI_CALC_OP2_LD1(var2) PSI_CALC_OP2(ldval, ldval, var2) #else -#define PSI_CALC_NO_LD abort() -#define PSI_CALC_OP_LD PSI_CALC_NO_LD -#define PSI_CALC_OP2_LD2(var) PSI_CALC_NO_LD -#define PSI_CALC_OP2_LD1(var) PSI_CALC_NO_LD +# define PSI_CALC_NO_LD abort() +# define PSI_CALC_OP_LD PSI_CALC_NO_LD +# define PSI_CALC_OP2_LD2(var) PSI_CALC_NO_LD +# define PSI_CALC_OP2_LD1(var) PSI_CALC_NO_LD #endif -#define PSI_CALC_FN(op) int psi_calc_##op(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res) \ +#define PSI_CALC_FN(op) token_t psi_calc_##op(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) \ { \ if (t1 == t2) { \ switch (t1) { \ @@ -271,7 +277,7 @@ int psi_calc_num_exp(num_exp *exp, impl_val *strct, impl_val *res) { break; \ } \ } \ - ZEND_ASSERT(0); \ + assert(0); \ return 0; \ } @@ -287,3 +293,62 @@ PSI_CALC_FN(sub) #undef PSI_CALC #define PSI_CALC(var1, var2) (var1) / (var2) PSI_CALC_FN(div) +#undef PSI_CALC + +token_t psi_calc_mod(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) +{ + impl_val i1, i2; + + PSI_CALC_CAST(t1, v1, =, PSI_T_INT64, &i1); + PSI_CALC_CAST(t2, v2, =, PSI_T_INT64, &i2); + + res->i64 = i1.i64 % i2.i64; + + return PSI_T_INT64; +} + +#define PSI_CALC_BIT_FN(op) token_t psi_calc_##op(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) \ +{ \ + impl_val i1, i2; \ + PSI_CALC_CAST(t1, v1, =, PSI_T_UINT64, &i1); \ + PSI_CALC_CAST(t2, v2, =, PSI_T_UINT64, &i2); \ + res->u64 = PSI_CALC(i1.u64, i2.u64); \ + return PSI_T_UINT64; \ +} + +#define PSI_CALC(var1, var2) (var1) << (var2) +PSI_CALC_BIT_FN(bin_lshift) +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) >> (var2) +PSI_CALC_BIT_FN(bin_rshift) +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) & (var2) +PSI_CALC_BIT_FN(bin_and) +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) ^ (var2) +PSI_CALC_BIT_FN(bin_xor) +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) | (var2) +PSI_CALC_BIT_FN(bin_or) +#undef PSI_CALC + +token_t psi_calc_not(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) +{ + (void) t2; + (void) v2; + + PSI_CALC_CAST(t1, v1, =!, t1, res); + return t1; +} + +token_t psi_calc_bin_not(token_t t1, impl_val *v1, token_t t2, impl_val *v2, impl_val *res) +{ + impl_val i1; + + (void) t2; + (void) v2; + + PSI_CALC_CAST(t1, v1, =, PSI_T_UINT64, &i1); + PSI_CALC_CAST_INT(t1, &i1, =~, t1, res); + return t1; +}