X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fcontext.c;h=7d353bed872cc5e8af756622a9b334a34a9e2f80;hp=f0080f753e1ca6ec5aa15b2b5ec559e69e9a707b;hb=a6ffb2bfbf83ef3511cc356bd931d460feabe7a2;hpb=207ff7bc85e967235f0ad1ffbf47c0f85f375063 diff --git a/src/context.c b/src/context.c index f0080f7..7d353be 100644 --- a/src/context.c +++ b/src/context.c @@ -49,6 +49,7 @@ typedef struct psi_predef_struct_member { #define PSI_PREDEF_STRUCT_MEMBERS 32 typedef struct psi_predef_struct { const char *name; + size_t size; psi_predef_struct_member members[PSI_PREDEF_STRUCT_MEMBERS]; } psi_predef_struct; static const psi_predef_struct psi_predef_structs[] = { @@ -56,6 +57,15 @@ static const psi_predef_struct psi_predef_structs[] = { }; #define psi_predef_struct_count() psi_predef_count(_struct) +typedef struct psi_predef_func { + const char *name; + void (*func)(void); +} psi_predef_func; +static psi_predef_func psi_predef_funcs[] = { + PHP_PSI_FUNCS{0} +}; +#define psi_predef_func_count() psi_predef_count(_func) + static int validate_lib(PSI_Data *data, void **dlopened) { char lib[MAXPATHLEN]; const char *ptr = data->psi.file.ln; @@ -78,7 +88,7 @@ static int validate_lib(PSI_Data *data, void **dlopened) { } if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) { data->error(PSI_WARNING, "Could not open library '%s': %s.", - data->psi.file.fn, dlerror()); + data->psi.file.ln, dlerror()); return 0; } return 1; @@ -168,7 +178,7 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) { return 0; } - ZEND_ASSERT(!darg->var->arg); + ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg); darg->var->arg = darg; if (!darg->layout) { @@ -229,8 +239,20 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ #endif decl->dlptr = dlsym(dl ?: RTLD_NEXT, func->var->name); if (!decl->dlptr) { - data->error(PSI_WARNING, "Failed to located symbol '%s': %s", - func->var->name, dlerror()); + 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; + break; + } + } + if (!decl->dlptr) { + data->error(PSI_WARNING, "Failed to locate symbol '%s': %s", + func->var->name, dlerror()); + } } return 1; } @@ -254,18 +276,79 @@ static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) { return 1; } +static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) { + size_t i; + + ZEND_ASSERT(s); + for (i = 0; i < s->args->count; ++i) { + decl_arg *darg = s->args->args[i]; + + if (!strcmp(var->name, darg->var->name)) { + return var->arg = darg; + } + } + + return NULL; +} +static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *ref) { + size_t i; + decl_type *ref_type = real_decl_type(ref->type); + decl_var *set_var = set->vars->vars[0]; + + switch (set->func->type) { + case PSI_T_TO_BOOL: + set->func->handler = psi_to_bool; + break; + case PSI_T_TO_INT: + set->func->handler = psi_to_int; + break; + case PSI_T_TO_FLOAT: + set->func->handler = psi_to_double; + break; + case PSI_T_TO_STRING: + set->func->handler = psi_to_string; + break; + case PSI_T_TO_ARRAY: + set->func->handler = psi_to_array; + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + + if (strcmp(set_var->name, ref->var->name)) { + return 0; + } + + if (set->count && (set->func->type != PSI_T_TO_ARRAY || ref_type->type != PSI_T_STRUCT)) { + data->error(E_WARNING, "Inner `set` statement casts only work with to_array() casts on structs"); + return 0; + } + for (i = 0; i < set->count; ++i) { + decl_var *sub_var = set->inner[i]->vars->vars[0]; + decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var); + + if (sub_ref) { + if (!validate_set_value(data, set->inner[i], sub_ref)) { + return 0; + } + } + } + + return 1; +} static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) { size_t i; for (i = 0; i < decls->count; ++i) { - if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) { - ret->decl->arg = decls->list[i]->func; + if (!strcmp(decls->list[i]->func->var->name, ret->set->vars->vars[0]->name)) { + ret->decl = decls->list[i]->func; return decls->list[i]; } } return NULL; } static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { + return_stmt *ret; + /* we must have exactly one ret stmt delcaring the native func to call */ /* and which type cast to apply */ if (impl->stmts->ret.count != 1) { @@ -279,11 +362,17 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { } return 0; } - if (!(impl->decl = locate_impl_decl(data->decls, impl->stmts->ret.list[0]))) { + + ret = impl->stmts->ret.list[0]; + + if (!(impl->decl = locate_impl_decl(data->decls, ret))) { data->error(PSI_WARNING, "Missing declaration for implementation %s", impl->func->name); return 0; } + if (!validate_set_value(data, ret->set, ret->decl)) { + return 0; + } return 1; } @@ -377,6 +466,9 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { if (!strcmp(set_var->name, set_arg->var->name)) { check = 1; + if (!validate_set_value(data, set->val, set_arg)) { + return 0; + } set_var->arg = set_arg; break; } @@ -505,6 +597,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr } dstruct = init_decl_struct(pre->name, dargs); + dstruct->size = pre->size; T.structs = add_decl_struct(T.structs, dstruct); }