raising the head after a three-weeks refactoring
[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 #include "php_psi_stdinc.h"
27 #include "token.h"
28 #include "php_psi_stdtypes.h"
29 #include "data.h"
30
31 struct psi_decl_type *psi_decl_type_init(token_t type, const char *name)
32 {
33 struct psi_decl_type *t = calloc(1, sizeof(*t));
34 t->type = type;
35 t->name = strdup(name);
36 return t;
37 }
38
39 void psi_decl_type_free(struct psi_decl_type **type_ptr)
40 {
41 if (*type_ptr) {
42 struct psi_decl_type *type = *type_ptr;
43
44 *type_ptr = NULL;
45 if (type->token) {
46 free(type->token);
47 }
48 if (type->type == PSI_T_FUNCTION) {
49 psi_decl_free(&type->real.func);
50 }
51 free(type->name);
52 free(type);
53 }
54 }
55
56 struct psi_plist *psi_decl_type_get_args(struct psi_decl_type *dtyp,
57 struct psi_decl_type **real_typ_ptr)
58 {
59 struct psi_decl_type *var_typ;
60
61 var_typ = psi_decl_type_get_real(dtyp);
62 if (real_typ_ptr) {
63 *real_typ_ptr = var_typ;
64 }
65
66 switch (var_typ->type) {
67 case PSI_T_STRUCT:
68 return var_typ->real.strct->args;
69 case PSI_T_UNION:
70 return var_typ->real.unn->args;
71 default:
72 return NULL;
73 }
74 }
75
76 size_t psi_decl_type_get_size(struct psi_decl_type *dtyp,
77 struct psi_decl_type **real_typ_ptr)
78 {
79 struct psi_decl_type *var_typ;
80
81 var_typ = psi_decl_type_get_real(dtyp);
82 if (real_typ_ptr) {
83 *real_typ_ptr = var_typ;
84 }
85
86 switch (var_typ->type) {
87 case PSI_T_STRUCT:
88 return var_typ->real.strct->size;
89 case PSI_T_UNION:
90 return var_typ->real.unn->size;
91 default:
92 return psi_t_size(var_typ->type);
93 }
94 }
95
96 bool psi_decl_type_get_alias(struct psi_decl_type *type, struct psi_plist *defs)
97 {
98 size_t i = 0;
99 struct psi_std_type *stdtyp;
100 struct psi_decl_arg *def;
101
102 if (type->real.def) {
103 return true;
104 }
105 if (defs)
106 while (psi_plist_get(defs, i++, &def)) {
107 if (def->type->type != type->type
108 && !strcmp(def->var->name, type->name)) {
109 type->real.def = def;
110 return true;
111 }
112 }
113 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
114 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
115 type->type = stdtyp->type_tag;
116 return true;
117 }
118 }
119
120 return false;
121 }
122
123 bool psi_decl_type_get_struct(struct psi_decl_type *type, struct psi_plist *structs)
124 {
125 size_t i = 0;
126 struct psi_decl_struct *s;
127
128 if (type->real.strct) {
129 return true;
130 }
131 if (structs) {
132 while (psi_plist_get(structs, i++, &s)) {
133 if (!strcmp(s->name, type->name)) {
134 type->real.strct = s;
135 return true;
136 }
137 }
138 }
139 return false;
140 }
141
142 bool psi_decl_type_get_union(struct psi_decl_type *type, struct psi_plist *unions)
143 {
144 size_t i = 0;
145 struct psi_decl_union *u;
146
147 if (type->real.unn) {
148 return true;
149 }
150 if (unions) {
151 while (psi_plist_get(unions, i++, &u)) {
152 if (!strcmp(u->name, type->name)) {
153 type->real.unn = u;
154 return true;
155 }
156 }
157 }
158 return false;
159 }
160
161 bool psi_decl_type_get_enum(struct psi_decl_type *type, struct psi_plist *enums)
162 {
163 size_t i = 0;
164 struct psi_decl_enum *e;
165
166 if (type->real.enm) {
167 return true;
168 }
169 if (enums) {
170 while (psi_plist_get(enums, i++, &e)) {
171 if (!strcmp(e->name, type->name)) {
172 type->real.enm = e;
173 return true;
174 }
175 }
176 }
177 return false;
178 }
179
180 bool psi_decl_type_get_decl(struct psi_decl_type *type, struct psi_plist *decls)
181 {
182 size_t i = 0;
183 struct psi_decl *decl;
184
185 if (type->real.func) {
186 return true;
187 }
188 if (decls) {
189 while (psi_plist_get(decls, i++, &decl)) {
190 if (!strcmp(decl->func->var->name, type->name)) {
191 type->real.func = decl;
192 return true;
193 }
194 }
195 }
196 return false;
197 }
198
199 bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
200 struct psi_decl_arg *def)
201 {
202 if (psi_decl_type_is_weak(type)) {
203 if (!psi_decl_type_get_alias(type, data->types)) {
204 return false;
205 }
206 if (type->real.def) {
207 return psi_decl_type_validate(data, type->real.def->type,
208 type->real.def);
209 }
210 return true;
211 }
212
213 switch (type->type) {
214 case PSI_T_STRUCT:
215 if (!psi_decl_type_get_struct(type, data->structs) && !def) {
216 data->error(data, type->token, PSI_WARNING,
217 "Unknown struct '%s'", type->name);
218 return false;
219 }
220 break;
221 case PSI_T_UNION:
222 if (!psi_decl_type_get_union(type, data->unions) && !def) {
223 data->error(data, type->token, PSI_WARNING,
224 "Unknown union '%s'", type->name);
225 return false;
226 }
227 break;
228 case PSI_T_ENUM:
229 if (!psi_decl_type_get_enum(type, data->enums) && !def) {
230 data->error(data, type->token, PSI_WARNING,
231 "Unknown enum '%s'", type->name);
232 return false;
233 }
234 break;
235 case PSI_T_FUNCTION:
236 if (!psi_decl_type_get_decl(type, data->decls)) {
237 data->error(data, type->token, PSI_WARNING,
238 "Unknown decl '%s'", type->name);
239 return false;
240 }
241 if (!psi_decl_validate_nodl(data, type->real.func)) {
242 return false;
243 }
244 break;
245 }
246 return true;
247 }
248
249 void psi_decl_type_dump_args_with_layout(int fd, struct psi_plist *args,
250 unsigned level)
251 {
252 size_t i = 0;
253
254 dprintf(fd, " {\n");
255 if (args) {
256 struct psi_decl_arg *sarg;
257
258 ++level;
259 while (psi_plist_get(args, i++, &sarg)) {
260 dprintf(fd, "%s", psi_t_indent(level));
261 psi_decl_arg_dump(fd, sarg, level);
262 dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos,
263 sarg->layout->len);
264 }
265 --level;
266 }
267 dprintf(fd, "%s", psi_t_indent(level));
268 dprintf(fd, "}");
269 }
270
271 void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
272 {
273 switch (t->type) {
274 case PSI_T_POINTER:
275 dprintf(fd, "%s *", t->name);
276 return;
277
278 case PSI_T_ENUM:
279 dprintf(fd, "enum ");
280 if (psi_decl_type_is_anon(t->name, "enum")) {
281 size_t i = 0, c = psi_plist_count(t->real.enm->items);
282 struct psi_decl_enum_item *item;
283
284 dprintf(fd, "{\n");
285 ++level;
286 while (psi_plist_get(t->real.enm->items, i++, &item)) {
287 dprintf(fd, "%s", psi_t_indent(level));
288 psi_decl_enum_item_dump(fd, item);
289 if (i < c) {
290 dprintf(fd, "%s\n", i < c ? "," : "");
291 }
292 }
293 --level;
294 dprintf(fd, "%s} ", psi_t_indent(level));
295 return;
296 }
297 break;
298
299 case PSI_T_STRUCT:
300 dprintf(fd, "struct ");
301 if (psi_decl_type_is_anon(t->name, "struct")) {
302 psi_decl_type_dump_args_with_layout(fd, t->real.strct->args, level);
303 return;
304 }
305 break;
306
307 case PSI_T_UNION:
308 dprintf(fd, "union ");
309 if (psi_decl_type_is_anon(t->name, "union")) {
310 psi_decl_type_dump_args_with_layout(fd, t->real.unn->args, level);
311 return;
312 }
313 break;
314 }
315 dprintf(fd, "%s", t->name);
316 }
317
318 int psi_decl_type_is_weak(struct psi_decl_type *type)
319 {
320 switch (type->type) {
321 case PSI_T_CHAR:
322 case PSI_T_SHORT:
323 case PSI_T_INT:
324 case PSI_T_LONG:
325 case PSI_T_NAME:
326 return type->type;
327 default:
328 return 0;
329 }
330 }
331
332 struct psi_decl_type *psi_decl_type_get_real(struct psi_decl_type *type)
333 {
334 while (psi_decl_type_is_weak(type) && type->real.def) {
335 type = type->real.def->type;
336 }
337 return type;
338 }
339
340 size_t psi_decl_type_get_align(struct psi_decl_type *t)
341 {
342 struct psi_decl_type *real = psi_decl_type_get_real(t);
343 size_t align;
344
345 switch (real->type) {
346 case PSI_T_STRUCT:
347 align = psi_decl_struct_get_align(real->real.strct);
348 break;
349 case PSI_T_UNION:
350 align = psi_decl_union_get_align(real->real.unn);
351 break;
352 case PSI_T_ENUM:
353 default:
354 align = psi_t_alignment(real->type);
355 }
356
357 return align;
358 }
359
360 size_t psi_decl_type_get_args_align(struct psi_plist *args)
361 {
362 size_t i = 0, maxalign = 0;
363 struct psi_decl_arg *darg;
364
365 while (psi_plist_get(args, i++, &darg)) {
366 size_t align = psi_decl_arg_get_align(darg);
367
368 if (align > maxalign) {
369 maxalign = align;
370 }
371 }
372
373 return maxalign;
374 }
375