1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
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.
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 *******************************************************************************/
26 #include "php_psi_stdinc.h"
33 struct psi_let_exp
*psi_let_exp_init_ex(struct psi_decl_var
*var
,
34 enum psi_let_exp_kind kind
, void *data
)
36 struct psi_let_exp
*val
= psi_let_exp_init(kind
, data
);
41 struct psi_let_exp
*psi_let_exp_init(enum psi_let_exp_kind kind
, void *data
)
43 struct psi_let_exp
*let
= calloc(1, sizeof(*let
));
44 switch (let
->kind
= kind
) {
52 let
->data
.alloc
= data
;
54 case PSI_LET_CALLBACK
:
55 let
->data
.callback
= data
;
58 let
->data
.func
= data
;
69 void psi_let_exp_free(struct psi_let_exp
**let_ptr
)
72 struct psi_let_exp
*let
= *let_ptr
;
79 psi_num_exp_free(&let
->data
.num
);
82 psi_let_calloc_free(&let
->data
.alloc
);
84 case PSI_LET_CALLBACK
:
85 psi_let_callback_free(&let
->data
.callback
);
88 psi_let_func_free(&let
->data
.func
);
91 psi_decl_var_free(&let
->data
.var
);
97 psi_decl_var_free(&let
->var
);
103 void psi_let_exp_dump(int fd
, struct psi_let_exp
*val
, unsigned level
, int last
)
106 /* only if not directly after `set ...` */
107 dprintf(fd
, "%s", psi_t_indent(level
));
111 if (val
->var
->token
) {
112 psi_decl_var_dump(fd
, val
->var
);
116 if (val
->is_reference
) {
125 psi_decl_var_dump(fd
, val
->data
.var
);
126 dprintf(fd
, "\t/* fqn=%s */", val
->data
.var
->fqn
);
129 psi_let_calloc_dump(fd
, val
->data
.alloc
);
131 case PSI_LET_CALLBACK
:
132 psi_let_callback_dump(fd
, val
->data
.callback
, level
);
135 psi_let_func_dump(fd
, val
->data
.func
, level
);
138 psi_num_exp_dump(fd
, val
->data
.num
);
146 dprintf(fd
, "\t/* fqn=%s */", val
->var
->fqn
);
158 bool psi_let_exp_validate(struct psi_data
*data
, struct psi_let_exp
*val
,
159 struct psi_impl
*impl
)
161 struct psi_decl_var
*dvar
= psi_let_exp_get_decl_var(val
);
165 if (!psi_decl_var_validate(data
, val
->data
.var
, impl
->decl
, val
, NULL
)) {
166 data
->error(data
, dvar
->token
? : **(struct psi_token
***) &val
->data
,
167 PSI_WARNING
, "Unknown variable '%s'", dvar
->name
);
173 if (!psi_decl_var_validate(data
, dvar
, impl
->decl
, val
, NULL
)) {
174 data
->error(data
, dvar
->token
? : **(struct psi_token
***) &val
->data
,
175 PSI_WARNING
, "Unknown variable '%s'", dvar
->name
);
185 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
186 /* e.g. let foo = *bar; */
187 val
->var
->pointer_level
= val
->data
.var
->pointer_level
;
188 val
->var
->arg
= val
->data
.var
->arg
;
191 if (!psi_num_exp_validate(data
, val
->data
.num
, impl
, NULL
, val
, NULL
, NULL
)) {
196 if (!psi_num_exp_validate(data
, val
->data
.alloc
->nmemb
, impl
, NULL
, val
, NULL
, NULL
)) {
199 if (!psi_num_exp_validate(data
, val
->data
.alloc
->size
, impl
, NULL
, val
, NULL
, NULL
)) {
203 case PSI_LET_CALLBACK
:
204 if (!psi_let_func_validate(data
, val
, val
->data
.callback
->func
, impl
)) {
207 if (!psi_let_callback_validate(data
, val
, val
->data
.callback
, impl
)) {
212 if (!psi_let_func_validate(data
, val
, val
->data
.func
, impl
)) {
221 void *psi_let_exp_exec(struct psi_let_exp
*val
, struct psi_decl_arg
*darg
,
222 void *actual_location
, size_t actual_size
, struct psi_call_frame
*frame
)
224 struct psi_call_frame_symbol
*frame_sym
;
226 frame_sym
= psi_call_frame_fetch_symbol(frame
, val
->var
);
230 /* FIXME: sizeof_decl_arg */
231 if (darg
&& darg
->var
->array_size
) {
232 frame_sym
->temp_val
.ptr
= ecalloc(1, psi_decl_arg_get_size(darg
));
234 memset(&frame_sym
->temp_val
, 0, sizeof(frame_sym
->temp_val
));
240 struct psi_let_stmt
*let_temp
= psi_impl_get_let(frame
->impl
,
242 struct psi_call_frame_symbol
*temp_arg
;
244 temp_arg
= psi_call_frame_fetch_symbol(frame
, let_temp
->exp
->var
);
245 frame_sym
->temp_val
= *deref_impl_val(temp_arg
->ptr
, val
->data
.var
);
251 zend_long n
= psi_long_num_exp(val
->data
.alloc
->nmemb
, frame
, NULL
);
252 zend_long s
= psi_long_num_exp(val
->data
.alloc
->size
, frame
, NULL
);
253 void *tmp
= *psi_call_frame_push_auto(frame
,
254 safe_emalloc(n
, s
, sizeof(void *)));
256 memset(tmp
, 0, n
* s
+ sizeof(void *));
257 frame_sym
->temp_val
.ptr
= tmp
;
264 token_t val_type
= psi_decl_type_get_real(val
->var
->arg
->type
)->type
;
265 token_t res_type
= psi_num_exp_exec(val
->data
.num
, &res
, frame
, NULL
);
267 if (val_type
== res_type
) {
268 frame_sym
->temp_val
= res
;
270 psi_calc_cast(res_type
, &res
, val_type
, &frame_sym
->temp_val
);
275 case PSI_LET_CALLBACK
:
276 frame_sym
->temp_val
.ptr
= val
->data
.callback
->decl
->sym
;
280 if (!psi_let_func_exec(val
, val
->data
.func
, darg
, frame
)) {
286 if (val
->is_reference
) {
287 frame_sym
->ptr
= &frame_sym
->ival_ptr
;
289 frame_sym
->ptr
= frame_sym
->ival_ptr
;
292 if (actual_location
) {
293 assert(!val
->is_reference
|| actual_size
== SIZEOF_VOID_P
);
294 memcpy(actual_location
, frame_sym
->ptr
, actual_size
);
295 frame_sym
->ptr
= actual_location
;
298 return frame_sym
->ptr
;
301 struct psi_let_func
* psi_let_exp_get_func(struct psi_let_exp
* exp
)
305 case PSI_LET_CALLBACK
:
306 return exp
->data
.callback
->func
;
308 return exp
->data
.func
;
316 struct psi_decl_var
*psi_let_exp_get_decl_var(struct psi_let_exp
*val
)
319 const char *name
= psi_let_exp_get_decl_var_name(val
);
322 val
->var
= psi_decl_var_init(name
, 0, 0);
328 struct psi_impl_var
*psi_let_exp_get_impl_var(struct psi_let_exp
*val
)
330 struct psi_let_func
* fn
= psi_let_exp_get_func(val
);
331 return fn
? fn
->var
: NULL
;
334 const char* psi_let_exp_get_decl_var_name(struct psi_let_exp
* val
)
336 struct psi_impl_var
* var
;
338 return val
->var
->name
;
340 var
= psi_let_exp_get_impl_var(val
);
342 return &var
->name
[1];