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