parser: consolidate tokens
[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 } else {
515 data->error(data, exp->token, PSI_WARNING,
516 "Cannot compute sizeof(%s) (%u)",
517 exp->data.dtyp->name, exp->data.dtyp->type);
518 }
519 break;
520
521 case PSI_T_NSNAME:
522 while (psi_plist_get(data->consts, i++, &cnst)) {
523 if (!strcmp(cnst->name, exp->data.numb)) {
524 free(exp->data.numb);
525 exp->type = PSI_T_CONST;
526 exp->data.cnst = cnst;
527 return true;
528 }
529 }
530 data->error(data, exp->token, PSI_WARNING,
531 "Unknown constant '%s' in numeric expression",
532 exp->data.numb);
533 return false;
534
535 case PSI_T_NUMBER:
536 return psi_number_validate_number(data, exp);
537
538 case PSI_T_QUOTED_CHAR:
539 return psi_number_validate_char(data, exp);
540
541 default:
542 assert(0);
543 }
544
545 return false;
546 }
547
548 #include "Zend/zend_constants.h"
549
550 static inline token_t psi_number_eval_constant(struct psi_number *exp,
551 impl_val *res, struct psi_call_frame *frame)
552 {
553 switch (exp->data.cnst->type->type) {
554 case PSI_T_INT:
555 res->i64 = zend_get_constant_str(exp->data.cnst->name,
556 strlen(exp->data.cnst->name))->value.lval;
557 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
558 return PSI_T_INT64;
559 case PSI_T_FLOAT:
560 res->dval = zend_get_constant_str(exp->data.cnst->name,
561 strlen(exp->data.cnst->name))->value.dval;
562 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
563 return PSI_T_DOUBLE;
564 default:
565 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type);
566 return 0;
567 }
568 }
569
570
571 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
572 impl_val *res, struct psi_call_frame *frame)
573 {
574 impl_val *ref;
575 struct psi_call_frame_symbol *sym;
576 struct psi_decl_type *real;
577 struct psi_decl_var *var;
578 size_t size;
579
580 var = exp->data.dvar;
581 real = psi_decl_type_get_real(var->arg->type);
582 size = psi_decl_arg_get_size(var->arg);
583 sym = psi_call_frame_fetch_symbol(frame, var);
584 ref = deref_impl_val(sym->ptr, var);
585
586 memcpy(res, ref, size);
587
588 if (var->arg->var->pointer_level > var->pointer_level) {
589 switch (SIZEOF_VOID_P) {
590 case 4:
591 return PSI_T_INT32;
592 case 8:
593 return PSI_T_INT64;
594 default:
595 assert(0);
596 }
597 }
598 return real->type;
599 }
600
601 static inline token_t psi_number_eval_define(struct psi_number *exp,
602 impl_val *res, HashTable *defs)
603 {
604 struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb));
605
606 assert(!macro);
607
608 res->u8 = 0;
609 return PSI_T_UINT8;
610 }
611
612 token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame, HashTable *defs)
613 {
614 switch (exp->type) {
615 case PSI_T_INT8:
616 *res = exp->data.ival;
617 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
618 return PSI_T_INT8;
619 case PSI_T_UINT8:
620 *res = exp->data.ival;
621 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
622 return PSI_T_UINT8;
623 case PSI_T_INT16:
624 *res = exp->data.ival;
625 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
626 return PSI_T_INT16;
627 case PSI_T_UINT16:
628 *res = exp->data.ival;
629 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
630 return PSI_T_UINT16;
631 case PSI_T_INT32:
632 *res = exp->data.ival;
633 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
634 return PSI_T_INT32;
635 case PSI_T_UINT32:
636 *res = exp->data.ival;
637 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
638 return PSI_T_UINT32;
639 case PSI_T_INT64:
640 *res = exp->data.ival;
641 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
642 return PSI_T_INT64;
643 case PSI_T_UINT64:
644 *res = exp->data.ival;
645 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
646 return PSI_T_UINT64;
647
648 case PSI_T_DOUBLE:
649 *res = exp->data.ival;
650 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
651 return exp->type;
652
653 #if HAVE_LONG_DOUBLE
654 case PSI_T_LONG_DOUBLE:
655 *res = exp->data.ival;
656 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
657 return exp->type;
658 #endif
659
660 case PSI_T_ENUM:
661 res->i64 = exp->data.enm->val;
662 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
663 return PSI_T_INT64;
664
665 case PSI_T_NUMBER:
666 res->i64 = atol(exp->data.numb);
667 return PSI_T_INT64;
668
669 case PSI_T_CONST:
670 return psi_number_eval_constant(exp, res, frame);
671
672 case PSI_T_NAME:
673 return psi_number_eval_decl_var(exp, res, frame);
674
675 case PSI_T_DEFINE:
676 return psi_number_eval_define(exp, res, defs);
677
678 case PSI_T_FUNCTION:
679 res->u8 = 0;
680 return PSI_T_UINT8;
681
682 default:
683 assert(0);
684 }
685 return 0;
686 }