fix calling convention and arg types
[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_DUMP(dump, exp->data.ival, true);
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_QUOTED_CHAR:
306 case PSI_T_CPP_HEADER:
307 PSI_DUMP(dump, "%s", exp->data.numb->val);
308 break;
309 case PSI_T_DEFINE:
310 PSI_DUMP(dump, "%s /* DEFINE */", exp->data.numb->val);
311 break;
312 case PSI_T_FUNCTION:
313 psi_cpp_macro_call_dump(dump, exp->data.call);
314 break;
315 case PSI_T_CONST:
316 PSI_DUMP(dump, "%s", exp->data.cnst->name->val);
317 break;
318 case PSI_T_ENUM:
319 PSI_DUMP(dump, "%s /* ENUM */ ", exp->data.enm->name->val);
320 break;
321 case PSI_T_NAME:
322 psi_decl_var_dump(dump, exp->data.dvar);
323 break;
324 case PSI_T_SIZEOF:
325 PSI_DUMP(dump, "sizeof(");
326 psi_decl_type_dump(dump, exp->data.dtyp, 0);
327 PSI_DUMP(dump, ")");
328 break;
329 default:
330 assert(0);
331 }
332 #if 0
333 PSI_DUMP(dump, "\t/* number.type=%d */ ", exp->type);
334 #endif
335 }
336
337 static inline bool psi_number_validate_enum(struct psi_data *data,
338 struct psi_number *exp, struct psi_validate_scope *scope)
339 {
340 if (scope && scope->current_enum) {
341 size_t i = 0;
342 struct psi_decl_enum_item *itm;
343 struct psi_decl_enum *enm;
344
345 enm = scope->current_enum;
346
347 switch (exp->type) {
348 case PSI_T_NAME:
349 while (psi_plist_get(enm->items, i++, &itm)) {
350 if (zend_string_equals(itm->name, exp->data.dvar->name)) {
351 psi_decl_var_free(&exp->data.dvar);
352 exp->type = PSI_T_ENUM;
353 exp->data.enm = itm;
354 return psi_number_validate(data, exp, scope);
355 }
356 }
357 break;
358
359 case PSI_T_DEFINE:
360 while (psi_plist_get(enm->items, i++, &itm)) {
361 if (zend_string_equals(itm->name, exp->data.numb)) {
362 zend_string_release(exp->data.numb);
363 exp->type = PSI_T_ENUM;
364 exp->data.enm = itm;
365 return psi_number_validate(data, exp, scope);
366 }
367 }
368 break;
369
370 default:
371 assert(0);
372 }
373 }
374 return false;
375 }
376
377 static inline token_t validate_char(char *numb, impl_val *res, unsigned *lvl)
378 {
379 char *endptr;
380 token_t typ = PSI_T_INT8;
381
382 res->i8 = numb[0];
383 endptr = &numb[1];
384
385 switch(res->i8) {
386 case '\\':
387 res->i8 = numb[1];
388 endptr = &numb[2];
389
390 switch(res->i8) {
391 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
392 res->i8 = strtol(&numb[1], &endptr, 8);
393 break;
394
395 case 'x':
396 res->i8 = strtol(&numb[2], &endptr, 16);
397 break;
398
399 case 'a':
400 res->i8 = '\a';
401 break;
402 case 'b':
403 res->i8 = '\b';
404 break;
405 case 'f':
406 res->i8 = '\f';
407 break;
408 case 'n':
409 res->i8 = '\n';
410 break;
411 case 'r':
412 res->i8 = '\r';
413 break;
414 case 't':
415 res->i8 = '\t';
416 break;
417 case 'v':
418 res->i8 = '\v';
419 break;
420 default:
421 break;
422 }
423 break;
424 default:
425 break;
426 }
427
428 /* more to grok? */
429 if (*endptr) {
430 impl_val tmp_val = {0};
431 token_t tmp_typ = validate_char(endptr, &tmp_val, lvl);
432
433 if (!tmp_typ) {
434 return 0;
435 }
436
437 res->i32 = res->i8 << (8 * *lvl);
438 typ = psi_calc_add(PSI_T_INT32, res, tmp_typ, &tmp_val, res);
439 }
440
441 ++(*lvl);
442
443 return typ;
444 }
445 static inline bool psi_number_validate_char(struct psi_data *data, struct psi_number *exp)
446 {
447 impl_val val = {0};
448 unsigned lvl = 1;
449 token_t typ = validate_char(exp->data.numb->val, &val, &lvl);
450
451 if (!typ) {
452 return false;
453 }
454
455 zend_string_release(exp->data.numb);
456 exp->type = typ;
457 exp->data.ival = val;
458 return true;
459 }
460
461 static inline bool psi_number_validate_number(struct psi_data *data, struct psi_number *exp)
462 {
463 impl_val tmp = {0};
464
465 if (exp->flags) {
466 switch (exp->flags & 0x0f) {
467 case PSI_NUMBER_INT:
468 switch (exp->flags & 0x0f00) {
469 case PSI_NUMBER_L:
470 default:
471 tmp.i64 = strtol(exp->data.numb->val, NULL, 0);
472 zend_string_release(exp->data.numb);
473 exp->type = PSI_T_INT64;
474 exp->data.ival.i64 = tmp.i64;
475 break;
476 case PSI_NUMBER_LL:
477 tmp.i64 = strtoll(exp->data.numb->val, NULL, 0);
478 zend_string_release(exp->data.numb);
479 exp->type = PSI_T_INT64;
480 exp->data.ival.i64 = tmp.i64;
481 break;
482 case PSI_NUMBER_U:
483 case PSI_NUMBER_UL:
484 tmp.u64 = strtoul(exp->data.numb->val, NULL, 0);
485 zend_string_release(exp->data.numb);
486 exp->type = PSI_T_UINT64;
487 exp->data.ival.u64 = tmp.u64;
488 break;
489 case PSI_NUMBER_ULL:
490 tmp.u64 = strtoull(exp->data.numb->val, NULL, 0);
491 zend_string_release(exp->data.numb);
492 exp->type = PSI_T_UINT64;
493 exp->data.ival.u64 = tmp.u64;
494 break;
495 }
496 return true;
497
498 case PSI_NUMBER_FLT:
499 switch (exp->flags & 0x0ff00) {
500 case PSI_NUMBER_F:
501 tmp.fval = strtof(exp->data.numb->val, NULL);
502 zend_string_release(exp->data.numb);
503 exp->type = PSI_T_FLOAT;
504 exp->data.ival.fval = tmp.fval;
505 break;
506 case PSI_NUMBER_L:
507 case PSI_NUMBER_DL:
508 #if HAVE_LONG_DOUBLE
509 tmp.ldval = strtold(exp->data.numb->val, NULL);
510 zend_string_release(exp->data.numb);
511 exp->type = PSI_T_LONG_DOUBLE;
512 exp->data.ival.ldval = tmp.ldval;
513 break;
514 #endif
515 case PSI_NUMBER_DD:
516 default:
517 case PSI_NUMBER_DF:
518 tmp.dval = strtod(exp->data.numb->val, NULL);
519 zend_string_release(exp->data.numb);
520 exp->type = PSI_T_DOUBLE;
521 exp->data.ival.dval = tmp.dval;
522 break;
523 }
524 return true;
525 default:
526 assert(0);
527 break;
528 }
529 } else {
530 int type = is_numeric_string(exp->data.numb->val, exp->data.numb->len, (zend_long *) &tmp, (double *)&tmp, 0);
531 char *stop = NULL;
532 long lval;
533 unsigned long ulval;
534
535 switch (type) {
536 case IS_LONG:
537 zend_string_release(exp->data.numb);
538 exp->type = PSI_T_INT64;
539 exp->data.ival.i64 = tmp.zend.lval;
540 return true;
541
542 case IS_DOUBLE:
543 zend_string_release(exp->data.numb);
544 exp->type = PSI_T_DOUBLE;
545 exp->data.ival.dval = tmp.dval;
546 return true;
547
548 default:
549
550 errno = 0;
551
552 stop = exp->data.numb->val + exp->data.numb->len;
553 lval = strtol(exp->data.numb->val, &stop, 0);
554 switch (lval) {
555 case 0:
556 assert(stop == exp->data.numb->val + exp->data.numb->len);
557 /* no break */
558 case LONG_MIN:
559 assert(!errno);
560 /* no break */
561 case LONG_MAX:
562 if (errno == ERANGE) {
563 errno = 0;
564
565 stop = exp->data.numb->val + exp->data.numb->len;
566 ulval = strtoul(exp->data.numb->val, &stop, 0);
567 switch (ulval) {
568 case 0:
569 assert(stop == exp->data.numb->val + exp->data.numb->len);
570 case ULONG_MAX:
571 assert(!errno);
572 default:
573 zend_string_release(exp->data.numb);
574 exp->type = PSI_T_UINT64;
575 exp->data.ival.u64 = ulval;
576 return true;
577 }
578 }
579 /* no break */
580 default:
581 zend_string_release(exp->data.numb);
582 exp->type = PSI_T_INT64;
583 exp->data.ival.i64 = lval;
584 return true;
585 }
586
587 data->error(data, exp->token, PSI_WARNING, "Not a numeric string: '%s'", exp->data.numb->val);
588 }
589 }
590 data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)");
591 return false;
592
593 }
594 bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
595 struct psi_validate_scope *scope)
596 {
597 size_t i = 0;
598 struct psi_const *cnst;
599 struct psi_decl_enum *enm;
600
601 switch (exp->type) {
602 case PSI_T_NULL:
603 exp->type = PSI_T_UINT8;
604 /* no break */
605 case PSI_T_CONST:
606 case PSI_T_INT8:
607 case PSI_T_UINT8:
608 case PSI_T_INT16:
609 case PSI_T_UINT16:
610 case PSI_T_INT32:
611 case PSI_T_UINT32:
612 case PSI_T_INT64:
613 case PSI_T_UINT64:
614 #if HAVE_INT128
615 case PSI_T_INT128:
616 case PSI_T_UINT128:
617 #endif
618 case PSI_T_FLOAT:
619 case PSI_T_DOUBLE:
620 #if HAVE_LONG_DOUBLE
621 case PSI_T_LONG_DOUBLE:
622 #endif
623 case PSI_T_ENUM:
624 case PSI_T_DEFINED:
625 return true;
626
627 case PSI_T_NAME:
628 //if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.dvar->name)) {
629 // exp->type = PSI_T_DEFINE;
630 // goto define;
631 //}
632 if (scope && scope->current_enum && psi_number_validate_enum(data, exp, scope)) {
633 return true;
634 }
635 while (psi_plist_get(data->enums, i++, &enm)) {
636 struct psi_validate_scope enum_scope = *scope;
637 enum_scope.current_enum = enm;
638 if (psi_number_validate_enum(data, exp, &enum_scope)) {
639 return true;
640 }
641 }
642 if (exp->data.dvar->arg) {
643 return true;
644 }
645 if (psi_decl_var_validate(data, exp->data.dvar, scope)) {
646 return true;
647 }
648 data->error(data, exp->token, PSI_WARNING,
649 "Unknown variable '%s' in numeric expression",
650 exp->data.dvar->name->val);
651 return false;
652
653 case PSI_T_FUNCTION:
654 if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.call->name)) {
655 size_t i, argc;
656 struct psi_cpp_macro_call *call = exp->data.call;
657
658 for (i = 0, argc = psi_plist_count(call->args); i < argc; ++i) {
659 struct psi_num_exp *arg;
660
661 if (!psi_plist_get(call->args, i, &arg)) {
662 return false;
663 }
664 if (!psi_num_exp_validate(data, arg, scope)) {
665 return false;
666 }
667 }
668 return true;
669 }
670 if (psi_builtin_exists(exp->data.call->name)) {
671 exp->data.call->builtin = psi_builtin_get(exp->data.call->name);
672 return true;
673 }
674 return false;
675
676 case PSI_T_DEFINE:
677 if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.numb)) {
678 define: ;
679 if (!scope->macro || !zend_string_equals(scope->macro->token->text, exp->data.numb)) {
680 return true;
681 }
682 /* #define foo foo */
683 }
684 while (psi_plist_get(data->enums, i++, &enm)) {
685 struct psi_validate_scope enum_scope = *scope;
686 enum_scope.current_enum = enm;
687 if (psi_number_validate_enum(data, exp, &enum_scope)) {
688 return true;
689 }
690 }
691 return false;
692
693 case PSI_T_SIZEOF:
694 if (psi_decl_type_validate(data, exp->data.dtyp, NULL, scope)) {
695 struct psi_decl_type *dtyp = exp->data.dtyp;
696
697 exp->type = PSI_T_UINT64;
698 exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL);
699 psi_decl_type_free(&dtyp);
700 return true;
701 } else {
702 struct psi_decl_type *dtyp = exp->data.dtyp;
703
704 data->error(data, exp->token, PSI_WARNING,
705 "Cannot compute sizeof(%s) (%u)", dtyp->name->val, dtyp->type);
706
707 exp->type = PSI_T_UINT8;
708 exp->data.ival.u8 = 0;
709 psi_decl_type_free(&dtyp);
710 }
711 break;
712
713 case PSI_T_NSNAME:
714 {
715 zval *zc;
716
717 if (exp->data.numb->val[0] == '\\') {
718 zc = zend_get_constant_str(&exp->data.numb->val[1], exp->data.numb->len - 1);
719 } else {
720 zc = zend_get_constant(exp->data.numb);
721 }
722
723 if (zc) {
724 switch (Z_TYPE_P(zc)) {
725 case IS_LONG:
726 zend_string_release(exp->data.numb);
727 exp->type = PSI_T_INT64;
728 exp->data.ival.i64 = Z_LVAL_P(zc);
729 return true;
730
731 case IS_DOUBLE:
732 zend_string_release(exp->data.numb);
733 exp->type = PSI_T_DOUBLE;
734 exp->data.ival.dval = Z_DVAL_P(zc);
735 return true;
736
737 default:
738 assert(0);
739 }
740 }
741 }
742 while (psi_plist_get(data->consts, i++, &cnst)) {
743 if (zend_string_equals(cnst->name, exp->data.numb)) {
744 zend_string_release(exp->data.numb);
745 exp->type = PSI_T_CONST;
746 exp->data.cnst = cnst;
747 return true;
748 }
749 }
750 data->error(data, exp->token, PSI_WARNING,
751 "Unknown constant '%s' in numeric expression",
752 exp->data.numb->val);
753 return false;
754
755 case PSI_T_NUMBER:
756 return psi_number_validate_number(data, exp);
757
758 case PSI_T_QUOTED_CHAR:
759 return psi_number_validate_char(data, exp);
760
761 case PSI_T_CPP_HEADER:
762 return true;
763
764 default:
765 assert(0);
766 }
767
768 return false;
769 }
770
771 static inline token_t psi_number_eval_constant(struct psi_number *exp,
772 impl_val *res, struct psi_call_frame *frame)
773 {
774 token_t typ = exp->data.cnst->type ? exp->data.cnst->type->type : PSI_T_MIXED;
775
776 switch (typ) {
777 case PSI_T_INT:
778 res->i64 = zend_get_constant(exp->data.cnst->name)->value.lval;
779 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
780 return PSI_T_INT64;
781 case PSI_T_FLOAT:
782 res->dval = zend_get_constant(exp->data.cnst->name)->value.dval;
783 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
784 return PSI_T_DOUBLE;
785 default:
786 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type);
787 return 0;
788 }
789 }
790
791
792 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
793 impl_val *res, struct psi_call_frame *frame)
794 {
795 impl_val *ref;
796 struct psi_call_frame_symbol *sym;
797 struct psi_decl_type *real;
798 struct psi_decl_var *var;
799 size_t size;
800
801 var = exp->data.dvar;
802 real = psi_decl_type_get_real(var->arg->type);
803 size = psi_decl_arg_get_size(var->arg);
804 sym = psi_call_frame_fetch_symbol(frame, var);
805 ref = deref_impl_val(sym->ptr, var);
806
807 memcpy(res, ref, size);
808
809 if (var->arg->var->pointer_level > var->pointer_level) {
810 switch (SIZEOF_VOID_P) {
811 case 4:
812 return PSI_T_INT32;
813 case 8:
814 return PSI_T_INT64;
815 default:
816 assert(0);
817 }
818 }
819 return real->type;
820 }
821
822 static inline token_t psi_number_eval_define(struct psi_number *exp,
823 impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
824 {
825 if (cpp) {
826 struct psi_cpp_macro_decl *macro;
827
828 macro = zend_hash_find_ptr(&cpp->defs, exp->data.numb);
829 if (macro && macro->exp && macro->exp != rec_guard) {
830 return psi_num_exp_exec(macro->exp, res, NULL, cpp);
831 }
832 }
833
834 res->u8 = 0;
835 return PSI_T_UINT8;
836 }
837
838 static inline token_t psi_number_eval_function(struct psi_number *exp,
839 impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
840 {
841 if (cpp) {
842 PSI_DEBUG_PRINT(cpp->parser, "psi_number_eval(PSI_T_FUNCTION): %s\n", exp->token->text->val);
843 }
844 res->u8 = 0;
845 return PSI_T_UINT8;
846 }
847
848 token_t psi_number_eval(struct psi_number *exp, impl_val *res,
849 struct psi_call_frame *frame, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
850 {
851 switch (exp->type) {
852 case PSI_T_INT8:
853 *res = exp->data.ival;
854 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
855 return PSI_T_INT8;
856 case PSI_T_DEFINED:
857 case PSI_T_UINT8:
858 *res = exp->data.ival;
859 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
860 return PSI_T_UINT8;
861 case PSI_T_INT16:
862 *res = exp->data.ival;
863 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
864 return PSI_T_INT16;
865 case PSI_T_UINT16:
866 *res = exp->data.ival;
867 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
868 return PSI_T_UINT16;
869 case PSI_T_INT32:
870 *res = exp->data.ival;
871 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
872 return PSI_T_INT32;
873 case PSI_T_UINT32:
874 *res = exp->data.ival;
875 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
876 return PSI_T_UINT32;
877 case PSI_T_INT64:
878 *res = exp->data.ival;
879 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
880 return PSI_T_INT64;
881 case PSI_T_UINT64:
882 *res = exp->data.ival;
883 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
884 return PSI_T_UINT64;
885 #if HAVE_INT128
886 case PSI_T_INT128:
887 *res = exp->data.ival;
888 //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi128, res->i128);
889 return PSI_T_INT128;
890 case PSI_T_UINT128:
891 *res = exp->data.ival;
892 //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu128, res->u128);
893 return PSI_T_UINT128;
894 #endif
895 case PSI_T_FLOAT:
896 *res = exp->data.ival;
897 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
898 return exp->type;
899
900 case PSI_T_DOUBLE:
901 *res = exp->data.ival;
902 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
903 return exp->type;
904
905 #if HAVE_LONG_DOUBLE
906 case PSI_T_LONG_DOUBLE:
907 *res = exp->data.ival;
908 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
909 return exp->type;
910 #endif
911
912 case PSI_T_ENUM:
913 res->i64 = exp->data.enm->val;
914 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
915 return PSI_T_INT64;
916
917 case PSI_T_NUMBER:
918 res->i64 = atol(exp->data.numb->val);
919 return PSI_T_INT64;
920
921 case PSI_T_CONST:
922 return psi_number_eval_constant(exp, res, frame);
923
924 case PSI_T_NAME:
925 return psi_number_eval_decl_var(exp, res, frame);
926
927 case PSI_T_DEFINE:
928 return psi_number_eval_define(exp, res, cpp, rec_guard);
929
930 case PSI_T_FUNCTION:
931 return psi_number_eval_function(exp, res, cpp, rec_guard);
932
933 case PSI_T_CPP_HEADER:
934 res->u8 = 0;
935 return PSI_T_UINT8;
936
937 default:
938 assert(0);
939 }
940 return 0;
941 }