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