parser: consolidate tokens
[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 (!strcmp(def->var->name, type->name)) {
124 type->real.def = def;
125 return true;
126 }
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 bool is_pointer, 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 is_pointer, 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 if (is_pointer) {
238 return true;
239 } else {
240 data->error(data, type->token, PSI_WARNING,
241 "Unknown struct '%s'", type->name);
242 return false;
243 }
244 }
245 if (!psi_decl_struct_validate(data, type->real.strct, type_stack)) {
246 return false;
247 }
248 break;
249 case PSI_T_UNION:
250 if (!psi_decl_type_get_union(type, data->unions)) {
251 if (psi_validate_stack_has_union(type_stack, type->name)) {
252 type->real.unn = psi_validate_stack_get_union(type_stack, type->name);
253 } else if (is_pointer) {
254 return true;
255 } else {
256 data->error(data, type->token, PSI_WARNING,
257 "Unknown union '%s'", type->name);
258 return false;
259 }
260 }
261 if (!psi_decl_union_validate(data, type->real.unn, type_stack)) {
262 return false;
263 }
264 break;
265 case PSI_T_ENUM:
266 if (!psi_decl_type_get_enum(type, data->enums)) {
267 data->error(data, type->token, PSI_WARNING,
268 "Unknown enum '%s'", type->name);
269 return false;
270 }
271 break;
272 case PSI_T_FUNCTION:
273 if (!psi_decl_type_get_decl(type, data->decls)) {
274 data->error(data, type->token, PSI_WARNING,
275 "Unknown decl '%s'", type->name);
276 return false;
277 }
278 if (!psi_decl_validate_nodl(data, type->real.func, type_stack)) {
279 return false;
280 }
281 break;
282 default:
283 break;
284 }
285
286 return true;
287 }
288
289 void psi_decl_type_dump_args_with_layout(int fd, struct psi_plist *args,
290 unsigned level)
291 {
292 size_t i = 0;
293
294 dprintf(fd, " {\n");
295 if (args) {
296 struct psi_decl_arg *sarg;
297
298 ++level;
299 while (psi_plist_get(args, i++, &sarg)) {
300 dprintf(fd, "%s", psi_t_indent(level));
301 psi_decl_arg_dump(fd, sarg, level);
302 if (sarg->layout) {
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 } else {
309 dprintf(fd, ";\n");
310 }
311 }
312 --level;
313 }
314 dprintf(fd, "%s", psi_t_indent(level));
315 dprintf(fd, "}");
316 }
317
318 void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
319 {
320 switch (t->type) {
321 case PSI_T_POINTER:
322 dprintf(fd, "%s *", t->name);
323 return;
324
325 case PSI_T_ENUM:
326 dprintf(fd, "enum ");
327 if (psi_decl_type_is_anon(t->name, "enum")) {
328 size_t i = 0, c = psi_plist_count(t->real.enm->items);
329 struct psi_decl_enum_item *item;
330
331 dprintf(fd, "{\n");
332 ++level;
333 while (psi_plist_get(t->real.enm->items, i++, &item)) {
334 dprintf(fd, "%s", psi_t_indent(level));
335 psi_decl_enum_item_dump(fd, item);
336 if (i < c) {
337 dprintf(fd, "%s\n", i < c ? "," : "");
338 }
339 }
340 --level;
341 dprintf(fd, "%s\n} ", psi_t_indent(level));
342 return;
343 }
344 break;
345
346 case PSI_T_STRUCT:
347 dprintf(fd, "struct ");
348 if (psi_decl_type_is_anon(t->name, "struct")) {
349 psi_decl_type_dump_args_with_layout(fd, t->real.strct->args, level);
350 return;
351 }
352 break;
353
354 case PSI_T_UNION:
355 dprintf(fd, "union ");
356 if (psi_decl_type_is_anon(t->name, "union")) {
357 psi_decl_type_dump_args_with_layout(fd, t->real.unn->args, level);
358 return;
359 }
360 break;
361
362 default:
363 break;
364 }
365
366 dprintf(fd, "%s", t->name);
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