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 *******************************************************************************/
26 #include "php_psi_stdinc.h"
33 #include "Zend/zend_interfaces.h"
34 #include "ext/spl/spl_iterators.h"
36 zend_long
psi_zval_count(zval
*zvalue
)
38 /* mimic PHP count() */
42 switch (Z_TYPE_P(zvalue
)) {
50 count
= zend_array_count(Z_ARRVAL_P(zvalue
));
54 if (Z_OBJ_HT_P(zvalue
)->count_elements
) {
55 if (SUCCESS
== Z_OBJ_HT_P(zvalue
)->count_elements(zvalue
, &count
)) {
60 if (instanceof_function(Z_OBJCE_P(zvalue
), spl_ce_Countable
)) {
61 zend_call_method_with_0_params(zvalue
, NULL
, NULL
, "count", &retval
);
62 if (Z_TYPE(retval
) != IS_UNDEF
) {
63 count
= zval_get_long(&retval
);
64 zval_ptr_dtor(&retval
);
73 int psi_internal_type(struct psi_impl_type
*type
)
92 zend_internal_arg_info
*psi_internal_arginfo(struct psi_impl
*impl
)
94 size_t i
= 0, argc
= psi_plist_count(impl
->func
->args
);
95 zend_internal_arg_info
*aip
;
96 zend_internal_function_info
*fi
;
97 struct psi_impl_arg
*iarg
;
99 aip
= calloc(argc
+ 1 + !!impl
->func
->vararg
, sizeof(*aip
));
101 fi
= (zend_internal_function_info
*) &aip
[0];
102 #ifdef ZEND_TYPE_ENCODE
103 fi
->type
= ZEND_TYPE_ENCODE(psi_internal_type(impl
->func
->return_type
), 1);
106 fi
->type_hint
= psi_internal_type(impl
->func
->return_type
);
108 fi
->required_num_args
= psi_impl_num_min_args(impl
);
109 fi
->return_reference
= impl
->func
->return_reference
;
111 if (impl
->func
->vararg
) {
112 struct psi_impl_arg
*vararg
= impl
->func
->vararg
;
113 zend_internal_arg_info
*ai
= &aip
[argc
];
115 ai
->name
= vararg
->var
->name
;
116 #ifdef ZEND_TYPE_ENCODE
117 ai
->type
= ZEND_TYPE_ENCODE(psi_internal_type(vararg
->type
), 1);
120 ai
->type_hint
= psi_internal_type(vararg
->type
);
122 if (vararg
->var
->reference
) {
123 ai
->pass_by_reference
= 1;
128 while (psi_plist_get(impl
->func
->args
, i
++, &iarg
)) {
129 zend_internal_arg_info
*ai
= &aip
[i
];
131 ai
->name
= iarg
->var
->name
;
132 #ifdef ZEND_TYPE_ENCODE
133 ai
->type
= ZEND_TYPE_ENCODE(psi_internal_type(iarg
->type
), 1);
136 ai
->type_hint
= psi_internal_type(iarg
->type
);
138 if (iarg
->var
->reference
) {
139 ai
->pass_by_reference
= 1;
149 void psi_set_void(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
157 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
)
163 * set $ivar = zval(dvar)
165 void psi_set_zval(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
) {
166 RETVAL_ZVAL(ret_val
->ptr
, 1, 0);
170 * let dvar = zval($ivar)
172 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
)
174 *to_free
= tmp
->ptr
= emalloc(sizeof(zval
));
175 ZVAL_COPY_VALUE(tmp
->ptr
, zvalue
);
180 * return to_bool(dvar)
182 void psi_set_to_bool(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
184 psi_set_to_int(return_value
, set
, ret_val
, frame
);
185 convert_to_boolean(return_value
);
188 static inline impl_val
*psi_val_boolval(impl_val
*tmp
, token_t real_type
, zend_bool boolval
) {
190 case PSI_T_INT8
: tmp
->i8
= boolval
; break;
191 case PSI_T_UINT8
: tmp
->u8
= boolval
; break;
192 case PSI_T_INT16
: tmp
->i16
= boolval
; break;
193 case PSI_T_UINT16
: tmp
->u16
= boolval
; break;
194 case PSI_T_INT32
: tmp
->i32
= boolval
; break;
195 case PSI_T_UINT32
: tmp
->u32
= boolval
; break;
196 case PSI_T_INT64
: tmp
->i64
= boolval
; break;
197 case PSI_T_UINT64
: tmp
->u64
= boolval
; break;
199 case PSI_T_INT128
: tmp
->i128
= boolval
; break;
200 case PSI_T_UINT128
: tmp
->u128
= boolval
; break;
202 case PSI_T_FLOAT
: tmp
->fval
= boolval
; break;
203 case PSI_T_DOUBLE
: tmp
->dval
= boolval
; break;
204 #ifdef HAVE_LONG_DOUBLE
205 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= boolval
; break;
207 EMPTY_SWITCH_DEFAULT_CASE();
213 * let dvar = boolval($ivar)
215 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
)
218 token_t real_type
= spec
? psi_decl_type_get_real(spec
->type
)->type
: PSI_T_UINT8
;
220 if (ival
&& impl_type
== PSI_T_BOOL
) {
221 boolval
= ival
->zend
.bval
;
223 boolval
= zend_is_true(zvalue
);
226 return psi_val_boolval(tmp
, real_type
, boolval
);
230 static inline char *psi_u128_to_buf(char *buf
, unsigned __int128 u128
)
232 for (*buf
= 0; u128
> 0; u128
/= 10) {
233 *--buf
= ((u128
% 10) + '0') & 0xff;
238 static inline char *psi_i128_to_buf(char *buf
, __int128 i128
)
241 char *res
= psi_u128_to_buf(buf
, ~((unsigned __int128
) i128
) + 1);
246 return psi_u128_to_buf(buf
, i128
);
249 # define RETVAL_LONG_STR(V, s) do {\
250 char buf[0x30] = {0}; \
251 if (s && V >= ZEND_LONG_MIN && V <= ZEND_LONG_MAX) { \
253 } else if (!s && V <= ZEND_LONG_MAX) { \
255 } else if (!s && V <= ZEND_ULONG_MAX) { \
256 RETVAL_STRING(zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], V)); \
257 } else if (s && V >= INT128_MIN && V <= INT128_MAX) { \
258 RETVAL_STRING(psi_i128_to_buf(&buf[sizeof(buf) - 1], V)); \
260 RETVAL_STRING(psi_u128_to_buf(&buf[sizeof(buf) - 1], V)); \
264 # define RETVAL_LONG_STR(V, s) do {\
265 char buf[0x20] = {0}; \
266 if (s && V >= ZEND_LONG_MIN && V <= ZEND_LONG_MAX) { \
268 } else if (!s && V <= ZEND_LONG_MAX) { \
271 RETVAL_STRING(zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], V)); \
276 * set $ivar = to_int(*dvar)
278 void psi_set_to_int(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
280 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
281 token_t t
= psi_decl_type_get_real(var
->arg
->type
)->type
;
282 impl_val
*v
= deref_impl_val(ret_val
, var
);
285 case PSI_T_INT8
: RETVAL_LONG(v
->i8
); break;
286 case PSI_T_UINT8
: RETVAL_LONG(v
->u8
); break;
287 case PSI_T_INT16
: RETVAL_LONG(v
->i16
); break;
288 case PSI_T_UINT16
: RETVAL_LONG(v
->u16
); break;
290 case PSI_T_INT32
: RETVAL_LONG(v
->i32
); break;
291 case PSI_T_UINT32
: RETVAL_LONG(v
->u32
); break;
292 case PSI_T_INT64
: RETVAL_LONG(v
->i64
); break;
293 case PSI_T_UINT64
: RETVAL_LONG_STR(v
->u64
, 0); break;
295 case PSI_T_INT128
: RETVAL_LONG_STR(v
->i128
, 1); break;
296 case PSI_T_UINT128
: RETVAL_LONG_STR(v
->u128
, 0); break;
299 RETVAL_DOUBLE((double) v
->fval
);
300 convert_to_long(return_value
);
303 RETVAL_DOUBLE(v
->dval
);
304 convert_to_long(return_value
);
306 #ifdef HAVE_LONG_DOUBLE
307 case PSI_T_LONG_DOUBLE
:
308 RETVAL_DOUBLE((double) v
->ldval
);
309 convert_to_long(return_value
);
312 EMPTY_SWITCH_DEFAULT_CASE();
316 static inline impl_val
*psi_val_intval(impl_val
*tmp
, token_t real_type
, zend_long intval
) {
318 case PSI_T_INT8
: tmp
->i8
= intval
; break;
319 case PSI_T_UINT8
: tmp
->u8
= intval
; break;
320 case PSI_T_INT16
: tmp
->i16
= intval
; break;
321 case PSI_T_UINT16
: tmp
->u16
= intval
; break;
323 case PSI_T_INT32
: tmp
->i32
= intval
; break;
324 case PSI_T_UINT32
: tmp
->u32
= intval
; break;
325 case PSI_T_INT64
: tmp
->i64
= intval
; break;
326 case PSI_T_UINT64
: tmp
->u64
= intval
; break;
328 case PSI_T_INT128
: tmp
->i128
= intval
; break;
329 case PSI_T_UINT128
: tmp
->u128
= intval
; break;
331 case PSI_T_FLOAT
: tmp
->fval
= intval
; break;
332 case PSI_T_DOUBLE
: tmp
->dval
= intval
; break;
333 #ifdef HAVE_LONG_DOUBLE
334 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= intval
; break;
336 EMPTY_SWITCH_DEFAULT_CASE();
343 void psi_strto_i128(char *ptr
, char *end
, token_t real_type
, impl_val
*val
) {
344 unsigned __int128 i
= 0;
345 bool oct
= false, hex
= false, sign
= false;
349 } else if (*ptr
== '-') {
352 } else if (*ptr
== '\\') {
358 case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':
372 case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':
382 case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
387 i
+= 10 + (*ptr
- 'a');
389 case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
394 i
+= 10 + (*ptr
- 'A');
398 zend_error(E_WARNING
, "A non well formed numeric value encountered");
405 if (real_type
== PSI_T_UINT128
) {
422 * let dvar = intval($ivar)
424 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
)
427 token_t real_type
= spec
? psi_decl_type_get_real(spec
->type
)->type
: PSI_T_INT64
;
430 if (ival
&& impl_type
== PSI_T_INT
) {
431 intval
= ival
->zend
.lval
;
433 } else if ((real_type
== PSI_T_UINT128
|| real_type
== PSI_T_INT128
) &&
434 !((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
))) {
435 zend_string
*str
= zval_get_string(zvalue
);
436 psi_strto_i128(str
->val
, str
->val
+ str
->len
, real_type
, tmp
);
437 zend_string_release(str
);
441 intval
= zval_get_long(zvalue
);
444 return psi_val_intval(tmp
, real_type
, intval
);
448 * set $ivar = to_float(dvar)
450 void psi_set_to_float(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
452 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
453 token_t t
= psi_decl_type_get_real(var
->arg
->type
)->type
;
454 impl_val
*v
= deref_impl_val(ret_val
, var
);
457 case PSI_T_FLOAT
: RETVAL_DOUBLE((double) v
->fval
); break;
458 case PSI_T_DOUBLE
: RETVAL_DOUBLE(v
->dval
); break;
459 #ifdef HAVE_LONG_DOUBLE
460 case PSI_T_LONG_DOUBLE
: RETVAL_DOUBLE((double) v
->ldval
); break;
462 case PSI_T_INT8
: RETVAL_DOUBLE((double) v
->i8
); break;
463 case PSI_T_UINT8
: RETVAL_DOUBLE((double) v
->u8
); break;
464 case PSI_T_INT16
: RETVAL_DOUBLE((double) v
->i16
); break;
465 case PSI_T_UINT16
: RETVAL_DOUBLE((double) v
->u16
); break;
466 case PSI_T_INT32
: RETVAL_DOUBLE((double) v
->i32
); break;
467 case PSI_T_UINT32
: RETVAL_DOUBLE((double) v
->u32
); break;
468 case PSI_T_INT64
: RETVAL_DOUBLE((double) v
->i64
); break;
469 case PSI_T_UINT64
: RETVAL_DOUBLE((double) v
->u64
); break;
471 case PSI_T_INT128
: RETVAL_DOUBLE((double) v
->i128
); break;
472 case PSI_T_UINT128
: RETVAL_DOUBLE((double) v
->u128
); break;
474 EMPTY_SWITCH_DEFAULT_CASE();
478 static inline impl_val
*psi_val_floatval(impl_val
*tmp
, token_t real_type
, double floatval
) {
480 case PSI_T_INT8
: tmp
->i8
= floatval
; break;
481 case PSI_T_UINT8
: tmp
->u8
= floatval
; break;
482 case PSI_T_INT16
: tmp
->i16
= floatval
; break;
483 case PSI_T_UINT16
: tmp
->u16
= floatval
; break;
484 case PSI_T_INT32
: tmp
->i32
= floatval
; break;
485 case PSI_T_UINT32
: tmp
->u32
= floatval
; break;
486 case PSI_T_INT64
: tmp
->i64
= floatval
; break;
487 case PSI_T_UINT64
: tmp
->u64
= floatval
; break;
489 case PSI_T_INT128
: tmp
->i128
= floatval
; break;
490 case PSI_T_UINT128
: tmp
->u128
= floatval
; break;
492 case PSI_T_FLOAT
: tmp
->fval
= floatval
; break;
493 case PSI_T_DOUBLE
: tmp
->dval
= floatval
; break;
494 #ifdef HAVE_LONG_DOUBLE
495 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= floatval
; break;
497 EMPTY_SWITCH_DEFAULT_CASE();
504 * let dvar = floatval($ivar)
506 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
)
509 token_t real_type
= spec
? psi_decl_type_get_real(spec
->type
)->type
: PSI_T_DOUBLE
;
511 if (ival
&& (impl_type
== PSI_T_FLOAT
|| impl_type
== PSI_T_DOUBLE
)) {
512 floatval
= ival
->dval
;
514 floatval
= zval_get_double(zvalue
);
517 return psi_val_floatval(tmp
, real_type
, floatval
);
521 * set $ivar = to_string(dvar)
523 void psi_set_to_string(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
525 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
526 impl_val
*ptr
= deref_impl_val(ret_val
, var
);
529 if (var
->arg
->var
->array_size
&& var
->arg
->var
->pointer_level
== 1) {
538 RETVAL_EMPTY_STRING();
543 * set $ivar = to_string(dvar, num_exp)
545 void psi_set_to_stringl(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*ret_val
, struct psi_call_frame
*frame
)
547 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
548 char *str
= deref_impl_val(ret_val
, var
)->ptr
;
551 struct psi_set_exp
*sub_exp
;
553 psi_plist_get(set
->inner
, 0, &sub_exp
);
554 RETVAL_STRINGL(str
, psi_num_exp_get_long(sub_exp
->data
.num
, frame
, NULL
));
556 RETVAL_EMPTY_STRING();
561 * let dvar = strval($ivar)
563 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
)
565 if (ival
&& impl_type
== PSI_T_STRING
) {
566 if (ival
->zend
.str
) {
567 tmp
->ptr
= ival
->zend
.str
->val
;
572 zend_string
*zs
= zval_get_string(zvalue
);
573 tmp
->ptr
= estrdup(zs
->val
);
575 zend_string_release(zs
);
582 * let dvar = pathval($ivar)
584 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
)
586 tmp
= psi_let_strval(tmp
, spec
, impl_type
, ival
, zvalue
, to_free
);
587 if (SUCCESS
!= php_check_open_basedir(tmp
->ptr
)) {
590 return *to_free
= NULL
;
596 * let dvar = strlen($ivar)
598 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
)
600 if (ival
&& impl_type
== PSI_T_STRING
) {
601 if (ival
->zend
.str
) {
602 tmp
->u64
= ival
->zend
.str
->len
;
607 zend_string
*zs
= zval_get_string(zvalue
);
609 zend_string_release(zs
);
613 psi_calc_cast(PSI_T_UINT64
, tmp
, psi_decl_type_get_real(spec
->type
)->type
, tmp
);
619 static impl_val
*iterate(impl_val
*val
, size_t size
, unsigned i
, impl_val
*tmp
)
621 memset(tmp
, 0, sizeof(*tmp
));
622 memcpy(tmp
, ((char *) val
) + size
* i
, size
);
628 * set $ivar = to_array(dvar,
629 * $foo = to_int(d_foo),
630 * $bar = to_string(d_bar),
631 * $baz = to_array(*d_next, ...)
633 void psi_set_to_recursive(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
) {
634 set
->outer
->data
.func
->handler(return_value
, set
, r_val
, frame
);
638 * set $ivar = to_array(dvar, to_string(*dvar));
640 void psi_set_to_array_simple(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
642 struct psi_set_exp
*sub_exp
;
643 struct psi_decl_var
*var
;
648 array_init(return_value
);
650 var
= psi_set_exp_get_decl_var(set
);
651 ret_val
= deref_impl_val(r_val
, var
);
652 if ((intptr_t) ret_val
<= (intptr_t) 0) {
656 psi_plist_get(set
->inner
, 0, &sub_exp
);
658 size
= psi_decl_arg_get_size(var
->arg
);
659 for (ptr
= ret_val
->ptr
; *(void **) ptr
; ptr
+= size
) {
663 sub_exp
->data
.func
->handler(&ele
, sub_exp
, (void *) ptr
, frame
);
664 add_next_index_zval(return_value
, &ele
);
669 * set $ivar = to_array(dvar, num_exp, to_string(*dvar));
671 void psi_set_to_array_counted(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
673 struct psi_set_exp
*sub_exp
;
674 struct psi_decl_var
*var
;
680 array_init(return_value
);
682 var
= psi_set_exp_get_decl_var(set
);
683 ret_val
= deref_impl_val(r_val
, var
);
684 if ((intptr_t) ret_val
<= (intptr_t) 0) {
688 psi_plist_get(set
->inner
, 0, &sub_exp
);
689 count
= psi_num_exp_get_long(sub_exp
->data
.num
, frame
, NULL
);
690 psi_plist_get(set
->inner
, 1, &sub_exp
);
692 size
= psi_decl_var_get_size(psi_set_exp_get_decl_var(sub_exp
));
693 for (ptr
= (char *) ret_val
; 0 < count
--; ptr
+= size
) {
697 sub_exp
->data
.func
->handler(&ele
, sub_exp
, (void *) &ptr
, frame
);
698 add_next_index_zval(return_value
, &ele
);
705 * set $ivar = to_array(dvar,
706 * $foo = to_int(d_foo),
707 * $bar = to_string(d_bar));
709 void psi_set_to_array(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
711 struct psi_set_exp
*sub_exp
;
712 struct psi_decl_var
*var
;
716 array_init(return_value
);
718 var
= psi_set_exp_get_decl_var(set
);
719 ret_val
= deref_impl_val(r_val
, var
);
720 if ((intptr_t) ret_val
<= (intptr_t) 0) {
724 while (psi_plist_get(set
->inner
, i
++, &sub_exp
)) {
726 struct psi_decl_var
*dvar
= psi_set_exp_get_decl_var(sub_exp
);
727 struct psi_impl_var
*ivar
= psi_set_exp_get_impl_var(sub_exp
);
728 struct psi_call_frame_symbol
*sym
;
730 sym
= psi_call_frame_fetch_symbol(frame
, dvar
);
731 sym
->ptr
= ((char *) ret_val
) + dvar
->arg
->layout
->pos
;
734 psi_set_exp_exec_ex(sub_exp
, &ele
, sym
->ptr
, frame
);
735 add_assoc_zval(return_value
, ivar
->name
+ 1, &ele
);
740 * let dvar = count($ivar)
742 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
)
744 return psi_val_intval(tmp
, psi_decl_type_get_real(spec
->type
)->type
, psi_zval_count(zvalue
));
748 * set $ivar = to_object(dvar)
750 void psi_set_to_object(zval
*return_value
, struct psi_set_exp
*set
, impl_val
*r_val
, struct psi_call_frame
*frame
)
752 struct psi_decl_var
*var
= psi_set_exp_get_decl_var(set
);
753 impl_val
*ret_val
= deref_impl_val(r_val
, var
);
755 if ((intptr_t) ret_val
->ptr
> (intptr_t) 0) {
756 object_init_ex(return_value
, psi_object_get_class_entry());
757 PSI_OBJ(return_value
, NULL
)->data
= ret_val
->ptr
;
764 * let dvar = objval($ivar)
766 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
)
770 if (Z_TYPE_P(zvalue
) != IS_OBJECT
771 || !instanceof_function(Z_OBJCE_P(zvalue
), psi_object_get_class_entry())) {
775 obj
= PSI_OBJ(zvalue
, NULL
);
776 tmp
->ptr
= obj
->data
;