null pointer safeguards
[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 (def->type->type != type->type
124 && !strcmp(def->var->name, type->name)) {
125 type->real.def = def;
126 return true;
127 }
128 }
129 }
130 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
131 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
132 type->type = stdtyp->type_tag;
133 return true;
134 }
135 }
136
137 return false;
138 }
139
140 bool psi_decl_type_get_struct(struct psi_decl_type *type, struct psi_plist *structs)
141 {
142 size_t i = 0;
143 struct psi_decl_struct *s;
144
145 if (type->real.strct) {
146 return true;
147 }
148 if (structs) {
149 while (psi_plist_get(structs, i++, &s)) {
150 if (!strcmp(s->name, type->name)) {
151 type->real.strct = s;
152 return true;
153 }
154 }
155 }
156 return false;
157 }
158
159 bool psi_decl_type_get_union(struct psi_decl_type *type, struct psi_plist *unions)
160 {
161 size_t i = 0;
162 struct psi_decl_union *u;
163
164 if (type->real.unn) {
165 return true;
166 }
167 if (unions) {
168 while (psi_plist_get(unions, i++, &u)) {
169 if (!strcmp(u->name, type->name)) {
170 type->real.unn = u;
171 return true;
172 }
173 }
174 }
175 return false;
176 }
177
178 bool psi_decl_type_get_enum(struct psi_decl_type *type, struct psi_plist *enums)
179 {
180 size_t i = 0;
181 struct psi_decl_enum *e;
182
183 if (type->real.enm) {
184 return true;
185 }
186 if (enums) {
187 while (psi_plist_get(enums, i++, &e)) {
188 if (!strcmp(e->name, type->name)) {
189 type->real.enm = e;
190 return true;
191 }
192 }
193 }
194 return false;
195 }
196
197 bool psi_decl_type_get_decl(struct psi_decl_type *type, struct psi_plist *decls)
198 {
199 size_t i = 0;
200 struct psi_decl *decl;
201
202 if (type->real.func) {
203 return true;
204 }
205 if (decls) {
206 while (psi_plist_get(decls, i++, &decl)) {
207 if (!strcmp(decl->func->var->name, type->name)) {
208 type->real.func = decl;
209 return true;
210 }
211 }
212 }
213 return false;
214 }
215
216 bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
217 bool is_pointer, struct psi_validate_stack *type_stack)
218 {
219 if (psi_decl_type_is_weak(type)) {
220 if (!psi_decl_type_get_alias(type, data->types)) {
221 if (!psi_validate_stack_has_type(type_stack, type->name)) {
222 return false;
223 }
224 type->real.def = psi_validate_stack_get_type(type_stack, type->name);
225 }
226 if (type->real.def) {
227 return psi_decl_type_validate(data, type->real.def->type,
228 is_pointer, type_stack);
229 }
230 return true;
231 }
232
233 switch (type->type) {
234 case PSI_T_STRUCT:
235 if (!psi_decl_type_get_struct(type, data->structs)) {
236 if (psi_validate_stack_has_struct(type_stack, type->name)) {
237 type->real.strct = psi_validate_stack_get_struct(type_stack, type->name);
238 } else if (is_pointer) {
239 return true;
240 } else {
241 data->error(data, type->token, PSI_WARNING,
242 "Unknown struct '%s'", type->name);
243 return false;
244 }
245 }
246 if (!psi_decl_struct_validate(data, type->real.strct, type_stack)) {
247 return false;
248 }
249 break;
250 case PSI_T_UNION:
251 if (!psi_decl_type_get_union(type, data->unions)) {
252 if (psi_validate_stack_has_union(type_stack, type->name)) {
253 type->real.unn = psi_validate_stack_get_union(type_stack, type->name);
254 } else if (is_pointer) {
255 return true;
256 } else {
257 data->error(data, type->token, PSI_WARNING,
258 "Unknown union '%s'", type->name);
259 return false;
260 }
261 }
262 if (!psi_decl_union_validate(data, type->real.unn, type_stack)) {
263 return false;
264 }
265 break;
266 case PSI_T_ENUM:
267 if (!psi_decl_type_get_enum(type, data->enums)) {
268 data->error(data, type->token, PSI_WARNING,
269 "Unknown enum '%s'", type->name);
270 return false;
271 }
272 break;
273 case PSI_T_FUNCTION:
274 if (!psi_decl_type_get_decl(type, data->decls)) {
275 data->error(data, type->token, PSI_WARNING,
276 "Unknown decl '%s'", type->name);
277 return false;
278 }
279 if (!psi_decl_validate_nodl(data, type->real.func, type_stack)) {
280 return false;
281 }
282 break;
283 default:
284 break;
285 }
286
287 return true;
288 }
289
290 void psi_decl_type_dump_args_with_layout(int fd, struct psi_plist *args,
291 unsigned level)
292 {
293 size_t i = 0;
294
295 dprintf(fd, " {\n");
296 if (args) {
297 struct psi_decl_arg *sarg;
298
299 ++level;
300 while (psi_plist_get(args, i++, &sarg)) {
301 dprintf(fd, "%s", psi_t_indent(level));
302 psi_decl_arg_dump(fd, sarg, level);
303 if (sarg->layout) {
304 if (sarg->layout->bfw) {
305 dprintf(fd, ":%zu", sarg->layout->bfw->len);
306 }
307 dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos,
308 sarg->layout->len);
309 } else {
310 dprintf(fd, ";\n");
311 }
312 }
313 --level;
314 }
315 dprintf(fd, "%s", psi_t_indent(level));
316 dprintf(fd, "}");
317 }
318
319 void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
320 {
321 switch (t->type) {
322 case PSI_T_POINTER:
323 dprintf(fd, "%s *", t->name);
324 return;
325
326 case PSI_T_ENUM:
327 dprintf(fd, "enum ");
328 if (psi_decl_type_is_anon(t->name, "enum")) {
329 size_t i = 0, c = psi_plist_count(t->real.enm->items);
330 struct psi_decl_enum_item *item;
331
332 dprintf(fd, "{\n");
333 ++level;
334 while (psi_plist_get(t->real.enm->items, i++, &item)) {
335 dprintf(fd, "%s", psi_t_indent(level));
336 psi_decl_enum_item_dump(fd, item);
337 if (i < c) {
338 dprintf(fd, "%s\n", i < c ? "," : "");
339 }
340 }
341 --level;
342 dprintf(fd, "%s\n} ", psi_t_indent(level));
343 return;
344 }
345 break;
346
347 case PSI_T_STRUCT:
348 dprintf(fd, "struct ");
349 if (psi_decl_type_is_anon(t->name, "struct")) {
350 psi_decl_type_dump_args_with_layout(fd, t->real.strct->args, level);
351 return;
352 }
353 break;
354
355 case PSI_T_UNION:
356 dprintf(fd, "union ");
357 if (psi_decl_type_is_anon(t->name, "union")) {
358 psi_decl_type_dump_args_with_layout(fd, t->real.unn->args, level);
359 return;
360 }
361 break;
362 }
363 dprintf(fd, "%s", t->name);
364 }
365
366 int psi_decl_type_is_weak(struct psi_decl_type *type)
367 {
368 switch (type->type) {
369 case PSI_T_CHAR:
370 case PSI_T_SHORT:
371 case PSI_T_INT:
372 case PSI_T_LONG:
373 case PSI_T_UNSIGNED:
374 case PSI_T_SIGNED:
375 case PSI_T_NAME:
376 return type->type;
377 default:
378 return 0;
379 }
380 }
381
382 struct psi_decl_type *psi_decl_type_get_real(struct psi_decl_type *type)
383 {
384 while (psi_decl_type_is_weak(type) && type->real.def) {
385 type = type->real.def->type;
386 }
387 return type;
388 }
389
390 size_t psi_decl_type_get_align(struct psi_decl_type *t)
391 {
392 struct psi_decl_type *real = psi_decl_type_get_real(t);
393 size_t align;
394
395 switch (real->type) {
396 case PSI_T_STRUCT:
397 align = psi_decl_struct_get_align(real->real.strct);
398 break;
399 case PSI_T_UNION:
400 align = psi_decl_union_get_align(real->real.unn);
401 break;
402 case PSI_T_ENUM:
403 default:
404 align = psi_t_alignment(real->type);
405 }
406
407 return align;
408 }
409
410 size_t psi_decl_type_get_args_align(struct psi_plist *args)
411 {
412 size_t i = 0, maxalign = 0;
413 struct psi_decl_arg *darg;
414
415 while (psi_plist_get(args, i++, &darg)) {
416 size_t align = psi_decl_arg_get_align(darg);
417
418 if (align > maxalign) {
419 maxalign = align;
420 }
421 }
422
423 return maxalign;
424 }
425