1e71a64762ee7f0e77f876a13d34f37635844783
4 # include "php_config.h"
14 void psi_to_void(zval
*return_value
, set_value
*set
, impl_val
*ret_val
)
19 impl_val
*psi_let_void(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
24 void psi_to_zval(zval
*return_value
, set_value
*set
, impl_val
*ret_val
) {
25 RETVAL_ZVAL(ret_val
->ptr
, 1, 0);
28 impl_val
*psi_let_zval(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
30 *to_free
= tmp
->ptr
= emalloc(sizeof(zval
));
31 ZVAL_COPY_VALUE(tmp
->ptr
, zvalue
);
35 void psi_to_bool(zval
*return_value
, set_value
*set
, impl_val
*ret_val
)
37 psi_to_int(return_value
, set
, ret_val
);
38 convert_to_boolean(return_value
);
41 static inline impl_val
*psi_val_boolval(impl_val
*tmp
, token_t real_type
, zend_bool boolval
) {
43 case PSI_T_INT8
: tmp
->i8
= boolval
; break;
44 case PSI_T_UINT8
: tmp
->u8
= boolval
; break;
45 case PSI_T_INT16
: tmp
->i16
= boolval
; break;
46 case PSI_T_UINT16
: tmp
->u16
= boolval
; break;
47 case PSI_T_INT32
: tmp
->i32
= boolval
; break;
48 case PSI_T_UINT32
: tmp
->u32
= boolval
; break;
49 case PSI_T_INT64
: tmp
->i64
= boolval
; break;
50 case PSI_T_UINT64
: tmp
->u64
= boolval
; break;
51 case PSI_T_FLOAT
: tmp
->fval
= boolval
; break;
52 case PSI_T_DOUBLE
: tmp
->dval
= boolval
; break;
53 #ifdef HAVE_LONG_DOUBLE
54 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= boolval
; break;
56 EMPTY_SWITCH_DEFAULT_CASE();
61 impl_val
*psi_let_boolval(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
64 token_t real_type
= spec
? real_decl_type(spec
)->type
: PSI_T_UINT8
;
66 if (ival
&& impl_type
== PSI_T_BOOL
) {
67 boolval
= ival
->zend
.bval
;
69 boolval
= zend_is_true(zvalue
);
72 return psi_val_boolval(tmp
, real_type
, boolval
);
75 # define RETVAL_LONG_U64(V) \
76 if (V > ZEND_LONG_MAX) { \
78 RETVAL_STRING(zend_print_ulong_to_buf(&d[22], V)); \
83 void psi_to_int(zval
*return_value
, set_value
*set
, impl_val
*ret_val
)
85 decl_var
*var
= set
->vars
->vars
[0];
86 token_t t
= real_decl_type(var
->arg
->type
)->type
;
87 impl_val
*v
= deref_impl_val(ret_val
, var
);
90 case PSI_T_INT8
: RETVAL_LONG(v
->i8
); break;
91 case PSI_T_UINT8
: RETVAL_LONG(v
->u8
); break;
92 case PSI_T_INT16
: RETVAL_LONG(v
->i16
); break;
93 case PSI_T_UINT16
: RETVAL_LONG(v
->u16
); break;
94 case PSI_T_INT32
: RETVAL_LONG(v
->i32
); break;
95 case PSI_T_UINT32
: RETVAL_LONG(v
->u32
); break;
96 case PSI_T_INT64
: RETVAL_LONG(v
->i64
); break;
97 case PSI_T_UINT64
: RETVAL_LONG_U64(v
->u64
); break;
98 case PSI_T_FLOAT
: RETVAL_DOUBLE((double) v
->fval
); break;
99 case PSI_T_DOUBLE
: RETVAL_DOUBLE(v
->dval
); break;
100 #ifdef HAVE_LONG_DOUBLE
101 case PSI_T_LONG_DOUBLE
: RETVAL_DOUBLE((double) v
->ldval
); break;
103 EMPTY_SWITCH_DEFAULT_CASE();
106 convert_to_long(return_value
);
109 static inline impl_val
*psi_val_intval(impl_val
*tmp
, token_t real_type
, zend_long intval
) {
111 case PSI_T_INT8
: tmp
->i8
= intval
; break;
112 case PSI_T_UINT8
: tmp
->u8
= intval
; break;
113 case PSI_T_INT16
: tmp
->i16
= intval
; break;
114 case PSI_T_UINT16
: tmp
->u16
= intval
; break;
115 case PSI_T_INT32
: tmp
->i32
= intval
; break;
116 case PSI_T_UINT32
: tmp
->u32
= intval
; break;
117 case PSI_T_INT64
: tmp
->i64
= intval
; break;
118 case PSI_T_UINT64
: tmp
->u64
= intval
; break;
119 case PSI_T_INT
: tmp
->ival
= intval
; break;
120 case PSI_T_LONG
: tmp
->lval
= intval
; break;
121 case PSI_T_FLOAT
: tmp
->fval
= intval
; break;
122 case PSI_T_DOUBLE
: tmp
->dval
= intval
; break;
123 #ifdef HAVE_LONG_DOUBLE
124 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= intval
; break;
126 EMPTY_SWITCH_DEFAULT_CASE();
132 impl_val
*psi_let_intval(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
135 token_t real_type
= spec
? real_decl_type(spec
)->type
: PSI_T_LONG
;
137 if (ival
&& impl_type
== PSI_T_INT
) {
138 intval
= ival
->zend
.lval
;
140 intval
= zval_get_long(zvalue
);
143 return psi_val_intval(tmp
, real_type
, intval
);
146 void psi_to_double(zval
*return_value
, set_value
*set
, impl_val
*ret_val
)
148 decl_var
*var
= set
->vars
->vars
[0];
149 token_t t
= real_decl_type(var
->arg
->type
)->type
;
150 impl_val
*v
= deref_impl_val(ret_val
, var
);
153 case PSI_T_FLOAT
: RETVAL_DOUBLE((double) v
->fval
); break;
154 case PSI_T_DOUBLE
: RETVAL_DOUBLE(v
->dval
); break;
155 #ifdef HAVE_LONG_DOUBLE
156 case PSI_T_LONG_DOUBLE
: RETVAL_DOUBLE((double) v
->ldval
); break;
158 case PSI_T_INT8
: RETVAL_DOUBLE((double) v
->i8
); break;
159 case PSI_T_UINT8
: RETVAL_DOUBLE((double) v
->u8
); break;
160 case PSI_T_INT16
: RETVAL_DOUBLE((double) v
->i16
); break;
161 case PSI_T_UINT16
: RETVAL_DOUBLE((double) v
->u16
); break;
162 case PSI_T_INT32
: RETVAL_DOUBLE((double) v
->i32
); break;
163 case PSI_T_UINT32
: RETVAL_DOUBLE((double) v
->u32
); break;
164 case PSI_T_INT64
: RETVAL_DOUBLE((double) v
->i64
); break;
165 case PSI_T_UINT64
: RETVAL_DOUBLE((double) v
->u64
); break;
166 EMPTY_SWITCH_DEFAULT_CASE();
170 static inline impl_val
*psi_val_floatval(impl_val
*tmp
, token_t real_type
, double floatval
) {
172 case PSI_T_INT8
: tmp
->i8
= floatval
; break;
173 case PSI_T_UINT8
: tmp
->u8
= floatval
; break;
174 case PSI_T_INT16
: tmp
->i16
= floatval
; break;
175 case PSI_T_UINT16
: tmp
->u16
= floatval
; break;
176 case PSI_T_INT32
: tmp
->i32
= floatval
; break;
177 case PSI_T_UINT32
: tmp
->u32
= floatval
; break;
178 case PSI_T_INT64
: tmp
->i64
= floatval
; break;
179 case PSI_T_UINT64
: tmp
->u64
= floatval
; break;
180 case PSI_T_FLOAT
: tmp
->fval
= floatval
; break;
181 case PSI_T_DOUBLE
: tmp
->dval
= floatval
; break;
182 #ifdef HAVE_LONG_DOUBLE
183 case PSI_T_LONG_DOUBLE
: tmp
->ldval
= floatval
; break;
185 EMPTY_SWITCH_DEFAULT_CASE();
191 impl_val
*psi_let_floatval(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
194 token_t real_type
= spec
? real_decl_type(spec
)->type
: PSI_T_DOUBLE
;
196 if (ival
&& (impl_type
== PSI_T_FLOAT
|| impl_type
== PSI_T_DOUBLE
)) {
197 floatval
= ival
->dval
;
199 floatval
= zval_get_double(zvalue
);
202 return psi_val_floatval(tmp
, real_type
, floatval
);
205 void psi_to_string(zval
*return_value
, set_value
*set
, impl_val
*ret_val
)
208 decl_var
*var
= set
->vars
->vars
[0];
209 token_t t
= real_decl_type(var
->arg
->type
)->type
;
212 case PSI_T_FLOAT
: RETVAL_DOUBLE((double) deref_impl_val(ret_val
, var
)->fval
); break;
213 case PSI_T_DOUBLE
: RETVAL_DOUBLE(deref_impl_val(ret_val
, var
)->dval
); break;
214 #ifdef HAVE_LONG_DOUBLE
215 case PSI_T_LONG_DOUBLE
: RETVAL_DOUBLE((double) deref_impl_val(ret_val
, var
)->ldval
); break;
218 if (!var
->arg
->var
->pointer_level
) {
219 RETVAL_STRINGL(&ret_val
->cval
, 1);
221 ret_val
= deref_impl_val(ret_val
, var
);
222 if (var
->arg
->var
->array_size
) {
223 str
= (char *) ret_val
;
229 zend_long n
= psi_long_num_exp(set
->num
, set
->outer
.val
);
230 RETVAL_STRINGL(str
, n
);
235 RETVAL_EMPTY_STRING();
241 convert_to_string(return_value
);
244 impl_val
*psi_let_strval(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
246 if (ival
&& impl_type
== PSI_T_STRING
) {
247 if (ival
->zend
.str
) {
248 /*tmp->ptr = estrndup(ival->zend.str->val, ival->zend.str->len);
249 *to_free = tmp->ptr;*/
250 tmp
->ptr
= ival
->zend
.str
->val
;
254 } else if (0 && Z_TYPE_P(zvalue
) == IS_STRING
) {
255 tmp
->ptr
= Z_STRVAL_P(zvalue
);
257 zend_string
*zs
= zval_get_string(zvalue
);
258 tmp
->ptr
= estrdup(zs
->val
);
260 zend_string_release(zs
);
266 impl_val
*psi_let_pathval(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
268 tmp
= psi_let_strval(tmp
, spec
, impl_type
, ival
, zvalue
, to_free
);
269 if (SUCCESS
!= php_check_open_basedir(tmp
->ptr
)) {
272 return *to_free
= NULL
;
277 impl_val
*psi_let_strlen(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
279 if (ival
&& impl_type
== PSI_T_STRING
) {
280 if (ival
->zend
.str
) {
281 tmp
->lval
= ival
->zend
.str
->len
;
286 zend_string
*zs
= zval_get_string(zvalue
);
288 zend_string_release(zs
);
294 static impl_val
*iterate(impl_val
*val
, size_t size
, unsigned i
, impl_val
*tmp
)
296 memset(tmp
, 0, sizeof(*tmp
));
297 memcpy(tmp
, ((char *) val
) + size
* i
, size
);
301 void psi_from_zval_ex(void *cb_ctx
, impl_val
**ptr
, decl_arg
*spec
, token_t cast
, zval
*zv
, void **tmp
)
303 decl_type
*real
= real_decl_type(spec
->type
);
304 impl_val
*val
= *ptr
;
306 switch (real
->type
) {
309 val
->i64
= zval_get_long(zv
);
312 val
->i8
= zval_get_long(zv
);
315 val
->u8
= zval_get_long(zv
);
318 val
->i16
= zval_get_long(zv
);
321 val
->u16
= zval_get_long(zv
);
324 val
->i32
= zval_get_long(zv
);
327 val
->u32
= zval_get_long(zv
);
330 val
->i64
= zval_get_long(zv
);
333 val
->u64
= zval_get_long(zv
);
336 val
->fval
= zval_get_double(zv
);
339 val
->dval
= zval_get_double(zv
);
341 #ifdef HAVE_LONG_DOUBLE
342 case PSI_T_LONG_DOUBLE
:
343 val
->ldval
= zval_get_double(zv
);
347 val
->ival
= zval_get_long(zv
);
350 *tmp
= *ptr
= psi_array_to_struct_ex(real
->real
.strct
, HASH_OF(zv
), psi_from_zval_ex
, cb_ctx
);
353 *tmp
= *ptr
= psi_array_to_union_ex(real
->real
.unn
, HASH_OF(zv
), psi_from_zval_ex
, cb_ctx
);
361 if (Z_TYPE_P(zv
) == IS_OBJECT
&& instanceof_function(Z_OBJCE_P(zv
), psi_object_get_class_entry())) {
362 *ptr
= PSI_OBJ(zv
, NULL
)->data
;
364 zend_string
*zs
= zval_get_string(zv
);
365 *tmp
= val
->ptr
= estrndup(zs
->val
, zs
->len
);
366 zend_string_release(zs
);
372 void *psi_array_to_struct_ex(decl_struct
*s
, HashTable
*arr
, psi_marshal_zval cb
, void *cb_ctx
) {
374 char *mem
= ecalloc(1, s
->size
+ s
->args
->count
* sizeof(void *));
376 if (arr
) for (i
= 0; i
< s
->args
->count
; ++i
) {
377 decl_arg
*darg
= s
->args
->args
[i
];
378 zval
*entry
= zend_hash_str_find_ind(arr
, darg
->var
->name
, strlen(darg
->var
->name
));
381 impl_val val
, *ptr
= &val
;
384 memset(&val
, 0, sizeof(val
));
385 cb(cb_ctx
, &ptr
, darg
, /*FIXME*/0, entry
, &tmp
);
386 memcpy(mem
+ darg
->layout
->pos
, ptr
, darg
->layout
->len
);
388 ((void **)(mem
+ s
->size
))[j
++] = tmp
;
395 void *psi_array_to_struct(decl_struct
*s
, HashTable
*arr
)
397 return psi_array_to_struct_ex(s
, arr
, psi_from_zval_ex
, NULL
);
400 void *psi_array_to_union_ex(decl_union
*u
, HashTable
*arr
, psi_marshal_zval cb
, void *cb_ctx
) {
402 char *mem
= ecalloc(1, u
->size
+ sizeof(void *));
404 if (arr
) for (i
= 0; i
< u
->args
->count
; ++i
) {
405 decl_arg
*darg
= u
->args
->args
[i
];
406 zval
*entry
= zend_hash_str_find_ind(arr
, darg
->var
->name
, strlen(darg
->var
->name
));
409 impl_val val
, *ptr
= &val
;
412 memset(&val
, 0, sizeof(val
));
413 cb(cb_ctx
, &ptr
, darg
, /*FIXME*/0, entry
, &tmp
);
414 memcpy(mem
, &val
, darg
->layout
->len
);
416 ((void **)(mem
+ u
->size
))[0] = tmp
;
418 /* first found entry wins */
426 void *psi_array_to_union(decl_union
*u
, HashTable
*arr
) {
427 return psi_array_to_union_ex(u
, arr
, psi_from_zval_ex
, NULL
);
430 void psi_to_recursive(zval
*return_value
, set_value
*set
, impl_val
*r_val
) {
431 set
->outer
.set
->func
->handler(return_value
, set
, r_val
);
434 void psi_to_array(zval
*return_value
, set_value
*set
, impl_val
*r_val
)
437 decl_var
*var
= set
->vars
->vars
[0];
438 token_t t
= real_decl_type(var
->arg
->type
)->type
;
439 impl_val tmp
, *ret_val
= deref_impl_val(r_val
, var
);
441 if ((intptr_t) ret_val
<= (intptr_t) 0) {
445 array_init(return_value
);
447 if (t
== PSI_T_STRUCT
|| t
== PSI_T_UNION
) {
448 // decl_struct *s = real_decl_type(var->arg->type)->strct;
450 if (set
->inner
&& set
->inner
->count
) {
451 /* explicit member casts */
452 for (i
= 0; i
< set
->inner
->count
; ++i
) {
453 set_value
*sub_set
= set
->inner
->vals
[i
];
454 decl_var
*sub_var
= sub_set
->vars
->vars
[0];
456 sub_set
->outer
.val
= ret_val
;
459 impl_val
*tmp
= NULL
, *val
;
462 val
= struct_member_ref(sub_var
->arg
, ret_val
, &tmp
);
463 sub_set
->func
->handler(&ztmp
, sub_set
, val
);
464 add_assoc_zval(return_value
, sub_var
->name
, &ztmp
);
475 if (var
->arg
->var
->array_size
) {
476 /* to_array(foo[NUMBER]) */
477 for (i
= 0; i
< var
->arg
->var
->array_size
; ++i
) {
478 size_t size
= psi_t_size(var
->arg
->var
->pointer_level
> 1 ? PSI_T_POINTER
: t
);
479 impl_val
*ptr
= iterate(ret_val
->ptr
, size
, i
, &tmp
);
484 ZVAL_DOUBLE(&ele
, (double) ptr
->fval
);
487 ZVAL_DOUBLE(&ele
, ptr
->dval
);
490 ZVAL_LONG(&ele
, ptr
->lval
);
494 add_next_index_zval(return_value
, &ele
);
497 } else if (set
->num
) {
498 /* to_array(arr_var, num_expr, to_int(*arr_var)) */
501 zend_long i
, n
= psi_long_num_exp(set
->num
, set
->outer
.val
);
502 size_t size
= psi_t_size(var
->arg
->var
->pointer_level
? PSI_T_POINTER
: t
);
503 set_value
*sub_set
= set
->inner
->vals
[0];
505 sub_set
->outer
.val
= set
->outer
.val
;
506 for (i
= 0; i
< n
; ++i
) {
507 ptr
= (char *) ret_val
->ptr
+ i
* size
;
508 sub_set
->func
->handler(&ele
, sub_set
, (void *) ptr
);
509 add_next_index_zval(return_value
, &ele
);
512 /* to_array(arr_var, to_int(*arr_var)) */
514 char *ptr
= ret_val
->ptr
;
515 size_t size
= psi_t_size(var
->arg
->var
->pointer_level
? PSI_T_POINTER
: t
);
516 set_value
*sub_set
= set
->inner
->vals
[0];
518 sub_set
->outer
.val
= set
->outer
.val
;
519 while (*(void **) ptr
) {
520 sub_set
->func
->handler(&ele
, sub_set
, (void *) ptr
);
521 add_next_index_zval(return_value
, &ele
);
527 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
)
529 decl_type
*real
= real_decl_type(spec
);
533 decl_arg tmp_arg
= {0};
535 if (impl_type
!= PSI_T_ARRAY
) {
536 SEPARATE_ARG_IF_REF(zvalue
);
537 convert_to_array(zvalue
);
539 arr
= HASH_OF(zvalue
);
541 switch (real
->type
) {
543 *to_free
= tmp
= psi_array_to_struct(real
->real
.strct
, arr
);
546 *to_free
= tmp
= psi_array_to_union(real
->real
.unn
, arr
);
549 sz
= psi_t_size(real
->type
);
550 tmp
= *to_free
= ecalloc(zend_hash_num_elements(arr
), sz
);
552 tmp_arg
.var
= spec_var
;
553 ZEND_HASH_FOREACH_VAL_IND(arr
, zv
)
555 void *ptr
= ((char *) tmp
) + (i
++ * sz
);
556 psi_from_zval_ex(NULL
, (impl_val
**) &ptr
, &tmp_arg
, 0, zv
, NULL
);
558 ZEND_HASH_FOREACH_END();
564 impl_val
*psi_let_count(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
566 return psi_val_intval(tmp
, real_decl_type(spec
)->type
, psi_zval_count(zvalue
));
570 void psi_to_object(zval
*return_value
, set_value
*set
, impl_val
*r_val
)
572 decl_var
*var
= set
->vars
->vars
[0];
573 impl_val
*ret_val
= deref_impl_val(r_val
, var
);
575 if ((intptr_t) ret_val
->ptr
> (intptr_t) 0) {
576 object_init_ex(return_value
, psi_object_get_class_entry());
577 PSI_OBJ(return_value
, NULL
)->data
= ret_val
->ptr
;
583 impl_val
*psi_let_objval(impl_val
*tmp
, decl_type
*spec
, token_t impl_type
, impl_val
*ival
, zval
*zvalue
, void **to_free
)
587 if (Z_TYPE_P(zvalue
) != IS_OBJECT
588 || !instanceof_function(Z_OBJCE_P(zvalue
), psi_object_get_class_entry())) {
592 obj
= PSI_OBJ(zvalue
, NULL
);
593 tmp
->ptr
= obj
->data
;