flush
authorMichael Wallner <mike@php.net>
Tue, 12 Jan 2016 14:38:14 +0000 (15:38 +0100)
committerMichael Wallner <mike@php.net>
Tue, 12 Jan 2016 14:38:51 +0000 (15:38 +0100)
m4/netdb.m4
psi.d/netdb.psi
src/context.c
src/module.c
tests/netdb/gai001.phpt [new file with mode: 0644]

index 4043210ea3ec4888634a4fc22d99f792e1890ebd..b14b54fe7832ee489a46c04b0a9b151043e7c90e 100644 (file)
@@ -57,6 +57,9 @@ AC_DEFUN(PSI_CHECK_NETDB, [
        PSI_CONST(NI_NUMERICSCOPE, int)
        PSI_CONST(NI_DGRAM, int)
        
+       PSI_CONST(NI_MAXHOST, int)
+       PSI_CONST(NI_MAXSERV, int)
+       
        PSI_CONST(EAI_AGAIN, int)
        PSI_CONST(EAI_BADFLAGS, int)
        PSI_CONST(EAI_FAIL, int)
@@ -76,7 +79,7 @@ AC_DEFUN(PSI_CHECK_NETDB, [
        PSI_DECL(char *gai_strerror, [(int errcode)])
        PSI_DECL(int getaddrinfo, [(char *node, char *service, struct addrinfo *hints, struct addrinfo **res)])
        PSI_DECL(struct hostent *gethostent, [(void)])
-       PSI_DECL(int getnameinfo, [(struct sockaddr *sa, socklen_t salen, char *host, socklen_t host_len, char *serv, socklen_t servlen, int flags)])
+       PSI_DECL(int getnameinfo, [(struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)])
        PSI_DECL(struct netent *getnetbyaddr, [(uint32_t net, int type)])
        PSI_DECL(struct netent *getnetbyname, [(char *name)])
        PSI_DECL(struct netent *getnetent, [(void)])
index dd81ed882de993602f2e670fd1c91b4f75ca3272..259fcec6f436372c8ab3a23f8b5e1e1bb27f43d7 100644 (file)
@@ -43,7 +43,7 @@ function psi\gai_strerror(int $errcode) : string {
        return to_string(gai_strerror);
 }
 
-// extern int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
+// 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);
@@ -61,4 +61,18 @@ function psi\getaddrinfo(string $node, string $service, array $hints, object &$r
                to_array(*ai_next, ...)
        );
        free freeaddrinfo(res);
-}
\ No newline at end of file
+}
+
+// extern int getnameinfo(struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
+function psi\getnameinfo(string $addr, string &$host = NULL, string &$service = NULL, int $flags = 0) : int {
+       let sa = strval($addr);
+       let salen = strlen($addr);
+       let hostlen = psi\NI_MAXHOST;
+       let host = calloc(hostlen, psi\SIZEOF_CHAR);
+       let servlen = psi\NI_MAXSERV;
+       let serv = calloc(servlen, psi\SIZEOF_CHAR);
+       let flags = intval($flags);
+       return to_int(getnameinfo);
+       set $host = to_string(host);
+       set $service = to_string(serv);
+}
index c3f1cb11ac5e57221909d8bc2a3301153c646a44..4a4f4720bf058ee74e5916508b42f02bbff2107e 100644 (file)
@@ -957,6 +957,33 @@ static inline int validate_impl_stmts(PSI_Data *data, impl *impl) {
        return 1;
 }
 
+static inline int validate_impl_args(PSI_Data *data, impl *impl) {
+       int def = 0;
+       size_t i;
+
+       for (i = 0; i < impl->func->args->count; ++i) {
+               impl_arg *iarg = impl->func->args->args[i];
+
+               if (iarg->def) {
+                       def = 1;
+               } else if (def) {
+                       data->error(impl->func->token, PSI_WARNING,
+                                       "Non-optional argument %zu '$%s' of implementation '%s'"
+                                       " follows optional argument",
+                                       i+1, iarg->var->name, impl->func->name);
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+static inline int validate_impl(PSI_Data *data, impl *impl) {
+       if (!validate_impl_args(data, impl)) {
+               return 0;
+       }
+       return validate_impl_stmts(data, impl);
+}
+
 PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error)
 {
        size_t i;
@@ -1153,7 +1180,7 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
                size_t i;
 
                for (i = 0; i < D->impls->count; ++i) {
-                       if (validate_impl_stmts(PSI_DATA(C), D->impls->list[i])) {
+                       if (validate_impl(PSI_DATA(C), D->impls->list[i])) {
                                C->impls = add_impl(C->impls, D->impls->list[i]);
                        }
                }
index 152c949dabedd873dc9076a62ea96ea2aa54536b..2257a0d9d68a5256f2758cc7a6d9c823a57a0600 100644 (file)
@@ -144,6 +144,7 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl)
                zend_internal_arg_info *ai = &aip[impl->func->args->count];
 
                ai->name = vararg->var->name;
+               ai->allow_null = 1;
                ai->type_hint = psi_internal_type(vararg->type);
                if (vararg->var->reference) {
                        ai->pass_by_reference = 1;
@@ -160,9 +161,9 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl)
                if (iarg->var->reference) {
                        ai->pass_by_reference = 1;
                }
-               if (iarg->var->reference || (iarg->def && iarg->def->type == PSI_T_NULL)) {
+               //if (iarg->var->reference || (iarg->def && iarg->def->type == PSI_T_NULL)) {
                        ai->allow_null = 1;
-               }
+               //}
        }
 
        return aip;
@@ -636,7 +637,7 @@ static inline ZEND_RESULT_CODE psi_let_val(token_t let_func, impl_arg *iarg, imp
        case PSI_T_STRVAL:
                if (iarg->type->type == PSI_T_STRING) {
                        if (iarg->val.zend.str) {
-                               arg_val->ptr = estrdup(iarg->val.zend.str->val);
+                               arg_val->ptr = estrndup(iarg->val.zend.str->val, iarg->val.zend.str->len);
                                *to_free = arg_val->ptr;
                        } else {
                                arg_val->ptr = "";
@@ -767,6 +768,22 @@ static inline void psi_do_free(free_stmt *fre)
        }
 }
 
+static inline void psi_clean_array_struct(decl_arg *darg) {
+       if (darg->let
+       &&      darg->let->val->kind == PSI_LET_FUNC
+       &&      darg->let->val->data.func->type == PSI_T_ARRVAL) {
+               decl_type *type = real_decl_type(darg->type);
+
+               if (type->type == PSI_T_STRUCT) {
+                       void **ptr = (void **) ((char *) darg->mem + type->strct->size);
+
+                       while (*ptr) {
+                               efree(*ptr++);
+                       }
+               }
+       }
+}
+
 static inline void psi_do_clean(impl *impl)
 {
        size_t i;
@@ -787,15 +804,7 @@ static inline void psi_do_clean(impl *impl)
                decl_arg *darg = impl->decl->args->args[i];
 
                if (darg->mem) {
-                       decl_type *type = real_decl_type(darg->type);
-
-                       if (type->type == PSI_T_STRUCT) {
-                               void **ptr = (void **) ((char *) darg->mem + type->strct->size);
-
-                               while (*ptr) {
-                                       efree(*ptr++);
-                               }
-                       }
+                       psi_clean_array_struct(darg);
                        efree(darg->mem);
                        darg->mem = NULL;
                }
diff --git a/tests/netdb/gai001.phpt b/tests/netdb/gai001.phpt
new file mode 100644 (file)
index 0000000..42e83fc
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+getaddrinfo
+--INI--
+psi.directory={PWD}:{PWD}/../../psi.d
+--SKIPIF--
+<?php 
+extension_loaded("psi") or die("skip -- need ext/psi");
+?>
+--FILE--
+===TEST===
+<?php 
+
+$rc = psi\getaddrinfo("m6w6.name", NULL, NULL, $ai);
+
+if ($rc) {
+       printf("%s\n", psi\gai_strerror($rc));
+       exit;
+}
+
+$flags = psi\NI_NUMERICHOST|psi\NI_NUMERICSERV;
+do {
+       var_dump(psi\getnameinfo($ai["ai_addr"], $host, $serv, $flags), $host, $serv);
+} while (($ai = $ai["ai_next"]));
+
+?>
+===DONE===
+--EXPECT--
+===TEST===
+int(0)
+string(12) "78.46.223.30"
+string(1) "0"
+int(0)
+string(12) "78.46.223.30"
+string(1) "0"
+int(0)
+string(12) "78.46.223.30"
+string(1) "0"
+===DONE===
\ No newline at end of file