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