73e89595a36717288a516697d37908a96cab1777
[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->size;
105 case PSI_T_UNION:
106 return var_typ->real.unn->size;
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 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_validate_stack *type_stack)
217 {
218 if (psi_decl_type_is_weak(type)) {
219 if (!psi_decl_type_get_alias(type, data->types)) {
220 if (!psi_validate_stack_has_type(type_stack, type->name)) {
221 return false;
222 }
223 type->real.def = psi_validate_stack_get_type(type_stack, type->name);
224 }
225 if (type->real.def) {
226 return psi_decl_type_validate(data, type->real.def->type,
227 type_stack);
228 }
229 return true;
230 }
231
232 switch (type->type) {
233 case PSI_T_STRUCT:
234 if (!psi_decl_type_get_struct(type, data->structs)) {
235 if (psi_validate_stack_has_struct(type_stack, type->name)) {
236 type->real.strct = psi_validate_stack_get_struct(type_stack, type->name);
237 } else {
238 data->error(data, type->token, PSI_WARNING,
239 "Unknown struct '%s'", type->name);
240 return false;
241 }
242 }
243 if (!psi_decl_struct_validate(data, type->real.strct, type_stack)) {
244 return false;
245 }
246 break;
247 case PSI_T_UNION:
248 if (!psi_decl_type_get_union(type, data->unions)) {
249 if (psi_validate_stack_has_union(type_stack, type->name)) {
250 type->real.unn = psi_validate_stack_get_union(type_stack, type->name);
251 } else {
252 data->error(data, type->token, PSI_WARNING,
253 "Unknown union '%s'", type->name);
254 return false;
255 }
256 }
257 if (!psi_decl_union_validate(data, type->real.unn, type_stack)) {
258 return false;
259 }
260 break;
261 case PSI_T_ENUM:
262 if (!psi_decl_type_get_enum(type, data->enums)) {
263 data->error(data, type->token, PSI_WARNING,
264 "Unknown enum '%s'", type->name);
265 return false;
266 }
267 break;
268 case PSI_T_FUNCTION:
269 if (!psi_decl_type_get_decl(type, data->decls)) {
270 data->error(data, type->token, PSI_WARNING,
271 "Unknown decl '%s'", type->name);
272 return false;
273 }
274 if (!psi_decl_validate_nodl(data, type->real.func, type_stack)) {
275 return false;
276 }
277 break;
278 default:
279 break;
280 }
281
282 return true;
283 }
284
285 void psi_decl_type_dump_args_with_layout(int fd, struct psi_plist *args,
286 unsigned level)
287 {
288 size_t i = 0;
289
290 dprintf(fd, " {\n");
291 if (args) {
292 struct psi_decl_arg *sarg;
293
294 ++level;
295 while (psi_plist_get(args, i++, &sarg)) {
296 dprintf(fd, "%s", psi_t_indent(level));
297 psi_decl_arg_dump(fd, sarg, level);
298 if (sarg->layout->bfw) {
299 dprintf(fd, ":%zu", sarg->layout->bfw->len);
300 }
301 dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos,
302 sarg->layout->len);
303 }
304 --level;
305 }
306 dprintf(fd, "%s", psi_t_indent(level));
307 dprintf(fd, "}");
308 }
309
310 void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
311 {
312 switch (t->type) {
313 case PSI_T_POINTER:
314 dprintf(fd, "%s *", t->name);
315 return;
316
317 case PSI_T_ENUM:
318 dprintf(fd, "enum ");
319 if (psi_decl_type_is_anon(t->name, "enum")) {
320 size_t i = 0, c = psi_plist_count(t->real.enm->items);
321 struct psi_decl_enum_item *item;
322
323 dprintf(fd, "{\n");
324 ++level;
325 while (psi_plist_get(t->real.enm->items, i++, &item)) {
326 dprintf(fd, "%s", psi_t_indent(level));
327 psi_decl_enum_item_dump(fd, item);
328 if (i < c) {
329 dprintf(fd, "%s\n", i < c ? "," : "");
330 }
331 }
332 --level;
333 dprintf(fd, "%s} ", psi_t_indent(level));
334 return;
335 }
336 break;
337
338 case PSI_T_STRUCT:
339 dprintf(fd, "struct ");
340 if (psi_decl_type_is_anon(t->name, "struct")) {
341 psi_decl_type_dump_args_with_layout(fd, t->real.strct->args, level);
342 return;
343 }
344 break;
345
346 case PSI_T_UNION:
347 dprintf(fd, "union ");
348 if (psi_decl_type_is_anon(t->name, "union")) {
349 psi_decl_type_dump_args_with_layout(fd, t->real.unn->args, level);
350 return;
351 }
352 break;
353 }
354 dprintf(fd, "%s", t->name);
355 }
356
357 int psi_decl_type_is_weak(struct psi_decl_type *type)
358 {
359 switch (type->type) {
360 case PSI_T_CHAR:
361 case PSI_T_SHORT:
362 case PSI_T_INT:
363 case PSI_T_LONG:
364 case PSI_T_UNSIGNED:
365 case PSI_T_SIGNED:
366 case PSI_T_NAME:
367 return type->type;
368 default:
369 return 0;
370 }
371 }
372
373 struct psi_decl_type *psi_decl_type_get_real(struct psi_decl_type *type)
374 {
375 while (psi_decl_type_is_weak(type) && type->real.def) {
376 type = type->real.def->type;
377 }
378 return type;
379 }
380
381 size_t psi_decl_type_get_align(struct psi_decl_type *t)
382 {
383 struct psi_decl_type *real = psi_decl_type_get_real(t);
384 size_t align;
385
386 switch (real->type) {
387 case PSI_T_STRUCT:
388 align = psi_decl_struct_get_align(real->real.strct);
389 break;
390 case PSI_T_UNION:
391 align = psi_decl_union_get_align(real->real.unn);
392 break;
393 case PSI_T_ENUM:
394 default:
395 align = psi_t_alignment(real->type);
396 }
397
398 return align;
399 }
400
401 size_t psi_decl_type_get_args_align(struct psi_plist *args)
402 {
403 size_t i = 0, maxalign = 0;
404 struct psi_decl_arg *darg;
405
406 while (psi_plist_get(args, i++, &darg)) {
407 size_t align = psi_decl_arg_get_align(darg);
408
409 if (align > maxalign) {
410 maxalign = align;
411 }
412 }
413
414 return maxalign;
415 }
416