1d8e2ec93b8a92d6c280a364fdac8aa18a07f302
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"
32 struct psi_let_exp
*psi_let_exp_init_ex(struct psi_decl_var
*var
,
33 enum psi_let_exp_kind kind
, void *data
)
35 struct psi_let_exp
*val
= psi_let_exp_init(kind
, data
);
40 struct psi_let_exp
*psi_let_exp_init(enum psi_let_exp_kind kind
, void *data
)
42 struct psi_let_exp
*let
= calloc(1, sizeof(*let
));
43 switch (let
->kind
= kind
) {
51 let
->data
.alloc
= data
;
53 case PSI_LET_CALLBACK
:
54 let
->data
.callback
= data
;
57 let
->data
.func
= data
;
68 void psi_let_exp_free(struct psi_let_exp
**let_ptr
)
71 struct psi_let_exp
*let
= *let_ptr
;
78 psi_num_exp_free(&let
->data
.num
);
81 psi_let_calloc_free(&let
->data
.alloc
);
83 case PSI_LET_CALLBACK
:
84 psi_let_callback_free(&let
->data
.callback
);
87 psi_let_func_free(&let
->data
.func
);
90 psi_decl_var_free(&let
->data
.var
);
96 psi_decl_var_free(&let
->var
);
102 void psi_let_exp_dump(int fd
, struct psi_let_exp
*val
, unsigned level
, int last
)
105 /* only if not directly after `set ...` */
106 dprintf(fd
, "%s", psi_t_indent(level
));
110 if (val
->var
->token
) {
111 psi_decl_var_dump(fd
, val
->var
);
115 if (val
->is_reference
) {
124 psi_decl_var_dump(fd
, val
->data
.var
);
125 dprintf(fd
, "\t/* fqn=%s */", val
->data
.var
->fqn
);
128 psi_let_calloc_dump(fd
, val
->data
.alloc
);
130 case PSI_LET_CALLBACK
:
131 psi_let_callback_dump(fd
, val
->data
.callback
, level
);
134 psi_let_func_dump(fd
, val
->data
.func
, level
);
137 psi_num_exp_dump(fd
, val
->data
.num
);
145 dprintf(fd
, "\t/* fqn=%s */", val
->var
->fqn
);
157 bool psi_let_exp_validate(struct psi_data
*data
, struct psi_let_exp
*val
,
158 struct psi_impl
*impl
)
160 struct psi_decl_var
*dvar
= psi_let_exp_get_decl_var(val
);
164 if (!psi_decl_var_validate(data
, val
->data
.var
, impl
->decl
, val
, NULL
)) {
165 data
->error(data
, dvar
->token
? : **(struct psi_token
***) &val
->data
,
166 PSI_WARNING
, "Unknown variable '%s'", dvar
->name
);
172 if (!psi_decl_var_validate(data
, dvar
, impl
->decl
, val
, NULL
)) {
173 data
->error(data
, dvar
->token
? : **(struct psi_token
***) &val
->data
,
174 PSI_WARNING
, "Unknown variable '%s'", dvar
->name
);
184 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
185 /* e.g. let foo = *bar; */
186 val
->var
->pointer_level
= val
->data
.var
->pointer_level
;
187 val
->var
->arg
= val
->data
.var
->arg
;
190 if (!psi_num_exp_validate(data
, val
->data
.num
, impl
, NULL
, val
, NULL
, NULL
)) {
195 if (!psi_num_exp_validate(data
, val
->data
.alloc
->nmemb
, impl
, NULL
, val
, NULL
, NULL
)) {
198 if (!psi_num_exp_validate(data
, val
->data
.alloc
->size
, impl
, NULL
, val
, NULL
, NULL
)) {
202 case PSI_LET_CALLBACK
:
203 if (!psi_let_func_validate(data
, val
, val
->data
.callback
->func
, impl
)) {
206 if (!psi_let_callback_validate(data
, val
, val
->data
.callback
, impl
)) {
211 if (!psi_let_func_validate(data
, val
, val
->data
.func
, impl
)) {
220 void *psi_let_exp_exec(struct psi_let_exp
*val
, struct psi_decl_arg
*darg
,
221 void *actual_location
, size_t actual_size
, struct psi_call_frame
*frame
)
223 struct psi_call_frame_symbol
*frame_sym
;
225 frame_sym
= psi_call_frame_fetch_symbol(frame
, val
->var
);
229 /* FIXME: sizeof_decl_arg */
230 if (darg
&& darg
->var
->array_size
) {
231 frame_sym
->temp_val
.ptr
= ecalloc(1, psi_decl_arg_get_size(darg
));
233 memset(&frame_sym
->temp_val
, 0, sizeof(frame_sym
->temp_val
));
239 struct psi_let_stmt
*let_temp
= psi_impl_get_let(frame
->impl
,
241 struct psi_call_frame_symbol
*temp_arg
;
243 temp_arg
= psi_call_frame_fetch_symbol(frame
, let_temp
->exp
->var
);
244 frame_sym
->temp_val
= *deref_impl_val(temp_arg
->ptr
, val
->data
.var
);
250 zend_long n
= psi_long_num_exp(val
->data
.alloc
->nmemb
, frame
);
251 zend_long s
= psi_long_num_exp(val
->data
.alloc
->size
, frame
);
252 void *tmp
= *psi_call_frame_push_auto(frame
,
253 safe_emalloc(n
, s
, sizeof(void *)));
255 memset(tmp
, 0, n
* s
+ sizeof(void *));
256 frame_sym
->temp_val
.ptr
= tmp
;
261 frame_sym
->temp_val
.zend
.lval
= psi_long_num_exp(val
->data
.num
, frame
);
264 case PSI_LET_CALLBACK
:
265 frame_sym
->temp_val
.ptr
= val
->data
.callback
->decl
->sym
;
269 if (!psi_let_func_exec(val
, val
->data
.func
, darg
, frame
)) {
275 if (val
->is_reference
) {
276 frame_sym
->ptr
= &frame_sym
->ival_ptr
;
278 frame_sym
->ptr
= frame_sym
->ival_ptr
;
281 if (actual_location
) {
282 assert(!val
->is_reference
|| actual_size
== SIZEOF_VOID_P
);
283 memcpy(actual_location
, frame_sym
->ptr
, actual_size
);
284 frame_sym
->ptr
= actual_location
;
287 return frame_sym
->ptr
;
290 struct psi_let_func
* psi_let_exp_get_func(struct psi_let_exp
* exp
)
294 case PSI_LET_CALLBACK
:
295 return exp
->data
.callback
->func
;
297 return exp
->data
.func
;
305 struct psi_decl_var
*psi_let_exp_get_decl_var(struct psi_let_exp
*val
)
308 const char *name
= psi_let_exp_get_decl_var_name(val
);
311 val
->var
= psi_decl_var_init(name
, 0, 0);
317 struct psi_impl_var
*psi_let_exp_get_impl_var(struct psi_let_exp
*val
)
319 struct psi_let_func
* fn
= psi_let_exp_get_func(val
);
320 return fn
? fn
->var
: NULL
;
323 const char* psi_let_exp_get_decl_var_name(struct psi_let_exp
* val
)
325 struct psi_impl_var
* var
;
327 return val
->var
->name
;
329 var
= psi_let_exp_get_impl_var(val
);
331 return &var
->name
[1];