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