1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
29 # include "php_config.h"
37 #include "Zend/zend_interfaces.h"
38 #include "ext/spl/spl_iterators.h"
40 zend_long
psi_zval_count(zval
*zvalue
)
42 /* mimic PHP count() */
46 switch (Z_TYPE_P(zvalue
)) {
54 count
= zend_array_count(Z_ARRVAL_P(zvalue
));
58 if (Z_OBJ_HT_P(zvalue
)->count_elements
) {
59 if (SUCCESS
== Z_OBJ_HT_P(zvalue
)->count_elements(zvalue
, &count
)) {
64 if (instanceof_function(Z_OBJCE_P(zvalue
), spl_ce_Countable
)) {
65 zend_call_method_with_0_params(zvalue
, NULL
, NULL
, "count", &retval
);
66 if (Z_TYPE(retval
) != IS_UNDEF
) {
67 count
= zval_get_long(&retval
);
68 zval_ptr_dtor(&retval
);
77 int psi_internal_type(struct psi_impl_type
*type
)
96 zend_internal_arg_info
*psi_internal_arginfo(struct psi_impl
*impl
)
98 size_t i
= 0, argc
= psi_plist_count(impl
->func
->args
);
99 zend_internal_arg_info
*aip
;
100 zend_internal_function_info
*fi
;
101 struct psi_impl_arg
*iarg
;
103 aip
= pecalloc(argc
+ 1 + !!impl
->func
->vararg
, sizeof(*aip
), 1);
105 fi
= (zend_internal_function_info
*) &aip
[0];
106 #ifdef ZEND_TYPE_ENCODE
107 fi
->type
= ZEND_TYPE_ENCODE(psi_internal_type(impl
->func
->return_type
), 1);
110 fi
->type_hint
= psi_internal_type(impl
->func
->return_type
);
112 fi
->required_num_args
= psi_impl_num_min_args(impl
);
113 fi
->return_reference
= impl
->func
->return_reference
;
115 if (impl
->func
->vararg
) {
116 struct psi_impl_arg
*vararg
= impl
->func
->vararg
;
117 zend_internal_arg_info
*ai
= &aip
[argc
];
119 ai
->name
= vararg
->var
->name
->val
;
120 #ifdef ZEND_TYPE_ENCODE
121 ai
->type
= ZEND_TYPE_ENCODE(psi_internal_type(vararg
->type
), 1);
124 ai
->type_hint
= psi_internal_type(vararg
->type
);
126 if (vararg
->var
->reference
) {
127 ai
->pass_by_reference
= 1;
132 while (psi_plist_get(impl
->func
->args
, i
++, &iarg
)) {
133 zend_internal_arg_info
*ai
= &aip
[i
];
135 ai
->name
= iarg
->var
->name
->val
;
136 #ifdef ZEND_TYPE_ENCODE
137 ai
->type
= ZEND_TYPE_ENCODE(psi_internal_type(iarg
->type
), 1);
140 ai
->type_hint
= psi_internal_type(iarg
->type
);
142 if (iarg
->var
->reference
) {
143 ai
->pass_by_reference
= 1;
153 void psi_set_void(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
161 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
)
167 * set $ivar = zval(dvar)
169 void psi_set_zval(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
) {
170 RETVAL_ZVAL(ret_val
->ptr
, 1, 0);
174 * let dvar = zval($ivar)
176 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
)
178 *to_free
= tmp
->ptr
= emalloc(sizeof(zval
));
179 ZVAL_COPY_VALUE(tmp
->ptr
, zvalue
);
184 * return to_bool(dvar)
186 void psi_set_to_bool(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
188 psi_set_to_int(return_value
, set
, ret_val
, frame
);
189 convert_to_boolean(return_value
);
192 static inline impl_val
*psi_val_boolval(impl_val
*tmp
, token_t real_type
, zend_bool boolval
) {
194 case PSI_T_INT8
: tmp
->i8
= boolval
; break;
195 case PSI_T_UINT8
: tmp
->u8
= boolval
; break;
196 case PSI_T_INT16
: tmp
->i16
= boolval
; break;
197 case PSI_T_UINT16
: tmp
->u16
= boolval
; break;
198 case PSI_T_INT32
: tmp
->i32
= boolval
; break;
199 case PSI_T_UINT32
: tmp
->u32
= boolval
; break;
200 case PSI_T_INT64
: tmp
->i64
= boolval
; break;
201 case PSI_T_UINT64
: tmp
->u64
= boolval
; break;
203 case PSI_T_INT128
: tmp
->i128
= boolval
; break;
204 case PSI_T_UINT128
: tmp
->u128
= boolval
; break;
206 case PSI_T_FLOAT
: tmp
->fval
= boolval
; break;
207 case PSI_T_DOUBLE
: tmp
->dval
= boolval
; break;
208 #ifdef HAVE_LONG_DOUBLE
209 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= boolval
; break;
211 EMPTY_SWITCH_DEFAULT_CASE();
217 * let dvar = boolval($ivar)
219 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
)
222 token_t real_type
= spec
? psi_decl_type_get_real(spec
->type
)->type
: PSI_T_UINT8
;
224 if (ival
&& impl_type
== PSI_T_BOOL
) {
225 boolval
= ival
->zend
.bval
;
227 boolval
= zend_is_true(zvalue
);
230 return psi_val_boolval(tmp
, real_type
, boolval
);
234 * set $ivar = to_int(*dvar)
236 void psi_set_to_int(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
238 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
239 token_t t
= psi_decl_type_get_real(var
->arg
->type
)->type
;
240 impl_val
*v
= deref_impl_val(ret_val
, var
);
243 case PSI_T_INT8
: RETVAL_LONG(v
->i8
); break;
244 case PSI_T_UINT8
: RETVAL_LONG(v
->u8
); break;
245 case PSI_T_INT16
: RETVAL_LONG(v
->i16
); break;
246 case PSI_T_UINT16
: RETVAL_LONG(v
->u16
); break;
248 case PSI_T_INT32
: RETVAL_LONG(v
->i32
); break;
249 case PSI_T_UINT32
: RETVAL_LONG(v
->u32
); break;
250 case PSI_T_INT64
: RETVAL_LONG(v
->i64
); break;
251 case PSI_T_UINT64
: RETVAL_LONG_DOUBLE_STR(v
->u64
,); break;
253 case PSI_T_INT128
: RETVAL_LONG_DOUBLE_STR(v
->i128
, is_signed
=true); break;
254 case PSI_T_UINT128
: RETVAL_LONG_DOUBLE_STR(v
->u128
,); break;
257 RETVAL_DOUBLE((double) v
->fval
);
258 convert_to_long(return_value
);
261 RETVAL_DOUBLE(v
->dval
);
262 convert_to_long(return_value
);
264 #ifdef HAVE_LONG_DOUBLE
265 case PSI_T_LONG_DOUBLE
:
266 RETVAL_DOUBLE((double) v
->ldval
);
267 convert_to_long(return_value
);
270 EMPTY_SWITCH_DEFAULT_CASE();
274 static inline impl_val
*psi_val_intval(impl_val
*tmp
, token_t real_type
, zend_long intval
) {
276 case PSI_T_INT8
: tmp
->i8
= intval
; break;
277 case PSI_T_UINT8
: tmp
->u8
= intval
; break;
278 case PSI_T_INT16
: tmp
->i16
= intval
; break;
279 case PSI_T_UINT16
: tmp
->u16
= intval
; break;
281 case PSI_T_INT32
: tmp
->i32
= intval
; break;
282 case PSI_T_UINT32
: tmp
->u32
= intval
; break;
283 case PSI_T_INT64
: tmp
->i64
= intval
; break;
284 case PSI_T_UINT64
: tmp
->u64
= intval
; break;
286 case PSI_T_INT128
: tmp
->i128
= intval
; break;
287 case PSI_T_UINT128
: tmp
->u128
= intval
; break;
289 case PSI_T_FLOAT
: tmp
->fval
= intval
; break;
290 case PSI_T_DOUBLE
: tmp
->dval
= intval
; break;
291 #ifdef HAVE_LONG_DOUBLE
292 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= intval
; break;
294 EMPTY_SWITCH_DEFAULT_CASE();
301 static void psi_strto_i128(char *ptr
, char *end
, token_t real_type
, impl_val
*val
) {
302 unsigned __int128 i
= 0;
303 bool oct
= false, hex
= false, sign
= false;
307 } else if (*ptr
== '-') {
310 } else if (*ptr
== '\\') {
316 case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':
330 case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':
340 case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
345 i
+= 10 + (*ptr
- 'a');
347 case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
352 i
+= 10 + (*ptr
- 'A');
356 zend_error(E_WARNING
, "A non well formed numeric value encountered");
363 if (real_type
== PSI_T_UINT128
) {
380 * let dvar = intval($ivar)
382 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
)
385 token_t real_type
= spec
? psi_decl_type_get_real(spec
->type
)->type
: PSI_T_INT64
;
388 if (ival
&& impl_type
== PSI_T_INT
) {
389 intval
= ival
->zend
.lval
;
391 } else if ((real_type
== PSI_T_UINT128
|| real_type
== PSI_T_INT128
) &&
392 !((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
))) {
393 zend_string
*str
= zval_get_string(zvalue
);
394 psi_strto_i128(str
->val
, str
->val
+ str
->len
, real_type
, tmp
);
395 zend_string_release(str
);
399 intval
= zval_get_long(zvalue
);
402 return psi_val_intval(tmp
, real_type
, intval
);
406 * set $ivar = to_float(dvar)
408 void psi_set_to_float(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
410 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
411 token_t t
= psi_decl_type_get_real(var
->arg
->type
)->type
;
412 impl_val
*v
= deref_impl_val(ret_val
, var
);
415 case PSI_T_FLOAT
: RETVAL_DOUBLE((double) v
->fval
); break;
416 case PSI_T_DOUBLE
: RETVAL_DOUBLE(v
->dval
); break;
417 #ifdef HAVE_LONG_DOUBLE
418 case PSI_T_LONG_DOUBLE
: RETVAL_DOUBLE((double) v
->ldval
); break;
420 case PSI_T_INT8
: RETVAL_DOUBLE((double) v
->i8
); break;
421 case PSI_T_UINT8
: RETVAL_DOUBLE((double) v
->u8
); break;
422 case PSI_T_INT16
: RETVAL_DOUBLE((double) v
->i16
); break;
423 case PSI_T_UINT16
: RETVAL_DOUBLE((double) v
->u16
); break;
424 case PSI_T_INT32
: RETVAL_DOUBLE((double) v
->i32
); break;
425 case PSI_T_UINT32
: RETVAL_DOUBLE((double) v
->u32
); break;
426 case PSI_T_INT64
: RETVAL_DOUBLE((double) v
->i64
); break;
427 case PSI_T_UINT64
: RETVAL_DOUBLE((double) v
->u64
); break;
429 case PSI_T_INT128
: RETVAL_DOUBLE((double) v
->i128
); break;
430 case PSI_T_UINT128
: RETVAL_DOUBLE((double) v
->u128
); break;
432 EMPTY_SWITCH_DEFAULT_CASE();
436 static inline impl_val
*psi_val_floatval(impl_val
*tmp
, token_t real_type
, double floatval
) {
438 case PSI_T_INT8
: tmp
->i8
= floatval
; break;
439 case PSI_T_UINT8
: tmp
->u8
= floatval
; break;
440 case PSI_T_INT16
: tmp
->i16
= floatval
; break;
441 case PSI_T_UINT16
: tmp
->u16
= floatval
; break;
442 case PSI_T_INT32
: tmp
->i32
= floatval
; break;
443 case PSI_T_UINT32
: tmp
->u32
= floatval
; break;
444 case PSI_T_INT64
: tmp
->i64
= floatval
; break;
445 case PSI_T_UINT64
: tmp
->u64
= floatval
; break;
447 case PSI_T_INT128
: tmp
->i128
= floatval
; break;
448 case PSI_T_UINT128
: tmp
->u128
= floatval
; break;
450 case PSI_T_FLOAT
: tmp
->fval
= floatval
; break;
451 case PSI_T_DOUBLE
: tmp
->dval
= floatval
; break;
452 #ifdef HAVE_LONG_DOUBLE
453 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= floatval
; break;
455 EMPTY_SWITCH_DEFAULT_CASE();
462 * let dvar = floatval($ivar)
464 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
)
467 token_t real_type
= spec
? psi_decl_type_get_real(spec
->type
)->type
: PSI_T_DOUBLE
;
469 if (ival
&& (impl_type
== PSI_T_FLOAT
|| impl_type
== PSI_T_DOUBLE
)) {
470 floatval
= ival
->dval
;
472 floatval
= zval_get_double(zvalue
);
475 return psi_val_floatval(tmp
, real_type
, floatval
);
479 * set $ivar = to_string(dvar)
481 void psi_set_to_string(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
483 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
484 impl_val
*ptr
= deref_impl_val(ret_val
, var
);
487 if (var
->arg
->var
->array_size
&& var
->arg
->var
->pointer_level
== 1) {
496 RETVAL_EMPTY_STRING();
501 * set $ivar = to_string(dvar, num_exp)
503 void psi_set_to_stringl(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
505 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
506 char *str
= deref_impl_val(ret_val
, var
)->ptr
;
509 struct psi_set_exp
*sub_exp
;
511 psi_plist_get(set
->inner
, 0, &sub_exp
);
512 RETVAL_STRINGL(str
, psi_num_exp_get_long(sub_exp
->data
.num
, frame
, NULL
));
514 RETVAL_EMPTY_STRING();
519 * let dvar = strval($ivar)
521 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
)
523 if (ival
&& impl_type
== PSI_T_STRING
) {
524 if (ival
->zend
.str
) {
525 tmp
->ptr
= ival
->zend
.str
->val
;
530 zend_string
*zs
= zval_get_string(zvalue
);
531 tmp
->ptr
= estrdup(zs
->val
);
533 zend_string_release(zs
);
540 * let dvar = pathval($ivar)
542 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
)
544 tmp
= psi_let_strval(tmp
, spec
, impl_type
, ival
, zvalue
, to_free
);
545 if (SUCCESS
!= php_check_open_basedir(tmp
->ptr
)) {
548 return *to_free
= NULL
;
554 * let dvar = strlen($ivar)
556 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
)
558 if (ival
&& impl_type
== PSI_T_STRING
) {
559 if (ival
->zend
.str
) {
560 tmp
->u64
= ival
->zend
.str
->len
;
565 zend_string
*zs
= zval_get_string(zvalue
);
567 zend_string_release(zs
);
571 psi_calc_cast(PSI_T_UINT64
, tmp
, psi_decl_type_get_real(spec
->type
)->type
, tmp
);
577 static impl_val
*iterate(impl_val
*val
, size_t size
, unsigned i
, impl_val
*tmp
)
579 memset(tmp
, 0, sizeof(*tmp
));
580 memcpy(tmp
, ((char *) val
) + size
* i
, size
);
586 * set $ivar = to_array(dvar,
587 * $foo = to_int(d_foo),
588 * $bar = to_string(d_bar),
589 * $baz = to_array(*d_next, ...)
591 void psi_set_to_recursive(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
) {
592 set
->outer
->data
.func
->handler(return_value
, set
, r_val
, frame
);
596 * set $ivar = to_array(dvar, to_string(*dvar));
598 void psi_set_to_array_simple(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
600 struct psi_set_exp
*sub_exp
;
601 struct psi_decl_var
*var
;
606 array_init(return_value
);
608 var
= psi_set_exp_get_decl_var(set
);
609 ret_val
= deref_impl_val(r_val
, var
);
610 if ((intptr_t) ret_val
<= (intptr_t) 0) {
614 psi_plist_get(set
->inner
, 0, &sub_exp
);
616 size
= psi_decl_arg_get_size(var
->arg
);
617 for (ptr
= ret_val
->ptr
; *(void **) ptr
; ptr
+= size
) {
621 sub_exp
->data
.func
->handler(&ele
, sub_exp
, (void *) ptr
, frame
);
622 add_next_index_zval(return_value
, &ele
);
627 * set $ivar = to_array(dvar, num_exp, to_string(*dvar));
629 void psi_set_to_array_counted(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
631 struct psi_set_exp
*sub_exp
;
632 struct psi_decl_var
*var
;
638 array_init(return_value
);
640 var
= psi_set_exp_get_decl_var(set
);
641 ret_val
= deref_impl_val(r_val
, var
);
642 if ((intptr_t) ret_val
<= (intptr_t) 0) {
646 psi_plist_get(set
->inner
, 0, &sub_exp
);
647 count
= psi_num_exp_get_long(sub_exp
->data
.num
, frame
, NULL
);
648 psi_plist_get(set
->inner
, 1, &sub_exp
);
650 size
= psi_decl_var_get_size(psi_set_exp_get_decl_var(sub_exp
));
651 for (ptr
= (char *) ret_val
; 0 < count
--; ptr
+= size
) {
655 sub_exp
->data
.func
->handler(&ele
, sub_exp
, (void *) &ptr
, frame
);
656 add_next_index_zval(return_value
, &ele
);
663 * set $ivar = to_array(dvar,
664 * $foo = to_int(d_foo),
665 * $bar = to_string(d_bar));
667 void psi_set_to_array(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
669 struct psi_set_exp
*sub_exp
;
670 struct psi_decl_var
*var
;
674 array_init(return_value
);
676 var
= psi_set_exp_get_decl_var(set
);
677 ret_val
= deref_impl_val(r_val
, var
);
678 if ((intptr_t) ret_val
<= (intptr_t) 0) {
682 while (psi_plist_get(set
->inner
, i
++, &sub_exp
)) {
684 struct psi_decl_var
*dvar
= psi_set_exp_get_decl_var(sub_exp
);
685 struct psi_impl_var
*ivar
= psi_set_exp_get_impl_var(sub_exp
);
686 struct psi_call_frame_symbol
*sym
;
688 sym
= psi_call_frame_fetch_symbol(frame
, dvar
);
689 sym
->ptr
= ((char *) ret_val
) + dvar
->arg
->layout
->pos
;
692 psi_set_exp_exec_ex(sub_exp
, &ele
, sym
->ptr
, frame
);
693 add_assoc_zval_ex(return_value
, ivar
->name
->val
+ 1, ivar
->name
->len
- 1, &ele
);
698 * let dvar = count($ivar)
700 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
)
702 return psi_val_intval(tmp
, psi_decl_type_get_real(spec
->type
)->type
, psi_zval_count(zvalue
));
706 * set $ivar = to_object(dvar)
708 void psi_set_to_object(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
710 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
711 impl_val
*ret_val
= deref_impl_val(r_val
, var
);
713 if ((intptr_t) ret_val
->ptr
> (intptr_t) 0) {
714 object_init_ex(return_value
, psi_object_get_class_entry());
715 PSI_OBJ(return_value
, NULL
)->data
= ret_val
->ptr
;
722 * let dvar = objval($ivar)
724 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
)
728 if (Z_TYPE_P(zvalue
) != IS_OBJECT
729 || !instanceof_function(Z_OBJCE_P(zvalue
), psi_object_get_class_entry())) {
733 obj
= PSI_OBJ(zvalue
, NULL
);
734 tmp
->ptr
= obj
->data
;