66fb5f4e3a4d4d1be90fa5200605a70bc84c84cf
[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 if (psi_decl_type_is_anon(t->name, "enum")) {
330 psi_decl_enum_dump(dump, t->real.enm, level);
331 return;
332 }
333 PSI_DUMP(dump, "enum ");
334 break;
335
336 case PSI_T_STRUCT:
337 PSI_DUMP(dump, "struct ");
338 if (psi_decl_type_is_anon(t->name, "struct")) {
339 PSI_DUMP(dump, "/*::(%zu, %zu)*/", t->real.strct->align, t->real.strct->size);
340 psi_decl_type_dump_args_with_layout(dump, t->real.strct->args, level);
341 return;
342 }
343 break;
344
345 case PSI_T_UNION:
346 PSI_DUMP(dump, "union ");
347 if (psi_decl_type_is_anon(t->name, "union")) {
348 psi_decl_type_dump_args_with_layout(dump, t->real.unn->args, level);
349 return;
350 }
351 break;
352
353 case PSI_T_FUNCTION:
354 psi_decl_type_dump(dump, t->real.func->func->type, level);
355 return;
356
357 default:
358 break;
359 }
360
361 PSI_DUMP(dump, "%s", t->name->val);
362 }
363
364 int psi_decl_type_is_weak(struct psi_decl_type *type)
365 {
366 switch (type->type) {
367 case PSI_T_CHAR:
368 case PSI_T_SHORT:
369 case PSI_T_INT:
370 case PSI_T_LONG:
371 case PSI_T_UNSIGNED:
372 case PSI_T_SIGNED:
373 case PSI_T_NAME:
374 return type->type;
375 default:
376 return 0;
377 }
378 }
379
380 struct psi_decl_type *psi_decl_type_get_real(struct psi_decl_type *type)
381 {
382 while (psi_decl_type_is_weak(type) && type->real.def) {
383 type = type->real.def->type;
384 }
385 return type;
386 }
387
388 size_t psi_decl_type_get_align(struct psi_decl_type *t)
389 {
390 struct psi_decl_type *real = psi_decl_type_get_real(t);
391 size_t align;
392
393 switch (real->type) {
394 case PSI_T_STRUCT:
395 align = psi_decl_struct_get_align(real->real.strct);
396 break;
397 case PSI_T_UNION:
398 align = psi_decl_union_get_align(real->real.unn);
399 break;
400 case PSI_T_ENUM:
401 default:
402 align = psi_t_alignment(real->type);
403 break;
404 }
405
406 return align;
407 }
408
409 size_t psi_decl_type_get_args_align(struct psi_plist *args)
410 {
411 size_t i = 0, maxalign = 0;
412 struct psi_decl_arg *darg;
413
414 while (psi_plist_get(args, i++, &darg)) {
415 size_t align = psi_decl_arg_get_align(darg);
416
417 if (align > maxalign) {
418 maxalign = align;
419 }
420 }
421
422 return maxalign;
423 }
424