flush
[m6w6/ext-psi] / src / types / decl_type.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
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.
13
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 *******************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #else
29 # include "php_config.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <stdio.h>
34
35 #include "token.h"
36 #include "php_psi_stdtypes.h"
37
38 #include "data.h"
39
40 decl_type *init_decl_type(token_t type, const char *name) {
41 decl_type *t = calloc(1, sizeof(*t));
42 t->type = type;
43 t->name = strdup(name);
44 return t;
45 }
46
47 void free_decl_type(decl_type *type) {
48 if (type->token) {
49 free(type->token);
50 }
51 if (type->type == PSI_T_FUNCTION) {
52 free_decl(type->real.func);
53 }
54 free(type->name);
55 free(type);
56 }
57
58 decl_args *extract_decl_type_args(decl_type *dtyp, decl_type **real_typ_ptr) {
59 decl_type *var_typ;
60 var_typ = real_decl_type(dtyp);
61 if (real_typ_ptr) {
62 *real_typ_ptr = var_typ;
63 }
64 switch (var_typ->type) {
65 case PSI_T_STRUCT:
66 return var_typ->real.strct->args;
67 case PSI_T_UNION:
68 return var_typ->real.unn->args;
69 default:
70 return NULL;
71 }
72 }
73
74 size_t extract_decl_type_size(decl_type *dtyp, decl_type **real_typ_ptr) {
75 decl_type *var_typ;
76 var_typ = real_decl_type(dtyp);
77 if (real_typ_ptr) {
78 *real_typ_ptr = var_typ;
79 }
80 switch (var_typ->type) {
81 case PSI_T_STRUCT:
82 return var_typ->real.strct->size;
83 case PSI_T_UNION:
84 return var_typ->real.unn->size;
85 default:
86 return psi_t_size(var_typ->type);
87 }
88 }
89
90
91
92 int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
93 size_t i;
94 struct psi_std_type *stdtyp;
95
96 if (type->real.def) {
97 return 1;
98 }
99 if (defs) for (i = 0; i < defs->count; ++i) {
100 decl_arg *def = defs->list[i];
101
102 if (def->type->type != type->type && !strcmp(def->var->name, type->name)) {
103 type->real.def = def;
104 return 1;
105 }
106 }
107 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
108 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
109 type->type = stdtyp->type_tag;
110 return 1;
111 }
112 }
113
114 return 0;
115 }
116
117 int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
118 size_t i;
119
120 if (type->real.strct) {
121 return 1;
122 }
123 if (structs) for (i = 0; i < structs->count; ++i) {
124 if (!strcmp(structs->list[i]->name, type->name)) {
125 type->real.strct = structs->list[i];
126 return 1;
127 }
128 }
129 return 0;
130 }
131
132 int locate_decl_type_union(decl_unions *unions, decl_type *type) {
133 size_t i;
134
135 if (type->real.unn) {
136 return 1;
137 }
138 if (unions) for (i = 0; i < unions->count; ++i) {
139 if (!strcmp(unions->list[i]->name, type->name)) {
140 type->real.unn = unions->list[i];
141 return 1;
142 }
143 }
144 return 0;
145 }
146
147 int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
148 size_t i;
149
150 if (type->real.enm) {
151 return 1;
152 }
153 if (enums) for (i = 0; i < enums->count; ++i) {
154 if (!strcmp(enums->list[i]->name, type->name)) {
155 type->real.enm = enums->list[i];
156 return 1;
157 }
158 }
159 return 0;
160 }
161
162 int locate_decl_type_decl(decls *decls, decl_type *type) {
163 size_t i;
164
165 if (type->real.func) {
166 return 1;
167 }
168 if (decls) for (i = 0; i < decls->count; ++i) {
169 if (!strcmp(decls->list[i]->func->var->name, type->name)) {
170 type->real.func = decls->list[i];
171 return 1;
172 }
173 }
174
175 return 0;
176 }
177
178 int validate_decl_type(struct psi_data *data, decl_type *type, decl_arg *def) {
179 if (weak_decl_type(type)) {
180 if (!locate_decl_type_alias(data->defs, type)) {
181 return 0;
182 }
183 if (type->real.def) {
184 return validate_decl_type(data, type->real.def->type, type->real.def);
185 }
186 return 1;
187 }
188
189 switch (type->type) {
190 case PSI_T_STRUCT:
191 if (!locate_decl_type_struct(data->structs, type)) {
192 return 0;
193 }
194 break;
195 case PSI_T_UNION:
196 if (!locate_decl_type_union(data->unions, type)) {
197 return 0;
198 }
199 break;
200 case PSI_T_ENUM:
201 if (!locate_decl_type_enum(data->enums, type)) {
202 return 0;
203 }
204 break;
205 case PSI_T_FUNCTION:
206 if (!locate_decl_type_decl(data->decls, type)) {
207 return 0;
208 }
209 if (!validate_decl_nodl(data, type->real.func)) {
210 return 0;
211 }
212 break;
213 }
214 return 1;
215 }
216
217 void dump_decl_type(int fd, decl_type *t, unsigned level) {
218 switch (t->type) {
219 case PSI_T_POINTER:
220 dprintf(fd, "%s *", t->name);
221 return;
222
223 case PSI_T_ENUM:
224 dprintf(fd, "enum ");
225 if (is_anon_type(t->name, "enum")) {
226 dump_decl_enum_items(fd, t->real.enm->items, level);
227 return;
228 }
229 break;
230
231 case PSI_T_STRUCT:
232 dprintf(fd, "struct ");
233 if (is_anon_type(t->name, "struct")) {
234 dump_decl_args_with_layout(fd, t->real.strct->args, level);
235 return;
236 }
237 break;
238
239 case PSI_T_UNION:
240 dprintf(fd, "union ");
241 if (is_anon_type(t->name, "union")) {
242 dump_decl_args_with_layout(fd, t->real.unn->args, level);
243 return;
244 }
245 break;
246 }
247 dprintf(fd, "%s", t->name);
248 }
249
250 int weak_decl_type(decl_type *type) {
251 switch (type->type) {
252 case PSI_T_CHAR:
253 case PSI_T_SHORT:
254 case PSI_T_INT:
255 case PSI_T_LONG:
256 case PSI_T_NAME:
257 return type->type;
258 default:
259 return 0;
260 }
261 }
262
263 decl_type *real_decl_type(decl_type *type) {
264 while (weak_decl_type(type) && type->real.def) {
265 type = type->real.def->type;
266 }
267 return type;
268 }
269
270 size_t alignof_decl_type(decl_type *t) {
271 decl_type *real = real_decl_type(t);
272 size_t align;
273
274 switch (real->type) {
275 case PSI_T_STRUCT:
276 align = alignof_decl_struct(real->real.strct);
277 break;
278 case PSI_T_UNION:
279 align = alignof_decl_union(real->real.unn);
280 break;
281 case PSI_T_ENUM:
282 default:
283 align = psi_t_alignment(real->type);
284 }
285
286 return align;
287 }