parser: RETURN [<native call> AS] SET_FUNC
[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
30 #include "data.h"
31 #include "calc.h"
32 #include "call.h"
33 #include "parser.h"
34
35 struct psi_number *psi_number_init(token_t t, void *num, unsigned flags)
36 {
37 struct psi_number *exp = calloc(1, sizeof(*exp));
38
39 exp->flags = flags;
40 switch (exp->type = t) {
41 case PSI_T_INT8:
42 exp->data.ival.i8 = *(int8_t *) num;
43 break;
44 case PSI_T_UINT8:
45 exp->data.ival.u8 = *(uint8_t *) num;
46 break;
47 case PSI_T_INT16:
48 exp->data.ival.i16 = *(int16_t *) num;
49 break;
50 case PSI_T_UINT16:
51 exp->data.ival.u16 = *(uint16_t *) num;
52 break;
53 case PSI_T_INT32:
54 exp->data.ival.i32 = *(int32_t *) num;
55 break;
56 case PSI_T_UINT32:
57 exp->data.ival.u32 = *(uint32_t *) num;
58 break;
59 case PSI_T_INT64:
60 exp->data.ival.i64 = *(int64_t *) num;
61 break;
62 case PSI_T_UINT64:
63 exp->data.ival.u64 = *(uint64_t *) num;
64 break;
65 case PSI_T_FLOAT:
66 exp->data.ival.dval = *(float *) num;
67 exp->type = PSI_T_DOUBLE;
68 break;
69 case PSI_T_DOUBLE:
70 exp->data.ival.dval = *(double *) num;
71 break;
72 #if HAVE_LONG_DOUBLE
73 case PSI_T_LONG_DOUBLE:
74 exp->data.ival.ldval = *(long double *) num;
75 break;
76 #endif
77 case PSI_T_NULL:
78 break;
79 case PSI_T_QUOTED_CHAR:
80 case PSI_T_NUMBER:
81 case PSI_T_NSNAME:
82 case PSI_T_DEFINE:
83 exp->data.numb = strdup(num);
84 break;
85 case PSI_T_NAME:
86 exp->data.dvar = num;
87 break;
88 case PSI_T_FUNCTION:
89 exp->data.call = num;
90 break;
91 case PSI_T_SIZEOF:
92 exp->data.dtyp = num;
93 break;
94 default:
95 assert(0);
96 }
97
98 return exp;
99 }
100
101 struct psi_number *psi_number_copy(struct psi_number *exp)
102 {
103 struct psi_number *num = calloc(1, sizeof(*num));
104
105 *num = *exp;
106
107 if (num->token) {
108 num->token = psi_token_copy(num->token);
109 }
110 switch (num->type) {
111 case PSI_T_INT8:
112 case PSI_T_UINT8:
113 case PSI_T_INT16:
114 case PSI_T_UINT16:
115 case PSI_T_INT32:
116 case PSI_T_UINT32:
117 case PSI_T_INT64:
118 case PSI_T_UINT64:
119 case PSI_T_DOUBLE:
120 #if HAVE_LONG_DOUBLE
121 case PSI_T_LONG_DOUBLE:
122 #endif
123 case PSI_T_ENUM:
124 case PSI_T_CONST:
125 case PSI_T_NULL:
126 break;
127 case PSI_T_NUMBER:
128 case PSI_T_NSNAME:
129 case PSI_T_DEFINE:
130 case PSI_T_QUOTED_CHAR:
131 num->data.numb = strdup(num->data.numb);
132 break;
133 case PSI_T_NAME:
134 num->data.dvar = psi_decl_var_copy(num->data.dvar);
135 break;
136 case PSI_T_FUNCTION:
137 num->data.call = psi_cpp_macro_call_copy(num->data.call);
138 break;
139 case PSI_T_SIZEOF:
140 num->data.dtyp = psi_decl_type_copy(num->data.dtyp);
141 break;
142 default:
143 assert(0);
144 }
145 return num;
146 }
147
148 void psi_number_free(struct psi_number **exp_ptr)
149 {
150 if (*exp_ptr) {
151 struct psi_number *exp = *exp_ptr;
152
153 *exp_ptr = NULL;
154 if (exp->token) {
155 free(exp->token);
156 }
157 switch (exp->type) {
158 case PSI_T_INT8:
159 case PSI_T_UINT8:
160 case PSI_T_INT16:
161 case PSI_T_UINT16:
162 case PSI_T_INT32:
163 case PSI_T_UINT32:
164 case PSI_T_INT64:
165 case PSI_T_UINT64:
166 case PSI_T_DOUBLE:
167 #if HAVE_LONG_DOUBLE
168 case PSI_T_LONG_DOUBLE:
169 #endif
170 case PSI_T_ENUM:
171 case PSI_T_CONST:
172 case PSI_T_NULL:
173 break;
174 case PSI_T_FUNCTION:
175 psi_cpp_macro_call_free(&exp->data.call);
176 break;
177 case PSI_T_NSNAME:
178 case PSI_T_NUMBER:
179 case PSI_T_DEFINE:
180 case PSI_T_QUOTED_CHAR:
181 free(exp->data.numb);
182 break;
183 case PSI_T_NAME:
184 psi_decl_var_free(&exp->data.dvar);
185 break;
186 case PSI_T_SIZEOF:
187 psi_decl_type_free(&exp->data.dtyp);
188 break;
189 default:
190 assert(0);
191 }
192 free(exp);
193 }
194 }
195
196 void psi_number_dump(int fd, struct psi_number *exp)
197 {
198 switch (exp->type) {
199 case PSI_T_INT8:
200 dprintf(fd, "%" PRId8, exp->data.ival.i8);
201 break;
202 case PSI_T_UINT8:
203 dprintf(fd, "%" PRIu8, exp->data.ival.u8);
204 break;
205 case PSI_T_INT16:
206 dprintf(fd, "%" PRId16, exp->data.ival.i16);
207 break;
208 case PSI_T_UINT16:
209 dprintf(fd, "%" PRIu16, exp->data.ival.u16);
210 break;
211 case PSI_T_INT32:
212 dprintf(fd, "%" PRId32, exp->data.ival.i32);
213 break;
214 case PSI_T_UINT32:
215 dprintf(fd, "%" PRIu32, exp->data.ival.u32);
216 break;
217 case PSI_T_INT64:
218 dprintf(fd, "%" PRId64, exp->data.ival.i64);
219 break;
220 case PSI_T_UINT64:
221 dprintf(fd, "%" PRIu64, exp->data.ival.u64);
222 break;
223 case PSI_T_FLOAT:
224 dprintf(fd, "%" PRIfval, exp->data.ival.dval);
225 break;
226 case PSI_T_DOUBLE:
227 dprintf(fd, "%" PRIdval, exp->data.ival.dval);
228 break;
229 #if HAVE_LONG_DOUBLE
230 case PSI_T_LONG_DOUBLE:
231 dprintf(fd, "%" PRIldval, exp->data.ival.ldval);
232 break;
233 #endif
234 case PSI_T_NULL:
235 dprintf(fd, "NULL");
236 break;
237 case PSI_T_NUMBER:
238 case PSI_T_NSNAME:
239 case PSI_T_DEFINE:
240 case PSI_T_QUOTED_CHAR:
241 dprintf(fd, "%s", exp->data.numb);
242 break;
243 case PSI_T_FUNCTION:
244 psi_cpp_macro_call_dump(fd, exp->data.call);
245 break;
246 case PSI_T_CONST:
247 dprintf(fd, "%s", exp->data.cnst->name);
248 break;
249 case PSI_T_ENUM:
250 dprintf(fd, "%s", exp->data.enm->name);
251 break;
252 case PSI_T_NAME:
253 psi_decl_var_dump(fd, exp->data.dvar);
254 break;
255 case PSI_T_SIZEOF:
256 psi_decl_type_dump(fd, exp->data.dtyp, 0);
257 break;
258 default:
259 assert(0);
260 }
261 }
262
263 static inline bool psi_number_validate_enum(struct psi_data *data, struct psi_number *exp,
264 struct psi_decl_enum *enm)
265 {
266 size_t i = 0;
267 struct psi_decl_enum_item *itm;
268
269 while (psi_plist_get(enm->items, i++, &itm)) {
270 if (!strcmp(itm->name, exp->data.dvar->name)) {
271 psi_decl_var_free(&exp->data.dvar);
272 exp->type = PSI_T_ENUM;
273 exp->data.enm = itm;
274 return psi_number_validate(data, exp, NULL, NULL, NULL, NULL, enm);
275 }
276 }
277
278 return false;
279 }
280
281 static inline token_t validate_char(char *numb, impl_val *res, unsigned *lvl)
282 {
283 char *endptr;
284 token_t typ = PSI_T_INT8;
285
286 res->i8 = numb[0];
287 endptr = &numb[1];
288
289 switch(res->i8) {
290 case '\\':
291 res->i8 = numb[1];
292 endptr = &numb[2];
293
294 switch(res->i8) {
295 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
296 res->i8 = strtol(&numb[1], &endptr, 8);
297 break;
298
299 case 'x':
300 res->i8 = strtol(&numb[2], &endptr, 16);
301 break;
302
303 case 'a':
304 res->i8 = '\a';
305 break;
306 case 'b':
307 res->i8 = '\b';
308 break;
309 case 'f':
310 res->i8 = '\f';
311 break;
312 case 'n':
313 res->i8 = '\n';
314 break;
315 case 'r':
316 res->i8 = '\r';
317 break;
318 case 't':
319 res->i8 = '\t';
320 break;
321 case 'v':
322 res->i8 = '\v';
323 break;
324 default:
325 break;
326 }
327 break;
328 default:
329 break;
330 }
331
332 /* more to grok? */
333 if (*endptr) {
334 impl_val tmp_val = {0};
335 token_t tmp_typ = validate_char(endptr, &tmp_val, lvl);
336
337 if (!tmp_typ) {
338 return 0;
339 }
340
341 res->i32 = res->i8 << (8 * *lvl);
342 typ = psi_calc_add(PSI_T_INT32, res, tmp_typ, &tmp_val, res);
343 }
344
345 ++(*lvl);
346
347 return typ;
348 }
349 static inline bool psi_number_validate_char(struct psi_data *data, struct psi_number *exp)
350 {
351 impl_val val = {0};
352 unsigned lvl = 1;
353 token_t typ = validate_char(exp->data.numb, &val, &lvl);
354
355 if (!typ) {
356 return false;
357 }
358
359 free(exp->data.numb);
360 exp->type = typ;
361 exp->data.ival = val;
362 return true;
363 }
364
365 static inline bool psi_number_validate_number(struct psi_data *data, struct psi_number *exp)
366 {
367 impl_val tmp = {0};
368
369 if (exp->flags) {
370 switch (exp->flags & 0x0f) {
371 case PSI_NUMBER_INT:
372 switch (exp->flags & 0x0f00) {
373 case PSI_NUMBER_L:
374 default:
375 tmp.i64 = strtol(exp->data.numb, NULL, 0);
376 free(exp->data.numb);
377 exp->type = PSI_T_INT64;
378 exp->data.ival.i64 = tmp.i64;
379 break;
380 case PSI_NUMBER_LL:
381 tmp.i64 = strtoll(exp->data.numb, NULL, 0);
382 free(exp->data.numb);
383 exp->type = PSI_T_INT64;
384 exp->data.ival.i64 = tmp.i64;
385 break;
386 case PSI_NUMBER_U:
387 case PSI_NUMBER_UL:
388 tmp.u64 = strtoul(exp->data.numb, NULL, 0);
389 free(exp->data.numb);
390 exp->type = PSI_T_UINT64;
391 exp->data.ival.u64 = tmp.u64;
392 break;
393 case PSI_NUMBER_ULL:
394 tmp.u64 = strtoull(exp->data.numb, NULL, 0);
395 free(exp->data.numb);
396 exp->type = PSI_T_UINT64;
397 exp->data.ival.u64 = tmp.u64;
398 break;
399 }
400 return true;
401
402 case PSI_NUMBER_FLT:
403 switch (exp->flags & 0x0ff00) {
404 case PSI_NUMBER_F:
405 case PSI_NUMBER_DF:
406 tmp.fval = strtof(exp->data.numb, NULL);
407 free(exp->data.numb);
408 exp->type = PSI_T_FLOAT;
409 exp->data.ival.fval = tmp.fval;
410 break;
411 case PSI_NUMBER_L:
412 case PSI_NUMBER_DL:
413 #if HAVE_LONG_DOUBLE
414 tmp.ldval = strtold(exp->data.numb, NULL);
415 free(exp->data.numb);
416 exp->type = PSI_T_LONG_DOUBLE;
417 exp->data.ival.ldval = tmp.ldval;
418 break;
419 #endif
420 case PSI_NUMBER_DD:
421 default:
422 tmp.dval = strtod(exp->data.numb, NULL);
423 free(exp->data.numb);
424 exp->type = PSI_T_DOUBLE;
425 exp->data.ival.dval = tmp.dval;
426 break;
427 }
428 return true;
429 default:
430 assert(0);
431 break;
432 }
433 } else {
434 switch (is_numeric_string(exp->data.numb, strlen(exp->data.numb), (zend_long *) &tmp, (double *) &tmp, 1)) {
435 case IS_LONG:
436 free(exp->data.numb);
437 exp->type = PSI_T_INT64;
438 exp->data.ival.i64 = tmp.zend.lval;
439 return true;
440
441 case IS_DOUBLE:
442 free(exp->data.numb);
443 exp->type = PSI_T_DOUBLE;
444 exp->data.ival.dval = tmp.dval;
445 return true;
446 }
447 }
448 data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)");
449 return false;
450
451 }
452 bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
453 struct psi_impl *impl, struct psi_decl *cb_decl, struct psi_let_exp *current_let,
454 struct psi_set_exp *current_set, struct psi_decl_enum *current_enum)
455 {
456 size_t i = 0;
457 struct psi_const *cnst;
458 struct psi_decl_enum *enm;
459
460 switch (exp->type) {
461 case PSI_T_NULL:
462 exp->type = PSI_T_UINT8;
463 /* no break */
464 case PSI_T_CONST:
465 case PSI_T_INT8:
466 case PSI_T_UINT8:
467 case PSI_T_INT16:
468 case PSI_T_UINT16:
469 case PSI_T_INT32:
470 case PSI_T_UINT32:
471 case PSI_T_INT64:
472 case PSI_T_UINT64:
473 case PSI_T_DOUBLE:
474 #if HAVE_LONG_DOUBLE
475 case PSI_T_LONG_DOUBLE:
476 #endif
477 case PSI_T_ENUM:
478 case PSI_T_DEFINE:
479 case PSI_T_FUNCTION:
480 return true;
481
482 case PSI_T_NAME:
483 if (current_enum && psi_number_validate_enum(data, exp, current_enum)) {
484 return true;
485 }
486 while (psi_plist_get(data->enums, i++, &enm)) {
487 if (psi_number_validate_enum(data, exp, enm)) {
488 return true;
489 }
490 }
491 if (exp->data.dvar->arg) {
492 return true;
493 }
494 if (psi_decl_var_validate(data, exp->data.dvar, impl,
495 impl ? impl->decl : NULL, current_let, current_set)) {
496 return true;
497 }
498 if (cb_decl && psi_decl_var_validate(data, exp->data.dvar,
499 NULL, cb_decl, NULL, NULL)) {
500 return true;
501 }
502 data->error(data, exp->token, PSI_WARNING,
503 "Unknown variable '%s' in numeric expression",
504 exp->data.dvar->name);
505 return false;
506
507 case PSI_T_SIZEOF:
508 if (psi_decl_type_validate(data, exp->data.dtyp, 0, NULL)) {
509 struct psi_decl_type *dtyp = exp->data.dtyp;
510
511 exp->type = PSI_T_UINT64;
512 exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL);
513 return true;
514 }
515 break;
516
517 case PSI_T_NSNAME:
518 while (psi_plist_get(data->consts, i++, &cnst)) {
519 if (!strcmp(cnst->name, exp->data.numb)) {
520 free(exp->data.numb);
521 exp->type = PSI_T_CONST;
522 exp->data.cnst = cnst;
523 return true;
524 }
525 }
526 data->error(data, exp->token, PSI_WARNING,
527 "Unknown constant '%s' in numeric expression",
528 exp->data.numb);
529 return false;
530
531 case PSI_T_NUMBER:
532 return psi_number_validate_number(data, exp);
533
534 case PSI_T_QUOTED_CHAR:
535 return psi_number_validate_char(data, exp);
536
537 default:
538 assert(0);
539 }
540
541 return false;
542 }
543
544 #include "Zend/zend_constants.h"
545
546 static inline token_t psi_number_eval_constant(struct psi_number *exp,
547 impl_val *res, struct psi_call_frame *frame)
548 {
549 switch (exp->data.cnst->type->type) {
550 case PSI_T_INT:
551 res->i64 = zend_get_constant_str(exp->data.cnst->name,
552 strlen(exp->data.cnst->name))->value.lval;
553 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
554 return PSI_T_INT64;
555 case PSI_T_FLOAT:
556 res->dval = zend_get_constant_str(exp->data.cnst->name,
557 strlen(exp->data.cnst->name))->value.dval;
558 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
559 return PSI_T_DOUBLE;
560 default:
561 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%d)", exp->data.cnst->type->type);
562 return 0;
563 }
564 }
565
566
567 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
568 impl_val *res, struct psi_call_frame *frame)
569 {
570 impl_val *ref;
571 struct psi_call_frame_symbol *sym;
572 struct psi_decl_type *real;
573 struct psi_decl_var *var;
574 size_t size;
575
576 var = exp->data.dvar;
577 real = psi_decl_type_get_real(var->arg->type);
578 size = psi_decl_arg_get_size(var->arg);
579 sym = psi_call_frame_fetch_symbol(frame, var);
580 ref = deref_impl_val(sym->ptr, var);
581
582 memcpy(res, ref, size);
583
584 if (var->arg->var->pointer_level > var->pointer_level) {
585 switch (SIZEOF_VOID_P) {
586 case 4:
587 return PSI_T_INT32;
588 case 8:
589 return PSI_T_INT64;
590 default:
591 assert(0);
592 }
593 }
594 return real->type;
595 }
596
597 static inline token_t psi_number_eval_define(struct psi_number *exp,
598 impl_val *res, HashTable *defs)
599 {
600 struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb));
601
602 assert(!macro);
603
604 res->u8 = 0;
605 return PSI_T_UINT8;
606 }
607
608 token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame, HashTable *defs)
609 {
610 switch (exp->type) {
611 case PSI_T_INT8:
612 *res = exp->data.ival;
613 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
614 return PSI_T_INT8;
615 case PSI_T_UINT8:
616 *res = exp->data.ival;
617 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
618 return PSI_T_UINT8;
619 case PSI_T_INT16:
620 *res = exp->data.ival;
621 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
622 return PSI_T_INT16;
623 case PSI_T_UINT16:
624 *res = exp->data.ival;
625 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
626 return PSI_T_UINT16;
627 case PSI_T_INT32:
628 *res = exp->data.ival;
629 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
630 return PSI_T_INT32;
631 case PSI_T_UINT32:
632 *res = exp->data.ival;
633 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
634 return PSI_T_UINT32;
635 case PSI_T_INT64:
636 *res = exp->data.ival;
637 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
638 return PSI_T_INT64;
639 case PSI_T_UINT64:
640 *res = exp->data.ival;
641 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
642 return PSI_T_UINT64;
643
644 case PSI_T_DOUBLE:
645 *res = exp->data.ival;
646 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
647 return exp->type;
648
649 #if HAVE_LONG_DOUBLE
650 case PSI_T_LONG_DOUBLE:
651 *res = exp->data.ival;
652 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
653 return exp->type;
654 #endif
655
656 case PSI_T_ENUM:
657 res->i64 = exp->data.enm->val;
658 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
659 return PSI_T_INT64;
660
661 case PSI_T_NUMBER:
662 res->i64 = atol(exp->data.numb);
663 return PSI_T_INT64;
664
665 case PSI_T_CONST:
666 return psi_number_eval_constant(exp, res, frame);
667
668 case PSI_T_NAME:
669 return psi_number_eval_decl_var(exp, res, frame);
670
671 case PSI_T_DEFINE:
672 return psi_number_eval_define(exp, res, defs);
673
674 case PSI_T_FUNCTION:
675 res->u8 = 0;
676 return PSI_T_UINT8;
677
678 default:
679 assert(0);
680 }
681 return 0;
682 }