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