types refactoring
[m6w6/ext-psi] / src / context.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #else
4 # include "php_config.h"
5 #endif
6
7 #include "php_psi_stdinc.h"
8
9 #include "php.h"
10
11 #ifdef HAVE_DIRENT_H
12 # include <dirent.h>
13 # define NAMLEN(dirent) strlen ((dirent)->d_name)
14 #else
15 # define dirent direct
16 # define NAMLEN(dirent) ((dirent)->d_namlen)
17 # ifdef HAVE_SYS_NDIR_H
18 # include <sys/ndir.h>
19 # endif
20 # ifdef HAVE_SYS_DIR_H
21 # include <sys/dir.h>
22 # endif
23 # ifdef HAVE_NDIR_H
24 # include <ndir.h>
25 # endif
26 #endif
27
28 #include <fnmatch.h>
29
30 #include "php_scandir.h"
31 #include "php_psi.h"
32 #include "calc.h"
33 #include "libjit.h"
34 #include "libffi.h"
35
36 #include "token.h"
37 #include "parser.h"
38
39 #include "php_psi_types.h"
40 #include "php_psi_consts.h"
41 #include "php_psi_decls.h"
42 #include "php_psi_va_decls.h"
43 #include "php_psi_fn_decls.h"
44 #include "php_psi_structs.h"
45 #include "php_psi_unions.h"
46
47 struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_ops *ops, psi_error_cb error, unsigned flags)
48 {
49 struct psi_data T;
50 struct psi_predef_type *predef_type;
51 struct psi_predef_const *predef_const;
52 struct psi_predef_struct *predef_struct;
53 struct psi_predef_union *predef_union;
54 struct psi_predef_decl *predef_decl;
55
56 if (!C) {
57 C = malloc(sizeof(*C));
58 }
59 memset(C, 0, sizeof(*C));
60
61 C->error = error;
62 C->flags = flags;
63 C->ops = ops;
64
65 if (ops->init) {
66 ops->init(C);
67 }
68
69 ZEND_ASSERT(ops->call != NULL);
70 ZEND_ASSERT(ops->compile != NULL);
71
72 /* build up predefs in a temporary PSI_Data for validation */
73 memset(&T, 0, sizeof(T));
74 T.error = error;
75
76 for (predef_type = &psi_predef_types[0]; predef_type->type_tag; ++predef_type) {
77 decl_type *type = init_decl_type(predef_type->type_tag, predef_type->type_name);
78 decl_var *var = init_decl_var(predef_type->alias, 0, 0); /* FIXME: indirection */
79 decl_arg *def = init_decl_arg(type, var);
80
81 T.defs = add_decl_typedef(T.defs, def);
82 }
83 for (predef_const = &psi_predef_consts[0]; predef_const->type_tag; ++predef_const) {
84 impl_def_val *val = init_impl_def_val(predef_const->val_type_tag, predef_const->val_text);
85 const_type *type = init_const_type(predef_const->type_tag, predef_const->type_name);
86 constant *constant = init_constant(type, predef_const->var_name, val);
87
88 T.consts = add_constant(T.consts, constant);
89 }
90 for (predef_struct = &psi_predef_structs[0]; predef_struct->type_tag; ++predef_struct) {
91 struct psi_predef_struct *member;
92 decl_args *dargs = init_decl_args(NULL);
93 decl_struct *dstruct = init_decl_struct(predef_struct->var_name, dargs);
94
95 dstruct->size = predef_struct->size;
96 dstruct->align = predef_struct->offset;
97 for (member = &predef_struct[1]; member->type_tag; ++member) {
98 decl_type *type;
99 decl_var *dvar;
100 decl_arg *darg;
101
102 type = init_decl_type(member->type_tag, member->type_name);
103 dvar = init_decl_var(member->var_name, member->pointer_level, member->array_size);
104 darg = init_decl_arg(type, dvar);
105 darg->layout = init_decl_struct_layout(member->offset, member->size);
106 dargs = add_decl_arg(dargs, darg);
107 }
108
109 T.structs = add_decl_struct(T.structs, dstruct);
110 predef_struct = member;
111 }
112 for (predef_union = &psi_predef_unions[0]; predef_union->type_tag; ++predef_union) {
113 struct psi_predef_union *member;
114 decl_args *dargs = init_decl_args(NULL);
115 decl_union *dunion = init_decl_union(predef_union->var_name, dargs);
116
117 dunion->size = predef_union->size;
118 dunion->align = predef_union->offset;
119 for (member = &predef_union[1]; member->type_tag; ++member) {
120 decl_type *type;
121 decl_var *dvar;
122 decl_arg *darg;
123
124 type = init_decl_type(member->type_tag, member->type_name);
125 dvar = init_decl_var(member->var_name, member->pointer_level, member->array_size);
126 darg = init_decl_arg(type, dvar);
127 darg->layout = init_decl_struct_layout(member->offset, member->size);
128 dargs = add_decl_arg(dargs, darg);
129 }
130
131 T.unions = add_decl_union(T.unions, dunion);
132 predef_union = member;
133 }
134 for (predef_decl = &psi_predef_decls[0]; predef_decl->type_tag; ++predef_decl) {
135 struct psi_predef_decl *farg;
136 decl_type *ftype = init_decl_type(predef_decl->type_tag, predef_decl->type_name);
137 decl_var *fname = init_decl_var(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size);
138 decl_arg *func = init_decl_arg(ftype, fname);
139 decl_args *args = init_decl_args(NULL);
140 decl *decl = init_decl(init_decl_abi("default"), func, args);
141
142 for (farg = &predef_decl[1]; farg->type_tag; ++farg) {
143 decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name);
144 decl_var *arg_var = init_decl_var(farg->var_name, farg->pointer_level, farg->array_size);
145 decl_arg *darg = init_decl_arg(arg_type, arg_var);
146 args = add_decl_arg(args, darg);
147 }
148
149 T.decls = add_decl(T.decls, decl);
150 predef_decl = farg;
151 }
152
153 for (predef_decl = &psi_predef_vararg_decls[0]; predef_decl->type_tag; ++predef_decl) {
154 struct psi_predef_decl *farg;
155 decl_type *ftype = init_decl_type(predef_decl->type_tag, predef_decl->type_name);
156 decl_var *fname = init_decl_var(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size);
157 decl_arg *func = init_decl_arg(ftype, fname);
158 decl_args *args = init_decl_args(NULL);
159 decl *decl = init_decl(init_decl_abi("default"), func, args);
160
161 for (farg = &predef_decl[1]; farg->type_tag; ++farg) {
162 decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name);
163 decl_var *arg_var = init_decl_var(farg->var_name, farg->pointer_level, farg->array_size);
164 decl_arg *darg = init_decl_arg(arg_type, arg_var);
165 args = add_decl_arg(args, darg);
166 }
167 args->varargs = 1;
168
169 T.decls = add_decl(T.decls, decl);
170 predef_decl = farg;
171 }
172
173 for (predef_decl = &psi_predef_functor_decls[0]; predef_decl->type_tag; ++predef_decl) {
174 struct psi_predef_decl *farg;
175 decl_type *dtype, *ftype = init_decl_type(predef_decl->type_tag, predef_decl->type_name);
176 decl_var *fname = init_decl_var(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size);
177 decl_arg *tdef, *func = init_decl_arg(ftype, fname);
178 decl_args *args = init_decl_args(NULL);
179 decl *decl = init_decl(init_decl_abi("default"), func, args);
180
181 for (farg = &predef_decl[1]; farg->type_tag; ++farg) {
182 decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name);
183 decl_var *arg_var = init_decl_var(farg->var_name, farg->pointer_level, farg->array_size);
184 decl_arg *darg = init_decl_arg(arg_type, arg_var);
185 args = add_decl_arg(args, darg);
186 }
187
188 dtype = init_decl_type(PSI_T_FUNCTION, fname->name);
189 dtype->real.func = decl;
190 tdef = init_decl_arg(dtype, copy_decl_var(fname));
191 T.defs = add_decl_typedef(T.defs, tdef);
192
193 predef_decl = farg;
194 }
195
196 psi_context_validate_data(PSI_DATA(C), &T);
197
198 C->count = 1;
199 C->data = malloc(sizeof(*C->data));
200 psi_data_exchange(C->data, &T);
201
202 return C;
203 }
204
205 static int psi_select_dirent(const struct dirent *entry)
206 {
207 #ifndef FNM_CASEFOLD
208 #define FNM_CASEFOLD 0
209 #endif
210 return 0 == fnmatch("*.psi", entry->d_name, FNM_CASEFOLD);
211 }
212
213 void psi_context_build(struct psi_context *C, const char *paths)
214 {
215 int i, n;
216 char *sep = NULL, *cpy = strdup(paths), *ptr = cpy;
217 struct dirent **entries;
218
219 do {
220 sep = strchr(ptr, ':');
221
222 if (sep) {
223 *sep = 0;
224 }
225
226 entries = NULL;
227 n = php_scandir(ptr, &entries, psi_select_dirent, alphasort);
228
229 if (n > 0) {
230 for (i = 0; i < n; ++i) {
231 char psi[MAXPATHLEN];
232 struct psi_parser P;
233
234 if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) {
235 C->error(C, NULL, PSI_WARNING, "Path to PSI file too long: %s/%s",
236 ptr, entries[i]->d_name);
237 }
238 if (!psi_parser_init(&P, psi, C->error, C->flags)) {
239 C->error(C, NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s",
240 psi, strerror(errno));
241 continue;
242 }
243
244 while (0 < psi_parser_scan(&P)) {
245 psi_parser_parse(&P, psi_token_alloc(&P));
246 if (P.num == PSI_T_EOF) {
247 break;
248 }
249 }
250
251 psi_parser_parse(&P, NULL);
252 psi_context_validate(C, &P);
253 psi_parser_dtor(&P);
254 }
255 }
256
257 if (entries) {
258 for (i = 0; i < n; ++i) {
259 free(entries[i]);
260 }
261 free(entries);
262 }
263
264 ptr = sep + 1;
265 } while (sep);
266
267
268 if (psi_context_compile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) {
269 C->error(C, NULL, PSI_WARNING, "Failed to register functions!");
270 }
271
272 free(cpy);
273
274 }
275
276 zend_function_entry *psi_context_compile(struct psi_context *C)
277 {
278 size_t i;
279 zend_constant zc;
280
281 zc.flags = CONST_PERSISTENT|CONST_CS;
282 zc.module_number = EG(current_module)->module_number;
283
284 if (C->consts) {
285 for (i = 0; i < C->consts->count; ++i) {
286 constant *c = C->consts->list[i];
287
288 zc.name = zend_string_init(c->name + (c->name[0] == '\\'), strlen(c->name) - (c->name[0] == '\\'), 1);
289 ZVAL_NEW_STR(&zc.value, zend_string_init(c->val->text, strlen(c->val->text), 1));
290
291 switch (c->type->type) {
292 case PSI_T_BOOL:
293 convert_to_boolean(&zc.value);
294 break;
295 case PSI_T_INT:
296 convert_to_long(&zc.value);
297 break;
298 case PSI_T_FLOAT:
299 convert_to_double(&zc.value);
300 break;
301 case PSI_T_STRING:
302 case PSI_T_QUOTED_STRING:
303 break;
304 default:
305 assert(0);
306 }
307 zend_register_constant(&zc);
308 }
309 }
310 if (C->enums) {
311 for (i = 0; i < C->enums->count; ++i) {
312 decl_enum *e = C->enums->list[i];
313 size_t j;
314
315 for (j = 0; j < e->items->count; ++j) {
316 decl_enum_item *i = e->items->list[j];
317 zend_string *name = strpprintf(0, "psi\\%s\\%s", e->name, i->name);
318
319 zc.name = zend_string_dup(name, 1);
320 ZVAL_LONG(&zc.value, psi_long_num_exp(i->num, NULL));
321 zend_register_constant(&zc);
322 zend_string_release(name);
323 }
324 }
325 }
326
327 return C->closures = C->ops->compile(C);
328 }
329
330
331 void psi_context_call(struct psi_context *C, struct decl_callinfo *decl_call, struct impl_vararg *va)
332 {
333 C->ops->call(C, decl_call, va);
334 }
335
336
337 void psi_context_dtor(struct psi_context *C)
338 {
339 size_t i;
340 zend_function_entry *zfe;
341
342 if (C->ops->dtor) {
343 C->ops->dtor(C);
344 }
345
346 free_decl_libs(&C->psi.libs);
347
348 if (C->data) {
349 for (i = 0; i < C->count; ++i) {
350 psi_data_dtor(&C->data[i]);
351 }
352 free(C->data);
353 }
354
355 if (C->closures) {
356 for (zfe = C->closures; zfe->fname; ++zfe) {
357 free((void *) zfe->arg_info);
358 }
359 free(C->closures);
360 }
361
362 if (C->consts) {
363 if (C->consts->list) {
364 free(C->consts->list);
365 }
366 free(C->consts);
367 }
368 if (C->defs) {
369 if (C->defs->list) {
370 free(C->defs->list);
371 }
372 free(C->defs);
373 }
374 if (C->structs) {
375 if (C->structs->list) {
376 free(C->structs->list);
377 }
378 free(C->structs);
379 }
380 if (C->unions) {
381 if (C->unions->list) {
382 free(C->unions->list);
383 }
384 free(C->unions);
385 }
386 if (C->enums) {
387 if (C->enums->list) {
388 free(C->enums->list);
389 }
390 free(C->enums);
391 }
392 if (C->decls) {
393 if (C->decls->list) {
394 free(C->decls->list);
395 }
396 free(C->decls);
397 }
398 if (C->impls) {
399 if (C->impls->list) {
400 free(C->impls->list);
401 }
402 free(C->impls);
403 }
404
405 memset(C, 0, sizeof(*C));
406 }
407
408 void psi_context_free(struct psi_context **C)
409 {
410 if (*C) {
411 psi_context_dtor(*C);
412 free(*C);
413 *C = NULL;
414 }
415 }
416
417 int psi_context_validate(struct psi_context *C, struct psi_parser *P)
418 {
419 struct psi_data *D;
420 void *dlopened = NULL;
421 size_t i, count = C->count++, check_round, check_count;
422 decl_typedefs *check_defs = P->defs;
423 decl_structs *check_structs = P->structs;
424 decl_unions *check_unions = P->unions;
425 decl_enums *check_enums = P->enums;
426 unsigned flags = C->flags;
427
428 C->data = realloc(C->data, C->count * sizeof(*C->data));
429 D = psi_data_exchange(&C->data[count], PSI_DATA(P));
430
431 #define REVALIDATE(what) do { \
432 if (check_round && check_ ##what) { \
433 free(check_ ##what->list); \
434 free(check_ ##what); \
435 } \
436 check_ ##what = recheck_ ##what; \
437 } while (0)
438 #define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
439 #define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
440
441 if (!(flags & PSI_PARSER_SILENT)) {
442 /* no warnings on first round */
443 C->flags |= PSI_PARSER_SILENT;
444 }
445 for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
446 decl_typedefs *recheck_defs = NULL;
447 decl_structs *recheck_structs = NULL;
448 decl_unions *recheck_unions = NULL;
449 decl_enums *recheck_enums = NULL;
450
451 check_count = CHECK_TOTAL;
452
453 for (i = 0; i < CHECK_COUNT(defs); ++i) {
454 if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) {
455 C->defs = add_decl_typedef(C->defs, check_defs->list[i]);
456 } else {
457 recheck_defs = add_decl_typedef(recheck_defs, check_defs->list[i]);
458 }
459 }
460 for (i = 0; i < CHECK_COUNT(structs); ++i) {
461 if (validate_decl_struct(PSI_DATA(C), check_structs->list[i])) {
462 C->structs = add_decl_struct(C->structs, check_structs->list[i]);
463 } else {
464 recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]);
465 }
466 }
467 for (i = 0; i < CHECK_COUNT(unions); ++i) {
468 if (validate_decl_union(PSI_DATA(C), check_unions->list[i])) {
469 C->unions = add_decl_union(C->unions, check_unions->list[i]);
470 } else {
471 recheck_unions = add_decl_union(recheck_unions, check_unions->list[i]);
472 }
473 }
474 for (i = 0; i < CHECK_COUNT(enums); ++i) {
475 if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) {
476 C->enums = add_decl_enum(C->enums, check_enums->list[i]);
477 } else {
478 recheck_enums = add_decl_enum(recheck_enums, check_enums->list[i]);
479 }
480 }
481
482 REVALIDATE(defs);
483 REVALIDATE(structs);
484 REVALIDATE(unions);
485 REVALIDATE(enums);
486
487 if (check_round == 0 && !(flags & PSI_PARSER_SILENT)) {
488 C->flags ^= PSI_PARSER_SILENT;
489 }
490 }
491
492 C->flags = flags;
493
494 if (D->consts) {
495 for (i = 0; i < D->consts->count; ++i) {
496 if (validate_constant(PSI_DATA(C), D->consts->list[i])) {
497 C->consts = add_constant(C->consts, D->consts->list[i]);
498 }
499 }
500 }
501
502 if (!validate_file(D, &dlopened)) {
503 return 0;
504 }
505
506 add_decl_lib(&C->psi.libs, dlopened);
507
508 if (D->decls) {
509 for (i = 0; i < D->decls->count; ++i) {
510 if (validate_decl(PSI_DATA(C), dlopened, D->decls->list[i])) {
511 C->decls = add_decl(C->decls, D->decls->list[i]);
512 }
513 }
514 }
515 if (D->impls) {
516 for (i = 0; i < D->impls->count; ++i) {
517 if (validate_impl(PSI_DATA(C), D->impls->list[i])) {
518 C->impls = add_impl(C->impls, D->impls->list[i]);
519 }
520 }
521 }
522
523 return 1;
524 }
525
526 int psi_context_validate_data(struct psi_data *dest, struct psi_data *source)
527 {
528 size_t i;
529 int errors = 0;
530
531 if (source->defs) for (i = 0; i < source->defs->count; ++i) {
532 decl_arg *def = source->defs->list[i];
533
534 if (validate_decl_typedef(source, def)) {
535 if (dest) {
536 dest->defs = add_decl_typedef(dest->defs, def);
537 }
538 } else {
539 ++errors;
540 }
541 }
542
543 if (source->consts) for (i = 0; i < source->consts->count; ++i) {
544 constant *constant = source->consts->list[i];
545
546 if (validate_constant(source, constant)) {
547 if (dest) {
548 dest->consts = add_constant(dest->consts, constant);
549 }
550 } else {
551 ++errors;
552 }
553 }
554
555 if (source->structs) for (i = 0; i < source->structs->count; ++i) {
556 decl_struct *dstruct = source->structs->list[i];
557
558 if (validate_decl_struct(source, dstruct)) {
559 if (dest) {
560 dest->structs = add_decl_struct(dest->structs, dstruct);
561 }
562 } else {
563 ++errors;
564 }
565 }
566
567 if (source->unions) for (i = 0; i < source->unions->count; ++i) {
568 decl_union *dunion = source->unions->list[i];
569
570 if (validate_decl_union(source, dunion)) {
571 if (dest) {
572 dest->unions = add_decl_union(dest->unions, dunion);
573 }
574 } else {
575 ++errors;
576 }
577 }
578
579 if (source->enums) for (i = 0; i < source->enums->count; ++i) {
580 decl_enum *denum = source->enums->list[i];
581
582 if (validate_decl_enum(source, denum)) {
583 if (dest) {
584 dest->enums = add_decl_enum(dest->enums, denum);
585 }
586 } else {
587 ++errors;
588 }
589 }
590
591 if (source->decls) for (i = 0; i < source->decls->count; ++i) {
592 decl *decl = source->decls->list[i];
593
594 if (validate_decl(source, NULL, decl)) {
595 if (dest) {
596 dest->decls = add_decl(dest->decls, decl);
597 }
598 } else {
599 ++errors;
600 }
601 }
602
603 if (source->impls) for (i = 0; i < source->impls->count; ++i) {
604 impl *impl = source->impls->list[i];
605
606 if (validate_impl(source, impl)) {
607 if (dest) {
608 dest->impls = add_impl(dest->impls, impl);
609 }
610 } else {
611 ++errors;
612 }
613 }
614
615 return errors;
616 }
617
618 static inline void dump_data(int fd, struct psi_data *D) {
619 if (D->psi.file.fn) {
620 dprintf(fd, "// psi.filename=%s\n", D->psi.file.fn);
621 if (D->psi.file.ln) {
622 dprintf(fd, "lib \"%s\";\n", D->psi.file.ln);
623 }
624 } else {
625 dprintf(fd, "// builtin predef\n");
626 }
627 if (D->defs) {
628 dump_decl_typedefs(fd, D->defs);
629 dprintf(fd, "\n");
630 }
631 if (D->unions) {
632 dump_decl_unions(fd, D->unions);
633 dprintf(fd, "\n");
634 }
635 if (D->structs) {
636 dump_decl_structs(fd, D->structs);
637 dprintf(fd, "\n");
638 }
639 if (D->enums) {
640 dump_decl_enums(fd, D->enums);
641 dprintf(fd, "\n");
642 }
643 if (D->consts) {
644 dump_constants(fd, D->consts);
645 dprintf(fd, "\n");
646 }
647 if (D->decls) {
648 dump_decls(fd, D->decls);
649 dprintf(fd, "\n");
650 }
651 if (D->impls) {
652 dump_impls(fd, D->impls);
653 dprintf(fd, "\n");
654 }
655 }
656
657 void psi_context_dump(struct psi_context *C, int fd)
658 {
659 size_t i;
660
661 #ifdef HAVE_LIBJIT
662 if (C->ops == psi_libjit_ops()) {
663 dprintf(fd, "// psi.engine=jit\n");
664 }
665 #endif
666 #ifdef HAVE_LIBFFI
667 if (C->ops == psi_libffi_ops()) {
668 dprintf(fd, "// psi.engine=ffi\n");
669 }
670 #endif
671 dprintf(fd, "\n");
672
673 for (i = 0; i < C->count; ++i) {
674 dump_data(fd, &C->data[i]);
675 }
676
677 }