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"
31 #include "php_psi_posix.h"
33 struct psi_decl_type
*psi_decl_type_init(token_t type
, zend_string
*name
)
35 struct psi_decl_type
*t
= calloc(1, sizeof(*t
));
37 t
->name
= zend_string_copy(name
);
41 void psi_decl_type_free(struct psi_decl_type
**type_ptr
)
44 struct psi_decl_type
*type
= *type_ptr
;
47 psi_token_free(&type
->token
);
48 if (type
->type
== PSI_T_FUNCTION
) {
49 psi_decl_free(&type
->real
.func
);
51 zend_string_release(type
->name
);
56 struct psi_decl_type
*psi_decl_type_copy(struct psi_decl_type
*src
)
58 struct psi_decl_type
*dst
= calloc(1, sizeof(*dst
));
60 dst
->type
= src
->type
;
62 dst
->name
= zend_string_copy(src
->name
);
65 dst
->token
= psi_token_copy(src
->token
);
70 struct psi_plist
*psi_decl_type_get_args(struct psi_decl_type
*dtyp
,
71 struct psi_decl_type
**real_typ_ptr
)
73 struct psi_decl_type
*var_typ
;
75 var_typ
= psi_decl_type_get_real(dtyp
);
77 *real_typ_ptr
= var_typ
;
80 switch (var_typ
->type
) {
82 return var_typ
->real
.strct
->args
;
84 return var_typ
->real
.unn
->args
;
90 size_t psi_decl_type_get_size(struct psi_decl_type
*dtyp
,
91 struct psi_decl_type
**real_typ_ptr
)
93 struct psi_decl_type
*var_typ
;
95 var_typ
= psi_decl_type_get_real(dtyp
);
97 *real_typ_ptr
= var_typ
;
100 switch (var_typ
->type
) {
102 return var_typ
->real
.strct
? var_typ
->real
.strct
->size
: 0;
104 return var_typ
->real
.unn
? var_typ
->real
.unn
->size
: 0;
106 return psi_t_size(var_typ
->type
);
110 bool psi_decl_type_get_alias(struct psi_decl_type
*type
, struct psi_plist
*defs
)
113 struct psi_std_type
*stdtyp
;
114 struct psi_decl_arg
*def
;
116 if (type
->real
.def
) {
120 while (psi_plist_get(defs
, i
++, &def
)) {
121 if (zend_string_equals(def
->var
->name
, type
->name
)) {
122 type
->real
.def
= def
;
127 for (stdtyp
= &psi_std_types
[0]; stdtyp
->type_tag
; ++stdtyp
) {
128 if (!strcmp(type
->name
->val
, stdtyp
->alias
?: stdtyp
->type_name
)) {
129 type
->type
= stdtyp
->type_tag
;
137 bool psi_decl_type_get_struct(struct psi_decl_type
*type
, struct psi_plist
*structs
)
140 struct psi_decl_struct
*s
;
142 if (type
->real
.strct
) {
146 while (psi_plist_get(structs
, i
++, &s
)) {
147 if (zend_string_equals(s
->name
, type
->name
)) {
148 type
->real
.strct
= s
;
156 bool psi_decl_type_get_union(struct psi_decl_type
*type
, struct psi_plist
*unions
)
159 struct psi_decl_union
*u
;
161 if (type
->real
.unn
) {
165 while (psi_plist_get(unions
, i
++, &u
)) {
166 if (zend_string_equals(u
->name
, type
->name
)) {
175 bool psi_decl_type_get_enum(struct psi_decl_type
*type
, struct psi_plist
*enums
)
178 struct psi_decl_enum
*e
;
180 if (type
->real
.enm
) {
184 while (psi_plist_get(enums
, i
++, &e
)) {
185 if (zend_string_equals(e
->name
, type
->name
)) {
194 bool psi_decl_type_get_decl(struct psi_decl_type
*type
, struct psi_plist
*decls
)
197 struct psi_decl
*decl
;
199 if (type
->real
.func
) {
203 while (psi_plist_get(decls
, i
++, &decl
)) {
204 if (zend_string_equals(decl
->func
->var
->name
, type
->name
)) {
205 type
->real
.func
= decl
;
213 bool psi_decl_type_validate(struct psi_data
*data
, struct psi_decl_type
*type
,
214 struct psi_decl_arg
*def
, struct psi_validate_scope
*scope
)
216 if (psi_decl_type_is_weak(type
)) {
217 if (!psi_decl_type_get_alias(type
, data
->types
)) {
218 if (!psi_validate_scope_has_type(scope
, type
->name
)) {
221 type
->real
.def
= psi_validate_scope_get_type(scope
, type
->name
);
223 if (type
->real
.def
) {
224 if (!psi_decl_type_validate(data
, type
->real
.def
->type
,
225 type
->real
.def
, scope
)) {
229 def
->var
->pointer_level
+= type
->real
.def
->var
->pointer_level
;
235 switch (type
->type
) {
237 if (!psi_decl_type_get_struct(type
, data
->structs
)) {
238 if (psi_validate_scope_has_struct(scope
, type
->name
)) {
239 type
->real
.strct
= psi_validate_scope_get_struct(scope
, type
->name
);
240 } else if (def
&& def
->var
->pointer_level
) {
243 data
->error(data
, type
->token
, PSI_WARNING
,
244 "Unknown struct '%s'", type
->name
->val
);
248 if (!psi_decl_struct_validate(data
, type
->real
.strct
, scope
)) {
253 if (!psi_decl_type_get_union(type
, data
->unions
)) {
254 if (psi_validate_scope_has_union(scope
, type
->name
)) {
255 type
->real
.unn
= psi_validate_scope_get_union(scope
, type
->name
);
256 } else if (def
&& def
->var
->pointer_level
) {
259 data
->error(data
, type
->token
, PSI_WARNING
,
260 "Unknown union '%s'", type
->name
->val
);
264 if (!psi_decl_union_validate(data
, type
->real
.unn
, scope
)) {
269 if (!psi_decl_type_get_enum(type
, data
->enums
)) {
270 data
->error(data
, type
->token
, PSI_WARNING
,
271 "Unknown enum '%s'", type
->name
->val
);
276 if (!psi_decl_type_get_decl(type
, data
->decls
)) {
277 data
->error(data
, type
->token
, PSI_WARNING
,
278 "Unknown decl '%s'", type
->name
->val
);
281 if (!psi_decl_validate_nodl(data
, type
->real
.func
, scope
)) {
292 void psi_decl_type_dump_args_with_layout(int fd
, struct psi_plist
*args
,
299 struct psi_decl_arg
*sarg
;
302 while (psi_plist_get(args
, i
++, &sarg
)) {
303 dprintf(fd
, "%s", psi_t_indent(level
));
304 psi_decl_arg_dump(fd
, sarg
, level
);
306 if (sarg
->layout
->bfw
) {
307 dprintf(fd
, ":%zu", sarg
->layout
->bfw
->len
);
309 dprintf(fd
, "::(%zu, %zu);\n", sarg
->layout
->pos
,
317 dprintf(fd
, "%s", psi_t_indent(level
));
321 void psi_decl_type_dump(int fd
, struct psi_decl_type
*t
, unsigned level
)
325 dprintf(fd
, "%s *", t
->name
->val
);
329 dprintf(fd
, "enum ");
330 if (psi_decl_type_is_anon(t
->name
, "enum")) {
331 size_t i
= 0, c
= psi_plist_count(t
->real
.enm
->items
);
332 struct psi_decl_enum_item
*item
;
336 while (psi_plist_get(t
->real
.enm
->items
, i
++, &item
)) {
337 dprintf(fd
, "%s", psi_t_indent(level
));
338 psi_decl_enum_item_dump(fd
, item
);
340 dprintf(fd
, "%s\n", i
< c
? "," : "");
344 dprintf(fd
, "%s\n} ", psi_t_indent(level
));
350 dprintf(fd
, "struct ");
351 if (psi_decl_type_is_anon(t
->name
, "struct")) {
352 psi_decl_type_dump_args_with_layout(fd
, t
->real
.strct
->args
, level
);
358 dprintf(fd
, "union ");
359 if (psi_decl_type_is_anon(t
->name
, "union")) {
360 psi_decl_type_dump_args_with_layout(fd
, t
->real
.unn
->args
, level
);
366 psi_decl_type_dump(fd
, t
->real
.func
->func
->type
, level
);
373 dprintf(fd
, "%s", t
->name
->val
);
376 int psi_decl_type_is_weak(struct psi_decl_type
*type
)
378 switch (type
->type
) {
392 struct psi_decl_type
*psi_decl_type_get_real(struct psi_decl_type
*type
)
394 while (psi_decl_type_is_weak(type
) && type
->real
.def
) {
395 type
= type
->real
.def
->type
;
400 size_t psi_decl_type_get_align(struct psi_decl_type
*t
)
402 struct psi_decl_type
*real
= psi_decl_type_get_real(t
);
405 switch (real
->type
) {
407 align
= psi_decl_struct_get_align(real
->real
.strct
);
410 align
= psi_decl_union_get_align(real
->real
.unn
);
414 align
= psi_t_alignment(real
->type
);
421 size_t psi_decl_type_get_args_align(struct psi_plist
*args
)
423 size_t i
= 0, maxalign
= 0;
424 struct psi_decl_arg
*darg
;
426 while (psi_plist_get(args
, i
++, &darg
)) {
427 size_t align
= psi_decl_arg_get_align(darg
);
429 if (align
> maxalign
) {