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"
35 #include "php_psi_predef.h"
37 struct psi_decl_type
*psi_decl_type_init(token_t type
, zend_string
*name
)
39 struct psi_decl_type
*t
= pecalloc(1, sizeof(*t
), 1);
41 t
->name
= zend_string_copy(name
);
45 void psi_decl_type_free(struct psi_decl_type
**type_ptr
)
48 struct psi_decl_type
*type
= *type_ptr
;
51 psi_token_free(&type
->token
);
52 if (type
->type
== PSI_T_FUNCTION
) {
53 psi_decl_free(&type
->real
.func
);
55 zend_string_release(type
->name
);
60 struct psi_decl_type
*psi_decl_type_copy(struct psi_decl_type
*src
)
62 struct psi_decl_type
*dst
= pecalloc(1, sizeof(*dst
), 1);
64 dst
->type
= src
->type
;
66 dst
->name
= zend_string_copy(src
->name
);
69 dst
->token
= psi_token_copy(src
->token
);
74 struct psi_plist
*psi_decl_type_get_args(struct psi_decl_type
*dtyp
,
75 struct psi_decl_type
**real_typ_ptr
)
77 struct psi_decl_type
*var_typ
;
79 var_typ
= psi_decl_type_get_real(dtyp
);
81 *real_typ_ptr
= var_typ
;
84 switch (var_typ
->type
) {
86 return var_typ
->real
.strct
->args
;
88 return var_typ
->real
.unn
->args
;
94 size_t psi_decl_type_get_size(struct psi_decl_type
*dtyp
,
95 struct psi_decl_type
**real_typ_ptr
)
97 struct psi_decl_type
*var_typ
;
99 var_typ
= psi_decl_type_get_real(dtyp
);
101 *real_typ_ptr
= var_typ
;
104 switch (var_typ
->type
) {
106 return var_typ
->real
.strct
? var_typ
->real
.strct
->size
: 0;
108 return var_typ
->real
.unn
? var_typ
->real
.unn
->size
: 0;
110 return psi_t_size(var_typ
->type
);
114 bool psi_decl_type_get_alias(struct psi_decl_type
*type
, struct psi_plist
*defs
)
117 struct psi_std_type
*stdtyp
;
118 struct psi_decl_arg
*def
;
120 if (type
->real
.def
) {
124 while (psi_plist_get(defs
, i
++, &def
)) {
125 if (zend_string_equals(def
->var
->name
, type
->name
)) {
126 type
->real
.def
= def
;
131 for (stdtyp
= &psi_std_types
[0]; stdtyp
->type_tag
; ++stdtyp
) {
132 if (!strcmp(type
->name
->val
, stdtyp
->alias
?: stdtyp
->type_name
)) {
133 type
->type
= stdtyp
->type_tag
;
141 bool psi_decl_type_get_struct(struct psi_decl_type
*type
, struct psi_plist
*structs
)
144 struct psi_decl_struct
*s
;
146 if (type
->real
.strct
) {
150 while (psi_plist_get(structs
, i
++, &s
)) {
151 if (zend_string_equals(s
->name
, type
->name
)) {
152 type
->real
.strct
= s
;
160 bool psi_decl_type_get_union(struct psi_decl_type
*type
, struct psi_plist
*unions
)
163 struct psi_decl_union
*u
;
165 if (type
->real
.unn
) {
169 while (psi_plist_get(unions
, i
++, &u
)) {
170 if (zend_string_equals(u
->name
, type
->name
)) {
179 bool psi_decl_type_get_enum(struct psi_decl_type
*type
, struct psi_plist
*enums
)
182 struct psi_decl_enum
*e
;
184 if (type
->real
.enm
) {
188 while (psi_plist_get(enums
, i
++, &e
)) {
189 if (zend_string_equals(e
->name
, type
->name
)) {
198 bool psi_decl_type_get_decl(struct psi_decl_type
*type
, struct psi_plist
*decls
)
201 struct psi_decl
*decl
;
203 if (type
->real
.func
) {
207 while (psi_plist_get(decls
, i
++, &decl
)) {
208 if (zend_string_equals(decl
->func
->var
->name
, type
->name
)) {
209 type
->real
.func
= decl
;
217 bool psi_decl_type_validate(struct psi_data
*data
, struct psi_decl_type
*type
,
218 struct psi_decl_arg
*def
, struct psi_validate_scope
*scope
)
220 if (psi_decl_type_is_weak(type
)) {
221 if (!psi_decl_type_get_alias(type
, data
->types
)) {
222 if (!psi_validate_scope_has_type(scope
, type
->name
)) {
225 type
->real
.def
= psi_validate_scope_get_type(scope
, type
->name
);
227 if (type
->real
.def
) {
228 if (!psi_decl_type_validate(data
, type
->real
.def
->type
,
229 type
->real
.def
, scope
)) {
233 def
->var
->pointer_level
+= type
->real
.def
->var
->pointer_level
;
239 switch (type
->type
) {
241 if (!psi_decl_type_get_struct(type
, data
->structs
)) {
242 if (psi_validate_scope_has_struct(scope
, type
->name
)) {
243 type
->real
.strct
= psi_validate_scope_get_struct(scope
, type
->name
);
244 } else if (def
&& def
->var
->pointer_level
) {
247 data
->error(data
, type
->token
, PSI_WARNING
,
248 "Unknown struct '%s'", type
->name
->val
);
252 if (!psi_decl_struct_validate(data
, type
->real
.strct
, scope
)) {
257 if (!psi_decl_type_get_union(type
, data
->unions
)) {
258 if (psi_validate_scope_has_union(scope
, type
->name
)) {
259 type
->real
.unn
= psi_validate_scope_get_union(scope
, type
->name
);
260 } else if (def
&& def
->var
->pointer_level
) {
263 data
->error(data
, type
->token
, PSI_WARNING
,
264 "Unknown union '%s'", type
->name
->val
);
268 if (!psi_decl_union_validate(data
, type
->real
.unn
, scope
)) {
273 if (!psi_decl_type_get_enum(type
, data
->enums
)) {
274 data
->error(data
, type
->token
, PSI_WARNING
,
275 "Unknown enum '%s'", type
->name
->val
);
280 if (!psi_decl_type_get_decl(type
, data
->decls
)) {
281 data
->error(data
, type
->token
, PSI_WARNING
,
282 "Unknown decl '%s'", type
->name
->val
);
285 if (!psi_decl_validate_nodl(data
, type
->real
.func
, scope
)) {
296 void psi_decl_type_dump_args_with_layout(struct psi_dump
*dump
, struct psi_plist
*args
,
301 PSI_DUMP(dump
, " {\n");
303 struct psi_decl_arg
*sarg
;
306 while (psi_plist_get(args
, i
++, &sarg
)) {
307 PSI_DUMP(dump
, "%s", psi_t_indent(level
));
308 psi_decl_arg_dump(dump
, sarg
, level
);
310 if (sarg
->layout
->bfw
) {
311 PSI_DUMP(dump
, ":%zu", sarg
->layout
->bfw
->len
);
313 PSI_DUMP(dump
, "::(%zu, %zu);\n", sarg
->layout
->pos
,
316 PSI_DUMP(dump
, ";\n");
321 PSI_DUMP(dump
, "%s", psi_t_indent(level
));
325 void psi_decl_type_dump(struct psi_dump
*dump
, struct psi_decl_type
*t
, unsigned level
)
329 PSI_DUMP(dump
, "%s *", t
->name
->val
);
333 if (psi_decl_type_is_anon(t
->name
, "enum")) {
334 psi_decl_enum_dump(dump
, t
->real
.enm
, level
);
337 PSI_DUMP(dump
, "enum ");
341 PSI_DUMP(dump
, "struct ");
342 if (psi_decl_type_is_anon(t
->name
, "struct")) {
343 PSI_DUMP(dump
, "/*::(%zu, %zu)*/", t
->real
.strct
->align
, t
->real
.strct
->size
);
344 psi_decl_type_dump_args_with_layout(dump
, t
->real
.strct
->args
, level
);
350 PSI_DUMP(dump
, "union ");
351 if (psi_decl_type_is_anon(t
->name
, "union")) {
352 PSI_DUMP(dump
, "/*::(%zu, %zu)*/", t
->real
.unn
->align
, t
->real
.unn
->size
);
353 psi_decl_type_dump_args_with_layout(dump
, t
->real
.unn
->args
, level
);
359 psi_decl_type_dump(dump
, t
->real
.func
->func
->type
, level
);
366 PSI_DUMP(dump
, "%s", t
->name
->val
);
369 int psi_decl_type_is_weak(struct psi_decl_type
*type
)
371 switch (type
->type
) {
385 struct psi_decl_type
*psi_decl_type_get_real(struct psi_decl_type
*type
)
387 while (psi_decl_type_is_weak(type
) && type
->real
.def
) {
388 type
= type
->real
.def
->type
;
393 size_t psi_decl_type_get_align(struct psi_decl_type
*t
)
395 struct psi_decl_type
*real
= psi_decl_type_get_real(t
);
398 switch (real
->type
) {
400 align
= psi_decl_struct_get_align(real
->real
.strct
);
403 align
= psi_decl_union_get_align(real
->real
.unn
);
407 align
= psi_t_alignment(real
->type
);
414 size_t psi_decl_type_get_args_align(struct psi_plist
*args
)
416 size_t i
= 0, maxalign
= 0;
417 struct psi_decl_arg
*darg
;
419 while (psi_plist_get(args
, i
++, &darg
)) {
420 size_t align
= psi_decl_arg_get_align(darg
);
422 if (align
> maxalign
) {