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