fix returning arrays
[m6w6/ext-psi] / src / types / decl_extvar.c
index 5e7f14a4ad70c0a63bff1f32ab5821de70891e25..24ff39a0284cce4b550af4a14865b16a30aa951d 100644 (file)
 
 #include "php_psi.h"
 
-#include <dlfcn.h>
 #include <fnmatch.h>
+#include <Zend/zend_smart_str.h>
 
 #include "data.h"
 
 struct psi_decl_extvar *psi_decl_extvar_init(struct psi_decl_arg *arg)
 {
-       struct psi_decl_extvar *evar = calloc(1, sizeof(*evar));
+       struct psi_decl_extvar *evar = pecalloc(1, sizeof(*evar), 1);
 
        evar->arg = arg;
        return evar;
@@ -46,9 +46,7 @@ void psi_decl_extvar_free(struct psi_decl_extvar **evar_ptr)
                struct psi_decl_extvar *evar = *evar_ptr;
 
                *evar_ptr = NULL;
-               if (evar->token) {
-                       free(evar->token);
-               }
+               psi_token_free(&evar->token);
                psi_decl_arg_free(&evar->arg);
                psi_decl_free(&evar->getter);
                psi_decl_free(&evar->setter);
@@ -57,58 +55,53 @@ void psi_decl_extvar_free(struct psi_decl_extvar **evar_ptr)
 }
 
 bool psi_decl_extvar_validate(struct psi_data *data,
-               struct psi_decl_extvar *evar, void *dl,
-               struct psi_validate_stack *type_stack)
+               struct psi_decl_extvar *evar, struct psi_validate_scope *scope)
 {
-       if (!psi_decl_arg_validate(data, evar->arg, type_stack)) {
+       if (!psi_decl_arg_validate(data, evar->arg, scope)) {
                return false;
        }
 
        evar->size = psi_decl_arg_get_size(evar->arg);
        if (!evar->size) {
                data->error(data, evar->arg->var->token, PSI_WARNING,
-                               "Failed to calculate size of symbol '%s'", evar->arg->var->name);
+                               "Failed to calculate size of symbol '%s'", evar->arg->var->name->val);
                return false;
        }
 
        if (!evar->sym) {
-#ifndef RTLD_NEXT
-# define RTLD_NEXT ((void *) -1l)
-#endif
-#ifndef RTLD_DEFAULT
-# define RTLD_DEFAULT ((void *) 0)
-#endif
-               evar->sym = dlsym(dl ?: RTLD_DEFAULT, evar->arg->var->name);
-               if (!evar->sym) {
-                       data->error(data, evar->arg->var->token, PSI_WARNING,
-                                       "Failed to locate symbol '%s': %s", evar->arg->var->name,
-                                       dlerror() ?: "not found");
-                       return false;
-               }
+               evar->sym = psi_dlsym(data->file.dlopened, evar->arg->var->name->val,
+                       evar->redir ? evar->redir->val : NULL);
+       }
+       if (!evar->sym) {
+               data->error(data, evar->arg->var->token, PSI_WARNING,
+                               "Failed to locate symbol '%s': %s", evar->arg->var->name->val,
+                               dlerror() ?: "not found");
+               return false;
        }
 
        evar->getter = psi_decl_extvar_getter(evar);
-       if (!psi_decl_validate_nodl(data, evar->getter, type_stack)) {
+       if (!psi_decl_validate_nodl(data, evar->getter, scope)) {
                return false;
        }
        evar->setter = psi_decl_extvar_setter(evar);
-       if (!psi_decl_validate_nodl(data, evar->setter, type_stack)) {
+       if (!psi_decl_validate_nodl(data, evar->setter, scope)) {
                return false;
        }
 
        return true;
 }
 
-void psi_decl_extvar_dump(int fd, struct psi_decl_extvar *evar)
+void psi_decl_extvar_dump(struct psi_dump *dump, struct psi_decl_extvar *evar)
 {
-       dprintf(fd, "extern ");
-       psi_decl_arg_dump(fd, evar->arg, 0);
-       dprintf(fd, ";\n");
+       PSI_DUMP(dump, "extern ");
+       psi_decl_arg_dump(dump, evar->arg, 0);
+       PSI_DUMP(dump, ";\n");
 }
 
 struct psi_decl *psi_decl_extvar_setter(struct psi_decl_extvar *evar)
 {
-       struct psi_decl_type *func_type = psi_decl_type_init(PSI_T_VOID, "void");
+       zend_string *type_str = zend_string_init_interned(ZEND_STRS("void"), 1);
+       struct psi_decl_type *func_type = psi_decl_type_init(PSI_T_VOID, type_str);
        struct psi_decl_var *func_var = psi_decl_var_copy(evar->arg->var);
        struct psi_decl_arg *func = psi_decl_arg_init(func_type, func_var);
        struct psi_decl_type *arg_type = psi_decl_type_copy(evar->arg->type);
@@ -116,9 +109,19 @@ struct psi_decl *psi_decl_extvar_setter(struct psi_decl_extvar *evar)
        struct psi_decl_arg *arg = psi_decl_arg_init(arg_type, arg_var);
        struct psi_plist *args = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
        struct psi_decl *decl = psi_decl_init(func, psi_plist_add(args, &arg));
+       smart_str name = {0};
 
-       func_var->name = realloc(func_var->name, strlen(evar->arg->var->name) + sizeof("_set"));
-       strcat(func_var->name, "_set");
+       zend_string_release(type_str);
+
+       func_var->pointer_level = 0;
+       func_var->array_size = 0;
+
+       smart_str_append_ex(&name, func_var->name, 1);
+       smart_str_appendl_ex(&name, ZEND_STRL("_set"), 1);
+       zend_string_release(func_var->name);
+       func_var->name = zend_new_interned_string(smart_str_extract(&name));
+
+       decl->extvar = 1;
 
        return decl;
 }
@@ -134,16 +137,26 @@ struct psi_decl *psi_decl_extvar_getter(struct psi_decl_extvar *evar)
        struct psi_decl_var *func_var = psi_decl_var_copy(evar->arg->var);
        struct psi_decl_arg *func = psi_decl_arg_init(func_type, func_var);
        struct psi_decl *decl = psi_decl_init(func, NULL);
+       smart_str name = {0};
 
-       func_var->name = realloc(func_var->name, strlen(evar->arg->var->name) + sizeof("_get"));
-       strcat(func_var->name, "_get");
+       smart_str_append_ex(&name, func_var->name, 1);
+       smart_str_appendl_ex(&name, ZEND_STRL("_get"), 1);
+       zend_string_release(func_var->name);
+       func_var->name = zend_new_interned_string(smart_str_extract(&name));
+
+       decl->extvar = 1;
 
        return decl;
 }
 
 void psi_decl_extvar_get(struct psi_decl_extvar *evar, void *ptr)
 {
-       memcpy(ptr, evar->sym, evar->size);
+       if (evar->arg->var->array_size) {
+               /* arrays are passed as pointer */
+               *(void **) ptr = evar->sym;
+       } else {
+               memcpy(ptr, evar->sym, evar->size);
+       }
 }
 
 
@@ -159,4 +172,3 @@ bool psi_decl_extvar_is_blacklisted(const char *name)
        }
        return false;
 }
-