new zend_type
[m6w6/ext-psi] / src / marshal.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
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.
13
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 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27 #include "data.h"
28 #include "calc.h"
29
30 #include "php.h"
31 #include "php_psi.h"
32
33 #include "Zend/zend_interfaces.h"
34 #include "ext/spl/spl_iterators.h"
35
36 zend_long psi_zval_count(zval *zvalue)
37 {
38 /* mimic PHP count() */
39 zend_long count;
40 zval retval;
41
42 switch (Z_TYPE_P(zvalue)) {
43 default:
44 count = 1;
45 break;
46 case IS_NULL:
47 count = 0;
48 break;
49 case IS_ARRAY:
50 count = zend_array_count(Z_ARRVAL_P(zvalue));
51 break;
52 case IS_OBJECT:
53 count = 1;
54 if (Z_OBJ_HT_P(zvalue)->count_elements) {
55 if (SUCCESS == Z_OBJ_HT_P(zvalue)->count_elements(zvalue, &count)) {
56 break;
57 }
58 }
59
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);
65 }
66 }
67 break;
68 }
69
70 return count;
71 }
72
73 int psi_internal_type(struct psi_impl_type *type)
74 {
75 switch (type->type) {
76 case PSI_T_BOOL:
77 return _IS_BOOL;
78 case PSI_T_INT:
79 return IS_LONG;
80 case PSI_T_FLOAT:
81 case PSI_T_DOUBLE:
82 return IS_DOUBLE;
83 case PSI_T_STRING:
84 return IS_STRING;
85 case PSI_T_ARRAY:
86 return IS_ARRAY;
87 default:
88 return 0;
89 }
90 }
91
92 zend_internal_arg_info *psi_internal_arginfo(struct psi_impl *impl)
93 {
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;
98
99 aip = calloc(argc + 1 + !!impl->func->vararg, sizeof(*aip));
100
101 fi = (zend_internal_function_info *) &aip[0];
102 fi->type = ZEND_TYPE_ENCODE(psi_internal_type(impl->func->return_type), 1);
103 fi->required_num_args = psi_impl_num_min_args(impl);
104 fi->return_reference = impl->func->return_reference;
105
106 if (impl->func->vararg) {
107 struct psi_impl_arg *vararg = impl->func->vararg;
108 zend_internal_arg_info *ai = &aip[argc];
109
110 ai->name = vararg->var->name;
111 ai->type = ZEND_TYPE_ENCODE(psi_internal_type(vararg->type), 1);
112 if (vararg->var->reference) {
113 ai->pass_by_reference = 1;
114 }
115 ai->is_variadic = 1;
116 }
117
118 while (psi_plist_get(impl->func->args, i++, &iarg)) {
119 zend_internal_arg_info *ai = &aip[i];
120
121 ai->name = iarg->var->name;
122 ai->type = ZEND_TYPE_ENCODE(psi_internal_type(iarg->type), 1);
123 if (iarg->var->reference) {
124 ai->pass_by_reference = 1;
125 }
126 }
127
128 return aip;
129 }
130
131 /*
132 * return void(dvar)
133 */
134 void psi_set_void(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
135 {
136 RETVAL_NULL();
137 }
138
139 /*
140 * ?
141 */
142 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)
143 {
144 return tmp;
145 }
146
147 /*
148 * set $ivar = zval(dvar)
149 */
150 void psi_set_zval(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame) {
151 RETVAL_ZVAL(ret_val->ptr, 1, 0);
152 }
153
154 /*
155 * let dvar = zval($ivar)
156 */
157 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)
158 {
159 *to_free = tmp->ptr = emalloc(sizeof(zval));
160 ZVAL_COPY_VALUE(tmp->ptr, zvalue);
161 return tmp;
162 }
163
164 /*
165 * return to_bool(dvar)
166 */
167 void psi_set_to_bool(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
168 {
169 psi_set_to_int(return_value, set, ret_val, frame);
170 convert_to_boolean(return_value);
171 }
172
173 static inline impl_val *psi_val_boolval(impl_val *tmp, token_t real_type, zend_bool boolval) {
174 switch (real_type) {
175 case PSI_T_INT8: tmp->i8 = boolval; break;
176 case PSI_T_UINT8: tmp->u8 = boolval; break;
177 case PSI_T_INT16: tmp->i16 = boolval; break;
178 case PSI_T_UINT16: tmp->u16 = boolval; break;
179 case PSI_T_INT32: tmp->i32 = boolval; break;
180 case PSI_T_UINT32: tmp->u32 = boolval; break;
181 case PSI_T_INT64: tmp->i64 = boolval; break;
182 case PSI_T_UINT64: tmp->u64 = boolval; break;
183 case PSI_T_FLOAT: tmp->fval = boolval; break;
184 case PSI_T_DOUBLE: tmp->dval = boolval; break;
185 #ifdef HAVE_LONG_DOUBLE
186 case PSI_T_LONG_DOUBLE: tmp->ldval = boolval; break;
187 #endif
188 EMPTY_SWITCH_DEFAULT_CASE();
189 }
190 return tmp;
191 }
192
193 /*
194 * let dvar = boolval($ivar)
195 */
196 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)
197 {
198 zend_bool boolval;
199 token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_UINT8;
200
201 if (ival && impl_type == PSI_T_BOOL) {
202 boolval = ival->zend.bval;
203 } else {
204 boolval = zend_is_true(zvalue);
205 }
206
207 return psi_val_boolval(tmp, real_type, boolval);
208 }
209
210 # define RETVAL_LONG_U64(V) \
211 if (V > ZEND_LONG_MAX) { \
212 char d[24] = {0}; \
213 RETVAL_STRING(zend_print_ulong_to_buf(&d[22], V)); \
214 } else { \
215 RETVAL_LONG(V); \
216 }
217
218 /*
219 * set $ivar = to_int(*dvar)
220 */
221 void psi_set_to_int(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
222 {
223 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
224 token_t t = psi_decl_type_get_real(var->arg->type)->type;
225 impl_val *v = deref_impl_val(ret_val, var);
226
227 switch (t) {
228 case PSI_T_INT8: RETVAL_LONG(v->i8); break;
229 case PSI_T_UINT8: RETVAL_LONG(v->u8); break;
230 case PSI_T_INT16: RETVAL_LONG(v->i16); break;
231 case PSI_T_UINT16: RETVAL_LONG(v->u16); break;
232 case PSI_T_INT32: RETVAL_LONG(v->i32); break;
233 case PSI_T_UINT32: RETVAL_LONG(v->u32); break;
234 case PSI_T_INT64: RETVAL_LONG(v->i64); break;
235 case PSI_T_UINT64: RETVAL_LONG_U64(v->u64); break;
236 case PSI_T_FLOAT: RETVAL_DOUBLE((double) v->fval); break;
237 case PSI_T_DOUBLE: RETVAL_DOUBLE(v->dval); break;
238 #ifdef HAVE_LONG_DOUBLE
239 case PSI_T_LONG_DOUBLE: RETVAL_DOUBLE((double) v->ldval); break;
240 #endif
241 EMPTY_SWITCH_DEFAULT_CASE();
242 }
243
244 convert_to_long(return_value);
245 }
246
247 static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_long intval) {
248 switch (real_type) {
249 case PSI_T_INT8: tmp->i8 = intval; break;
250 case PSI_T_UINT8: tmp->u8 = intval; break;
251 case PSI_T_INT16: tmp->i16 = intval; break;
252 case PSI_T_UINT16: tmp->u16 = intval; break;
253 case PSI_T_INT32: tmp->i32 = intval; break;
254 case PSI_T_UINT32: tmp->u32 = intval; break;
255 case PSI_T_INT64: tmp->i64 = intval; break;
256 case PSI_T_UINT64: tmp->u64 = intval; break;
257 case PSI_T_INT: tmp->ival = intval; break;
258 case PSI_T_LONG: tmp->lval = intval; break;
259 case PSI_T_FLOAT: tmp->fval = intval; break;
260 case PSI_T_DOUBLE: tmp->dval = intval; break;
261 #ifdef HAVE_LONG_DOUBLE
262 case PSI_T_LONG_DOUBLE: tmp->ldval = intval; break;
263 #endif
264 EMPTY_SWITCH_DEFAULT_CASE();
265 }
266
267 return tmp;
268 }
269
270 /*
271 * let dvar = intval($ivar)
272 */
273 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)
274 {
275 zend_long intval;
276 token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_LONG;
277
278 if (ival && impl_type == PSI_T_INT) {
279 intval = ival->zend.lval;
280 } else {
281 intval = zval_get_long(zvalue);
282 }
283
284 return psi_val_intval(tmp, real_type, intval);
285 }
286
287 /*
288 * set $ivar = to_float(dvar)
289 */
290 void psi_set_to_float(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
291 {
292 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
293 token_t t = psi_decl_type_get_real(var->arg->type)->type;
294 impl_val *v = deref_impl_val(ret_val, var);
295
296 switch (t) {
297 case PSI_T_FLOAT: RETVAL_DOUBLE((double) v->fval); break;
298 case PSI_T_DOUBLE: RETVAL_DOUBLE(v->dval); break;
299 #ifdef HAVE_LONG_DOUBLE
300 case PSI_T_LONG_DOUBLE: RETVAL_DOUBLE((double) v->ldval); break;
301 #endif
302 case PSI_T_INT8: RETVAL_DOUBLE((double) v->i8); break;
303 case PSI_T_UINT8: RETVAL_DOUBLE((double) v->u8); break;
304 case PSI_T_INT16: RETVAL_DOUBLE((double) v->i16); break;
305 case PSI_T_UINT16: RETVAL_DOUBLE((double) v->u16); break;
306 case PSI_T_INT32: RETVAL_DOUBLE((double) v->i32); break;
307 case PSI_T_UINT32: RETVAL_DOUBLE((double) v->u32); break;
308 case PSI_T_INT64: RETVAL_DOUBLE((double) v->i64); break;
309 case PSI_T_UINT64: RETVAL_DOUBLE((double) v->u64); break;
310 EMPTY_SWITCH_DEFAULT_CASE();
311 }
312 }
313
314 static inline impl_val *psi_val_floatval(impl_val *tmp, token_t real_type, double floatval) {
315 switch (real_type) {
316 case PSI_T_INT8: tmp->i8 = floatval; break;
317 case PSI_T_UINT8: tmp->u8 = floatval; break;
318 case PSI_T_INT16: tmp->i16 = floatval; break;
319 case PSI_T_UINT16: tmp->u16 = floatval; break;
320 case PSI_T_INT32: tmp->i32 = floatval; break;
321 case PSI_T_UINT32: tmp->u32 = floatval; break;
322 case PSI_T_INT64: tmp->i64 = floatval; break;
323 case PSI_T_UINT64: tmp->u64 = floatval; break;
324 case PSI_T_FLOAT: tmp->fval = floatval; break;
325 case PSI_T_DOUBLE: tmp->dval = floatval; break;
326 #ifdef HAVE_LONG_DOUBLE
327 case PSI_T_LONG_DOUBLE: tmp->ldval = floatval; break;
328 #endif
329 EMPTY_SWITCH_DEFAULT_CASE();
330 }
331
332 return tmp;
333 }
334
335 /*
336 * let dvar = floatval($ivar)
337 */
338 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)
339 {
340 double floatval;
341 token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_DOUBLE;
342
343 if (ival && (impl_type == PSI_T_FLOAT || impl_type == PSI_T_DOUBLE)) {
344 floatval = ival->dval;
345 } else {
346 floatval = zval_get_double(zvalue);
347 }
348
349 return psi_val_floatval(tmp, real_type, floatval);
350 }
351
352 /*
353 * set $ivar = to_string(dvar)
354 */
355 void psi_set_to_string(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
356 {
357 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
358 impl_val *ptr = deref_impl_val(ret_val, var);
359 char *str;
360
361 if (var->arg->var->array_size) {
362 str = (char *) ptr;
363 } else {
364 str = ptr->ptr;
365 }
366
367 if (str) {
368 RETVAL_STRING(str);
369 } else {
370 RETVAL_EMPTY_STRING();
371 }
372 }
373
374 /*
375 * set $ivar = to_string(dvar, num_exp)
376 */
377 void psi_set_to_stringl(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
378 {
379 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
380 char *str = deref_impl_val(ret_val, var)->ptr;
381
382 if (str) {
383 struct psi_set_exp *sub_exp;
384
385 psi_plist_get(set->inner, 0, &sub_exp);
386 RETVAL_STRINGL(str, psi_long_num_exp(sub_exp->data.num, frame));
387 } else {
388 RETVAL_EMPTY_STRING();
389 }
390 }
391
392 /*
393 * let dvar = strval($ivar)
394 */
395 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)
396 {
397 if (ival && impl_type == PSI_T_STRING) {
398 if (ival->zend.str) {
399 tmp->ptr = ival->zend.str->val;
400 } else {
401 tmp->ptr = "";
402 }
403 } else if (0 && Z_TYPE_P(zvalue) == IS_STRING) {
404 tmp->ptr = Z_STRVAL_P(zvalue);
405 } else {
406 zend_string *zs = zval_get_string(zvalue);
407 tmp->ptr = estrdup(zs->val);
408 *to_free = tmp->ptr;
409 zend_string_release(zs);
410 }
411
412 return tmp;
413 }
414
415 /*
416 * let dvar = pathval($ivar)
417 */
418 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)
419 {
420 tmp = psi_let_strval(tmp, spec, impl_type, ival, zvalue, to_free);
421 if (SUCCESS != php_check_open_basedir(tmp->ptr)) {
422 efree(tmp->ptr);
423 tmp->ptr = NULL;
424 return *to_free = NULL;
425 }
426 return tmp;
427 }
428
429 /*
430 * let dvar = strlen($ivar)
431 */
432 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)
433 {
434 if (ival && impl_type == PSI_T_STRING) {
435 if (ival->zend.str) {
436 tmp->lval = ival->zend.str->len;
437 } else {
438 tmp->lval = 0;
439 }
440 } else {
441 zend_string *zs = zval_get_string(zvalue);
442 tmp->lval = zs->len;
443 zend_string_release(zs);
444 }
445
446 return tmp;
447 }
448
449 static impl_val *iterate(impl_val *val, size_t size, unsigned i, impl_val *tmp)
450 {
451 memset(tmp, 0, sizeof(*tmp));
452 memcpy(tmp, ((char *) val) + size * i, size);
453 return tmp;
454 }
455
456 /*
457 * set $ivar = to_array(dvar,
458 * $foo = to_int(d_foo),
459 * $bar = to_string(d_bar),
460 * $baz = to_array(*d_next, ...)
461 */
462 void psi_set_to_recursive(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame) {
463 set->outer->data.func->handler(return_value, set, r_val, frame);
464 }
465
466 /*
467 * set $ivar = to_array(dvar, to_string(*dvar));
468 */
469 void psi_set_to_array_simple(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
470 {
471 struct psi_set_exp *sub_exp;
472 struct psi_decl_var *var;
473 impl_val *ret_val;
474 char *ptr;
475 size_t size;
476
477 array_init(return_value);
478
479 var = psi_set_exp_get_decl_var(set);
480 ret_val = deref_impl_val(r_val, var);
481 if ((intptr_t) ret_val <= (intptr_t) 0) {
482 return;
483 }
484
485 psi_plist_get(set->inner, 0, &sub_exp);
486
487 size = psi_decl_arg_get_size(var->arg);
488 for (ptr = ret_val->ptr; *(void **) ptr; ptr += size) {
489 zval ele;
490
491 ZVAL_NULL(&ele);
492 sub_exp->data.func->handler(&ele, sub_exp, (void *) ptr, frame);
493 add_next_index_zval(return_value, &ele);
494 }
495 }
496
497 /*
498 * set $ivar = to_array(dvar, num_exp, to_string(*dvar));
499 */
500 void psi_set_to_array_counted(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
501 {
502 struct psi_set_exp *sub_exp;
503 struct psi_decl_var *var;
504 impl_val *ret_val;
505 char *ptr;
506 size_t size;
507 zend_long count;
508
509 array_init(return_value);
510
511 var = psi_set_exp_get_decl_var(set);
512 ret_val = deref_impl_val(r_val, var);
513 if ((intptr_t) ret_val <= (intptr_t) 0) {
514 return;
515 }
516
517 psi_plist_get(set->inner, 0, &sub_exp);
518 count = psi_long_num_exp(sub_exp->data.num, frame);
519 psi_plist_get(set->inner, 1, &sub_exp);
520
521 for (ptr = (char *) ret_val; 0 < count--; ptr += size) {
522 size = psi_decl_var_get_size(psi_set_exp_get_decl_var(sub_exp));
523 zval ele;
524
525 ZVAL_NULL(&ele);
526 sub_exp->data.func->handler(&ele, sub_exp, (void *) &ptr, frame);
527 add_next_index_zval(return_value, &ele);
528 }
529 }
530
531 #include "call.h"
532
533 /*
534 * set $ivar = to_array(dvar,
535 * $foo = to_int(d_foo),
536 * $bar = to_string(d_bar));
537 */
538 void psi_set_to_array(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
539 {
540 struct psi_set_exp *sub_exp;
541 struct psi_decl_var *var;
542 impl_val *ret_val;
543 size_t i = 0;
544
545 array_init(return_value);
546
547 var = psi_set_exp_get_decl_var(set);
548 ret_val = deref_impl_val(r_val, var);
549 if ((intptr_t) ret_val <= (intptr_t) 0) {
550 return;
551 }
552
553 while (psi_plist_get(set->inner, i++, &sub_exp)) {
554 zval ele;
555 struct psi_decl_var *dvar = psi_set_exp_get_decl_var(sub_exp);
556 struct psi_impl_var *ivar = psi_set_exp_get_impl_var(sub_exp);
557 struct psi_call_frame_symbol *sym;
558
559 sym = psi_call_frame_fetch_symbol(frame, dvar);
560 sym->ptr = ((char *) ret_val) + dvar->arg->layout->pos;
561
562 ZVAL_NULL(&ele);
563 psi_set_exp_exec_ex(sub_exp, &ele, sym->ptr, frame);
564 add_assoc_zval(return_value, ivar->name + 1, &ele);
565 }
566 }
567
568 //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)
569 //{
570 // decl_type *real = real_decl_type(spec);
571 // HashTable *arr;
572 // zval *zv;
573 // size_t i, sz;
574 // decl_arg tmp_arg = {0};
575 //
576 // if (impl_type != PSI_T_ARRAY) {
577 // SEPARATE_ARG_IF_REF(zvalue);
578 // convert_to_array(zvalue);
579 // }
580 // arr = HASH_OF(zvalue);
581 //
582 // switch (real->type) {
583 // case PSI_T_STRUCT:
584 // *to_free = tmp = psi_array_to_struct(real->real.strct, arr);
585 // break;
586 // case PSI_T_UNION:
587 // *to_free = tmp = psi_array_to_union(real->real.unn, arr);
588 // break;
589 // default:
590 // sz = psi_t_size(real->type);
591 // tmp = *to_free = ecalloc(zend_hash_num_elements(arr), sz);
592 // tmp_arg.type = spec;
593 // tmp_arg.var = spec_var;
594 // ZEND_HASH_FOREACH_VAL_IND(arr, zv)
595 // {
596 // void *ptr = ((char *) tmp) + (i++ * sz);
597 // psi_from_zval_ex(NULL, (impl_val **) &ptr, &tmp_arg, 0, zv, NULL);
598 // }
599 // ZEND_HASH_FOREACH_END();
600 // }
601 //
602 // return tmp;
603 //}
604
605 /*
606 * let dvar = count($ivar)
607 */
608 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)
609 {
610 return psi_val_intval(tmp, psi_decl_type_get_real(spec)->type, psi_zval_count(zvalue));
611 }
612
613 /*
614 * set $ivar = to_object(dvar)
615 */
616 void psi_set_to_object(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
617 {
618 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
619 impl_val *ret_val = deref_impl_val(r_val, var);
620
621 if ((intptr_t) ret_val->ptr > (intptr_t) 0) {
622 object_init_ex(return_value, psi_object_get_class_entry());
623 PSI_OBJ(return_value, NULL)->data = ret_val->ptr;
624 } else {
625 RETVAL_NULL();
626 }
627 }
628
629 /*
630 * let dvar = objval($ivar)
631 */
632 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)
633 {
634 psi_object *obj;
635
636 if (Z_TYPE_P(zvalue) != IS_OBJECT
637 || !instanceof_function(Z_OBJCE_P(zvalue), psi_object_get_class_entry())) {
638 return NULL;
639 }
640
641 obj = PSI_OBJ(zvalue, NULL);
642 tmp->ptr = obj->data;
643
644 return tmp;
645 }
646