X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fmarshal.c;h=c7651f6c023243b1b0c4de855aebd921713291d7;hp=63a7dc914bbcfc278c98c627d809fafac260325f;hb=fecb0372ee8e219a7ebd51406dee3e1008ccb7ec;hpb=6d8fda8d1cd382e6d6626df5353d285176bd9bf2 diff --git a/src/marshal.c b/src/marshal.c index 63a7dc9..c7651f6 100644 --- a/src/marshal.c +++ b/src/marshal.c @@ -154,7 +154,7 @@ void psi_set_void(zval *return_value, struct psi_set_exp *set, impl_val *ret_val /* * ? */ -impl_val *psi_let_void(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_void(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { return tmp; } @@ -169,7 +169,7 @@ void psi_set_zval(zval *return_value, struct psi_set_exp *set, impl_val *ret_val /* * let dvar = zval($ivar) */ -impl_val *psi_let_zval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_zval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { *to_free = tmp->ptr = emalloc(sizeof(zval)); ZVAL_COPY_VALUE(tmp->ptr, zvalue); @@ -195,6 +195,10 @@ static inline impl_val *psi_val_boolval(impl_val *tmp, token_t real_type, zend_b case PSI_T_UINT32: tmp->u32 = boolval; break; case PSI_T_INT64: tmp->i64 = boolval; break; case PSI_T_UINT64: tmp->u64 = boolval; break; +#ifdef HAVE_INT128 + case PSI_T_INT128: tmp->i128 = boolval; break; + case PSI_T_UINT128: tmp->u128 = boolval; break; +#endif case PSI_T_FLOAT: tmp->fval = boolval; break; case PSI_T_DOUBLE: tmp->dval = boolval; break; #ifdef HAVE_LONG_DOUBLE @@ -208,10 +212,10 @@ static inline impl_val *psi_val_boolval(impl_val *tmp, token_t real_type, zend_b /* * let dvar = boolval($ivar) */ -impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { zend_bool boolval; - token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_UINT8; + token_t real_type = spec ? psi_decl_type_get_real(spec->type)->type : PSI_T_UINT8; if (ival && impl_type == PSI_T_BOOL) { boolval = ival->zend.bval; @@ -222,14 +226,52 @@ impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_type *spec, token_t imp return psi_val_boolval(tmp, real_type, boolval); } -# define RETVAL_LONG_U64(V) \ - if (V > ZEND_LONG_MAX) { \ - char d[24] = {0}; \ - RETVAL_STRING(zend_print_ulong_to_buf(&d[22], V)); \ +#if HAVE_INT128 +static inline char *psi_u128_to_buf(char *buf, unsigned __int128 u128) +{ + for (*buf = 0; u128 > 0; u128 /= 10) { + *--buf = ((u128 % 10) + '0') & 0xff; + } + return buf; +} + +static inline char *psi_i128_to_buf(char *buf, __int128 i128) +{ + if (i128 < 0) { + char *res = psi_u128_to_buf(buf, ~((unsigned __int128) i128) + 1); + + *--res = '-'; + return res; + } + return psi_u128_to_buf(buf, i128); +} + +# define RETVAL_LONG_STR(V, s) do {\ + char buf[0x30] = {0}; \ + if (s && V >= ZEND_LONG_MIN && V <= ZEND_LONG_MAX) { \ + RETVAL_LONG(V); \ + } else if (!s && V <= ZEND_LONG_MAX) { \ + RETVAL_LONG(V); \ + } else if (!s && V <= ZEND_ULONG_MAX) { \ + RETVAL_STRING(zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], V)); \ + } else if (s && V >= INT128_MIN && V <= INT128_MAX) { \ + RETVAL_STRING(psi_i128_to_buf(&buf[sizeof(buf) - 1], V)); \ } else { \ + RETVAL_STRING(psi_u128_to_buf(&buf[sizeof(buf) - 1], V)); \ + } \ + } while (0) +#else +# define RETVAL_LONG_STR(V, s) do {\ + char buf[0x20] = {0}; \ + if (s && V >= ZEND_LONG_MIN && V <= ZEND_LONG_MAX) { \ RETVAL_LONG(V); \ - } - + } else if (!s && V <= ZEND_LONG_MAX) { \ + RETVAL_LONG(V); \ + } else { \ + RETVAL_STRING(zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], V)); \ + } \ + } while (0) +#endif /* * set $ivar = to_int(*dvar) */ @@ -244,19 +286,31 @@ void psi_set_to_int(zval *return_value, struct psi_set_exp *set, impl_val *ret_v case PSI_T_UINT8: RETVAL_LONG(v->u8); break; case PSI_T_INT16: RETVAL_LONG(v->i16); break; case PSI_T_UINT16: RETVAL_LONG(v->u16); break; + case PSI_T_ENUM: case PSI_T_INT32: RETVAL_LONG(v->i32); break; case PSI_T_UINT32: RETVAL_LONG(v->u32); break; case PSI_T_INT64: RETVAL_LONG(v->i64); break; - case PSI_T_UINT64: RETVAL_LONG_U64(v->u64); break; - case PSI_T_FLOAT: RETVAL_DOUBLE((double) v->fval); break; - case PSI_T_DOUBLE: RETVAL_DOUBLE(v->dval); break; + case PSI_T_UINT64: RETVAL_LONG_STR(v->u64, 0); break; +#ifdef HAVE_INT128 + case PSI_T_INT128: RETVAL_LONG_STR(v->i128, 1); break; + case PSI_T_UINT128: RETVAL_LONG_STR(v->u128, 0); break; +#endif + case PSI_T_FLOAT: + RETVAL_DOUBLE((double) v->fval); + convert_to_long(return_value); + break; + case PSI_T_DOUBLE: + RETVAL_DOUBLE(v->dval); + convert_to_long(return_value); + break; #ifdef HAVE_LONG_DOUBLE - case PSI_T_LONG_DOUBLE: RETVAL_DOUBLE((double) v->ldval); break; + case PSI_T_LONG_DOUBLE: + RETVAL_DOUBLE((double) v->ldval); + convert_to_long(return_value); + break; #endif EMPTY_SWITCH_DEFAULT_CASE(); } - - convert_to_long(return_value); } static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_long intval) { @@ -265,12 +319,15 @@ static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_lo case PSI_T_UINT8: tmp->u8 = intval; break; case PSI_T_INT16: tmp->i16 = intval; break; case PSI_T_UINT16: tmp->u16 = intval; break; + case PSI_T_ENUM: case PSI_T_INT32: tmp->i32 = intval; break; case PSI_T_UINT32: tmp->u32 = intval; break; case PSI_T_INT64: tmp->i64 = intval; break; case PSI_T_UINT64: tmp->u64 = intval; break; - case PSI_T_INT: tmp->ival = intval; break; - case PSI_T_LONG: tmp->lval = intval; break; +#if HAVE_INT128 + case PSI_T_INT128: tmp->i128 = intval; break; + case PSI_T_UINT128: tmp->u128 = intval; break; +#endif case PSI_T_FLOAT: tmp->fval = intval; break; case PSI_T_DOUBLE: tmp->dval = intval; break; #ifdef HAVE_LONG_DOUBLE @@ -282,16 +339,104 @@ static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_lo return tmp; } +#if HAVE_INT128 +void psi_strto_i128(char *ptr, char *end, token_t real_type, impl_val *val) { + unsigned __int128 i = 0; + bool oct = false, hex = false, sign = false; + + if (*ptr == '+') { + ++ptr; + } else if (*ptr == '-') { + sign = true; + ++ptr; + } else if (*ptr == '\\') { + switch (*++ptr) { + case 'x': + hex = true; + ++ptr; + break; + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7': + oct = true; + break; + default: + goto fail; + } + } + while (ptr < end) { + switch (*ptr) { + case '8':case '9': + if (oct) { + goto fail; + } + /* no break */ + case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7': + if (oct) { + i <<= 3; + } else if (hex) { + i <<= 4; + } else { + i *= 10; + } + i += *ptr - '0'; + break; + case 'a':case 'b':case 'c':case 'd':case 'e':case 'f': + if (!hex) { + goto fail; + } + i <<= 4; + i += 10 + (*ptr - 'a'); + break; + case 'A':case 'B':case 'C':case 'D':case 'E':case 'F': + if (!hex) { + goto fail; + } + i <<= 4; + i += 10 + (*ptr - 'A'); + break; + default: + fail: + zend_error(E_WARNING, "A non well formed numeric value encountered"); + goto stop; + } + ++ptr; + } + +stop: + if (real_type == PSI_T_UINT128) { + if (sign) { + val->u128 = -i; + } else { + val->u128 = i; + } + } else { + if (sign) { + val->i128 = -i; + } else { + val->i128 = i; + } + } +} +#endif + /* * let dvar = intval($ivar) */ -impl_val *psi_let_intval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_intval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { - zend_long intval; - token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_LONG; + int64_t intval; + token_t real_type = spec ? psi_decl_type_get_real(spec->type)->type : PSI_T_INT64; + if (ival && impl_type == PSI_T_INT) { intval = ival->zend.lval; +#if HAVE_INT128 + } else if ((real_type == PSI_T_UINT128 || real_type == PSI_T_INT128) && + !((Z_TYPE_P(zvalue) == IS_TRUE || Z_TYPE_P(zvalue) == IS_FALSE || Z_TYPE_P(zvalue) == IS_LONG || Z_TYPE_P(zvalue) == IS_DOUBLE || Z_TYPE_P(zvalue) == IS_NULL))) { + zend_string *str = zval_get_string(zvalue); + psi_strto_i128(str->val, str->val + str->len, real_type, tmp); + zend_string_release(str); + return tmp; +#endif } else { intval = zval_get_long(zvalue); } @@ -322,6 +467,10 @@ void psi_set_to_float(zval *return_value, struct psi_set_exp *set, impl_val *ret case PSI_T_UINT32: RETVAL_DOUBLE((double) v->u32); break; case PSI_T_INT64: RETVAL_DOUBLE((double) v->i64); break; case PSI_T_UINT64: RETVAL_DOUBLE((double) v->u64); break; +#if HAVE_INT128 + case PSI_T_INT128: RETVAL_DOUBLE((double) v->i128); break; + case PSI_T_UINT128: RETVAL_DOUBLE((double) v->u128); break; +#endif EMPTY_SWITCH_DEFAULT_CASE(); } } @@ -336,6 +485,10 @@ static inline impl_val *psi_val_floatval(impl_val *tmp, token_t real_type, doubl case PSI_T_UINT32: tmp->u32 = floatval; break; case PSI_T_INT64: tmp->i64 = floatval; break; case PSI_T_UINT64: tmp->u64 = floatval; break; +#if HAVE_INT128 + case PSI_T_INT128: tmp->i128 = floatval; break; + case PSI_T_UINT128: tmp->u128 = floatval; break; +#endif case PSI_T_FLOAT: tmp->fval = floatval; break; case PSI_T_DOUBLE: tmp->dval = floatval; break; #ifdef HAVE_LONG_DOUBLE @@ -350,10 +503,10 @@ static inline impl_val *psi_val_floatval(impl_val *tmp, token_t real_type, doubl /* * let dvar = floatval($ivar) */ -impl_val *psi_let_floatval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_floatval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { double floatval; - token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_DOUBLE; + token_t real_type = spec ? psi_decl_type_get_real(spec->type)->type : PSI_T_DOUBLE; if (ival && (impl_type == PSI_T_FLOAT || impl_type == PSI_T_DOUBLE)) { floatval = ival->dval; @@ -373,7 +526,7 @@ void psi_set_to_string(zval *return_value, struct psi_set_exp *set, impl_val *re impl_val *ptr = deref_impl_val(ret_val, var); char *str; - if (var->arg->var->array_size) { + if (var->arg->var->array_size && var->arg->var->pointer_level == 1) { str = (char *) ptr; } else { str = ptr->ptr; @@ -398,7 +551,7 @@ void psi_set_to_stringl(zval *return_value, struct psi_set_exp *set, impl_val *r struct psi_set_exp *sub_exp; psi_plist_get(set->inner, 0, &sub_exp); - RETVAL_STRINGL(str, psi_long_num_exp(sub_exp->data.num, frame)); + RETVAL_STRINGL(str, psi_num_exp_get_long(sub_exp->data.num, frame, NULL)); } else { RETVAL_EMPTY_STRING(); } @@ -407,7 +560,7 @@ void psi_set_to_stringl(zval *return_value, struct psi_set_exp *set, impl_val *r /* * let dvar = strval($ivar) */ -impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { if (ival && impl_type == PSI_T_STRING) { if (ival->zend.str) { @@ -428,7 +581,7 @@ impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_type *spec, token_t impl /* * let dvar = pathval($ivar) */ -impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { tmp = psi_let_strval(tmp, spec, impl_type, ival, zvalue, to_free); if (SUCCESS != php_check_open_basedir(tmp->ptr)) { @@ -442,29 +595,34 @@ impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_type *spec, token_t imp /* * let dvar = strlen($ivar) */ -impl_val *psi_let_strlen(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_strlen(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { if (ival && impl_type == PSI_T_STRING) { if (ival->zend.str) { - tmp->lval = ival->zend.str->len; + tmp->u64 = ival->zend.str->len; } else { - tmp->lval = 0; + tmp->u64 = 0; } } else { zend_string *zs = zval_get_string(zvalue); - tmp->lval = zs->len; + tmp->u64 = zs->len; zend_string_release(zs); } + if (spec) { + psi_calc_cast(PSI_T_UINT64, tmp, psi_decl_type_get_real(spec->type)->type, tmp); + } return tmp; } +#if 0 static impl_val *iterate(impl_val *val, size_t size, unsigned i, impl_val *tmp) { memset(tmp, 0, sizeof(*tmp)); memcpy(tmp, ((char *) val) + size * i, size); return tmp; } +#endif /* * set $ivar = to_array(dvar, @@ -528,11 +686,11 @@ void psi_set_to_array_counted(zval *return_value, struct psi_set_exp *set, impl_ } psi_plist_get(set->inner, 0, &sub_exp); - count = psi_long_num_exp(sub_exp->data.num, frame); + count = psi_num_exp_get_long(sub_exp->data.num, frame, NULL); psi_plist_get(set->inner, 1, &sub_exp); - for (ptr = (char *) ret_val; 0 < count--; ptr += size) { size = psi_decl_var_get_size(psi_set_exp_get_decl_var(sub_exp)); + for (ptr = (char *) ret_val; 0 < count--; ptr += size) { zval ele; ZVAL_NULL(&ele); @@ -578,49 +736,12 @@ void psi_set_to_array(zval *return_value, struct psi_set_exp *set, impl_val *r_v } } -//impl_val *psi_let_arrval(impl_val *tmp, decl_type *spec, decl_var *spec_var, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) -//{ -// decl_type *real = real_decl_type(spec); -// HashTable *arr; -// zval *zv; -// size_t i, sz; -// decl_arg tmp_arg = {0}; -// -// if (impl_type != PSI_T_ARRAY) { -// SEPARATE_ARG_IF_REF(zvalue); -// convert_to_array(zvalue); -// } -// arr = HASH_OF(zvalue); -// -// switch (real->type) { -// case PSI_T_STRUCT: -// *to_free = tmp = psi_array_to_struct(real->real.strct, arr); -// break; -// case PSI_T_UNION: -// *to_free = tmp = psi_array_to_union(real->real.unn, arr); -// break; -// default: -// sz = psi_t_size(real->type); -// tmp = *to_free = ecalloc(zend_hash_num_elements(arr), sz); -// tmp_arg.type = spec; -// tmp_arg.var = spec_var; -// ZEND_HASH_FOREACH_VAL_IND(arr, zv) -// { -// void *ptr = ((char *) tmp) + (i++ * sz); -// psi_from_zval_ex(NULL, (impl_val **) &ptr, &tmp_arg, 0, zv, NULL); -// } -// ZEND_HASH_FOREACH_END(); -// } -// -// return tmp; -//} - /* * let dvar = count($ivar) */ -impl_val *psi_let_count(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_count(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { - return psi_val_intval(tmp, psi_decl_type_get_real(spec)->type, psi_zval_count(zvalue)); + return psi_val_intval(tmp, psi_decl_type_get_real(spec->type)->type, psi_zval_count(zvalue)); } /* @@ -642,7 +763,7 @@ void psi_set_to_object(zval *return_value, struct psi_set_exp *set, impl_val *r_ /* * let dvar = objval($ivar) */ -impl_val *psi_let_objval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) +impl_val *psi_let_objval(impl_val *tmp, struct psi_decl_arg *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free) { psi_object *obj;