X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=src%2Fcontext.c;h=987fb9abc0a45a660ba8353d25047a8e75c6feb4;hb=6bdeeb7b332a272617814a4358d51bb07c872407;hp=7d353bed872cc5e8af756622a9b334a34a9e2f80;hpb=a6ffb2bfbf83ef3511cc356bd931d460feabe7a2;p=m6w6%2Fext-psi diff --git a/src/context.c b/src/context.c index 7d353be..987fb9a 100644 --- a/src/context.c +++ b/src/context.c @@ -57,6 +57,8 @@ static const psi_predef_struct psi_predef_structs[] = { }; #define psi_predef_struct_count() psi_predef_count(_struct) +PHP_PSI_MACROS + typedef struct psi_predef_func { const char *name; void (*func)(void); @@ -75,11 +77,7 @@ static int validate_lib(PSI_Data *data, void **dlopened) { /* FIXME: assume stdlib */ return 1; } else if (!strchr(ptr, '/')) { -#ifdef DARWIN - len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr); -#else - len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr); -#endif + len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX); if (MAXPATHLEN == len) { data->error(PSI_WARNING, "Library name too long: '%s'", ptr); } @@ -237,19 +235,19 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ #ifndef RTLD_NEXT # define RTLD_NEXT ((void *) -1l) #endif - decl->dlptr = dlsym(dl ?: RTLD_NEXT, func->var->name); - if (!decl->dlptr) { + decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name); + if (!decl->call.sym) { size_t i; for (i = 0; i < psi_predef_func_count(); ++i) { psi_predef_func *pre = &psi_predef_funcs[i]; if (!strcmp(func->var->name, pre->name)) { - decl->dlptr = pre->func; + decl->call.sym = pre->func; break; } } - if (!decl->dlptr) { + if (!decl->call.sym) { data->error(PSI_WARNING, "Failed to locate symbol '%s': %s", func->var->name, dlerror()); } @@ -370,10 +368,13 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { impl->func->name); return 0; } + if (!validate_set_value(data, ret->set, ret->decl)) { return 0; } + impl->decl->impl = impl; + return 1; } static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { @@ -484,34 +485,59 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { } return 1; } +static inline decl *locate_free_decl(decls *decls, free_call *f) { + size_t i; + + for (i = 0; i < decls->count; ++i) { + if (!strcmp(decls->list[i]->func->var->name, f->func)) { + f->decl = decls->list[i]; + return decls->list[i]; + } + } + return NULL; +} static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { - size_t i, j, k; + size_t i, j, k, l; /* we can have any count of free stmts; freeing any out vars */ for (i = 0; i < impl->stmts->fre.count; ++i) { free_stmt *fre = impl->stmts->fre.list[i]; - for (j = 0; j < fre->vars->count; ++j) { - decl_var *free_var = fre->vars->vars[j]; - int check = 0; + for (j = 0; j < fre->calls->count; ++j) { + free_call *free_call = fre->calls->list[j]; - if (!strcmp(free_var->name, impl->decl->func->var->name)) { - continue; + /* first find the decl of the free func */ + if (!locate_free_decl(data->decls, free_call)) { + data->error(PSI_WARNING, "Unknown function '%s' in `free` statement" + " of implementation '%s'", free_call->func, impl->func->name); + return 0; + } + if (!impl->decl->args) { + data->error(PSI_WARNING, "Declaration '%s' of implementation '%s'" + " does not have any arguments to free", + impl->decl->func->var->name, impl->func->name); } - if (impl->decl->args) for (k = 0; k < impl->decl->args->count; ++k) { - decl_arg *free_arg = impl->decl->args->args[k]; - if (!strcmp(free_var->name, free_arg->var->name)) { - check = 1; - free_var->arg = free_arg; - break; + /* now check for known vars */ + for (l = 0; l < free_call->vars->count; ++l) { + int check = 0; + decl_var *free_var = free_call->vars->vars[l]; + + for (k = 0; k < impl->decl->args->count; ++k) { + decl_arg *free_arg = impl->decl->args->args[k]; + + if (!strcmp(free_var->name, free_arg->var->name)) { + check = 1; + free_var->arg = free_arg; + break; + } } - } - if (!check) { - data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement" - " of implementation '%s'", - free_var->name, impl->func->name); - return 0; + if (!check) { + data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement" + " of implementation '%s'", + free_var->name, impl->func->name); + return 0; + } } } } @@ -553,7 +579,13 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr C->error = error; C->ops = ops; - ops->init(C); + + if (ops->init) { + ops->init(C); + } + + ZEND_ASSERT(ops->call != NULL); + ZEND_ASSERT(ops->compile != NULL); /* build up predefs in a temporary PSI_Data for validation */ memset(&T, 0, sizeof(T)); @@ -705,47 +737,62 @@ 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 *path) +void PSI_ContextBuild(PSI_Context *C, const char *paths) { int i, n; + char *sep = NULL, *cpy = strdup(paths), *ptr = cpy; struct dirent **entries = NULL; - n = php_scandir(path, &entries, psi_select_dirent, alphasort); - if (n < 0) { - return; - } else for (i = 0; i < n; ++i) { - char psi[MAXPATHLEN]; - PSI_Parser P; + do { + sep = strchr(ptr, ':'); - if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", path, entries[i]->d_name)) { - C->error(PSI_WARNING, "Path to PSI file too long: %s/%s", - path, entries[i]->d_name); + if (sep) { + *sep = 0; } - if (!PSI_ParserInit(&P, psi, C->error, 0)) { - C->error(PSI_WARNING, "Failed to init PSI parser (%s): %s", - psi, strerror(errno)); - continue; + + n = php_scandir(ptr, &entries, psi_select_dirent, alphasort); + + if (n > 0) { + for (i = 0; i < n; ++i) { + char psi[MAXPATHLEN]; + PSI_Parser P; + + if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) { + C->error(PSI_WARNING, "Path to PSI file too long: %s/%s", + ptr, entries[i]->d_name); + } + if (!PSI_ParserInit(&P, psi, C->error, 0)) { + C->error(PSI_WARNING, "Failed to init PSI parser (%s): %s", + psi, strerror(errno)); + continue; + } + + while (-1 != PSI_ParserScan(&P)) { + PSI_ParserParse(&P, PSI_TokenAlloc(&P)); + }; + PSI_ParserParse(&P, NULL); + PSI_ContextValidate(C, &P); + PSI_ParserDtor(&P); + } } - while (-1 != PSI_ParserScan(&P)) { - PSI_ParserParse(&P, PSI_TokenAlloc(&P)); - }; - PSI_ParserParse(&P, NULL); - PSI_ContextValidate(C, &P); - PSI_ParserDtor(&P); - } + if (entries) { + for (i = 0; i < n; ++i) { + free(entries[i]); + } + free(entries); + } + + ptr = sep + 1; + } while (sep); + if (PSI_ContextCompile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) { C->error(PSI_WARNING, "Failed to register functions!"); } - if (entries) { - for (i = 0; i < n; ++i) { - free(entries[i]); - } - free(entries); - } + free(cpy); } @@ -780,23 +827,34 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C) } } - return C->closures = C->ops->compile(C); } + +void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl) +{ + C->ops->call(C, ret_val, decl); +} + void PSI_ContextDtor(PSI_Context *C) { size_t i; + zend_function_entry *zfe; - C->ops->dtor(C); + if (C->ops->dtor) { + C->ops->dtor(C); + } free_decl_libs(&C->psi.libs); for (i = 0; i < C->count; ++i) { PSI_DataDtor(&C->data[i]); } - free(C->data); + + for (zfe = C->closures; zfe->fname; ++zfe) { + free((void *) zfe->arg_info); + } free(C->closures); if (C->consts) {