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