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)
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)])
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);
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);
+}
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;
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]);
}
}
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;
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;
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 = "";
}
}
+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;
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;
}
--- /dev/null
+--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