3be8e88d3f99fbb9fd641fe2368c2e8de849719e
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 *******************************************************************************/
29 # include "php_config.h"
38 let_val
*init_let_val(enum let_val_kind kind
, void *data
) {
39 let_val
*let
= calloc(1, sizeof(*let
));
40 switch (let
->kind
= kind
) {
47 let
->data
.alloc
= data
;
49 case PSI_LET_CALLBACK
:
50 let
->data
.callback
= data
;
53 let
->data
.func
= data
;
64 void free_let_val(let_val
*let
) {
69 free_num_exp(let
->data
.num
);
72 free_let_calloc(let
->data
.alloc
);
74 case PSI_LET_CALLBACK
:
75 free_let_callback(let
->data
.callback
);
78 free_let_func(let
->data
.func
);
81 free_decl_var(let
->data
.var
);
89 void dump_let_val(int fd
, let_val
*val
, unsigned level
, int last
) {
91 /* only if not directly after `set ...` */
92 dprintf(fd
, "%s", psi_t_indent(level
));
95 dprintf(fd
, "%s", val
->flags
.one
.is_reference
? "&" : "");
102 dump_decl_var(fd
, val
->data
.var
);
105 dprintf(fd
, "calloc(");
106 dump_num_exp(fd
, val
->data
.alloc
->nmemb
);
108 dump_num_exp(fd
, val
->data
.alloc
->size
);
111 case PSI_LET_CALLBACK
:
112 dprintf(fd
, "callback %s(%s(", val
->data
.callback
->func
->name
,
113 val
->data
.callback
->func
->var
->name
);
114 if (val
->data
.callback
->args
) {
115 size_t i
, c
= val
->data
.callback
->args
->count
;
118 for (i
= 0; i
< c
; ++i
) {
119 set_value
*set
= val
->data
.callback
->args
->vals
[i
];
121 dump_set_value(fd
, set
, level
, i
+ 1 == c
);
124 dprintf(fd
, "%s", psi_t_indent(level
));
129 dump_let_func(fd
, val
->data
.func
, level
);
132 dump_num_exp(fd
, val
->data
.num
);
148 int validate_let_val(struct psi_data
*data
, let_val
*val
, decl_var
*let_var
, impl
*impl
) {
154 data
->error(data
, NULL
, PSI_WARNING
,
155 "Ivalid let statement value of implementation '%s'",
159 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
160 /* e.g. let foo = *bar; */
161 let_var
->pointer_level
= val
->data
.var
->pointer_level
;
162 let_var
->arg
= init_decl_arg(
164 real_decl_type(val
->data
.var
->arg
->type
)->type
,
165 real_decl_type(val
->data
.var
->arg
->type
)->name
),
168 let_var
->pointer_level
,
169 let_var
->array_size
));
172 if (!validate_num_exp(data
, val
->data
.num
, impl
->decl
->args
, impl
->decl
->func
, NULL
)) {
177 if (!validate_num_exp(data
, val
->data
.alloc
->nmemb
, impl
->decl
->args
, impl
->decl
->func
, NULL
)) {
180 if (!validate_num_exp(data
, val
->data
.alloc
->size
, impl
->decl
->args
, impl
->decl
->func
, NULL
)) {
184 case PSI_LET_CALLBACK
:
186 data
->error(data
, NULL
, PSI_WARNING
,
187 "Ivalid let statement value of implementation '%s'",
191 if (val
->data
.callback
->func
->inner
) {
193 decl_type
*var_typ
= real_decl_type(let_var
->arg
->type
);
196 switch (var_typ
->type
) {
198 sub_args
= var_typ
->real
.strct
->args
;
201 sub_args
= var_typ
->real
.unn
->args
;
204 data
->error(data
, let_var
->token
, PSI_WARNING
,
205 "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
206 real_decl_type(let_var
->arg
->type
)->name
, let_var
->name
);
209 for (i
= 0; i
< val
->data
.callback
->func
->inner
->count
; ++i
) {
210 let_val
*inner
= val
->data
.callback
->func
->inner
->vals
[i
];
211 switch (inner
->kind
) {
213 inner
->data
.func
->outer
= val
;
214 inner
->data
.func
->ref
= locate_decl_arg(sub_args
,
215 &inner
->data
.func
->var
->name
[1]);
219 case PSI_LET_CALLBACK
:
220 inner
->data
.callback
->func
->outer
= val
;
221 inner
->data
.callback
->func
->ref
= locate_decl_arg(sub_args
,
222 &inner
->data
.callback
->func
->var
->name
[1]);
227 if (!validate_let_callback(data
, let_var
, val
->data
.callback
, impl
)) {
232 if (val
->data
.func
->inner
) {
234 decl_type
*var_typ
= real_decl_type(let_var
->arg
->type
);
237 switch (var_typ
->type
) {
239 sub_args
= var_typ
->real
.strct
->args
;
242 sub_args
= var_typ
->real
.unn
->args
;
245 data
->error(data
, let_var
->token
, PSI_WARNING
,
246 "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
247 real_decl_type(let_var
->arg
->type
)->name
, let_var
->name
);
250 for (i
= 0; i
< val
->data
.func
->inner
->count
; ++i
) {
251 let_val
*inner
= val
->data
.func
->inner
->vals
[i
];
252 switch (inner
->kind
) {
254 inner
->data
.func
->outer
= val
;
255 inner
->data
.func
->ref
= locate_decl_arg(sub_args
,
256 &inner
->data
.func
->var
->name
[1]);
258 case PSI_LET_CALLBACK
:
259 inner
->data
.callback
->func
->outer
= val
;
260 inner
->data
.callback
->func
->ref
= locate_decl_arg(sub_args
,
261 &inner
->data
.callback
->func
->var
->name
[1]);
269 if (!validate_let_func(data
, val
->data
.func
, let_var
, impl
)) {