PHP 8 compatibility
[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 struct psi_decl_extvar *evar;
606
607 switch (exp->type) {
608 case PSI_T_NULL:
609 exp->type = PSI_T_UINT8;
610 /* no break */
611 case PSI_T_CONST:
612 case PSI_T_INT8:
613 case PSI_T_UINT8:
614 case PSI_T_INT16:
615 case PSI_T_UINT16:
616 case PSI_T_INT32:
617 case PSI_T_UINT32:
618 case PSI_T_INT64:
619 case PSI_T_UINT64:
620 #if HAVE_INT128
621 case PSI_T_INT128:
622 case PSI_T_UINT128:
623 #endif
624 case PSI_T_FLOAT:
625 case PSI_T_DOUBLE:
626 #if HAVE_LONG_DOUBLE
627 case PSI_T_LONG_DOUBLE:
628 #endif
629 case PSI_T_ENUM:
630 case PSI_T_DEFINED:
631 return true;
632
633 case PSI_T_NAME:
634 //if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.dvar->name)) {
635 // exp->type = PSI_T_DEFINE;
636 // goto define;
637 //}
638 if (scope && scope->current_enum && psi_number_validate_enum(data, exp, scope)) {
639 return true;
640 }
641 while (psi_plist_get(data->enums, i++, &enm)) {
642 struct psi_validate_scope enum_scope = *scope;
643 enum_scope.current_enum = enm;
644 if (psi_number_validate_enum(data, exp, &enum_scope)) {
645 return true;
646 }
647 }
648 if (exp->data.dvar->arg) {
649 return true;
650 }
651 for (i = 0; psi_plist_get(data->vars, i, &evar); ++i) {
652 if (zend_string_equals(exp->data.dvar->name, evar->arg->var->name)) {
653 exp->data.dvar->arg = evar->arg;
654 return true;
655 }
656 }
657 if (psi_decl_var_validate(data, exp->data.dvar, scope)) {
658 return true;
659 } else {
660 data->error(data, exp->token, PSI_WARNING,
661 "Unknown variable '%s' in numeric expression",
662 exp->data.dvar->name->val);
663 return false;
664 }
665 break;
666
667 case PSI_T_FUNCTION:
668 if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.call->name)) {
669 size_t i, argc;
670 struct psi_cpp_macro_call *call = exp->data.call;
671
672 for (i = 0, argc = psi_plist_count(call->args); i < argc; ++i) {
673 struct psi_num_exp *arg;
674
675 if (!psi_plist_get(call->args, i, &arg)) {
676 return false;
677 }
678 if (!psi_num_exp_validate(data, arg, scope)) {
679 return false;
680 }
681 }
682 return true;
683 }
684 if (psi_builtin_exists(exp->data.call->name)) {
685 exp->data.call->builtin = psi_builtin_get(exp->data.call->name);
686 return true;
687 }
688 return false;
689
690 case PSI_T_DEFINE:
691 if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.numb)) {
692 if (!scope->macro || !zend_string_equals(scope->macro->token->text, exp->data.numb)) {
693 return true;
694 }
695 /* #define foo foo */
696 }
697 while (psi_plist_get(data->enums, i++, &enm)) {
698 struct psi_validate_scope enum_scope = *scope;
699 enum_scope.current_enum = enm;
700 if (psi_number_validate_enum(data, exp, &enum_scope)) {
701 return true;
702 }
703 }
704 /* undefined */
705 return false;
706
707 case PSI_T_SIZEOF:
708 if (psi_decl_type_validate(data, exp->data.dtyp, NULL, scope)) {
709 struct psi_decl_type *dtyp = exp->data.dtyp;
710
711 exp->type = PSI_T_UINT64;
712 exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL);
713 psi_decl_type_free(&dtyp);
714 return true;
715 } else {
716 struct psi_decl_type *dtyp = exp->data.dtyp;
717
718 data->error(data, exp->token, PSI_WARNING,
719 "Cannot compute sizeof(%s) (%u)", dtyp->name->val, dtyp->type);
720
721 exp->type = PSI_T_UINT8;
722 exp->data.ival.u8 = 0;
723 psi_decl_type_free(&dtyp);
724 }
725 break;
726
727 case PSI_T_NSNAME:
728 {
729 zval *zc;
730
731 if (exp->data.numb->val[0] == '\\') {
732 zc = zend_get_constant_str(&exp->data.numb->val[1], exp->data.numb->len - 1);
733 } else {
734 zc = zend_get_constant(exp->data.numb);
735 }
736
737 if (zc) {
738 switch (Z_TYPE_P(zc)) {
739 case IS_LONG:
740 zend_string_release(exp->data.numb);
741 exp->type = PSI_T_INT64;
742 exp->data.ival.i64 = Z_LVAL_P(zc);
743 return true;
744
745 case IS_DOUBLE:
746 zend_string_release(exp->data.numb);
747 exp->type = PSI_T_DOUBLE;
748 exp->data.ival.dval = Z_DVAL_P(zc);
749 return true;
750
751 default:
752 assert(0);
753 }
754 }
755 }
756 while (psi_plist_get(data->consts, i++, &cnst)) {
757 if (zend_string_equals(cnst->name, exp->data.numb)) {
758 zend_string_release(exp->data.numb);
759 exp->type = PSI_T_CONST;
760 exp->data.cnst = cnst;
761 return true;
762 }
763 }
764 data->error(data, exp->token, PSI_WARNING,
765 "Unknown constant '%s' in numeric expression",
766 exp->data.numb->val);
767 return false;
768
769 case PSI_T_NUMBER:
770 return psi_number_validate_number(data, exp);
771
772 case PSI_T_QUOTED_CHAR:
773 return psi_number_validate_char(data, exp);
774
775 case PSI_T_CPP_HEADER:
776 return true;
777
778 default:
779 assert(0);
780 }
781
782 return false;
783 }
784
785 static inline token_t psi_number_eval_constant(struct psi_number *exp,
786 impl_val *res, struct psi_call_frame *frame)
787 {
788 token_t typ = exp->data.cnst->type ? exp->data.cnst->type->type : PSI_T_MIXED;
789
790 switch (typ) {
791 case PSI_T_INT:
792 res->i64 = zend_get_constant(exp->data.cnst->name)->value.lval;
793 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
794 return PSI_T_INT64;
795 case PSI_T_FLOAT:
796 res->dval = zend_get_constant(exp->data.cnst->name)->value.dval;
797 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
798 return PSI_T_DOUBLE;
799 default:
800 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type);
801 return 0;
802 }
803 }
804
805
806 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
807 impl_val *res, struct psi_call_frame *frame)
808 {
809 impl_val *ref;
810 struct psi_call_frame_symbol *sym;
811 struct psi_decl_type *real;
812 struct psi_decl_var *var;
813 size_t size;
814
815 var = exp->data.dvar;
816 real = psi_decl_type_get_real(var->arg->type);
817 size = psi_decl_arg_get_size(var->arg);
818
819 if (frame) {
820 sym = psi_call_frame_fetch_symbol(frame, var);
821 ref = deref_impl_val(sym->ptr, var);
822
823 memcpy(res, ref, size);
824 }
825
826 if (var->arg->var->pointer_level > var->pointer_level) {
827 switch (SIZEOF_VOID_P) {
828 case 4:
829 return PSI_T_INT32;
830 case 8:
831 return PSI_T_INT64;
832 default:
833 assert(0);
834 }
835 }
836 return real->type;
837 }
838
839 static inline token_t psi_number_eval_define(struct psi_number *exp,
840 impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
841 {
842 if (cpp) {
843 struct psi_cpp_macro_decl *macro;
844
845 macro = zend_hash_find_ptr(&cpp->defs, exp->data.numb);
846 if (macro && macro->exp && macro->exp != rec_guard) {
847 return psi_num_exp_exec(macro->exp, res, NULL, cpp);
848 }
849 }
850
851 res->u8 = 0;
852 return PSI_T_UINT8;
853 }
854
855 static inline token_t psi_number_eval_function(struct psi_number *exp,
856 impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
857 {
858 if (cpp) {
859 PSI_DEBUG_PRINT(cpp->parser, "psi_number_eval(PSI_T_FUNCTION): %s\n", exp->token->text->val);
860 }
861 res->u8 = 0;
862 return PSI_T_UINT8;
863 }
864
865 token_t psi_number_eval(struct psi_number *exp, impl_val *res,
866 struct psi_call_frame *frame, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
867 {
868 switch (exp->type) {
869 case PSI_T_INT8:
870 *res = exp->data.ival;
871 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
872 return PSI_T_INT8;
873 case PSI_T_DEFINED:
874 case PSI_T_UINT8:
875 *res = exp->data.ival;
876 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
877 return PSI_T_UINT8;
878 case PSI_T_INT16:
879 *res = exp->data.ival;
880 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
881 return PSI_T_INT16;
882 case PSI_T_UINT16:
883 *res = exp->data.ival;
884 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
885 return PSI_T_UINT16;
886 case PSI_T_INT32:
887 *res = exp->data.ival;
888 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
889 return PSI_T_INT32;
890 case PSI_T_UINT32:
891 *res = exp->data.ival;
892 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
893 return PSI_T_UINT32;
894 case PSI_T_INT64:
895 *res = exp->data.ival;
896 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
897 return PSI_T_INT64;
898 case PSI_T_UINT64:
899 *res = exp->data.ival;
900 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
901 return PSI_T_UINT64;
902 #if HAVE_INT128
903 case PSI_T_INT128:
904 *res = exp->data.ival;
905 //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi128, res->i128);
906 return PSI_T_INT128;
907 case PSI_T_UINT128:
908 *res = exp->data.ival;
909 //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu128, res->u128);
910 return PSI_T_UINT128;
911 #endif
912 case PSI_T_FLOAT:
913 *res = exp->data.ival;
914 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
915 return exp->type;
916
917 case PSI_T_DOUBLE:
918 *res = exp->data.ival;
919 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
920 return exp->type;
921
922 #if HAVE_LONG_DOUBLE
923 case PSI_T_LONG_DOUBLE:
924 *res = exp->data.ival;
925 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
926 return exp->type;
927 #endif
928
929 case PSI_T_ENUM:
930 res->i64 = exp->data.enm->val;
931 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
932 return PSI_T_INT64;
933
934 case PSI_T_NUMBER:
935 res->i64 = atol(exp->data.numb->val);
936 return PSI_T_INT64;
937
938 case PSI_T_CONST:
939 return psi_number_eval_constant(exp, res, frame);
940
941 case PSI_T_NAME:
942 return psi_number_eval_decl_var(exp, res, frame);
943
944 case PSI_T_DEFINE:
945 return psi_number_eval_define(exp, res, cpp, rec_guard);
946
947 case PSI_T_FUNCTION:
948 return psi_number_eval_function(exp, res, cpp, rec_guard);
949
950 case PSI_T_CPP_HEADER:
951 res->u8 = 0;
952 return PSI_T_UINT8;
953
954 default:
955 assert(0);
956 }
957 return 0;
958 }