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