travis: update
[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 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #else
29 # include "php_config.h"
30 #endif
31 #include "data.h"
32
33 #include "zend_smart_str.h"
34
35 #include <assert.h>
36 #include <math.h>
37
38 #define PSI_IMPL_DEF_VAL_DEBUG 0
39
40 struct psi_impl_def_val *psi_impl_def_val_init(token_t t, void *data)
41 {
42 struct psi_impl_def_val *def = pecalloc(1, sizeof(*def), 1);
43
44 switch ((def->type = t)) {
45 case PSI_T_TRUE:
46 def->ival.zend.bval = 1;
47 /* no break */
48 case PSI_T_FALSE:
49 def->ityp = PSI_T_UINT8;
50 /* no break */
51 case PSI_T_NULL:
52 break;
53 case PSI_T_QUOTED_STRING:
54 /* immediate upgrade */
55 def->type = PSI_T_STRING;
56 /* no break */
57 case PSI_T_STRING:
58 if (data) {
59 def->ival.zend.str = zend_string_copy(data);
60 }
61 break;
62
63 case PSI_T_NUMBER:
64 def->data.num = data;
65 break;
66
67 default:
68 assert(0);
69 }
70
71 return def;
72 }
73
74 void psi_impl_def_val_free(struct psi_impl_def_val **def_ptr)
75 {
76 if (*def_ptr) {
77 struct psi_impl_def_val *def = *def_ptr;
78
79 *def_ptr = NULL;
80 psi_token_free(&def->token);
81 switch (def->type) {
82 case PSI_T_NUMBER:
83 psi_num_exp_free(&def->data.num);
84 break;
85
86 case PSI_T_STRING:
87 if (def->ival.zend.str) {
88 zend_string_release(def->ival.zend.str);
89 }
90 break;
91 default:
92 break;
93 }
94 free(def);
95 }
96 }
97
98 void psi_impl_def_val_get_zval(struct psi_impl_def_val *val, token_t typ, zval *zv)
99 {
100 impl_val tmp = val->ival;
101
102 /* c->val has already been forced to the type of the containing constant or impl_arg */
103 switch (typ) {
104 case PSI_T_BOOL:
105 ZVAL_BOOL(zv, tmp.zend.bval);
106 break;
107 case PSI_T_INT:
108 ZVAL_LONG(zv, tmp.zend.lval);
109 break;
110 case PSI_T_FLOAT:
111 case PSI_T_DOUBLE:
112 is_double: ;
113 ZVAL_DOUBLE(zv, tmp.dval);
114 break;
115 case PSI_T_STRING:
116 is_string: ;
117 ZVAL_NEW_STR(zv, zend_string_copy(tmp.zend.str));
118 if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
119 Z_TYPE_FLAGS_P(zv) = 0;
120 }
121 break;
122 case PSI_T_MIXED:
123 switch (val->type) {
124 case PSI_T_NULL:
125 ZVAL_NULL(zv);
126 break;
127 case PSI_T_TRUE:
128 ZVAL_TRUE(zv);
129 break;
130 case PSI_T_FALSE:
131 ZVAL_FALSE(zv);
132 break;
133 case PSI_T_STRING:
134 goto is_string;
135 break;
136 case PSI_T_NUMBER:
137 switch (val->ityp) {
138 case PSI_T_INT8:
139 case PSI_T_UINT8:
140 case PSI_T_INT16:
141 case PSI_T_UINT16:
142 case PSI_T_INT32:
143 case PSI_T_UINT32:
144 psi_calc_cast(val->ityp, &tmp, PSI_T_INT64, &tmp);
145 /* no break */
146 case PSI_T_INT64:
147 ZVAL_LONG(zv, tmp.i64);
148 break;
149 case PSI_T_UINT64:
150 ZVAL_LONG_DOUBLE_STR(zv, tmp.u64, is_signed=false;persistent=true);
151 break;
152 #if HAVE_INT128
153 case PSI_T_INT128:
154 ZVAL_LONG_DOUBLE_STR(zv, tmp.i128, is_signed=true;persistent=true);
155 break;
156 case PSI_T_UINT128:
157 ZVAL_LONG_DOUBLE_STR(zv, tmp.u128, is_signed=false;persistent=true);
158 #endif
159 break;
160 case PSI_T_FLOAT:
161 ZVAL_DOUBLE(zv, tmp.fval);
162 break;
163 case PSI_T_DOUBLE:
164 goto is_double;
165 break;
166 #if HAVE_LONG_DOUBLE
167 case PSI_T_LONG_DOUBLE:
168 ZVAL_DOUBLE(zv, tmp.ldval);
169 break;
170 #endif
171 default:
172 assert(0);
173 }
174 break;
175 default:
176 assert(0);
177 break;
178 }
179 break;
180 default:
181 assert(0);
182 break;
183 }
184
185 }
186
187 static inline bool psi_impl_def_val_validate_impl_type(struct psi_data *data,
188 struct psi_impl_def_val *val, struct psi_impl_type *type,
189 struct psi_validate_scope *scope)
190 {
191 switch (type->type) {
192 case PSI_T_BOOL:
193 switch (val->type) {
194 case PSI_T_TRUE:
195 case PSI_T_FALSE:
196 return true;
197 case PSI_T_STRING:
198 if (val->ival.zend.str) {
199 zend_string *tmp = val->ival.zend.str;
200
201 val->ival.zend.bval = (*tmp->val && *tmp->val != '0');
202 zend_string_release(tmp);
203 }
204 val->ityp = PSI_T_UINT8;
205 val->type = PSI_T_BOOL;
206 return true;
207 default:
208 assert(0);
209 break;
210 }
211 break;
212 case PSI_T_INT:
213 if (val->type == PSI_T_STRING) {
214 zend_string *str = val->ival.zend.str;
215 switch (is_numeric_str_function(str, &val->ival.zend.lval, &val->ival.dval)) {
216 case IS_DOUBLE:
217 val->ival.zend.lval = zend_dval_to_lval_cap(val->ival.dval);
218 /* no break */
219 case IS_LONG:
220 break;
221 default:
222 val->ival.zend.lval = 0;
223 }
224 zend_string_release(str);
225 val->ityp = PSI_T_INT64;
226 return true;
227 }
228 psi_calc_cast(val->ityp, &val->ival, PSI_T_INT64, &val->ival);
229 val->type = PSI_T_INT;
230 val->ityp = PSI_T_INT64;
231 return true;
232 case PSI_T_FLOAT:
233 case PSI_T_DOUBLE:
234 if (val->type == PSI_T_STRING) {
235 zend_string *str = val->ival.zend.str;
236 switch (is_numeric_str_function(str, &val->ival.zend.lval, &val->ival.dval)) {
237 case IS_LONG:
238 val->ival.dval = val->ival.zend.lval;
239 /* no break */
240 case IS_DOUBLE:
241 break;
242 default:
243 val->ival.dval = 0;
244 }
245 zend_string_release(str);
246 val->type = val->ityp = PSI_T_DOUBLE;
247 return true;
248 }
249 psi_calc_cast(val->ityp, &val->ival, PSI_T_DOUBLE, &val->ival);
250 val->ityp = PSI_T_DOUBLE;
251 return true;
252 case PSI_T_STRING:
253 if (val->type == PSI_T_STRING) {
254 return true;
255 } else {
256 smart_str str = {0};
257 struct psi_dump dump = {{.hn = &str},
258 .fun = (psi_dump_cb) smart_str_append_printf};
259
260 switch (val->ityp) {
261 CASE_IMPLVAL_NUM_DUMP(&dump, val->ival, false);
262 default:
263 assert(0);
264 }
265 val->ival.zend.str = smart_str_extract(&str);
266 val->type = PSI_T_STRING;
267 return true;
268 }
269 break;
270 default:
271 data->error(data, val->token, PSI_WARNING,
272 "Invalid default value type '%s', "
273 "expected one of bool, int, float/double or string.",
274 type->name->val);
275
276 }
277 return false;
278 }
279
280 bool psi_impl_def_val_validate(struct psi_data *data,
281 struct psi_impl_def_val *val, struct psi_impl_type *type,
282 struct psi_validate_scope *scope)
283 {
284 /* NULL can be anything */
285 if (val->type == PSI_T_NULL) {
286 return true;
287 }
288
289 /* a number can be anything */
290 if (val->type == PSI_T_NUMBER) {
291 if (!psi_num_exp_validate(data, val->data.num, scope)) {
292 return false;
293 }
294 val->ityp = psi_num_exp_exec(val->data.num, &val->ival, NULL, scope->cpp);
295 }
296
297 /* forced type, like `const <type> foo`, or function param `<type> $xyz` */
298 if (type) {
299 return psi_impl_def_val_validate_impl_type(data, val, type, scope);
300 }
301
302 switch (val->type) {
303 case PSI_T_NUMBER:
304 case PSI_T_NULL:
305 case PSI_T_TRUE:
306 case PSI_T_FALSE:
307 case PSI_T_STRING:
308 return true;
309 default:
310 assert(0);
311 break;
312 }
313
314 return false;
315 }
316
317 void psi_impl_def_val_dump(struct psi_dump *dump, struct psi_impl_def_val *val) {
318 switch (val->type) {
319 case PSI_T_NULL:
320 PSI_DUMP(dump, "NULL");
321 break;
322 case PSI_T_TRUE:
323 PSI_DUMP(dump, "true");
324 break;
325 case PSI_T_FALSE:
326 PSI_DUMP(dump, "false");
327 break;
328 case PSI_T_BOOL:
329 PSI_DUMP(dump, "%s", val->ival.zend.bval ? "true" : "false");
330 break;
331 case PSI_T_INT:
332 PSI_DUMP(dump, ZEND_LONG_FMT, val->ival.zend.lval);
333 break;
334 case PSI_T_FLOAT:
335 case PSI_T_DOUBLE:
336 if (isinf(val->ival.dval)) {
337 PSI_DUMP(dump, "\\INF");
338 } else if (isnan(val->ival.dval)) {
339 PSI_DUMP(dump, "\\NAN");
340 } else {
341 PSI_DUMP(dump, "%" PRIdval, val->ival.dval);
342 }
343 break;
344 case PSI_T_STRING:
345 PSI_DUMP(dump, "\"%s\"", val->ival.zend.str->val);
346 break;
347 case PSI_T_NUMBER:
348 psi_num_exp_dump(dump, val->data.num);
349 break;
350 default:
351 assert(0);
352 }
353 #if 0
354 PSI_DUMP(dump, "\t/* impl_def_val.type=%d */ ", val->type);
355 #endif
356 }