flush
authorMichael Wallner <mike@php.net>
Tue, 12 Jan 2016 12:15:48 +0000 (13:15 +0100)
committerMichael Wallner <mike@php.net>
Tue, 12 Jan 2016 12:15:48 +0000 (13:15 +0100)
m4/sys_socket.m4
psi.d/glob.psi
psi.d/netdb.psi
psi.d/stdio.psi
psi.d/time.psi
psi.d/uname.psi
src/context.c
src/module.c
src/parser.h
tests/iconv/iconv001.phpt

index 331bd16..3d403cd 100644 (file)
@@ -31,6 +31,7 @@ AC_DEFUN(PSI_CHECK_SYS_SOCKET, [
        )
        
        PSI_CONST(AF_INET, int)
+       PSI_CONST(AF_INET6, int)
     PSI_CONST(AF_UNIX, int)
     PSI_CONST(AF_UNSPEC, int)
     PSI_CONST(MSG_CTRUNC, int)
index 02d1c3d..ce6f5a7 100644 (file)
@@ -9,7 +9,7 @@ function psi\glob(string $pattern, int $flags, array &$glob = NULL) : int {
                to_int(gl_pathc),
                to_int(gl_offs),
                to_int(gl_flags),
-               to_array(**gl_pathv, gl_pathc + gl_offs, to_string(*gl_pathv))
+               to_array(gl_pathv, gl_pathc + gl_offs, to_string(gl_pathv))
        );
        free globfree(buf);
 }
index 0820c20..dd81ed8 100644 (file)
@@ -11,18 +11,46 @@ function psi\endservent() : void {
        return void(endservent);
 }
 
+function psi\sethostent(bool $stayopen) : void {
+       let stayopen = intval($stayopen);
+       return void(sethostent);
+}
+function psi\setnetset(bool $stayopen) : void {
+       let stayopen = intval($stayopen);
+       return void(setnetent);
+}
+function psi\setprotoent(bool $stayopen) : void {
+       let stayopen = intval($stayopen);
+       return void(setprotoent);
+}
+function psi\setservent(bool $stayopen) : void {
+       let stayopen = intval($stayopen);
+       return void(setservent);
+}
+
+function psi\gethostent() : array {
+       return to_array(gethostent, 
+               to_string(h_name),
+               to_array(h_aliases, to_string(h_aliases)),
+               to_int(h_addrtype),
+               to_int(h_length),
+               to_array(h_addr_list, to_string(h_addr_list, h_length))
+       );
+}
+
 function psi\gai_strerror(int $errcode) : string {
        let errcode = intval($errcode);
        return to_string(gai_strerror);
 }
 
+// extern int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
 function psi\getaddrinfo(string $node, string $service, array $hints, object &$res = NULL) : int {
        let node = strval($node);
        let service = strval($service);
        let hints = arrval($hints);
        let res = &NULL;
        return to_int(getaddrinfo);
-       set $res = to_array(*res,
+       set $res = to_array(**res,
                to_int(ai_flags),
                to_int(ai_family),
                to_int(ai_socktype),
@@ -30,7 +58,7 @@ function psi\getaddrinfo(string $node, string $service, array $hints, object &$r
                to_int(ai_addrlen),
                to_string(ai_addr, ai_addrlen),
                to_string(ai_canonname),
-               to_array(ai_next, ...)
+               to_array(*ai_next, ...)
        );
        free freeaddrinfo(res);
 }
\ No newline at end of file
index 43987de..6909354 100644 (file)
@@ -2,7 +2,7 @@
 function psi\fopen(string $path, string $mode) : object {
        let path = pathval($path);
        let mode = strval($mode);
-       return to_object(*fopen);
+       return to_object(fopen);
 }
 
 // extern int fclose(FILE *stream);
index ae16b0a..ff81e93 100644 (file)
@@ -77,7 +77,7 @@ function psi\nanosleep(array $rq = NULL, array &$rm = NULL) : int {
 function psi\times(array &$tms = NULL) : int {
        let buf = calloc(1, psi\SIZEOF_STRUCT_TMS);
        return to_int(times);
-       set $tms = to_array(*buf,
+       set $tms = to_array(buf,
                to_int(tms_utime),
                to_int(tms_stime),
                to_int(tms_cutime),
index 6c6a6b0..b7aed96 100644 (file)
@@ -8,4 +8,4 @@ function psi\uname(array &$u = NULL) : int {
                to_string(version), 
                to_string(machine),
                to_string(domainname));
-}
\ No newline at end of file
+}
index ee79c8f..c3f1cb1 100644 (file)
@@ -151,6 +151,12 @@ static struct psi_predef_const {
 
 PSI_MACROS
 
+struct utsname *uname2() {
+       struct utsname *u = calloc(1, sizeof(*u));
+       uname(u);
+       return u;
+}
+
 int psi_glob(const char *pattern, int flags,
                int (*errfunc) (const char *epath, int eerrno),
                glob_t *pglob) {
@@ -169,6 +175,7 @@ static struct psi_func_redir {
        void (*func)(void);
 } psi_func_redirs[] = {
        {"glob", (void (*)(void)) psi_glob},
+       {"uname2", (void (*)(void)) uname2},
        PSI_REDIRS
        {0}
 };
@@ -527,6 +534,8 @@ static inline int validate_set_value_handler(set_value *set) {
        case PSI_T_ELLIPSIS:
                if (set->outer.set && set->outer.set->func->type == PSI_T_TO_ARRAY) {
                        set->func->handler = psi_to_recursive;
+                       set->inner = set->outer.set->inner;
+                       set->count = set->outer.set->count;
                        break;
                }
                /* no break */
@@ -589,13 +598,15 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg
 
        if (ref_type->type == PSI_T_STRUCT) {
                /* to_array(struct, to_...) */
-               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_ex(data, set->inner[i], sub_ref, ref_type->strct->args)) {
-                                       return 0;
+               if (!set->outer.set || set->outer.set->inner != set->inner) {
+                       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_ex(data, set->inner[i], sub_ref, ref_type->strct->args)) {
+                                               return 0;
+                                       }
                                }
                        }
                }
@@ -886,25 +897,26 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) {
                                                free_call->func, impl->func->name);
                                return 0;
                        }
-                       if (!impl->decl->args) {
-                               data->error(free_call->token, PSI_WARNING,
-                                               "Declaration '%s' of implementation '%s'"
-                                               " does not have any arguments to free",
-                                               impl->decl->func->var->name, impl->func->name);
-                       }
+
+
 
                        /* 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, impl->decl->func->var->name)) {
+                                       check = 1;
+                                       free_var->arg = impl->decl->func;
+                               } else 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;
+                                               if (!strcmp(free_var->name, free_arg->var->name)) {
+                                                       check = 1;
+                                                       free_var->arg = free_arg;
+                                                       break;
+                                               }
                                        }
                                }
 
@@ -1318,7 +1330,7 @@ static inline void dump_num_exp(int fd, num_exp *exp) {
 }
 
 static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) {
-       size_t i, j;
+       size_t i;
 
        if (level > 1) {
                /* only if not directly after `set ...` */
index 607015d..152c949 100644 (file)
@@ -293,6 +293,7 @@ void psi_to_double(zval *return_value, set_value *set, impl_val *ret_val)
 
 void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val)
 {
+       char *str;
        decl_var *var = set->vars->vars[0];
        token_t t = real_decl_type(var->arg->type)->type;
 
@@ -304,26 +305,27 @@ void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val)
                RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval);
                break;
        default:
-       case PSI_T_VOID:
-       case PSI_T_INT8:
-       case PSI_T_UINT8:
                if (!var->arg->var->pointer_level) {
                        RETVAL_STRINGL(&ret_val->cval, 1);
                } else {
                        ret_val = deref_impl_val(ret_val, var);
-                       if (ret_val && ret_val->ptr) {
+                       if (var->arg->var->array_size) {
+                               str = (char *) ret_val;
+                       } else {
+                               str = ret_val->ptr;
+                       }
+                       if (str) {
                                if (set->num) {
-                                       RETVAL_STRINGL(ret_val->ptr, psi_long_num_exp(set->num, set->outer.val));
+                                       zend_long n = psi_long_num_exp(set->num, set->outer.val);
+                                       RETVAL_STRINGL(str, n);
                                } else {
-                                       RETVAL_STRING(ret_val->ptr);
+                                       RETVAL_STRING(str);
                                }
                        } else {
                                RETVAL_EMPTY_STRING();
                        }
                }
                return;
-               psi_to_int(return_value, set, ret_val);
-               break;
        }
        convert_to_string(return_value);
 }
@@ -332,7 +334,7 @@ void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val)
 static impl_val *iterate(impl_val *val, size_t size, unsigned i, impl_val *tmp)
 {
        memset(tmp, 0, sizeof(*tmp));
-       memcpy(tmp, ((void*) val->ptr) + size * i, size);
+       memcpy(tmp, ((void*) val) + size * i, size);
        return tmp;
 }
 
@@ -388,7 +390,7 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr)
 
 void psi_to_recursive(zval *return_value, set_value *set, impl_val *r_val)
 {
-       set->outer.set->func->handler(return_value, set->outer.set, r_val->ptr);
+       set->outer.set->func->handler(return_value, set, r_val);
 }
 
 void psi_to_array(zval *return_value, set_value *set, impl_val *r_val)
@@ -398,7 +400,7 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val)
        token_t t = real_decl_type(var->arg->type)->type;
        impl_val tmp, *ret_val = deref_impl_val(r_val, var);
 
-       if ((intptr_t) ret_val->ptr <= (intptr_t) 0) {
+       if ((intptr_t) ret_val <= (intptr_t) 0) {
                RETURN_NULL();
        }
 
@@ -413,13 +415,13 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val)
                                set_value *sub_set = set->inner[i];
                                decl_var *sub_var = sub_set->vars->vars[0];
 
-                               sub_set->outer.val = r_val;
+                               sub_set->outer.val = ret_val;
 
                                if (sub_var->arg) {
                                        impl_val *tmp = NULL, *val;
                                        zval ztmp;
 
-                                       val = deref_impl_val(struct_member_ref(sub_var->arg, ret_val, &tmp), sub_var);
+                                       val = struct_member_ref(sub_var->arg, ret_val, &tmp);
                                        sub_set->func->handler(&ztmp, sub_set, val);
                                        add_assoc_zval(return_value, sub_var->name, &ztmp);
 
@@ -455,20 +457,32 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val)
                }
                return;
        } else if (set->num) {
-               /* to_array(arr_var, num_expr, to_int(*arr_var))
-                */
+               /* to_array(arr_var, num_expr, to_int(*arr_var)) */
                zval ele;
+               char *ptr;
                zend_long i, n = psi_long_num_exp(set->num, set->outer.val);
+               size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t);
+               set_value *sub_set = set->inner[0];
 
+               sub_set->outer.val = set->outer.val;
                for (i = 0; i < n; ++i) {
-                       size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t);
-                       impl_val *ptr = iterate(ret_val, size, i, &tmp);
-
-                       set->inner[0]->func->handler(&ele, set->inner[0], ptr);
+                       ptr = (char *) ret_val->ptr + i * size;
+                       sub_set->func->handler(&ele, sub_set, (void *) ptr);
                        add_next_index_zval(return_value, &ele);
                }
        } else {
-               ZEND_ASSERT(0);
+               /* to_array(arr_var, to_int(*arr_var)) */
+               zval ele;
+               char *ptr = ret_val->ptr;
+               size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t);
+               set_value *sub_set = set->inner[0];
+
+               sub_set->outer.val = set->outer.val;
+               while (*(void **) ptr) {
+                       sub_set->func->handler(&ele, sub_set, (void *) ptr);
+                       add_next_index_zval(return_value, &ele);
+                       ptr += size;
+               }
        }
 }
 
@@ -588,6 +602,9 @@ static inline void *psi_do_calloc(let_calloc *alloc)
        zend_long n = psi_long_num_exp(alloc->nmemb, NULL), s = psi_long_num_exp(alloc->size, NULL);
        void *mem = safe_emalloc(n, s, sizeof(void *));
        memset(mem, 0, n * s + sizeof(void *));
+#if 0
+       fprintf(stderr, "calloc: %p\n", mem);
+#endif
        return mem;
 }
 
@@ -681,7 +698,12 @@ static inline void *psi_do_let(let_stmt *let)
 
        switch (let->val ? let->val->kind : PSI_LET_NULL) {
        case PSI_LET_TMP:
-               arg_val->ptr = deref_impl_val(let->val->data.var->arg->val.ptr, let->var);
+               memcpy(arg_val, deref_impl_val(let->val->data.var->arg->let->ptr, let->val->data.var), sizeof(*arg_val));
+#if 0
+               fprintf(stderr, "LET TMP: %p -> %p\n",
+                               let->val->data.var->arg->let->ptr,
+                               arg_val->ptr);
+#endif
                break;
        case PSI_LET_NULL:
                if (darg->var->array_size) {
@@ -715,8 +737,10 @@ static inline void *psi_do_let(let_stmt *let)
 
 static inline void psi_do_set(zval *return_value, set_value *set)
 {
+       decl_arg *set_arg = set->vars->vars[0]->arg;
+
        zval_dtor(return_value);
-       set->func->handler(return_value, set, set->vars->vars[0]->arg->ptr);
+       set->func->handler(return_value, set, set_arg->let ? set_arg->let->ptr : set_arg->ptr);
 }
 
 static inline void psi_do_return(zval *return_value, return_stmt *ret)
@@ -830,6 +854,8 @@ static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *strct, impl_val
        case PSI_T_NAME:
                if (strct) {
                        ref = struct_member_ref(exp->u.dvar->arg, strct, &tmp);
+               } else if (exp->u.dvar->arg->let) {
+                       ref = exp->u.dvar->arg->let->ptr;
                } else {
                        ref = exp->u.dvar->arg->ptr;
                }
index 2ea0ec8..5129097 100644 (file)
@@ -833,7 +833,7 @@ static inline void free_set_value(set_value *val) {
        if (val->vars) {
                free_decl_vars(val->vars);
        }
-       if (val->inner) {
+       if (val->inner && (!val->outer.set || val->outer.set->inner != val->inner)) {
                size_t i;
                for (i = 0; i < val->count; ++i) {
                        free_set_value(val->inner[i]);
@@ -1145,7 +1145,16 @@ static inline void add_decl_lib(decl_libs *libs, void *dlopened) {
 static inline impl_val *deref_impl_val(impl_val *ret_val, decl_var *var) {
        unsigned i;
 
-       if (var->arg->var != var) for (i = 1; i < var->pointer_level; ++i) {
+       ZEND_ASSERT(var->arg->var != var);
+#if 0
+       fprintf(stderr, "deref: %s pl=%u:%u as=%u:%u %p\n",
+                       var->name, var->pointer_level, var->arg->var->pointer_level,
+                       var->array_size, var->arg->var->array_size, ret_val);
+#endif
+       for (i = 0; i < var->pointer_level; ++i) {
+#if 0
+               fprintf(stderr, "-- %p %p %p\n", ret_val, *(void**)ret_val, ret_val->ptr);
+#endif
                ret_val = *(void **) ret_val;
        }
        return ret_val;
@@ -1155,11 +1164,21 @@ static inline impl_val *enref_impl_val(void *ptr, decl_var *var) {
        impl_val *val, *val_ptr;
        unsigned i;
 
+       ZEND_ASSERT(var->arg->var == var);
+#if 0
+       fprintf(stderr, "enref: %s pl=%u:%u as=%u:%u\n",
+                       var->name, var->pointer_level, var->arg->var->pointer_level,
+                       var->array_size, var->arg->var->array_size);
+#endif
        if (!var->pointer_level && real_decl_type(var->arg->type)->type != PSI_T_STRUCT) {
                return ptr;
        }
+
        val = val_ptr = calloc(var->pointer_level + 1, sizeof(void *));
-       for (i = 1; i < var->pointer_level; ++i) {
+       for (i = !var->arg->var->array_size; i < var->pointer_level; ++i) {
+#if 0
+               fprintf(stderr, "++\n");
+#endif
                val_ptr->ptr = (void **) val_ptr + 1;
                val_ptr = val_ptr->ptr;
        }
@@ -1168,16 +1187,14 @@ static inline impl_val *enref_impl_val(void *ptr, decl_var *var) {
 }
 
 static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_ptr, impl_val **to_free) {
-       void *ptr = (char *) struct_ptr->ptr + set_arg->layout->pos;
-       impl_val *val = enref_impl_val(ptr, set_arg->var);
-
-       if (val != ptr) {
-               *to_free = val;
-       }
-
-       return val;
+       void *ptr = (char *) struct_ptr + set_arg->layout->pos;
+#if 0
+       fprintf(stderr, "struct member %s: %p\n", set_arg->var->name, ptr);
+#endif
+       return ptr;
 }
 
+
 #define PSI_ERROR 16
 #define PSI_WARNING 32
 typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...);
index 6227c2a..779ee60 100644 (file)
@@ -14,15 +14,13 @@ psi.directory={PWD}/../../psi.d:{PWD}
 $cd = psi\iconv_open("latin1", "utf8");
 $in = "ß";
 $rc = psi\iconv($cd, $in, $tr);
-var_dump($tr === "\xdf");
-var_dump($in === "");
+if ($tr !== "\xdf") var_dump($tr);
+if ($in !== "") var_dump($in);
 var_dump(psi\iconv_close($cd));
 
 ?>
 ===DONE===
 --EXPECT--
 ===TEST===
-bool(true)
-bool(true)
 int(0)
 ===DONE===