number: handle INF/NAN
[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 = strdup(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 = strdup(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 free(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
221 ntoken = psi_token_init(PSI_T_POINTER, "*", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file);
222 list = psi_plist_add(list, &ntoken);
223 }
224 ntoken = temp;
225 }
226
227 list = psi_plist_add(list, &ntoken);
228
229 if (exp->data.dvar->array_size) {
230 char buf[0x20], *ptr;
231
232 ntoken = psi_token_init(PSI_T_LBRACKET, "[", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file);
233 list = psi_plist_add(list, &ntoken);
234 ptr = zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], exp->data.dvar->array_size);
235
236 ntoken = psi_token_init(PSI_T_NUMBER, ptr, strlen(ptr), ntoken->col+ntoken->size, ntoken->line, ntoken->file);
237 list = psi_plist_add(list, &ntoken);
238 }
239 break;
240
241 case PSI_T_SIZEOF:
242 /* decl_type */
243 ntoken = psi_token_copy(exp->token);
244 list = psi_plist_add(list, &ntoken);
245 ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file);
246 list = psi_plist_add(list, &ntoken);
247 ntoken = psi_token_copy(exp->data.dtyp->token);
248 list = psi_plist_add(list, &ntoken);
249 ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file);
250 list = psi_plist_add(list, &ntoken);
251 break;
252
253 default:
254 ntoken = psi_token_copy(exp->token);
255 list = psi_plist_add(list, &ntoken);
256 break;
257 }
258
259 return list;
260 }
261
262 void psi_number_dump(int fd, struct psi_number *exp)
263 {
264 switch (exp->type) {
265 case PSI_T_INT8:
266 dprintf(fd, "%" PRId8, exp->data.ival.i8);
267 break;
268 case PSI_T_UINT8:
269 dprintf(fd, "%" PRIu8, exp->data.ival.u8);
270 break;
271 case PSI_T_INT16:
272 dprintf(fd, "%" PRId16, exp->data.ival.i16);
273 break;
274 case PSI_T_UINT16:
275 dprintf(fd, "%" PRIu16, exp->data.ival.u16);
276 break;
277 case PSI_T_INT32:
278 dprintf(fd, "%" PRId32, exp->data.ival.i32);
279 break;
280 case PSI_T_UINT32:
281 dprintf(fd, "%" PRIu32, exp->data.ival.u32);
282 break;
283 case PSI_T_INT64:
284 dprintf(fd, "%" PRId64, exp->data.ival.i64);
285 break;
286 case PSI_T_UINT64:
287 dprintf(fd, "%" PRIu64, exp->data.ival.u64);
288 break;
289 case PSI_T_FLOAT:
290 if (isinf(exp->data.ival.dval)) {
291 dprintf(fd, "\\INF");
292 } else if (isnan(exp->data.ival.dval)) {
293 dprintf(fd, "\\NAN");
294 } else {
295 dprintf(fd, "%" PRIfval, exp->data.ival.dval);
296 }
297 break;
298 case PSI_T_DOUBLE:
299 if (isinf(exp->data.ival.dval)) {
300 dprintf(fd, "\\INF");
301 } else if (isnan(exp->data.ival.dval)) {
302 dprintf(fd, "\\NAN");
303 } else {
304 dprintf(fd, "%" PRIdval, exp->data.ival.dval);
305 }
306 break;
307 #if HAVE_LONG_DOUBLE
308 case PSI_T_LONG_DOUBLE:
309 if (isinfl(exp->data.ival.ldval)) {
310 dprintf(fd, "\\INF");
311 } else if (isnanl(exp->data.ival.ldval)) {
312 dprintf(fd, "\\NAN");
313 } else {
314 dprintf(fd, "%" PRIldval, exp->data.ival.ldval);
315 }
316 break;
317 #endif
318 case PSI_T_NULL:
319 dprintf(fd, "NULL");
320 break;
321 case PSI_T_NUMBER:
322 case PSI_T_NSNAME:
323 case PSI_T_DEFINE:
324 case PSI_T_QUOTED_CHAR:
325 dprintf(fd, "%s", exp->data.numb);
326 break;
327 case PSI_T_FUNCTION:
328 psi_cpp_macro_call_dump(fd, exp->data.call);
329 break;
330 case PSI_T_CONST:
331 dprintf(fd, "%s", exp->data.cnst->name);
332 break;
333 case PSI_T_ENUM:
334 dprintf(fd, "%s", exp->data.enm->name);
335 break;
336 case PSI_T_NAME:
337 psi_decl_var_dump(fd, exp->data.dvar);
338 break;
339 case PSI_T_SIZEOF:
340 dprintf(fd, "sizeof(");
341 psi_decl_type_dump(fd, exp->data.dtyp, 0);
342 dprintf(fd, ")");
343 break;
344 default:
345 assert(0);
346 }
347 }
348
349 static inline bool psi_number_validate_enum(struct psi_data *data,
350 struct psi_number *exp, struct psi_validate_scope *scope)
351 {
352 if (scope && scope->current_enum) {
353 size_t i = 0;
354 struct psi_decl_enum_item *itm;
355 struct psi_decl_enum *enm;
356
357 enm = scope->current_enum;
358
359 switch (exp->type) {
360 case PSI_T_NAME:
361 while (psi_plist_get(enm->items, i++, &itm)) {
362 if (!strcmp(itm->name, exp->data.dvar->name)) {
363 psi_decl_var_free(&exp->data.dvar);
364 exp->type = PSI_T_ENUM;
365 exp->data.enm = itm;
366 return psi_number_validate(data, exp, scope);
367 }
368 }
369 break;
370
371 case PSI_T_DEFINE:
372 while (psi_plist_get(enm->items, i++, &itm)) {
373 if (!strcmp(itm->name, exp->data.numb)) {
374 free(exp->data.numb);
375 exp->type = PSI_T_ENUM;
376 exp->data.enm = itm;
377 return psi_number_validate(data, exp, scope);
378 }
379 }
380 break;
381
382 default:
383 assert(0);
384 }
385 }
386 return false;
387 }
388
389 static inline token_t validate_char(char *numb, impl_val *res, unsigned *lvl)
390 {
391 char *endptr;
392 token_t typ = PSI_T_INT8;
393
394 res->i8 = numb[0];
395 endptr = &numb[1];
396
397 switch(res->i8) {
398 case '\\':
399 res->i8 = numb[1];
400 endptr = &numb[2];
401
402 switch(res->i8) {
403 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
404 res->i8 = strtol(&numb[1], &endptr, 8);
405 break;
406
407 case 'x':
408 res->i8 = strtol(&numb[2], &endptr, 16);
409 break;
410
411 case 'a':
412 res->i8 = '\a';
413 break;
414 case 'b':
415 res->i8 = '\b';
416 break;
417 case 'f':
418 res->i8 = '\f';
419 break;
420 case 'n':
421 res->i8 = '\n';
422 break;
423 case 'r':
424 res->i8 = '\r';
425 break;
426 case 't':
427 res->i8 = '\t';
428 break;
429 case 'v':
430 res->i8 = '\v';
431 break;
432 default:
433 break;
434 }
435 break;
436 default:
437 break;
438 }
439
440 /* more to grok? */
441 if (*endptr) {
442 impl_val tmp_val = {0};
443 token_t tmp_typ = validate_char(endptr, &tmp_val, lvl);
444
445 if (!tmp_typ) {
446 return 0;
447 }
448
449 res->i32 = res->i8 << (8 * *lvl);
450 typ = psi_calc_add(PSI_T_INT32, res, tmp_typ, &tmp_val, res);
451 }
452
453 ++(*lvl);
454
455 return typ;
456 }
457 static inline bool psi_number_validate_char(struct psi_data *data, struct psi_number *exp)
458 {
459 impl_val val = {0};
460 unsigned lvl = 1;
461 token_t typ = validate_char(exp->data.numb, &val, &lvl);
462
463 if (!typ) {
464 return false;
465 }
466
467 free(exp->data.numb);
468 exp->type = typ;
469 exp->data.ival = val;
470 return true;
471 }
472
473 static inline bool psi_number_validate_number(struct psi_data *data, struct psi_number *exp)
474 {
475 impl_val tmp = {0};
476
477 if (exp->flags) {
478 switch (exp->flags & 0x0f) {
479 case PSI_NUMBER_INT:
480 switch (exp->flags & 0x0f00) {
481 case PSI_NUMBER_L:
482 default:
483 tmp.i64 = strtol(exp->data.numb, NULL, 0);
484 free(exp->data.numb);
485 exp->type = PSI_T_INT64;
486 exp->data.ival.i64 = tmp.i64;
487 break;
488 case PSI_NUMBER_LL:
489 tmp.i64 = strtoll(exp->data.numb, NULL, 0);
490 free(exp->data.numb);
491 exp->type = PSI_T_INT64;
492 exp->data.ival.i64 = tmp.i64;
493 break;
494 case PSI_NUMBER_U:
495 case PSI_NUMBER_UL:
496 tmp.u64 = strtoul(exp->data.numb, NULL, 0);
497 free(exp->data.numb);
498 exp->type = PSI_T_UINT64;
499 exp->data.ival.u64 = tmp.u64;
500 break;
501 case PSI_NUMBER_ULL:
502 tmp.u64 = strtoull(exp->data.numb, NULL, 0);
503 free(exp->data.numb);
504 exp->type = PSI_T_UINT64;
505 exp->data.ival.u64 = tmp.u64;
506 break;
507 }
508 return true;
509
510 case PSI_NUMBER_FLT:
511 switch (exp->flags & 0x0ff00) {
512 case PSI_NUMBER_F:
513 case PSI_NUMBER_DF:
514 tmp.fval = strtof(exp->data.numb, NULL);
515 free(exp->data.numb);
516 exp->type = PSI_T_FLOAT;
517 exp->data.ival.fval = tmp.fval;
518 break;
519 case PSI_NUMBER_L:
520 case PSI_NUMBER_DL:
521 #if HAVE_LONG_DOUBLE
522 tmp.ldval = strtold(exp->data.numb, NULL);
523 free(exp->data.numb);
524 exp->type = PSI_T_LONG_DOUBLE;
525 exp->data.ival.ldval = tmp.ldval;
526 break;
527 #endif
528 case PSI_NUMBER_DD:
529 default:
530 tmp.dval = strtod(exp->data.numb, NULL);
531 free(exp->data.numb);
532 exp->type = PSI_T_DOUBLE;
533 exp->data.ival.dval = tmp.dval;
534 break;
535 }
536 return true;
537 default:
538 assert(0);
539 break;
540 }
541 } else {
542 switch (is_numeric_string(exp->data.numb, strlen(exp->data.numb), (zend_long *) &tmp, (double *) &tmp, 1)) {
543 case IS_LONG:
544 free(exp->data.numb);
545 exp->type = PSI_T_INT64;
546 exp->data.ival.i64 = tmp.zend.lval;
547 return true;
548
549 case IS_DOUBLE:
550 free(exp->data.numb);
551 exp->type = PSI_T_DOUBLE;
552 exp->data.ival.dval = tmp.dval;
553 return true;
554 }
555 }
556 data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)");
557 return false;
558
559 }
560 bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
561 struct psi_validate_scope *scope)
562 {
563 size_t i = 0;
564 struct psi_const *cnst;
565 struct psi_decl_enum *enm;
566
567 switch (exp->type) {
568 case PSI_T_NULL:
569 exp->type = PSI_T_UINT8;
570 /* no break */
571 case PSI_T_CONST:
572 case PSI_T_INT8:
573 case PSI_T_UINT8:
574 case PSI_T_INT16:
575 case PSI_T_UINT16:
576 case PSI_T_INT32:
577 case PSI_T_UINT32:
578 case PSI_T_INT64:
579 case PSI_T_UINT64:
580 case PSI_T_FLOAT:
581 case PSI_T_DOUBLE:
582 #if HAVE_LONG_DOUBLE
583 case PSI_T_LONG_DOUBLE:
584 #endif
585 case PSI_T_ENUM:
586 return true;
587
588 case PSI_T_NAME:
589 if (scope && scope->defs && zend_hash_str_exists(scope->defs, exp->data.dvar->name, strlen(exp->data.dvar->name))) {
590 return true;
591 }
592 if (scope && scope->current_enum && psi_number_validate_enum(data, exp, scope)) {
593 return true;
594 }
595 while (psi_plist_get(data->enums, i++, &enm)) {
596 struct psi_validate_scope enum_scope = *scope;
597 enum_scope.current_enum = enm;
598 if (psi_number_validate_enum(data, exp, &enum_scope)) {
599 return true;
600 }
601 }
602 if (exp->data.dvar->arg) {
603 return true;
604 }
605 if (psi_decl_var_validate(data, exp->data.dvar, scope)) {
606 return true;
607 }
608 data->error(data, exp->token, PSI_WARNING,
609 "Unknown variable '%s' in numeric expression",
610 exp->data.dvar->name);
611 return false;
612
613 case PSI_T_FUNCTION:
614 if (scope && scope->defs && zend_hash_str_exists(scope->defs, exp->data.numb, strlen(exp->data.numb))) {
615 return true;
616 }
617 return false;
618
619 case PSI_T_DEFINE:
620 if (scope && scope->defs && zend_hash_str_exists(scope->defs, exp->data.numb, strlen(exp->data.numb))) {
621 if (!scope->macro || strcmp(scope->macro->token->text, exp->data.numb)) {
622 return true;
623 }
624 /* #define foo foo */
625 }
626 while (psi_plist_get(data->enums, i++, &enm)) {
627 struct psi_validate_scope enum_scope = *scope;
628 enum_scope.current_enum = enm;
629 if (psi_number_validate_enum(data, exp, &enum_scope)) {
630 return true;
631 }
632 }
633 return false;
634
635 case PSI_T_SIZEOF:
636 if (psi_decl_type_validate(data, exp->data.dtyp, NULL, scope)) {
637 struct psi_decl_type *dtyp = exp->data.dtyp;
638
639 exp->type = PSI_T_UINT64;
640 exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL);
641 psi_decl_type_free(&dtyp);
642 return true;
643 } else {
644 struct psi_decl_type *dtyp = exp->data.dtyp;
645
646 data->error(data, exp->token, PSI_WARNING,
647 "Cannot compute sizeof(%s) (%u)", dtyp->name, dtyp->type);
648
649 exp->type = PSI_T_UINT8;
650 exp->data.ival.u8 = 0;
651 psi_decl_type_free(&dtyp);
652 }
653 break;
654
655 case PSI_T_NSNAME:
656 {
657 zval *zc;
658
659 if (*exp->data.numb == '\\') {
660 zc = zend_get_constant_str(exp->data.numb + 1, strlen(exp->data.numb) - 1);
661 } else {
662 zc = zend_get_constant_str(exp->data.numb, strlen(exp->data.numb));
663 }
664
665 if (zc) {
666 switch (Z_TYPE_P(zc)) {
667 case IS_LONG:
668 free(exp->data.numb);
669 exp->type = PSI_T_INT64;
670 exp->data.ival.i64 = Z_LVAL_P(zc);
671 return true;
672
673 case IS_DOUBLE:
674 free(exp->data.numb);
675 exp->type = PSI_T_DOUBLE;
676 exp->data.ival.dval = Z_DVAL_P(zc);
677 return true;
678
679 default:
680 assert(0);
681 }
682 }
683 }
684 while (psi_plist_get(data->consts, i++, &cnst)) {
685 if (!strcmp(cnst->name, exp->data.numb)) {
686 free(exp->data.numb);
687 exp->type = PSI_T_CONST;
688 exp->data.cnst = cnst;
689 return true;
690 }
691 }
692 data->error(data, exp->token, PSI_WARNING,
693 "Unknown constant '%s' in numeric expression",
694 exp->data.numb);
695 return false;
696
697 case PSI_T_NUMBER:
698 return psi_number_validate_number(data, exp);
699
700 case PSI_T_QUOTED_CHAR:
701 return psi_number_validate_char(data, exp);
702
703 default:
704 assert(0);
705 }
706
707 return false;
708 }
709
710 static inline token_t psi_number_eval_constant(struct psi_number *exp,
711 impl_val *res, struct psi_call_frame *frame)
712 {
713 switch (exp->data.cnst->type->type) {
714 case PSI_T_INT:
715 res->i64 = zend_get_constant_str(exp->data.cnst->name,
716 strlen(exp->data.cnst->name))->value.lval;
717 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
718 return PSI_T_INT64;
719 case PSI_T_FLOAT:
720 res->dval = zend_get_constant_str(exp->data.cnst->name,
721 strlen(exp->data.cnst->name))->value.dval;
722 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
723 return PSI_T_DOUBLE;
724 default:
725 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type);
726 return 0;
727 }
728 }
729
730
731 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
732 impl_val *res, struct psi_call_frame *frame)
733 {
734 impl_val *ref;
735 struct psi_call_frame_symbol *sym;
736 struct psi_decl_type *real;
737 struct psi_decl_var *var;
738 size_t size;
739
740 var = exp->data.dvar;
741 real = psi_decl_type_get_real(var->arg->type);
742 size = psi_decl_arg_get_size(var->arg);
743 sym = psi_call_frame_fetch_symbol(frame, var);
744 ref = deref_impl_val(sym->ptr, var);
745
746 memcpy(res, ref, size);
747
748 if (var->arg->var->pointer_level > var->pointer_level) {
749 switch (SIZEOF_VOID_P) {
750 case 4:
751 return PSI_T_INT32;
752 case 8:
753 return PSI_T_INT64;
754 default:
755 assert(0);
756 }
757 }
758 return real->type;
759 }
760
761 static inline token_t psi_number_eval_define(struct psi_number *exp,
762 impl_val *res, HashTable *defs, struct psi_num_exp *rec_guard)
763 {
764 if (defs) {
765 struct psi_cpp_macro_decl *macro;
766
767 macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb));
768 if (macro && macro->exp && macro->exp != rec_guard) {
769 return psi_num_exp_exec(macro->exp, res, NULL, defs);
770 }
771 }
772 res->u8 = 0;
773 return PSI_T_UINT8;
774 }
775
776 token_t psi_number_eval(struct psi_number *exp, impl_val *res,
777 struct psi_call_frame *frame, HashTable *defs, struct psi_num_exp *rec_guard)
778 {
779 switch (exp->type) {
780 case PSI_T_INT8:
781 *res = exp->data.ival;
782 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
783 return PSI_T_INT8;
784 case PSI_T_UINT8:
785 *res = exp->data.ival;
786 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
787 return PSI_T_UINT8;
788 case PSI_T_INT16:
789 *res = exp->data.ival;
790 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
791 return PSI_T_INT16;
792 case PSI_T_UINT16:
793 *res = exp->data.ival;
794 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
795 return PSI_T_UINT16;
796 case PSI_T_INT32:
797 *res = exp->data.ival;
798 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
799 return PSI_T_INT32;
800 case PSI_T_UINT32:
801 *res = exp->data.ival;
802 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
803 return PSI_T_UINT32;
804 case PSI_T_INT64:
805 *res = exp->data.ival;
806 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
807 return PSI_T_INT64;
808 case PSI_T_UINT64:
809 *res = exp->data.ival;
810 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
811 return PSI_T_UINT64;
812
813 case PSI_T_FLOAT:
814 *res = exp->data.ival;
815 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
816 return exp->type;
817
818 case PSI_T_DOUBLE:
819 *res = exp->data.ival;
820 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
821 return exp->type;
822
823 #if HAVE_LONG_DOUBLE
824 case PSI_T_LONG_DOUBLE:
825 *res = exp->data.ival;
826 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
827 return exp->type;
828 #endif
829
830 case PSI_T_ENUM:
831 res->i64 = exp->data.enm->val;
832 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
833 return PSI_T_INT64;
834
835 case PSI_T_NUMBER:
836 res->i64 = atol(exp->data.numb);
837 return PSI_T_INT64;
838
839 case PSI_T_CONST:
840 return psi_number_eval_constant(exp, res, frame);
841
842 case PSI_T_NAME:
843 return psi_number_eval_decl_var(exp, res, frame);
844
845 case PSI_T_DEFINE:
846 return psi_number_eval_define(exp, res, defs, rec_guard);
847
848 case PSI_T_FUNCTION:
849 res->u8 = 0;
850 return PSI_T_UINT8;
851
852 default:
853 assert(0);
854 }
855 return 0;
856 }