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