fix gdbinit; postprocessing macros
[m6w6/ext-psi] / src / types / impl_def_val.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 #include "data.h"
28
29 #include "zend_smart_str.h"
30
31 #include <assert.h>
32 #include <math.h>
33
34 #define PSI_IMPL_DEF_VAL_DEBUG 0
35
36 struct psi_impl_def_val *psi_impl_def_val_init(token_t t, void *data)
37 {
38 struct psi_impl_def_val *def = pecalloc(1, sizeof(*def), 1);
39
40 switch ((def->type = t)) {
41 case PSI_T_TRUE:
42 def->ival.zend.bval = 1;
43 /* no break */
44 case PSI_T_FALSE:
45 def->ityp = PSI_T_UINT8;
46 /* no break */
47 case PSI_T_NULL:
48 break;
49 case PSI_T_QUOTED_STRING:
50 /* immediate upgrade */
51 def->type = PSI_T_STRING;
52 /* no break */
53 case PSI_T_STRING:
54 if (data) {
55 def->ival.zend.str = zend_string_copy(data);
56 }
57 break;
58
59 case PSI_T_NUMBER:
60 def->data.num = data;
61 break;
62
63 default:
64 assert(0);
65 }
66
67 return def;
68 }
69
70 void psi_impl_def_val_free(struct psi_impl_def_val **def_ptr)
71 {
72 if (*def_ptr) {
73 struct psi_impl_def_val *def = *def_ptr;
74
75 *def_ptr = NULL;
76 psi_token_free(&def->token);
77 switch (def->type) {
78 case PSI_T_NUMBER:
79 psi_num_exp_free(&def->data.num);
80 break;
81
82 case PSI_T_STRING:
83 if (def->ival.zend.str) {
84 zend_string_release(def->ival.zend.str);
85 }
86 break;
87 default:
88 break;
89 }
90 free(def);
91 }
92 }
93
94 void psi_impl_def_val_get_zval(struct psi_impl_def_val *val, token_t typ, zval *zv)
95 {
96 impl_val tmp = val->ival;
97
98 /* c->val has already been forced to the type of the containing constant or impl_arg */
99 switch (typ) {
100 case PSI_T_BOOL:
101 ZVAL_BOOL(zv, tmp.zend.bval);
102 break;
103 case PSI_T_INT:
104 ZVAL_LONG(zv, tmp.zend.lval);
105 break;
106 case PSI_T_FLOAT:
107 case PSI_T_DOUBLE:
108 is_double: ;
109 ZVAL_DOUBLE(zv, tmp.dval);
110 break;
111 case PSI_T_STRING:
112 is_string: ;
113 ZVAL_NEW_STR(zv, zend_string_copy(tmp.zend.str));
114 if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
115 Z_TYPE_FLAGS_P(zv) = 0;
116 }
117 break;
118 case PSI_T_MIXED:
119 switch (val->type) {
120 case PSI_T_NULL:
121 ZVAL_NULL(zv);
122 break;
123 case PSI_T_TRUE:
124 ZVAL_TRUE(zv);
125 break;
126 case PSI_T_FALSE:
127 ZVAL_FALSE(zv);
128 break;
129 case PSI_T_STRING:
130 goto is_string;
131 break;
132 case PSI_T_NUMBER:
133 switch (val->ityp) {
134 case PSI_T_INT8:
135 case PSI_T_UINT8:
136 case PSI_T_INT16:
137 case PSI_T_UINT16:
138 case PSI_T_INT32:
139 case PSI_T_UINT32:
140 psi_calc_cast(val->ityp, &tmp, PSI_T_INT64, &tmp);
141 /* no break */
142 case PSI_T_INT64:
143 ZVAL_LONG(zv, tmp.i64);
144 break;
145 case PSI_T_UINT64:
146 ZVAL_LONG_DOUBLE_STR(zv, tmp.u64, is_signed=false;persistent=true);
147 break;
148 #if HAVE_INT128
149 case PSI_T_INT128:
150 ZVAL_LONG_DOUBLE_STR(zv, tmp.i128, is_signed=true;persistent=true);
151 break;
152 case PSI_T_UINT128:
153 ZVAL_LONG_DOUBLE_STR(zv, tmp.u128, is_signed=false;persistent=true);
154 #endif
155 break;
156 case PSI_T_FLOAT:
157 ZVAL_DOUBLE(zv, tmp.fval);
158 break;
159 case PSI_T_DOUBLE:
160 goto is_double;
161 break;
162 #if HAVE_LONG_DOUBLE
163 case PSI_T_LONG_DOUBLE:
164 ZVAL_DOUBLE(zv, tmp.ldval);
165 break;
166 #endif
167 default:
168 assert(0);
169 }
170 break;
171 default:
172 assert(0);
173 break;
174 }
175 break;
176 default:
177 assert(0);
178 break;
179 }
180
181 }
182 /*
183 token_t psi_impl_def_val_get_zend(struct psi_impl_def_val *val, impl_val *res)
184 {
185 switch (val->type) {
186 case PSI_T_NULL:
187 return PSI_T_NULL;
188 case PSI_T_TRUE:
189 case PSI_T_FALSE:
190 res->zend.bval = val->ival.zend.bval;
191 return PSI_T_BOOL;
192 case PSI_T_STRING:
193 res->zend.str = val->ival.zend.str
194 ? zend_string_copy(val->ival.zend.str)
195 : zend_empty_string;
196 return PSI_T_STRING;
197 case PSI_T_NUMBER:
198 switch (val->ityp) {
199 case PSI_T_FLOAT:
200 res->dval = val->ival.fval;
201 return PSI_T_DOUBLE;
202 case PSI_T_DOUBLE:
203 res->dval = val->ival.dval;
204 return PSI_T_DOUBLE;
205 #if HAVE_LONG_DOUBLE
206 case PSI_T_LONG_DOUBLE:
207 res->dval = val->ival.ldval;
208 return PSI_T_DOUBLE;
209 #endif
210 default:
211 psi_calc_cast(val->ityp, &val->ival, PSI_T_INT64, res);
212 return PSI_T_INT;
213 }
214 break;
215 default:
216 assert(0);
217 return 0;
218 }
219 }
220 */
221
222 static inline bool psi_impl_def_val_validate_impl_type(struct psi_data *data,
223 struct psi_impl_def_val *val, struct psi_impl_type *type,
224 struct psi_validate_scope *scope)
225 {
226 switch (type->type) {
227 case PSI_T_BOOL:
228 switch (val->type) {
229 case PSI_T_TRUE:
230 case PSI_T_FALSE:
231 return true;
232 case PSI_T_STRING:
233 if (val->ival.zend.str
234 && *val->ival.zend.str->val
235 && *val->ival.zend.str->val != '0') {
236 zend_string_release(val->ival.zend.str);
237 val->ival.zend.bval = 1;
238 } else {
239 if (val->ival.zend.str) {
240 zend_string_release(val->ival.zend.str);
241 }
242 val->ival.zend.bval = 0;
243 }
244 val->ityp = PSI_T_UINT8;
245 return true;
246 default:
247 assert(0);
248 break;
249 }
250 break;
251 case PSI_T_INT:
252 if (val->type == PSI_T_STRING) {
253 zend_string *str = val->ival.zend.str;
254 switch (is_numeric_str_function(str, &val->ival.zend.lval, &val->ival.dval)) {
255 case IS_DOUBLE:
256 val->ival.zend.lval = zend_dval_to_lval_cap(val->ival.dval);
257 /* no break */
258 case IS_LONG:
259 break;
260 default:
261 val->ival.zend.lval = 0;
262 }
263 zend_string_release(str);
264 val->ityp = PSI_T_INT64;
265 return true;
266 }
267 psi_calc_cast(val->ityp, &val->ival, PSI_T_INT64, &val->ival);
268 val->type = val->ityp = PSI_T_INT64;
269 return true;
270 case PSI_T_FLOAT:
271 case PSI_T_DOUBLE:
272 if (val->type == PSI_T_STRING) {
273 zend_string *str = val->ival.zend.str;
274 switch (is_numeric_str_function(str, &val->ival.zend.lval, &val->ival.dval)) {
275 case IS_LONG:
276 val->ival.dval = val->ival.zend.lval;
277 /* no break */
278 case IS_DOUBLE:
279 break;
280 default:
281 val->ival.dval = 0;
282 }
283 zend_string_release(str);
284 val->type = val->ityp = PSI_T_DOUBLE;
285 return true;
286 }
287 psi_calc_cast(val->ityp, &val->ival, PSI_T_DOUBLE, &val->ival);
288 val->ityp = PSI_T_DOUBLE;
289 return true;
290 case PSI_T_STRING:
291 if (val->type == PSI_T_STRING) {
292 return true;
293 } else {
294 smart_str str = {0};
295
296 switch (val->ityp) {
297 CASE_IMPLVAL_NUM_PRINTF(smart_str_append_printf, &str, val->ival, false);
298 default:
299 assert(0);
300 }
301 val->ival.zend.str = smart_str_extract(&str);
302 val->type = PSI_T_STRING;
303 return true;
304 }
305 break;
306 default:
307 data->error(data, val->token, PSI_WARNING,
308 "Invalid default value type '%s', "
309 "expected one of bool, int, float/double or string.",
310 type->name->val);
311
312 }
313 return false;
314 }
315
316 bool psi_impl_def_val_validate(struct psi_data *data,
317 struct psi_impl_def_val *val, struct psi_impl_type *type,
318 struct psi_validate_scope *scope)
319 {
320 /* NULL can be anything */
321 if (val->type == PSI_T_NULL) {
322 return true;
323 }
324
325 /* a number can be anything */
326 if (val->type == PSI_T_NUMBER) {
327 if (!psi_num_exp_validate(data, val->data.num, scope)) {
328 return false;
329 }
330 val->ityp = psi_num_exp_exec(val->data.num, &val->ival, NULL, scope->cpp);
331 }
332
333 /* forced type, like `const <type> foo`, or function param `<type> $xyz` */
334 if (type) {
335 return psi_impl_def_val_validate_impl_type(data, val, type, scope);
336 }
337
338 switch (val->type) {
339 case PSI_T_NUMBER:
340 case PSI_T_NULL:
341 case PSI_T_TRUE:
342 case PSI_T_FALSE:
343 case PSI_T_STRING:
344 return true;
345 default:
346 assert(0);
347 break;
348 }
349
350 return false;
351 /*
352 switch (type ? type->type : PSI_T_MIXED) {
353 case PSI_T_BOOL:
354 val->ival.zend.bval = val->type == PSI_T_TRUE ? 1 : 0;
355 return true;
356 break;
357
358 // macros
359 case PSI_T_NUMBER:
360 if (val->type == PSI_T_NUMBER) {
361 token_t typ = psi_num_exp_exec(val->data.num, &val->ival, NULL, scope->cpp);
362
363 switch (typ) {
364 case PSI_T_FLOAT:
365 val->ival.dval = val->ival.fval;
366 // no break
367 case PSI_T_DOUBLE:
368 val->type = PSI_T_FLOAT;
369 type->type = PSI_T_FLOAT;
370 zend_string_release(type->name);
371 type->name = zend_string_init_interned(ZEND_STRL("float"), 1);
372 break;
373 case PSI_T_UINT64:
374 if (val->ival.u64 > ZEND_LONG_MAX) {
375 data->error(data, val->token, PSI_WARNING,
376 "Integer too big for signed representation: '%" PRIu64 "'",
377 val->ival.u64);
378 }
379 default:
380 // FIXME big integers
381 val->type = PSI_T_INT;
382 type->type = PSI_T_INT;
383 zend_string_release(type->name);
384 type->name = zend_string_init_interned(ZEND_STRL("int"), 1);
385 break;
386 }
387 psi_num_exp_free(&val->data.num);
388 return true;
389 }
390 break;
391
392 case PSI_T_INT:
393 if (val->type == PSI_T_NUMBER) {
394 val->type = PSI_T_INT;
395 val->ival.zend.lval = psi_num_exp_get_long(val->data.num, NULL, scope->cpp);
396 #if PSI_IMPL_DEF_VAL_DEBUG
397 PSI_DEBUG_PRINT(data, "PSI: NUMBER (long) %" PRIi64 " from ", val->ival.zend.lval);
398 PSI_DEBUG_DUMP(data, psi_num_exp_dump, val->data.num);
399 PSI_DEBUG_PRINT(data, "\n");
400 #endif
401 psi_num_exp_free(&val->data.num);
402 }
403 if (val->type == PSI_T_INT) {
404 return true;
405 }
406 break;
407
408 case PSI_T_FLOAT:
409 case PSI_T_DOUBLE:
410 if (val->type == PSI_T_NUMBER) {
411 val->type = PSI_T_DOUBLE;
412 val->ival.dval = psi_num_exp_get_double(val->data.num, NULL, scope->cpp);
413 #if PSI_IMPL_DEF_VAL_DEBUG
414 PSI_DEBUG_PRINT(data, "PSI: NUMBER (double) %" PRIdval " from ", val->ival.dval);
415 PSI_DEBUG_DUMP(data, psi_num_exp_dump, val->data.num);
416 PSI_DEBUG_PRINT(data, "\n");
417 #endif
418 psi_num_exp_free(&val->data.num);
419 }
420 if (val->type == PSI_T_DOUBLE) {
421 return true;
422 }
423 break;
424
425 case PSI_T_STRING:
426 if (val->type == PSI_T_STRING) {
427 return true; data->error(data, val->token, PSI_WARNING,
428 "Invalid default value type '%s', "
429 "expected one of bool, int, float, string.",
430 type ? type->name->val : "mixed");
431
432 }
433 break;
434
435 case PSI_T_MIXED:
436
437 }
438 // no break
439 default:
440 }
441 */
442 }
443
444 void psi_impl_def_val_dump(struct psi_dump *dump, struct psi_impl_def_val *val) {
445 switch (val->type) {
446 case PSI_T_NULL:
447 PSI_DUMP(dump, "NULL");
448 break;
449 case PSI_T_TRUE:
450 PSI_DUMP(dump, "true");
451 break;
452 case PSI_T_FALSE:
453 PSI_DUMP(dump, "false");
454 break;
455 case PSI_T_BOOL:
456 PSI_DUMP(dump, "%s", val->ival.zend.bval ? "true" : "false");
457 break;
458 case PSI_T_INT:
459 PSI_DUMP(dump, ZEND_LONG_FMT, val->ival.zend.lval);
460 break;
461 case PSI_T_FLOAT:
462 case PSI_T_DOUBLE:
463 if (isinf(val->ival.dval)) {
464 PSI_DUMP(dump, "\\INF");
465 } else if (isnan(val->ival.dval)) {
466 PSI_DUMP(dump, "\\NAN");
467 } else {
468 PSI_DUMP(dump, "%" PRIdval, val->ival.dval);
469 }
470 break;
471 case PSI_T_STRING:
472 PSI_DUMP(dump, "\"%s\"", val->ival.zend.str->val);
473 break;
474 case PSI_T_NUMBER:
475 psi_num_exp_dump(dump, val->data.num);
476 break;
477 default:
478 assert(0);
479 }
480 PSI_DUMP(dump, "\t/* t=%d */ ", val->type);
481 }