afab9e307cae40995b9bd14abb91e6336d0f6a1b
[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 (def->type->type != type->type
124 && !strcmp(def->var->name, type->name)) {
125 type->real.def = def;
126 return true;
127 }
128 }
129 }
130 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
131 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
132 type->type = stdtyp->type_tag;
133 return true;
134 }
135 }
136
137 return false;
138 }
139
140 bool psi_decl_type_get_struct(struct psi_decl_type *type, struct psi_plist *structs)
141 {
142 size_t i = 0;
143 struct psi_decl_struct *s;
144
145 if (type->real.strct) {
146 return true;
147 }
148 if (structs) {
149 while (psi_plist_get(structs, i++, &s)) {
150 if (!strcmp(s->name, type->name)) {
151 type->real.strct = s;
152 return true;
153 }
154 }
155 }
156 return false;
157 }
158
159 bool psi_decl_type_get_union(struct psi_decl_type *type, struct psi_plist *unions)
160 {
161 size_t i = 0;
162 struct psi_decl_union *u;
163
164 if (type->real.unn) {
165 return true;
166 }
167 if (unions) {
168 while (psi_plist_get(unions, i++, &u)) {
169 if (!strcmp(u->name, type->name)) {
170 type->real.unn = u;
171 return true;
172 }
173 }
174 }
175 return false;
176 }
177
178 bool psi_decl_type_get_enum(struct psi_decl_type *type, struct psi_plist *enums)
179 {
180 size_t i = 0;
181 struct psi_decl_enum *e;
182
183 if (type->real.enm) {
184 return true;
185 }
186 if (enums) {
187 while (psi_plist_get(enums, i++, &e)) {
188 if (!strcmp(e->name, type->name)) {
189 type->real.enm = e;
190 return true;
191 }
192 }
193 }
194 return false;
195 }
196
197 bool psi_decl_type_get_decl(struct psi_decl_type *type, struct psi_plist *decls)
198 {
199 size_t i = 0;
200 struct psi_decl *decl;
201
202 if (type->real.func) {
203 return true;
204 }
205 if (decls) {
206 while (psi_plist_get(decls, i++, &decl)) {
207 if (!strcmp(decl->func->var->name, type->name)) {
208 type->real.func = decl;
209 return true;
210 }
211 }
212 }
213 return false;
214 }
215
216 bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
217 bool is_pointer, struct psi_validate_stack *type_stack)
218 {
219 if (psi_decl_type_is_weak(type)) {
220 if (!psi_decl_type_get_alias(type, data->types)) {
221 if (!psi_validate_stack_has_type(type_stack, type->name)) {
222 return false;
223 }
224 type->real.def = psi_validate_stack_get_type(type_stack, type->name);
225 }
226 if (type->real.def) {
227 return psi_decl_type_validate(data, type->real.def->type,
228 is_pointer, type_stack);
229 }
230 return true;
231 }
232
233 switch (type->type) {
234 case PSI_T_STRUCT:
235 if (!psi_decl_type_get_struct(type, data->structs)) {
236 if (psi_validate_stack_has_struct(type_stack, type->name)) {
237 type->real.strct = psi_validate_stack_get_struct(type_stack, type->name);
238 } else if (is_pointer) {
239 return true;
240 } else {
241 data->error(data, type->token, PSI_WARNING,
242 "Unknown struct '%s'", type->name);
243 return false;
244 }
245 }
246 if (!psi_decl_struct_validate(data, type->real.strct, type_stack)) {
247 return false;
248 }
249 break;
250 case PSI_T_UNION:
251 if (!psi_decl_type_get_union(type, data->unions)) {
252 if (psi_validate_stack_has_union(type_stack, type->name)) {
253 type->real.unn = psi_validate_stack_get_union(type_stack, type->name);
254 } else if (is_pointer) {
255 return true;
256 } else {
257 data->error(data, type->token, PSI_WARNING,
258 "Unknown union '%s'", type->name);
259 return false;
260 }
261 }
262 if (!psi_decl_union_validate(data, type->real.unn, type_stack)) {
263 return false;
264 }
265 break;
266 case PSI_T_ENUM:
267 if (!psi_decl_type_get_enum(type, data->enums)) {
268 data->error(data, type->token, PSI_WARNING,
269 "Unknown enum '%s'", type->name);
270 return false;
271 }
272 break;
273 case PSI_T_FUNCTION:
274 if (!psi_decl_type_get_decl(type, data->decls)) {
275 data->error(data, type->token, PSI_WARNING,
276 "Unknown decl '%s'", type->name);
277 return false;
278 }
279 if (!psi_decl_validate_nodl(data, type->real.func, type_stack)) {
280 return false;
281 }
282 break;
283 default:
284 break;
285 }
286
287 return true;
288 }
289
290 void psi_decl_type_dump_args_with_layout(int fd, struct psi_plist *args,
291 unsigned level)
292 {
293 size_t i = 0;
294
295 dprintf(fd, " {\n");
296 if (args) {
297 struct psi_decl_arg *sarg;
298
299 ++level;
300 while (psi_plist_get(args, i++, &sarg)) {
301 dprintf(fd, "%s", psi_t_indent(level));
302 psi_decl_arg_dump(fd, sarg, level);
303 if (sarg->layout->bfw) {
304 dprintf(fd, ":%zu", sarg->layout->bfw->len);
305 }
306 dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos,
307 sarg->layout->len);
308 }
309 --level;
310 }
311 dprintf(fd, "%s", psi_t_indent(level));
312 dprintf(fd, "}");
313 }
314
315 void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
316 {
317 switch (t->type) {
318 case PSI_T_POINTER:
319 dprintf(fd, "%s *", t->name);
320 return;
321
322 case PSI_T_ENUM:
323 dprintf(fd, "enum ");
324 if (psi_decl_type_is_anon(t->name, "enum")) {
325 size_t i = 0, c = psi_plist_count(t->real.enm->items);
326 struct psi_decl_enum_item *item;
327
328 dprintf(fd, "{\n");
329 ++level;
330 while (psi_plist_get(t->real.enm->items, i++, &item)) {
331 dprintf(fd, "%s", psi_t_indent(level));
332 psi_decl_enum_item_dump(fd, item);
333 if (i < c) {
334 dprintf(fd, "%s\n", i < c ? "," : "");
335 }
336 }
337 --level;
338 dprintf(fd, "%s\n} ", psi_t_indent(level));
339 return;
340 }
341 break;
342
343 case PSI_T_STRUCT:
344 dprintf(fd, "struct ");
345 if (psi_decl_type_is_anon(t->name, "struct")) {
346 psi_decl_type_dump_args_with_layout(fd, t->real.strct->args, level);
347 return;
348 }
349 break;
350
351 case PSI_T_UNION:
352 dprintf(fd, "union ");
353 if (psi_decl_type_is_anon(t->name, "union")) {
354 psi_decl_type_dump_args_with_layout(fd, t->real.unn->args, level);
355 return;
356 }
357 break;
358 }
359 dprintf(fd, "%s", t->name);
360 }
361
362 int psi_decl_type_is_weak(struct psi_decl_type *type)
363 {
364 switch (type->type) {
365 case PSI_T_CHAR:
366 case PSI_T_SHORT:
367 case PSI_T_INT:
368 case PSI_T_LONG:
369 case PSI_T_UNSIGNED:
370 case PSI_T_SIGNED:
371 case PSI_T_NAME:
372 return type->type;
373 default:
374 return 0;
375 }
376 }
377
378 struct psi_decl_type *psi_decl_type_get_real(struct psi_decl_type *type)
379 {
380 while (psi_decl_type_is_weak(type) && type->real.def) {
381 type = type->real.def->type;
382 }
383 return type;
384 }
385
386 size_t psi_decl_type_get_align(struct psi_decl_type *t)
387 {
388 struct psi_decl_type *real = psi_decl_type_get_real(t);
389 size_t align;
390
391 switch (real->type) {
392 case PSI_T_STRUCT:
393 align = psi_decl_struct_get_align(real->real.strct);
394 break;
395 case PSI_T_UNION:
396 align = psi_decl_union_get_align(real->real.unn);
397 break;
398 case PSI_T_ENUM:
399 default:
400 align = psi_t_alignment(real->type);
401 }
402
403 return align;
404 }
405
406 size_t psi_decl_type_get_args_align(struct psi_plist *args)
407 {
408 size_t i = 0, maxalign = 0;
409 struct psi_decl_arg *darg;
410
411 while (psi_plist_get(args, i++, &darg)) {
412 size_t align = psi_decl_arg_get_align(darg);
413
414 if (align > maxalign) {
415 maxalign = align;
416 }
417 }
418
419 return maxalign;
420 }
421