zend_string'ify
[m6w6/ext-psi] / src / types / number.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
28 #include <assert.h>
29 #include <math.h>
30
31 #include "data.h"
32 #include "calc.h"
33 #include "call.h"
34 #include "parser.h"
35
36 #include "Zend/zend_constants.h"
37 #include "Zend/zend_operators.h"
38
39
40 struct psi_number *psi_number_init(token_t t, void *num, unsigned flags)
41 {
42 struct psi_number *exp = calloc(1, sizeof(*exp));
43
44 exp->flags = flags;
45 switch (exp->type = t) {
46 case PSI_T_INT8:
47 exp->data.ival.i8 = *(int8_t *) num;
48 break;
49 case PSI_T_UINT8:
50 exp->data.ival.u8 = *(uint8_t *) num;
51 break;
52 case PSI_T_INT16:
53 exp->data.ival.i16 = *(int16_t *) num;
54 break;
55 case PSI_T_UINT16:
56 exp->data.ival.u16 = *(uint16_t *) num;
57 break;
58 case PSI_T_INT32:
59 exp->data.ival.i32 = *(int32_t *) num;
60 break;
61 case PSI_T_UINT32:
62 exp->data.ival.u32 = *(uint32_t *) num;
63 break;
64 case PSI_T_INT64:
65 exp->data.ival.i64 = *(int64_t *) num;
66 break;
67 case PSI_T_UINT64:
68 exp->data.ival.u64 = *(uint64_t *) num;
69 break;
70 case PSI_T_FLOAT:
71 exp->data.ival.fval = *(float *) num;
72 break;
73 case PSI_T_DOUBLE:
74 exp->data.ival.dval = *(double *) num;
75 break;
76 #if HAVE_LONG_DOUBLE
77 case PSI_T_LONG_DOUBLE:
78 exp->data.ival.ldval = *(long double *) num;
79 break;
80 #endif
81 case PSI_T_NULL:
82 break;
83 case PSI_T_QUOTED_CHAR:
84 case PSI_T_NUMBER:
85 case PSI_T_NSNAME:
86 case PSI_T_DEFINE:
87 exp->data.numb = zend_string_copy(num);
88 break;
89 case PSI_T_NAME:
90 exp->data.dvar = num;
91 break;
92 case PSI_T_FUNCTION:
93 exp->data.call = num;
94 break;
95 case PSI_T_SIZEOF:
96 exp->data.dtyp = num;
97 break;
98 default:
99 assert(0);
100 }
101
102 return exp;
103 }
104
105 struct psi_number *psi_number_copy(struct psi_number *exp)
106 {
107 struct psi_number *num = calloc(1, sizeof(*num));
108
109 *num = *exp;
110
111 if (num->token) {
112 num->token = psi_token_copy(num->token);
113 }
114 switch (num->type) {
115 case PSI_T_INT8:
116 case PSI_T_UINT8:
117 case PSI_T_INT16:
118 case PSI_T_UINT16:
119 case PSI_T_INT32:
120 case PSI_T_UINT32:
121 case PSI_T_INT64:
122 case PSI_T_UINT64:
123 case PSI_T_FLOAT:
124 case PSI_T_DOUBLE:
125 #if HAVE_LONG_DOUBLE
126 case PSI_T_LONG_DOUBLE:
127 #endif
128 case PSI_T_ENUM:
129 case PSI_T_CONST:
130 case PSI_T_NULL:
131 break;
132 case PSI_T_NUMBER:
133 case PSI_T_NSNAME:
134 case PSI_T_DEFINE:
135 case PSI_T_QUOTED_CHAR:
136 num->data.numb = zend_string_copy(num->data.numb);
137 break;
138 case PSI_T_NAME:
139 num->data.dvar = psi_decl_var_copy(num->data.dvar);
140 break;
141 case PSI_T_FUNCTION:
142 num->data.call = psi_cpp_macro_call_copy(num->data.call);
143 break;
144 case PSI_T_SIZEOF:
145 num->data.dtyp = psi_decl_type_copy(num->data.dtyp);
146 break;
147 default:
148 assert(0);
149 }
150 return num;
151 }
152
153 void psi_number_free(struct psi_number **exp_ptr)
154 {
155 if (*exp_ptr) {
156 struct psi_number *exp = *exp_ptr;
157
158 *exp_ptr = NULL;
159 if (exp->token) {
160 free(exp->token);
161 }
162 switch (exp->type) {
163 case PSI_T_INT8:
164 case PSI_T_UINT8:
165 case PSI_T_INT16:
166 case PSI_T_UINT16:
167 case PSI_T_INT32:
168 case PSI_T_UINT32:
169 case PSI_T_INT64:
170 case PSI_T_UINT64:
171 case PSI_T_FLOAT:
172 case PSI_T_DOUBLE:
173 #if HAVE_LONG_DOUBLE
174 case PSI_T_LONG_DOUBLE:
175 #endif
176 case PSI_T_ENUM:
177 case PSI_T_CONST:
178 case PSI_T_NULL:
179 break;
180 case PSI_T_FUNCTION:
181 psi_cpp_macro_call_free(&exp->data.call);
182 break;
183 case PSI_T_NSNAME:
184 case PSI_T_NUMBER:
185 case PSI_T_DEFINE:
186 case PSI_T_QUOTED_CHAR:
187 zend_string_release(exp->data.numb);
188 break;
189 case PSI_T_NAME:
190 psi_decl_var_free(&exp->data.dvar);
191 break;
192 case PSI_T_SIZEOF:
193 psi_decl_type_free(&exp->data.dtyp);
194 break;
195 default:
196 assert(0);
197 }
198 free(exp);
199 }
200 }
201
202 struct psi_plist *psi_number_tokens(struct psi_number *exp,
203 struct psi_plist *list)
204 {
205 struct psi_token *ntoken;
206 if (!list) {
207 list = psi_plist_init((psi_plist_dtor) psi_token_free);
208 }
209
210 switch (exp->type) {
211 case PSI_T_NAME:
212 /* decl_var */
213 ntoken = psi_token_copy(exp->data.dvar->token);
214
215 if (exp->data.dvar->pointer_level > 1 || !exp->data.dvar->array_size) {
216 struct psi_token *temp = ntoken;
217 unsigned pl = exp->data.dvar->pointer_level - !!exp->data.dvar->array_size;
218
219 while (pl--) {
220 ntoken = psi_token_init(PSI_T_POINTER, "*", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
221 list = psi_plist_add(list, &ntoken);
222 }
223 ntoken = temp;
224 }
225
226 list = psi_plist_add(list, &ntoken);
227
228 if (exp->data.dvar->array_size) {
229 char buf[0x20], *ptr;
230
231 ntoken = psi_token_init(PSI_T_LBRACKET, "[", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
232 list = psi_plist_add(list, &ntoken);
233 ptr = zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], exp->data.dvar->array_size);
234
235 ntoken = psi_token_init(PSI_T_NUMBER, ptr, strlen(ptr), ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
236 list = psi_plist_add(list, &ntoken);
237 }
238 break;
239
240 case PSI_T_SIZEOF:
241 /* decl_type */
242 ntoken = psi_token_copy(exp->token);
243 list = psi_plist_add(list, &ntoken);
244 ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
245 list = psi_plist_add(list, &ntoken);
246 ntoken = psi_token_copy(exp->data.dtyp->token);
247 list = psi_plist_add(list, &ntoken);
248 ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
249 list = psi_plist_add(list, &ntoken);
250 break;
251
252 default:
253 ntoken = psi_token_copy(exp->token);
254 list = psi_plist_add(list, &ntoken);
255 break;
256 }
257
258 return list;
259 }
260
261 void psi_number_dump(int fd, struct psi_number *exp)
262 {
263 switch (exp->type) {
264 case PSI_T_INT8:
265 dprintf(fd, "%" PRId8, exp->data.ival.i8);
266 break;
267 case PSI_T_UINT8:
268 dprintf(fd, "%" PRIu8, exp->data.ival.u8);
269 break;
270 case PSI_T_INT16:
271 dprintf(fd, "%" PRId16, exp->data.ival.i16);
272 break;
273 case PSI_T_UINT16:
274 dprintf(fd, "%" PRIu16, exp->data.ival.u16);
275 break;
276 case PSI_T_INT32:
277 dprintf(fd, "%" PRId32, exp->data.ival.i32);
278 break;
279 case PSI_T_UINT32:
280 dprintf(fd, "%" PRIu32, exp->data.ival.u32);
281 break;
282 case PSI_T_INT64:
283 dprintf(fd, "%" PRId64, exp->data.ival.i64);
284 break;
285 case PSI_T_UINT64:
286 dprintf(fd, "%" PRIu64, exp->data.ival.u64);
287 break;
288 case PSI_T_FLOAT:
289 if (isinf(exp->data.ival.dval)) {
290 dprintf(fd, "\\INF");
291 } else if (isnan(exp->data.ival.dval)) {
292 dprintf(fd, "\\NAN");
293 } else {
294 dprintf(fd, "%" PRIfval, exp->data.ival.dval);
295 }
296 break;
297 case PSI_T_DOUBLE:
298 if (isinf(exp->data.ival.dval)) {
299 dprintf(fd, "\\INF");
300 } else if (isnan(exp->data.ival.dval)) {
301 dprintf(fd, "\\NAN");
302 } else {
303 dprintf(fd, "%" PRIdval, exp->data.ival.dval);
304 }
305 break;
306 #if HAVE_LONG_DOUBLE
307 case PSI_T_LONG_DOUBLE:
308 if (isinfl(exp->data.ival.ldval)) {
309 dprintf(fd, "\\INF");
310 } else if (isnanl(exp->data.ival.ldval)) {
311 dprintf(fd, "\\NAN");
312 } else {
313 dprintf(fd, "%" PRIldval, exp->data.ival.ldval);
314 }
315 break;
316 #endif
317 case PSI_T_NULL:
318 dprintf(fd, "NULL");
319 break;
320 case PSI_T_NUMBER:
321 case PSI_T_NSNAME:
322 case PSI_T_DEFINE:
323 case PSI_T_QUOTED_CHAR:
324 dprintf(fd, "%s", exp->data.numb->val);
325 break;
326 case PSI_T_FUNCTION:
327 psi_cpp_macro_call_dump(fd, exp->data.call);
328 break;
329 case PSI_T_CONST:
330 dprintf(fd, "%s", exp->data.cnst->name->val);
331 break;
332 case PSI_T_ENUM:
333 dprintf(fd, "%s", exp->data.enm->name->val);
334 break;
335 case PSI_T_NAME:
336 psi_decl_var_dump(fd, exp->data.dvar);
337 break;
338 case PSI_T_SIZEOF:
339 dprintf(fd, "sizeof(");
340 psi_decl_type_dump(fd, exp->data.dtyp, 0);
341 dprintf(fd, ")");
342 break;
343 default:
344 assert(0);
345 }
346 }
347
348 static inline bool psi_number_validate_enum(struct psi_data *data,
349 struct psi_number *exp, struct psi_validate_scope *scope)
350 {
351 if (scope && scope->current_enum) {
352 size_t i = 0;
353 struct psi_decl_enum_item *itm;
354 struct psi_decl_enum *enm;
355
356 enm = scope->current_enum;
357
358 switch (exp->type) {
359 case PSI_T_NAME:
360 while (psi_plist_get(enm->items, i++, &itm)) {
361 if (zend_string_equals(itm->name, exp->data.dvar->name)) {
362 psi_decl_var_free(&exp->data.dvar);
363 exp->type = PSI_T_ENUM;
364 exp->data.enm = itm;
365 return psi_number_validate(data, exp, scope);
366 }
367 }
368 break;
369
370 case PSI_T_DEFINE:
371 while (psi_plist_get(enm->items, i++, &itm)) {
372 if (zend_string_equals(itm->name, exp->data.numb)) {
373 zend_string_release(exp->data.numb);
374 exp->type = PSI_T_ENUM;
375 exp->data.enm = itm;
376 return psi_number_validate(data, exp, scope);
377 }
378 }
379 break;
380
381 default:
382 assert(0);
383 }
384 }
385 return false;
386 }
387
388 static inline token_t validate_char(char *numb, impl_val *res, unsigned *lvl)
389 {
390 char *endptr;
391 token_t typ = PSI_T_INT8;
392
393 res->i8 = numb[0];
394 endptr = &numb[1];
395
396 switch(res->i8) {
397 case '\\':
398 res->i8 = numb[1];
399 endptr = &numb[2];
400
401 switch(res->i8) {
402 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
403 res->i8 = strtol(&numb[1], &endptr, 8);
404 break;
405
406 case 'x':
407 res->i8 = strtol(&numb[2], &endptr, 16);
408 break;
409
410 case 'a':
411 res->i8 = '\a';
412 break;
413 case 'b':
414 res->i8 = '\b';
415 break;
416 case 'f':
417 res->i8 = '\f';
418 break;
419 case 'n':
420 res->i8 = '\n';
421 break;
422 case 'r':
423 res->i8 = '\r';
424 break;
425 case 't':
426 res->i8 = '\t';
427 break;
428 case 'v':
429 res->i8 = '\v';
430 break;
431 default:
432 break;
433 }
434 break;
435 default:
436 break;
437 }
438
439 /* more to grok? */
440 if (*endptr) {
441 impl_val tmp_val = {0};
442 token_t tmp_typ = validate_char(endptr, &tmp_val, lvl);
443
444 if (!tmp_typ) {
445 return 0;
446 }
447
448 res->i32 = res->i8 << (8 * *lvl);
449 typ = psi_calc_add(PSI_T_INT32, res, tmp_typ, &tmp_val, res);
450 }
451
452 ++(*lvl);
453
454 return typ;
455 }
456 static inline bool psi_number_validate_char(struct psi_data *data, struct psi_number *exp)
457 {
458 impl_val val = {0};
459 unsigned lvl = 1;
460 token_t typ = validate_char(exp->data.numb->val, &val, &lvl);
461
462 if (!typ) {
463 return false;
464 }
465
466 zend_string_release(exp->data.numb);
467 exp->type = typ;
468 exp->data.ival = val;
469 return true;
470 }
471
472 static inline bool psi_number_validate_number(struct psi_data *data, struct psi_number *exp)
473 {
474 impl_val tmp = {0};
475
476 if (exp->flags) {
477 switch (exp->flags & 0x0f) {
478 case PSI_NUMBER_INT:
479 switch (exp->flags & 0x0f00) {
480 case PSI_NUMBER_L:
481 default:
482 tmp.i64 = strtol(exp->data.numb->val, NULL, 0);
483 zend_string_release(exp->data.numb);
484 exp->type = PSI_T_INT64;
485 exp->data.ival.i64 = tmp.i64;
486 break;
487 case PSI_NUMBER_LL:
488 tmp.i64 = strtoll(exp->data.numb->val, NULL, 0);
489 zend_string_release(exp->data.numb);
490 exp->type = PSI_T_INT64;
491 exp->data.ival.i64 = tmp.i64;
492 break;
493 case PSI_NUMBER_U:
494 case PSI_NUMBER_UL:
495 tmp.u64 = strtoul(exp->data.numb->val, NULL, 0);
496 zend_string_release(exp->data.numb);
497 exp->type = PSI_T_UINT64;
498 exp->data.ival.u64 = tmp.u64;
499 break;
500 case PSI_NUMBER_ULL:
501 tmp.u64 = strtoull(exp->data.numb->val, NULL, 0);
502 zend_string_release(exp->data.numb);
503 exp->type = PSI_T_UINT64;
504 exp->data.ival.u64 = tmp.u64;
505 break;
506 }
507 return true;
508
509 case PSI_NUMBER_FLT:
510 switch (exp->flags & 0x0ff00) {
511 case PSI_NUMBER_F:
512 case PSI_NUMBER_DF:
513 tmp.fval = strtof(exp->data.numb->val, NULL);
514 zend_string_release(exp->data.numb);
515 exp->type = PSI_T_FLOAT;
516 exp->data.ival.fval = tmp.fval;
517 break;
518 case PSI_NUMBER_L:
519 case PSI_NUMBER_DL:
520 #if HAVE_LONG_DOUBLE
521 tmp.ldval = strtold(exp->data.numb->val, NULL);
522 zend_string_release(exp->data.numb);
523 exp->type = PSI_T_LONG_DOUBLE;
524 exp->data.ival.ldval = tmp.ldval;
525 break;
526 #endif
527 case PSI_NUMBER_DD:
528 default:
529 tmp.dval = strtod(exp->data.numb->val, NULL);
530 zend_string_release(exp->data.numb);
531 exp->type = PSI_T_DOUBLE;
532 exp->data.ival.dval = tmp.dval;
533 break;
534 }
535 return true;
536 default:
537 assert(0);
538 break;
539 }
540 } else {
541 switch (is_numeric_str_function(exp->data.numb, (zend_long *) &tmp, (double *) &tmp)) {
542 case IS_LONG:
543 zend_string_release(exp->data.numb);
544 exp->type = PSI_T_INT64;
545 exp->data.ival.i64 = tmp.zend.lval;
546 return true;
547
548 case IS_DOUBLE:
549 zend_string_release(exp->data.numb);
550 exp->type = PSI_T_DOUBLE;
551 exp->data.ival.dval = tmp.dval;
552 return true;
553 }
554 }
555 data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)");
556 return false;
557
558 }
559 bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
560 struct psi_validate_scope *scope)
561 {
562 size_t i = 0;
563 struct psi_const *cnst;
564 struct psi_decl_enum *enm;
565
566 switch (exp->type) {
567 case PSI_T_NULL:
568 exp->type = PSI_T_UINT8;
569 /* no break */
570 case PSI_T_CONST:
571 case PSI_T_INT8:
572 case PSI_T_UINT8:
573 case PSI_T_INT16:
574 case PSI_T_UINT16:
575 case PSI_T_INT32:
576 case PSI_T_UINT32:
577 case PSI_T_INT64:
578 case PSI_T_UINT64:
579 case PSI_T_FLOAT:
580 case PSI_T_DOUBLE:
581 #if HAVE_LONG_DOUBLE
582 case PSI_T_LONG_DOUBLE:
583 #endif
584 case PSI_T_ENUM:
585 return true;
586
587 case PSI_T_NAME:
588 if (scope && scope->defs && zend_hash_exists(scope->defs, exp->data.dvar->name)) {
589 return true;
590 }
591 if (scope && scope->current_enum && psi_number_validate_enum(data, exp, scope)) {
592 return true;
593 }
594 while (psi_plist_get(data->enums, i++, &enm)) {
595 struct psi_validate_scope enum_scope = *scope;
596 enum_scope.current_enum = enm;
597 if (psi_number_validate_enum(data, exp, &enum_scope)) {
598 return true;
599 }
600 }
601 if (exp->data.dvar->arg) {
602 return true;
603 }
604 if (psi_decl_var_validate(data, exp->data.dvar, scope)) {
605 return true;
606 }
607 data->error(data, exp->token, PSI_WARNING,
608 "Unknown variable '%s' in numeric expression",
609 exp->data.dvar->name->val);
610 return false;
611
612 case PSI_T_FUNCTION:
613 if (scope && scope->defs && zend_hash_exists(scope->defs, exp->data.numb)) {
614 return true;
615 }
616 return false;
617
618 case PSI_T_DEFINE:
619 if (scope && scope->defs && zend_hash_exists(scope->defs, exp->data.numb)) {
620 if (!scope->macro || !zend_string_equals(scope->macro->token->text, exp->data.numb)) {
621 return true;
622 }
623 /* #define foo foo */
624 }
625 while (psi_plist_get(data->enums, i++, &enm)) {
626 struct psi_validate_scope enum_scope = *scope;
627 enum_scope.current_enum = enm;
628 if (psi_number_validate_enum(data, exp, &enum_scope)) {
629 return true;
630 }
631 }
632 return false;
633
634 case PSI_T_SIZEOF:
635 if (psi_decl_type_validate(data, exp->data.dtyp, NULL, scope)) {
636 struct psi_decl_type *dtyp = exp->data.dtyp;
637
638 exp->type = PSI_T_UINT64;
639 exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL);
640 psi_decl_type_free(&dtyp);
641 return true;
642 } else {
643 struct psi_decl_type *dtyp = exp->data.dtyp;
644
645 data->error(data, exp->token, PSI_WARNING,
646 "Cannot compute sizeof(%s) (%u)", dtyp->name->val, dtyp->type);
647
648 exp->type = PSI_T_UINT8;
649 exp->data.ival.u8 = 0;
650 psi_decl_type_free(&dtyp);
651 }
652 break;
653
654 case PSI_T_NSNAME:
655 {
656 zval *zc;
657
658 if (exp->data.numb->val[0] == '\\') {
659 zc = zend_get_constant_str(&exp->data.numb->val[1], exp->data.numb->len - 1);
660 } else {
661 zc = zend_get_constant(exp->data.numb);
662 }
663
664 if (zc) {
665 switch (Z_TYPE_P(zc)) {
666 case IS_LONG:
667 zend_string_release(exp->data.numb);
668 exp->type = PSI_T_INT64;
669 exp->data.ival.i64 = Z_LVAL_P(zc);
670 return true;
671
672 case IS_DOUBLE:
673 zend_string_release(exp->data.numb);
674 exp->type = PSI_T_DOUBLE;
675 exp->data.ival.dval = Z_DVAL_P(zc);
676 return true;
677
678 default:
679 assert(0);
680 }
681 }
682 }
683 while (psi_plist_get(data->consts, i++, &cnst)) {
684 if (zend_string_equals(cnst->name, exp->data.numb)) {
685 zend_string_release(exp->data.numb);
686 exp->type = PSI_T_CONST;
687 exp->data.cnst = cnst;
688 return true;
689 }
690 }
691 data->error(data, exp->token, PSI_WARNING,
692 "Unknown constant '%s' in numeric expression",
693 exp->data.numb->val);
694 return false;
695
696 case PSI_T_NUMBER:
697 return psi_number_validate_number(data, exp);
698
699 case PSI_T_QUOTED_CHAR:
700 return psi_number_validate_char(data, exp);
701
702 default:
703 assert(0);
704 }
705
706 return false;
707 }
708
709 static inline token_t psi_number_eval_constant(struct psi_number *exp,
710 impl_val *res, struct psi_call_frame *frame)
711 {
712 switch (exp->data.cnst->type->type) {
713 case PSI_T_INT:
714 res->i64 = zend_get_constant(exp->data.cnst->name)->value.lval;
715 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
716 return PSI_T_INT64;
717 case PSI_T_FLOAT:
718 res->dval = zend_get_constant(exp->data.cnst->name)->value.dval;
719 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
720 return PSI_T_DOUBLE;
721 default:
722 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type);
723 return 0;
724 }
725 }
726
727
728 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
729 impl_val *res, struct psi_call_frame *frame)
730 {
731 impl_val *ref;
732 struct psi_call_frame_symbol *sym;
733 struct psi_decl_type *real;
734 struct psi_decl_var *var;
735 size_t size;
736
737 var = exp->data.dvar;
738 real = psi_decl_type_get_real(var->arg->type);
739 size = psi_decl_arg_get_size(var->arg);
740 sym = psi_call_frame_fetch_symbol(frame, var);
741 ref = deref_impl_val(sym->ptr, var);
742
743 memcpy(res, ref, size);
744
745 if (var->arg->var->pointer_level > var->pointer_level) {
746 switch (SIZEOF_VOID_P) {
747 case 4:
748 return PSI_T_INT32;
749 case 8:
750 return PSI_T_INT64;
751 default:
752 assert(0);
753 }
754 }
755 return real->type;
756 }
757
758 static inline token_t psi_number_eval_define(struct psi_number *exp,
759 impl_val *res, HashTable *defs, struct psi_num_exp *rec_guard)
760 {
761 if (defs) {
762 struct psi_cpp_macro_decl *macro;
763
764 macro = zend_hash_find_ptr(defs, exp->data.numb);
765 if (macro && macro->exp && macro->exp != rec_guard) {
766 return psi_num_exp_exec(macro->exp, res, NULL, defs);
767 }
768 }
769 res->u8 = 0;
770 return PSI_T_UINT8;
771 }
772
773 token_t psi_number_eval(struct psi_number *exp, impl_val *res,
774 struct psi_call_frame *frame, HashTable *defs, struct psi_num_exp *rec_guard)
775 {
776 switch (exp->type) {
777 case PSI_T_INT8:
778 *res = exp->data.ival;
779 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
780 return PSI_T_INT8;
781 case PSI_T_UINT8:
782 *res = exp->data.ival;
783 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
784 return PSI_T_UINT8;
785 case PSI_T_INT16:
786 *res = exp->data.ival;
787 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
788 return PSI_T_INT16;
789 case PSI_T_UINT16:
790 *res = exp->data.ival;
791 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
792 return PSI_T_UINT16;
793 case PSI_T_INT32:
794 *res = exp->data.ival;
795 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
796 return PSI_T_INT32;
797 case PSI_T_UINT32:
798 *res = exp->data.ival;
799 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
800 return PSI_T_UINT32;
801 case PSI_T_INT64:
802 *res = exp->data.ival;
803 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
804 return PSI_T_INT64;
805 case PSI_T_UINT64:
806 *res = exp->data.ival;
807 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
808 return PSI_T_UINT64;
809
810 case PSI_T_FLOAT:
811 *res = exp->data.ival;
812 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
813 return exp->type;
814
815 case PSI_T_DOUBLE:
816 *res = exp->data.ival;
817 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
818 return exp->type;
819
820 #if HAVE_LONG_DOUBLE
821 case PSI_T_LONG_DOUBLE:
822 *res = exp->data.ival;
823 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
824 return exp->type;
825 #endif
826
827 case PSI_T_ENUM:
828 res->i64 = exp->data.enm->val;
829 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
830 return PSI_T_INT64;
831
832 case PSI_T_NUMBER:
833 res->i64 = atol(exp->data.numb->val);
834 return PSI_T_INT64;
835
836 case PSI_T_CONST:
837 return psi_number_eval_constant(exp, res, frame);
838
839 case PSI_T_NAME:
840 return psi_number_eval_decl_var(exp, res, frame);
841
842 case PSI_T_DEFINE:
843 return psi_number_eval_define(exp, res, defs, rec_guard);
844
845 case PSI_T_FUNCTION:
846 res->u8 = 0;
847 return PSI_T_UINT8;
848
849 default:
850 assert(0);
851 }
852 return 0;
853 }