flush
[m6w6/ext-psi] / src / context.c
index f0080f753e1ca6ec5aa15b2b5ec559e69e9a707b..3ff510f2f8aa47a6002dcedafb9ce9b45890fb78 100644 (file)
@@ -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[] = {
@@ -78,7 +79,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 +169,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,7 +230,7 @@ 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",
+               data->error(PSI_WARNING, "Failed to locate symbol '%s': %s",
                        func->var->name, dlerror());
        }
        return 1;
@@ -254,18 +255,77 @@ 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 darg;
+               }
+       }
+
+       return NULL;
+}
+static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *ref) {
+       size_t i;
+
+       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->vars->vars[0]->name, ref->var->name)) {
+               return 0;
+       }
+
+       if (set->count && (set->func->type != PSI_T_TO_ARRAY || real_decl_type(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_arg *sub_ref = locate_struct_member(real_decl_type(ref->type)->strct, set->inner[i]->vars->vars[0]);
+
+               if (!sub_ref) {
+                       return 0;
+               }
+               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 +339,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 +443,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 +574,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);
        }