X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fcontext.c;h=b7ae46f3ae68deffce6465b94069416a3949549f;hp=c86a595d8c79be86b07db026024c476080d3adcf;hb=c9b3436bd51a4dcf7d6cc6817d4c7a8ad99538d4;hpb=6eb5f114bb934c85515da1f38547728d80008961 diff --git a/src/context.c b/src/context.c index c86a595..b7ae46f 100644 --- a/src/context.c +++ b/src/context.c @@ -1,7 +1,11 @@ #ifdef HAVE_CONFIG_H # include "config.h" +#else +# include "php_config.h" #endif +#include "php_psi_stdinc.h" + #include "php.h" #ifdef HAVE_DIRENT_H @@ -23,23 +27,26 @@ #include -#include "php.h" #include "php_scandir.h" #include "php_psi.h" #include "calc.h" #include "libjit.h" #include "libffi.h" +#include "token.h" +#include "parser.h" + #include "php_psi_types.h" #include "php_psi_consts.h" #include "php_psi_decls.h" #include "php_psi_va_decls.h" +#include "php_psi_fn_decls.h" #include "php_psi_structs.h" #include "php_psi_unions.h" -PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error, unsigned flags) +struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_ops *ops, psi_error_cb error, unsigned flags) { - PSI_Data T; + struct psi_data T; struct psi_predef_type *predef_type; struct psi_predef_const *predef_const; struct psi_predef_struct *predef_struct; @@ -163,11 +170,34 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr predef_decl = farg; } - PSI_ContextValidateData(PSI_DATA(C), &T); + for (predef_decl = &psi_predef_functor_decls[0]; predef_decl->type_tag; ++predef_decl) { + struct psi_predef_decl *farg; + decl_type *dtype, *ftype = init_decl_type(predef_decl->type_tag, predef_decl->type_name); + decl_var *fname = init_decl_var(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size); + decl_arg *tdef, *func = init_decl_arg(ftype, fname); + decl_args *args = init_decl_args(NULL); + decl *decl = init_decl(init_decl_abi("default"), func, args); + + for (farg = &predef_decl[1]; farg->type_tag; ++farg) { + decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name); + decl_var *arg_var = init_decl_var(farg->var_name, farg->pointer_level, farg->array_size); + decl_arg *darg = init_decl_arg(arg_type, arg_var); + args = add_decl_arg(args, darg); + } + + dtype = init_decl_type(PSI_T_FUNCTION, fname->name); + dtype->real.func = decl; + tdef = init_decl_arg(dtype, copy_decl_var(fname)); + T.defs = add_decl_typedef(T.defs, tdef); + + predef_decl = farg; + } + + psi_context_validate_data(PSI_DATA(C), &T); C->count = 1; C->data = malloc(sizeof(*C->data)); - PSI_DataExchange(C->data, &T); + psi_data_exchange(C->data, &T); return C; } @@ -180,7 +210,7 @@ static int psi_select_dirent(const struct dirent *entry) return 0 == fnmatch("*.psi", entry->d_name, FNM_CASEFOLD); } -void PSI_ContextBuild(PSI_Context *C, const char *paths) +void psi_context_build(struct psi_context *C, const char *paths) { int i, n; char *sep = NULL, *cpy = strdup(paths), *ptr = cpy; @@ -199,28 +229,28 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths) if (n > 0) { for (i = 0; i < n; ++i) { char psi[MAXPATHLEN]; - PSI_Parser P; + struct psi_parser P; if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) { C->error(C, NULL, PSI_WARNING, "Path to PSI file too long: %s/%s", ptr, entries[i]->d_name); } - if (!PSI_ParserInit(&P, psi, C->error, C->flags)) { + if (!psi_parser_init(&P, psi, C->error, C->flags)) { C->error(C, NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s", psi, strerror(errno)); continue; } - while (0 < PSI_ParserScan(&P)) { - PSI_ParserParse(&P, PSI_TokenAlloc(&P)); + while (0 < psi_parser_scan(&P)) { + psi_parser_parse(&P, psi_token_alloc(&P)); if (P.num == PSI_T_EOF) { break; } } - PSI_ParserParse(&P, NULL); - PSI_ContextValidate(C, &P); - PSI_ParserDtor(&P); + psi_parser_parse(&P, NULL); + psi_context_validate(C, &P); + psi_parser_dtor(&P); } } @@ -235,7 +265,7 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths) } while (sep); - if (PSI_ContextCompile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) { + if (psi_context_compile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) { C->error(C, NULL, PSI_WARNING, "Failed to register functions!"); } @@ -243,7 +273,7 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths) } -zend_function_entry *PSI_ContextCompile(PSI_Context *C) +zend_function_entry *psi_context_compile(struct psi_context *C) { size_t i; zend_constant zc; @@ -268,6 +298,11 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C) case PSI_T_FLOAT: convert_to_double(&zc.value); break; + case PSI_T_STRING: + case PSI_T_QUOTED_STRING: + break; + default: + assert(0); } zend_register_constant(&zc); } @@ -293,13 +328,13 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C) } -void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va) +void psi_context_call(struct psi_context *C, struct decl_callinfo *decl_call, struct impl_vararg *va) { C->ops->call(C, decl_call, va); } -void PSI_ContextDtor(PSI_Context *C) +void psi_context_dtor(struct psi_context *C) { size_t i; zend_function_entry *zfe; @@ -312,7 +347,7 @@ void PSI_ContextDtor(PSI_Context *C) if (C->data) { for (i = 0; i < C->count; ++i) { - PSI_DataDtor(&C->data[i]); + psi_data_dtor(&C->data[i]); } free(C->data); } @@ -370,11 +405,273 @@ void PSI_ContextDtor(PSI_Context *C) memset(C, 0, sizeof(*C)); } -void PSI_ContextFree(PSI_Context **C) +void psi_context_free(struct psi_context **C) { if (*C) { - PSI_ContextDtor(*C); + psi_context_dtor(*C); free(*C); *C = NULL; } } + +int psi_context_validate(struct psi_context *C, struct psi_parser *P) +{ + struct psi_data *D; + void *dlopened = NULL; + size_t i, count = C->count++, check_round, check_count; + decl_typedefs *check_defs = P->defs; + decl_structs *check_structs = P->structs; + decl_unions *check_unions = P->unions; + decl_enums *check_enums = P->enums; + unsigned flags = C->flags; + + C->data = realloc(C->data, C->count * sizeof(*C->data)); + D = psi_data_exchange(&C->data[count], PSI_DATA(P)); + +#define REVALIDATE(what) do { \ + if (check_round && check_ ##what) { \ + free(check_ ##what->list); \ + free(check_ ##what); \ + } \ + check_ ##what = recheck_ ##what; \ +} while (0) +#define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums)) +#define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0) + + if (!(flags & PSI_PARSER_SILENT)) { + /* no warnings on first round */ + C->flags |= PSI_PARSER_SILENT; + } + for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) { + decl_typedefs *recheck_defs = NULL; + decl_structs *recheck_structs = NULL; + decl_unions *recheck_unions = NULL; + decl_enums *recheck_enums = NULL; + + check_count = CHECK_TOTAL; + + for (i = 0; i < CHECK_COUNT(defs); ++i) { + if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) { + C->defs = add_decl_typedef(C->defs, check_defs->list[i]); + } else { + recheck_defs = add_decl_typedef(recheck_defs, check_defs->list[i]); + } + } + for (i = 0; i < CHECK_COUNT(structs); ++i) { + if (validate_decl_struct(PSI_DATA(C), check_structs->list[i])) { + C->structs = add_decl_struct(C->structs, check_structs->list[i]); + } else { + recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]); + } + } + for (i = 0; i < CHECK_COUNT(unions); ++i) { + if (validate_decl_union(PSI_DATA(C), check_unions->list[i])) { + C->unions = add_decl_union(C->unions, check_unions->list[i]); + } else { + recheck_unions = add_decl_union(recheck_unions, check_unions->list[i]); + } + } + for (i = 0; i < CHECK_COUNT(enums); ++i) { + if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) { + C->enums = add_decl_enum(C->enums, check_enums->list[i]); + } else { + recheck_enums = add_decl_enum(recheck_enums, check_enums->list[i]); + } + } + + REVALIDATE(defs); + REVALIDATE(structs); + REVALIDATE(unions); + REVALIDATE(enums); + + if (check_round == 0 && !(flags & PSI_PARSER_SILENT)) { + C->flags ^= PSI_PARSER_SILENT; + } + } + + C->flags = flags; + + if (D->consts) { + for (i = 0; i < D->consts->count; ++i) { + if (validate_constant(PSI_DATA(C), D->consts->list[i])) { + C->consts = add_constant(C->consts, D->consts->list[i]); + } + } + } + + if (!validate_file(D, &dlopened)) { + return 0; + } + + add_decl_lib(&C->psi.libs, dlopened); + + if (D->decls) { + for (i = 0; i < D->decls->count; ++i) { + if (validate_decl(PSI_DATA(C), dlopened, D->decls->list[i])) { + C->decls = add_decl(C->decls, D->decls->list[i]); + } + } + } + if (D->impls) { + for (i = 0; i < D->impls->count; ++i) { + if (validate_impl(PSI_DATA(C), D->impls->list[i])) { + C->impls = add_impl(C->impls, D->impls->list[i]); + } + } + } + + return 1; +} + +int psi_context_validate_data(struct psi_data *dest, struct psi_data *source) +{ + size_t i; + int errors = 0; + + if (source->defs) for (i = 0; i < source->defs->count; ++i) { + decl_arg *def = source->defs->list[i]; + + if (validate_decl_typedef(source, def)) { + if (dest) { + dest->defs = add_decl_typedef(dest->defs, def); + } + } else { + ++errors; + } + } + + if (source->consts) for (i = 0; i < source->consts->count; ++i) { + constant *constant = source->consts->list[i]; + + if (validate_constant(source, constant)) { + if (dest) { + dest->consts = add_constant(dest->consts, constant); + } + } else { + ++errors; + } + } + + if (source->structs) for (i = 0; i < source->structs->count; ++i) { + decl_struct *dstruct = source->structs->list[i]; + + if (validate_decl_struct(source, dstruct)) { + if (dest) { + dest->structs = add_decl_struct(dest->structs, dstruct); + } + } else { + ++errors; + } + } + + if (source->unions) for (i = 0; i < source->unions->count; ++i) { + decl_union *dunion = source->unions->list[i]; + + if (validate_decl_union(source, dunion)) { + if (dest) { + dest->unions = add_decl_union(dest->unions, dunion); + } + } else { + ++errors; + } + } + + if (source->enums) for (i = 0; i < source->enums->count; ++i) { + decl_enum *denum = source->enums->list[i]; + + if (validate_decl_enum(source, denum)) { + if (dest) { + dest->enums = add_decl_enum(dest->enums, denum); + } + } else { + ++errors; + } + } + + if (source->decls) for (i = 0; i < source->decls->count; ++i) { + decl *decl = source->decls->list[i]; + + if (validate_decl(source, NULL, decl)) { + if (dest) { + dest->decls = add_decl(dest->decls, decl); + } + } else { + ++errors; + } + } + + if (source->impls) for (i = 0; i < source->impls->count; ++i) { + impl *impl = source->impls->list[i]; + + if (validate_impl(source, impl)) { + if (dest) { + dest->impls = add_impl(dest->impls, impl); + } + } else { + ++errors; + } + } + + return errors; +} + +static inline void dump_data(int fd, struct psi_data *D) { + if (D->psi.file.fn) { + dprintf(fd, "// psi.filename=%s\n", D->psi.file.fn); + if (D->psi.file.ln) { + dprintf(fd, "lib \"%s\";\n", D->psi.file.ln); + } + } else { + dprintf(fd, "// builtin predef\n"); + } + if (D->defs) { + dump_decl_typedefs(fd, D->defs); + dprintf(fd, "\n"); + } + if (D->unions) { + dump_decl_unions(fd, D->unions); + dprintf(fd, "\n"); + } + if (D->structs) { + dump_decl_structs(fd, D->structs); + dprintf(fd, "\n"); + } + if (D->enums) { + dump_decl_enums(fd, D->enums); + dprintf(fd, "\n"); + } + if (D->consts) { + dump_constants(fd, D->consts); + dprintf(fd, "\n"); + } + if (D->decls) { + dump_decls(fd, D->decls); + dprintf(fd, "\n"); + } + if (D->impls) { + dump_impls(fd, D->impls); + dprintf(fd, "\n"); + } +} + +void psi_context_dump(struct psi_context *C, int fd) +{ + size_t i; + +#ifdef HAVE_LIBJIT + if (C->ops == psi_libjit_ops()) { + dprintf(fd, "// psi.engine=jit\n"); + } +#endif +#ifdef HAVE_LIBFFI + if (C->ops == psi_libffi_ops()) { + dprintf(fd, "// psi.engine=ffi\n"); + } +#endif + dprintf(fd, "\n"); + + for (i = 0; i < C->count; ++i) { + dump_data(fd, &C->data[i]); + } + +}