bison
[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)
36 {
37 struct psi_number *exp = calloc(1, sizeof(*exp));
38
39 switch (exp->type = t) {
40 case PSI_T_INT8:
41 exp->data.ival.i8 = *(int8_t *) num;
42 break;
43 case PSI_T_UINT8:
44 exp->data.ival.u8 = *(uint8_t *) num;
45 break;
46 case PSI_T_INT16:
47 exp->data.ival.i16 = *(int16_t *) num;
48 break;
49 case PSI_T_UINT16:
50 exp->data.ival.u16 = *(uint16_t *) num;
51 break;
52 case PSI_T_INT32:
53 exp->data.ival.i32 = *(int32_t *) num;
54 break;
55 case PSI_T_UINT32:
56 exp->data.ival.u32 = *(uint32_t *) num;
57 break;
58 case PSI_T_INT64:
59 exp->data.ival.i64 = *(int64_t *) num;
60 break;
61 case PSI_T_UINT64:
62 exp->data.ival.u64 = *(uint64_t *) num;
63 break;
64 case PSI_T_FLOAT:
65 exp->data.ival.dval = *(float *) num;
66 exp->type = PSI_T_DOUBLE;
67 break;
68 case PSI_T_DOUBLE:
69 exp->data.ival.dval = *(double *) num;
70 break;
71 case PSI_T_QUOTED_CHAR:
72 case PSI_T_NUMBER:
73 case PSI_T_NSNAME:
74 case PSI_T_DEFINE:
75 exp->data.numb = strdup(num);
76 break;
77 case PSI_T_NAME:
78 exp->data.dvar = num;
79 break;
80 case PSI_T_FUNCTION:
81 exp->data.call = num;
82 break;
83 default:
84 assert(0);
85 }
86
87 return exp;
88 }
89
90 struct psi_number *psi_number_copy(struct psi_number *exp)
91 {
92 struct psi_number *num = calloc(1, sizeof(*num));
93
94 *num = *exp;
95
96 if (num->token) {
97 num->token = psi_token_copy(num->token);
98 }
99 switch (num->type) {
100 case PSI_T_INT8:
101 case PSI_T_UINT8:
102 case PSI_T_INT16:
103 case PSI_T_UINT16:
104 case PSI_T_INT32:
105 case PSI_T_UINT32:
106 case PSI_T_INT64:
107 case PSI_T_UINT64:
108 case PSI_T_DOUBLE:
109 case PSI_T_ENUM:
110 case PSI_T_CONST:
111 break;
112 case PSI_T_NUMBER:
113 case PSI_T_NSNAME:
114 case PSI_T_DEFINE:
115 case PSI_T_QUOTED_CHAR:
116 num->data.numb = strdup(num->data.numb);
117 break;
118 case PSI_T_NAME:
119 num->data.dvar = psi_decl_var_copy(num->data.dvar);
120 break;
121 case PSI_T_FUNCTION:
122 num->data.call = psi_cpp_macro_call_copy(num->data.call);
123 break;
124 default:
125 assert(0);
126 }
127 return num;
128 }
129
130 void psi_number_free(struct psi_number **exp_ptr)
131 {
132 if (*exp_ptr) {
133 struct psi_number *exp = *exp_ptr;
134
135 *exp_ptr = NULL;
136 if (exp->token) {
137 free(exp->token);
138 }
139 switch (exp->type) {
140 case PSI_T_INT8:
141 case PSI_T_UINT8:
142 case PSI_T_INT16:
143 case PSI_T_UINT16:
144 case PSI_T_INT32:
145 case PSI_T_UINT32:
146 case PSI_T_INT64:
147 case PSI_T_UINT64:
148 case PSI_T_DOUBLE:
149 case PSI_T_ENUM:
150 case PSI_T_CONST:
151 break;
152 case PSI_T_FUNCTION:
153 psi_cpp_macro_call_free(&exp->data.call);
154 break;
155 case PSI_T_NSNAME:
156 case PSI_T_NUMBER:
157 case PSI_T_DEFINE:
158 case PSI_T_QUOTED_CHAR:
159 free(exp->data.numb);
160 break;
161 case PSI_T_NAME:
162 psi_decl_var_free(&exp->data.dvar);
163 break;
164 default:
165 assert(0);
166 }
167 free(exp);
168 }
169 }
170
171 void psi_number_dump(int fd, struct psi_number *exp)
172 {
173 switch (exp->type) {
174 case PSI_T_INT8:
175 dprintf(fd, "%" PRId8, exp->data.ival.i8);
176 break;
177 case PSI_T_UINT8:
178 dprintf(fd, "%" PRIu8, exp->data.ival.u8);
179 break;
180 case PSI_T_INT16:
181 dprintf(fd, "%" PRId16, exp->data.ival.i16);
182 break;
183 case PSI_T_UINT16:
184 dprintf(fd, "%" PRIu16, exp->data.ival.u16);
185 break;
186 case PSI_T_INT32:
187 dprintf(fd, "%" PRId32, exp->data.ival.i32);
188 break;
189 case PSI_T_UINT32:
190 dprintf(fd, "%" PRIu32, exp->data.ival.u32);
191 break;
192 case PSI_T_INT64:
193 dprintf(fd, "%" PRId64, exp->data.ival.i64);
194 break;
195 case PSI_T_UINT64:
196 dprintf(fd, "%" PRIu64, exp->data.ival.u64);
197 break;
198 case PSI_T_DOUBLE:
199 dprintf(fd, "%F", exp->data.ival.dval);
200 break;
201 case PSI_T_NUMBER:
202 case PSI_T_NSNAME:
203 case PSI_T_DEFINE:
204 case PSI_T_QUOTED_CHAR:
205 dprintf(fd, "%s", exp->data.numb);
206 break;
207 case PSI_T_CONST:
208 dprintf(fd, "%s", exp->data.cnst->name);
209 break;
210 case PSI_T_ENUM:
211 dprintf(fd, "%s", exp->data.enm->name);
212 break;
213 case PSI_T_NAME:
214 psi_decl_var_dump(fd, exp->data.dvar);
215 break;
216 default:
217 assert(0);
218 }
219 }
220
221 static inline bool psi_number_validate_enum(struct psi_data *data, struct psi_number *exp,
222 struct psi_decl_enum *enm)
223 {
224 size_t i = 0;
225 struct psi_decl_enum_item *itm;
226
227 while (psi_plist_get(enm->items, i++, &itm)) {
228 if (!strcmp(itm->name, exp->data.dvar->name)) {
229 psi_decl_var_free(&exp->data.dvar);
230 exp->type = PSI_T_ENUM;
231 exp->data.enm = itm;
232 return psi_number_validate(data, exp, NULL, NULL, NULL, NULL, enm);
233 }
234 }
235
236 return false;
237 }
238
239 bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
240 struct psi_impl *impl, struct psi_decl *cb_decl, struct psi_let_exp *current_let,
241 struct psi_set_exp *current_set, struct psi_decl_enum *current_enum)
242 {
243 size_t i = 0;
244 impl_val tmp = {0};
245 struct psi_const *cnst;
246 struct psi_decl_enum *enm;
247
248 switch (exp->type) {
249 case PSI_T_CONST:
250 case PSI_T_INT8:
251 case PSI_T_UINT8:
252 case PSI_T_INT16:
253 case PSI_T_UINT16:
254 case PSI_T_INT32:
255 case PSI_T_UINT32:
256 case PSI_T_INT64:
257 case PSI_T_UINT64:
258 case PSI_T_DOUBLE:
259 case PSI_T_ENUM:
260 case PSI_T_DEFINE:
261 case PSI_T_FUNCTION:
262 return true;
263
264 case PSI_T_NAME:
265 if (current_enum && psi_number_validate_enum(data, exp, current_enum)) {
266 return true;
267 }
268 while (psi_plist_get(data->enums, i++, &enm)) {
269 if (psi_number_validate_enum(data, exp, enm)) {
270 return true;
271 }
272 }
273 if (exp->data.dvar->arg) {
274 return true;
275 }
276 if (psi_decl_var_validate(data, exp->data.dvar, impl ? impl->decl : NULL,
277 current_let, current_set)) {
278 return true;
279 }
280 if (cb_decl && psi_decl_var_validate(data, exp->data.dvar, cb_decl, NULL, NULL)) {
281 return true;
282 }
283 data->error(data, exp->token, PSI_WARNING,
284 "Unknown variable '%s' in numeric expression",
285 exp->data.dvar->name);
286 return false;
287
288 case PSI_T_NSNAME:
289 while (psi_plist_get(data->consts, i++, &cnst)) {
290 if (!strcmp(cnst->name, exp->data.numb)) {
291 free(exp->data.numb);
292 exp->type = PSI_T_CONST;
293 exp->data.cnst = cnst;
294 return true;
295 }
296 }
297 data->error(data, exp->token, PSI_WARNING,
298 "Unknown constant '%s' in numeric expression",
299 exp->data.numb);
300 return false;
301
302 case PSI_T_NUMBER:
303 switch (is_numeric_string(exp->data.numb, strlen(exp->data.numb), (zend_long *) &tmp, (double *) &tmp, 1)) {
304 case IS_LONG:
305 free(exp->data.numb);
306 exp->type = PSI_T_INT64;
307 exp->data.ival.i64 = tmp.zend.lval;
308 return true;
309
310 case IS_DOUBLE:
311 free(exp->data.numb);
312 exp->type = PSI_T_DOUBLE;
313 exp->data.ival.dval = tmp.dval;
314 return true;
315 }
316 data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)");
317 return false;
318
319 case PSI_T_QUOTED_CHAR:
320 /* FIXME L */
321 tmp.i8 = exp->data.numb[1 + (*exp->data.numb == 'L')];
322 switch(tmp.i8) {
323 case '\\':
324 tmp.i8 = exp->data.numb[2 + (*exp->data.numb == 'L')];
325 switch(tmp.i8) {
326 case 'x':
327 tmp.i8 = strtol(&exp->data.numb[3 + (*exp->data.numb == 'L')], &exp->data.numb[strlen(exp->data.numb)-1], 16);
328 free(exp->data.numb);
329 exp->type = PSI_T_INT8;
330 exp->data.ival.i8 = tmp.i8;
331 return true;
332 case '\'':
333 free(exp->data.numb);
334 exp->type = PSI_T_INT8;
335 exp->data.ival.i8 = '\'';
336 return true;
337 case 'a':
338 free(exp->data.numb);
339 exp->type = PSI_T_INT8;
340 exp->data.ival.i8 = '\a';
341 return true;
342 case 'b':
343 free(exp->data.numb);
344 exp->type = PSI_T_INT8;
345 exp->data.ival.i8 = '\b';
346 return true;
347 case 'f':
348 free(exp->data.numb);
349 exp->type = PSI_T_INT8;
350 exp->data.ival.i8 = '\f';
351 return true;
352 case 'n':
353 free(exp->data.numb);
354 exp->type = PSI_T_INT8;
355 exp->data.ival.i8 = '\n';
356 return true;
357 case 'r':
358 free(exp->data.numb);
359 exp->type = PSI_T_INT8;
360 exp->data.ival.i8 = '\r';
361 return true;
362 case 't':
363 free(exp->data.numb);
364 exp->type = PSI_T_INT8;
365 exp->data.ival.i8 = '\t';
366 return true;
367 case 'v':
368 free(exp->data.numb);
369 exp->type = PSI_T_INT8;
370 exp->data.ival.i8 = '\v';
371 return true;
372 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
373 tmp.i8 = strtol(&exp->data.numb[2 + (*exp->data.numb == 'L')], &exp->data.numb[strlen(exp->data.numb)-1], 8);
374 free(exp->data.numb);
375 exp->type = PSI_T_INT8;
376 exp->data.ival.i8 = tmp.i8;
377 return true;
378 default:
379 free(exp->data.numb);
380 exp->type = PSI_T_INT8;
381 exp->data.ival.i8 = tmp.i8;
382 return true;
383 }
384 break;
385 default:
386 free(exp->data.numb);
387 exp->type = PSI_T_INT8;
388 exp->data.ival.i8 = tmp.i8;
389 return true;
390 }
391 break;
392
393 default:
394 assert(0);
395 }
396
397 return false;
398 }
399
400 #include "Zend/zend_constants.h"
401
402 static inline token_t psi_number_eval_constant(struct psi_number *exp,
403 impl_val *res, struct psi_call_frame *frame)
404 {
405 switch (exp->data.cnst->type->type) {
406 case PSI_T_INT:
407 res->i64 = zend_get_constant_str(exp->data.cnst->name,
408 strlen(exp->data.cnst->name))->value.lval;
409 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
410 return PSI_T_INT64;
411 case PSI_T_FLOAT:
412 res->dval = zend_get_constant_str(exp->data.cnst->name,
413 strlen(exp->data.cnst->name))->value.dval;
414 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
415 return PSI_T_DOUBLE;
416 default:
417 if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%d)", exp->data.cnst->type->type);
418 return 0;
419 }
420 }
421
422
423 static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
424 impl_val *res, struct psi_call_frame *frame)
425 {
426 impl_val *ref;
427 struct psi_call_frame_symbol *sym;
428 struct psi_decl_type *real;
429 size_t size;
430
431 real = psi_decl_type_get_real(exp->data.dvar->arg->type);
432 size = psi_decl_arg_get_size(exp->data.dvar->arg);
433 sym = psi_call_frame_fetch_symbol(frame, exp->data.dvar);
434 ref = deref_impl_val(sym->ptr, exp->data.dvar);
435
436 memcpy(res, ref, size);
437
438 return real->type;
439 }
440
441 static inline token_t psi_number_eval_define(struct psi_number *exp,
442 impl_val *res, HashTable *defs)
443 {
444 struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb));
445
446 //WHATT?
447 fprintf(stderr, "number_eval_define: %s %s(%p)\n",
448 exp->token->text, macro ? macro->token->text : "", macro);
449
450 res->u8 = 0;
451 return PSI_T_UINT8;
452 }
453
454 token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame, HashTable *defs)
455 {
456 switch (exp->type) {
457 case PSI_T_INT8:
458 *res = exp->data.ival;
459 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
460 return PSI_T_INT8;
461 case PSI_T_UINT8:
462 *res = exp->data.ival;
463 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
464 return PSI_T_UINT8;
465 case PSI_T_INT16:
466 *res = exp->data.ival;
467 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
468 return PSI_T_INT16;
469 case PSI_T_UINT16:
470 *res = exp->data.ival;
471 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu16, res->u16);
472 return PSI_T_UINT16;
473 case PSI_T_INT32:
474 *res = exp->data.ival;
475 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
476 return PSI_T_INT32;
477 case PSI_T_UINT32:
478 *res = exp->data.ival;
479 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu32, res->u32);
480 return PSI_T_UINT32;
481 case PSI_T_INT64:
482 *res = exp->data.ival;
483 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
484 return PSI_T_INT64;
485 case PSI_T_UINT64:
486 *res = exp->data.ival;
487 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
488 return PSI_T_UINT64;
489
490 case PSI_T_DOUBLE:
491 *res = exp->data.ival;
492 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
493 return exp->type;
494
495 case PSI_T_ENUM:
496 res->i64 = exp->data.enm->val;
497 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
498 return PSI_T_INT64;
499
500 case PSI_T_CONST:
501 return psi_number_eval_constant(exp, res, frame);
502
503 case PSI_T_NAME:
504 return psi_number_eval_decl_var(exp, res, frame);
505
506 case PSI_T_DEFINE:
507 return psi_number_eval_define(exp, res, defs);
508
509 case PSI_T_FUNCTION:
510 res->u8 = 0;
511 return PSI_T_UINT8;
512
513 default:
514 assert(0);
515 }
516 return 0;
517 }