flush
authorMichael Wallner <mike@php.net>
Fri, 27 Nov 2015 12:21:30 +0000 (13:21 +0100)
committerMichael Wallner <mike@php.net>
Fri, 27 Nov 2015 12:21:30 +0000 (13:21 +0100)
18 files changed:
config.m4
m4/psi_decl.m4
m4/psi_macro.m4
m4/psi_struct.m4
m4/psi_type.m4
m4/stdlib.m4
m4/sys_select.m4 [new file with mode: 0644]
m4/sys_socket.m4 [new file with mode: 0644]
m4/sys_time.m4
m4/sys_utsname.m4 [new file with mode: 0644]
psi.d/stdlib.psi
psi.d/time.psi
psi.d/uname.psi
src/context.c
src/parser.h
src/parser.re
src/parser_proc.h
src/parser_proc.y

index c4eb578..e7d1e1f 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -21,11 +21,14 @@ if test "$PHP_PSI" != no; then
                [stdio.m4],
                [stdint.m4],
                [stdlib.m4],
+               [sys_select.m4],
+               [sys_socket.m4],
                [sys_stat.m4],
                [sys_time.m4],
                [sys_times.m4],
                [sys_types.m4],
                [sys_uio.m4],
+               [sys_utsname.m4],
                [time.m4],
                [wchar.m4]], [
                dnl pecl build
@@ -49,10 +52,13 @@ if test "$PHP_PSI" != no; then
        PSI_CHECK_STDIO
        PSI_CHECK_STDLIB
        PSI_CHECK_TIME
+       PSI_CHECK_SYS_SELECT
+       PSI_CHECK_SYS_SOCKET
        PSI_CHECK_SYS_TIME
        PSI_CHECK_SYS_TIMES
        PSI_CHECK_SYS_STAT
        PSI_CHECK_SYS_UIO
+       PSI_CHECK_SYS_UTSNAME
        PSI_CHECK_WCHAR
 
        PHP_SUBST(PSI_SHARED_LIBADD)
index 9b2d3eb..a08197e 100644 (file)
@@ -43,16 +43,12 @@ AC_DEFUN(PSI_FUNC, [
 AC_DEFUN(PSI_DECL_ARG, [
     m4_define([member_name], PSI_VAR_NAME($1))
     m4_define([member_type], PSI_VAR_TYPE($1))
-    m4_define([pointer_level], m4_len(m4_bpatsubst([$1], [[^*]])))
-       m4_define([array_size], [m4_bregexp([$1], [@<:@\([0-9]+\)@:>@], [\1])])
-       ifelse(array_size, [],
-               [m4_define([array_size], 0)],
-               [m4_define([pointer_level], m4_incr(pointer_level))]
-       )
+
+       PSI_TYPE_INDIRECTION([$1],, pl, as)
     if test -n "$psi_decl_args"; then
         psi_decl_args="$psi_decl_args, "
     fi
-    psi_decl_args="[$psi_decl_args{]PSI_TYPE_PAIR(member_type)[, \"]member_name[\",] pointer_level, array_size[}]"
+    psi_decl_args="[$psi_decl_args{]PSI_TYPE_PAIR(member_type)[, \"]member_name[\",] $pl, $as[}]"
 ])
 
 dnl PSI_DECL(type func, args)
@@ -62,7 +58,7 @@ AC_DEFUN(PSI_DECL, [
        m4_case([$2],
                [(void)], [],
                [()], [],
-               [m4_map_args_sep([PSI_DECL_ARG(], [)], [], [m4_bregexp([$2], [(\(.*\))], [\1])])])
+               [m4_map_args_sep([PSI_DECL_ARG(m4_normalize(], [))], [], m4_bregexp([$2], [(\(.*\))], [\1]))])
        PSI_FUNC(PSI_VAR_NAME($1), [
                PSI_DECLS="$psi_decl_args, {0}, $PSI_DECLS"
        ], [
index 439098f..0de4fdf 100644 (file)
@@ -2,8 +2,8 @@ dnl PSI_MACRO(macro, decl args, action-if-true)
 AC_DEFUN(PSI_MACRO, [
        AC_CHECK_DECL(PSI_VAR_NAME($1)$2, [
                $3
-               macro_type=PSI_VAR_TYPE($1)
-               macro_name=PSI_VAR_NAME($1)
+               macro_type="PSI_VAR_TYPE($1)"
+               macro_name="PSI_VAR_NAME($1)"
                ifelse([$2], [], [
                        macro_decl="()"
                        macro_call=""
index f0d273e..3255c94 100644 (file)
@@ -7,14 +7,8 @@ AC_DEFUN(PSI_STRUCT_MEMBER, [
        if test -n "$AS_TR_SH([ac_cv_sizeof_$1][_]member_name)" \
        && test "$AS_TR_SH([ac_cv_sizeof_$1][_]member_name)" -gt 0; then
                PSI_CHECK_OFFSETOF($1, member_name)
-               m4_define([pointer_level], m4_len(m4_bpatsubst([$2], [[^*]])))
-               m4_define([array_size], [m4_bregexp([$2], [@<:@\([0-9]+\)@:>@], [\1])])
-               ifelse(array_size, [],
-                       [m4_define([array_size], 0)],
-                       [m4_define([pointer_level], m4_incr(pointer_level))]
-               )
-               m4_define([member_size], PSI_TYPE_SIZE(member_type, pointer_level, array_size))
-               psi_struct_members="[$psi_struct_members, {]PSI_TYPE_PAIR(member_type)[, \"]member_name[\", $]AS_TR_SH([ac_cv_offsetof_]$1[_]member_name)[, ]member_size, pointer_level, array_size[}]"
+               PSI_TYPE_INDIRECTION($2, [$AS_TR_SH([ac_cv_sizeof_]$1[_]member_name)], pl, as)
+               psi_struct_members="[$psi_struct_members, {]PSI_TYPE_PAIR(member_type)[, \"]member_name[\", $]AS_TR_SH([ac_cv_offsetof_]$1[_]member_name)[, $]AS_TR_SH([ac_cv_sizeof_]$1[_]member_name), $pl, $as[}]"
        fi
 ])
 
@@ -22,7 +16,7 @@ AC_DEFUN(PSI_STRUCT, [
        AC_CHECK_SIZEOF($1, [], PSI_INCLUDES)
        psi_struct_name=m4_bregexp([$1], [^\(struct \)?\(\w+\)], [\2])
        psi_struct_members="{PSI_T_STRUCT, \"struct\", \"$psi_struct_name\", 0, $AS_TR_SH([ac_cv_sizeof_]$1), 0, 0}"
-       ifelse([$2],,,[m4_map_args_sep([PSI_STRUCT_MEMBER($1,], [)], [], $2)])
+       ifelse([$2],,,[m4_map_args_sep([PSI_STRUCT_MEMBER($1, m4_normalize(], [))], [], $2)])
        PSI_STRUCTS="$psi_struct_members, {0}, $PSI_STRUCTS"
        if test "$1" = "$psi_struct_name"; then
                PSI_TYPES="{PSI_T_STRUCT, \"$1\", \"$1\"}, $PSI_TYPES"
index 2cd9191..d1e0fbf 100644 (file)
@@ -42,8 +42,9 @@ AC_DEFUN(PSI_TYPE, [
        fi
 ])
 
-dnl unsigned char* buf[16] -> char
-AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [\(\(struct \)?[^ ]+\)[ *]+[^ ]+$], [\1])])
+dnl unsigned char* buf[16] -> unsigned char*
+dnl AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [\(\(struct \)?[^ ]+\)[ *]+[^ ]+$], [\1])])
+AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [^\(const \)?\(.*\) \([*]*\)[^ ]+$], [\2\3])])
 dnl unsigned char* buf[16] -> buf
 AC_DEFUN(PSI_VAR_NAME, [m4_bregexp(m4_bregexp([$1], [\([^ ]+\)$], [\1]), [\w+], [\&])])
 dnl PSI_TYPE_SIZE(type, pointer level, array size)
@@ -55,10 +56,40 @@ AC_DEFUN(PSI_TYPE_SIZE, [ifelse(
 dnl PSI_TYPE_BITS(type)
 AC_DEFUN(PSI_TYPE_BITS, [`expr 8 \* $AS_TR_SH([ac_cv_sizeof_]$1)`])
 
+dnl PSI_TYPE_INDIRECTION(type, size, pointer_level_var, array_size_var)
+AC_DEFUN(PSI_TYPE_INDIRECTION, [
+       AC_MSG_CHECKING(indirection of $1)
+       m4_define([pointer_level], m4_len(m4_bpatsubst([PSI_VAR_TYPE($1)], [[^*]])))
+       m4_define([array_size], [m4_bregexp([PSI_VAR_TYPE($1)], [@<:@\([0-9]+\)@:>@], [\1])])
+       
+       ifelse(array_size.$2,0., [
+               AC_MSG_ERROR([cannot compute dynamic array size of a non-struct member])
+       ], [
+               ifelse(pointer_level,0,[
+                       m4_define([type_size],[$]AS_TR_SH([ac_cv_sizeof_]m4_bregexp(PSI_VAR_TYPE([$1]), [^\( \|\w\)+], [\&])))
+               ],[
+                       m4_define([type_size],$ac_cv_sizeof_void_p)
+               ])
+       ])
+       
+       m4_case(array_size,,[
+               $3=pointer_level
+               $4=0]
+       ,0,[
+               $3=m4_incr(pointer_level)
+               $4="`expr $2 / type_size`"
+       ], [
+               $3=m4_incr(pointer_level)
+               $4=array_size
+       ])
+       
+       AC_MSG_RESULT([[$]$3, [$]$4])
+])
+
 AC_DEFUN(PSI_TYPE_PAIR, [m4_case(m4_bregexp([$1], [^\w+], [\&]),
        [void], [PSI_T_VOID, \"void\"],
        [struct], [PSI_T_STRUCT, \"m4_bregexp([$1], [^struct \(\w+\)], [\1])\"],
-       [PSI_T_NAME, \"$1\"])])
+       [PSI_T_NAME, \"m4_bregexp([$1], [^\(\w+ \)*\w+], [\&])\"])])
 
 AC_DEFUN(PSI_CHECK_STD_TYPES, [
        AC_CHECK_HEADERS(stdint.h)
index c84d44d..e521d43 100644 (file)
@@ -1,5 +1,14 @@
 AC_DEFUN(PSI_CHECK_STDLIB, [
        AC_CHECK_HEADERS(stdlib.h)
+       
+       PSI_STRUCT(div_t, [
+               int quot,
+               int rem
+       ])
+       PSI_STRUCT(ldiv_t, [
+               long quot,
+               long rem
+       ])
 
        PSI_CONST(EXIT_FAILURE, int)
        PSI_CONST(EXIT_SUCCESS, int)
@@ -12,7 +21,7 @@ AC_DEFUN(PSI_CHECK_STDLIB, [
        PSI_DECL(double atof, [(char *str)])
        PSI_DECL(int atoi, [(char *str)])
        PSI_DECL(long atol, [(char *str)])
-       PSI_DECL(div_t div, [(int numerator, int denominator)])
+       dnl PSI_DECL(div_t div, [(int numerator, int denominator)])
        PSI_DECL(double drand48, [()])
        PSI_DECL(double erand48, [(unsigned short xsubi@<:@3@:>@)])
        PSI_DECL(void exit, [(int status)])
@@ -23,7 +32,7 @@ AC_DEFUN(PSI_CHECK_STDLIB, [
        PSI_DECL(long jrand48, [(unsigned short xsubi@<:@3@:>@)])
        PSI_DECL(long labs, [(long l)])
        PSI_DECL(void lcong48, [(unsigned short param@<:@7@:>@)])
-       PSI_DECL(long ldiv, [(long numerator, long denominator)])
+       dnl PSI_DECL(ldiv_t ldiv, [(long numerator, long denominator)])
        PSI_DECL(long lrand48, [()])
        PSI_DECL(int mblen, [(const char *s, size_t n)])
        PSI_DECL(size_t mbstowcs, [(wchar_t *dest, char *src, size_t n)])
diff --git a/m4/sys_select.m4 b/m4/sys_select.m4
new file mode 100644 (file)
index 0000000..7ae010e
--- /dev/null
@@ -0,0 +1,17 @@
+AC_DEFUN(PSI_CHECK_SYS_SELECT, [
+       AC_CHECK_HEADERS(sys/select.h)
+       
+       PSI_STRUCT(fd_set, [])
+       
+       PSI_CONST(FD_SETSIZE, int)
+       
+       PSI_MACRO(void FD_CLEAR, [(int fd, fd_set *s)])
+       PSI_MACRO(void FD_COPY, [(fd_set *s1, fd_set *s2)])
+       PSI_MACRO(void FD_CLR, [(int fd, fd_set *s)])
+       PSI_MACRO(void FD_SET, [(int fd, fd_set *s)])
+       PSI_MACRO(int FD_ISSET, [(int fd, fd_set *s)])
+       PSI_MACRO(void FD_ZERO, [(fd_set *s)])
+       
+       PSI_DECL(int select, [(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)])
+       dnl PSI_DECL(int pselect, [(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout, sigset_t *sigmask)])
+])
\ No newline at end of file
diff --git a/m4/sys_socket.m4 b/m4/sys_socket.m4
new file mode 100644 (file)
index 0000000..331bd16
--- /dev/null
@@ -0,0 +1,93 @@
+AC_DEFUN(PSI_CHECK_SYS_SOCKET, [
+       AC_CHECK_HEADERS(sys/socket.h)
+       
+       PSI_TYPE(socklen_t, int)
+       PSI_TYPE(sa_family_t, uint)
+       
+       PSI_STRUCT(struct sockaddr, [
+               sa_family_t sa_family,
+               char sa_data@<:@0@:>@]
+       )
+       PSI_STRUCT(struct sockaddr_storage, [
+               sa_family_t ss_family]
+       )
+       PSI_STRUCT(struct msghdr, [
+               void *msg_name,
+               socklen_t msg_namelen,
+               struct iovec *msg_iov,
+               int msg_iovlen,
+               void *msg_control,
+               socklen_t msg_controllen,
+               int msg_flags]
+       )
+       PSI_STRUCT(struct cmsghdr, [
+               socklen_t cmsg_len,
+               int cmsg_level,
+               int cmsg_type]
+       )
+       PSI_STRUCT(struct linger, [
+               int l_onoff,
+               int l_linger]
+       )
+       
+       PSI_CONST(AF_INET, int)
+    PSI_CONST(AF_UNIX, int)
+    PSI_CONST(AF_UNSPEC, int)
+    PSI_CONST(MSG_CTRUNC, int)
+    PSI_CONST(MSG_DONTROUTE, int)
+    PSI_CONST(MSG_EOR, int)
+    PSI_CONST(MSG_NOSIGNAL, int)
+    PSI_CONST(MSG_OOB, int)
+    PSI_CONST(MSG_PEEK, int)
+    PSI_CONST(MSG_TRUNC, int)
+    PSI_CONST(MSG_WAITALL, int)
+    PSI_CONST(SCM_RIGHTS, int)
+    PSI_CONST(SHUT_RD, int)
+    PSI_CONST(SHUT_RDWR, int)
+    PSI_CONST(SHUT_WR, int)
+    PSI_CONST(SOCK_DGRAM, int)
+    PSI_CONST(SOCK_RAW, int)
+    PSI_CONST(SOCK_SEQPACKET, int)
+    PSI_CONST(SOCK_STREAM, int)
+    PSI_CONST(SOL_SOCKET, int)
+    PSI_CONST(SO_ACCEPTCONN, int)
+    PSI_CONST(SO_BROADCAST, int)
+    PSI_CONST(SO_DEBUG, int)
+    PSI_CONST(SO_DONTROUTE, int)
+    PSI_CONST(SO_ERROR, int)
+    PSI_CONST(SO_KEEPALIVE, int)
+    PSI_CONST(SO_LINGER, int)
+    PSI_CONST(SO_OOBINLINE, int)
+    PSI_CONST(SO_RCVBUF, int)
+    PSI_CONST(SO_RCVLOWAT, int)
+    PSI_CONST(SO_RCVTIMEO, int)
+    PSI_CONST(SO_REUSEADDR, int)
+    PSI_CONST(SO_SNDBUF, int)
+    PSI_CONST(SO_SNDLOWAT, int)
+    PSI_CONST(SO_SNDTIMEO, int)
+    PSI_CONST(SO_TYPE, int)
+    
+    PSI_MACRO(unsigned char *CMSG_DATA, [(struct cmsghdr *m)])
+       PSI_MACRO(struct cmsghdr *CMSG_NXTHDR, [(struct msghdr *m, struct cmsghdr *c)])
+       PSI_MACRO(struct cmsghdr *CMSG_FIRSTHDR, [(struct msghdr *m)])
+       
+       PSI_DECL(int accept, [(int socket, struct sockaddr *address, socklen_t *address_len)])
+       PSI_DECL(int bind, [(int socket, struct sockaddr *address, socklen_t address_len)])
+       PSI_DECL(int connect, [(int socket, struct sockaddr *address, socklen_t address_len)])
+       PSI_DECL(int getpeername, [(int socket, struct sockaddr *address, socklen_t *address_len)])
+       PSI_DECL(int getsockname, [(int socket, struct sockaddr *address, socklen_t *address_len)])
+       PSI_DECL(int getsockopt, [(int socket, int level, int option_name, void *option_value, socklen_t *option_len)])
+       PSI_DECL(int listen, [(int socket, int backlog)])
+       PSI_DECL(int recv, [(int socket, void *buffer, size_t length, int flags)])
+       PSI_DECL(int recvfrom, [(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len)])
+       PSI_DECL(int recvmsg, [(int socket, struct msghdr *message, int flags)])
+       PSI_DECL(int send, [(int socket, void *buffer, size_t length, int flags)])
+       PSI_DECL(int sendmsg, [(int socket, struct msghdr *message, int flags)])
+       PSI_DECL(int sendto, [(int socket, void *message, size_t length, int flags, struct sockaddr *dest_addr, socklen_t dest_len)])
+       PSI_DECL(int setsockopt, [(int socket, int level, int option_name, void *option_value, socklen_t option_len)])
+       PSI_DECL(int shutdown, [(int socket, int how)])
+       PSI_DECL(int sockatmark, [(int socket)])
+       PSI_DECL(int socket, [(int domain, int type, int protocol)])
+       PSI_DECL(int socketpair, [(int domain, int type, int protocol, int socket_vector@<:@2@:>@)])
+       
+])
\ No newline at end of file
index 861fa41..758ca79 100644 (file)
@@ -19,7 +19,7 @@ AC_DEFUN(PSI_CHECK_SYS_TIME, [
        )
 
        PSI_DECL(int getitimer, [(int which, struct itimerval *value)])
-       PSI_DECL(int setitimer, [(int which struct itimerval *value, struct itimerval *ovalue)])
+       PSI_DECL(int setitimer, [(int which, struct itimerval *value, struct itimerval *ovalue)])
        PSI_DECL(int gettimeofday, [(struct timeval *tp, struct timezone *tz)])
        PSI_DECL(int utimes, [(char *path, struct timeval times@<:@2@:>@)])
        PSI_DECL(int utimensat, [(int fd, char *path, struct timespec times@<:@2@:>@)])
diff --git a/m4/sys_utsname.m4 b/m4/sys_utsname.m4
new file mode 100644 (file)
index 0000000..475779f
--- /dev/null
@@ -0,0 +1,14 @@
+AC_DEFUN(PSI_CHECK_SYS_UTSNAME, [
+       AC_CHECK_HEADERS(sys/utsname.h)
+       
+       PSI_STRUCT(struct utsname, [
+               char sysname@<:@0@:>@,
+               char nodename@<:@0@:>@,
+               char release@<:@0@:>@,
+               char version@<:@0@:>@,
+               char machine@<:@0@:>@,
+               char domainname@<:@0@:>@
+       ])
+       
+       PSI_DECL(int uname, [(struct utsname *name)])
+])
\ No newline at end of file
index 6044d41..2400614 100644 (file)
@@ -1,2 +1,4 @@
-
-extern void free(void *ptr);
+function psi\abs(int $i) : int {
+       let n = intval($i);
+       return to_int(abs);
+}
index e01bd1b..a8082c6 100644 (file)
@@ -3,12 +3,12 @@ function psi\time() : int {
        return to_int(time);
 }
 
-extern int gettimeofday(struct timeval *tv, struct timezone *tz);
+// extern int gettimeofday(struct timeval *tp, struct timezone *tz);
 function psi\gettimeofday(array &$tv = NULL, array &$tz = NULL) : int {
-       let tv = calloc(1, struct timeval);
+       let tp = calloc(1, struct timeval);
        let tz = calloc(1, struct timezone);
        return to_int(gettimeofday);
-       set $tv = to_array(*tv,
+       set $tv = to_array(*tp,
                to_int(tv_sec),
                to_int(tv_usec));
        set $tz = to_array(*tz,
@@ -16,22 +16,22 @@ function psi\gettimeofday(array &$tv = NULL, array &$tz = NULL) : int {
                to_int(tz_dsttime));
 }
 
-extern char *asctime(struct tm *tm);
+// extern char *asctime(struct tm *tm);
 function psi\asctime(array $tm = NULL) : string {
        let tm = arrval($tm);
        return to_string(asctime);
 }
 
-extern char *asctime_r(struct tm *tm, char *buf);
+// extern char *asctime_r(struct tm *tm, char *buf);
 function psi\asctime_r(array $tm = NULL) : string {
        let tm = arrval($tm);
        let buf = calloc(32, char);
        return to_string(asctime_r);
 }
 
-extern struct tm *gmtime(time_t *tp);
+// extern struct tm *gmtime(time_t *t);
 function psi\gmtime(int $ts) : array {
-       let tp = &intval($ts);
+       let t = &intval($ts);
        return to_array(*gmtime,
                to_int(tm_sec),
                to_int(tm_min),
@@ -45,9 +45,9 @@ function psi\gmtime(int $ts) : array {
        );
 }
 
-extern struct tm *gmtime_r(time_t *tp, struct tm *buf);
+// extern struct tm *gmtime_r(time_t *t, struct tm *buf);
 function psi\gmtime_r(int $ts) : array {
-       let tp = &intval($ts);
+       let t = &intval($ts);
        let buf = calloc(1, struct tm);
        return to_array(*gmtime_r,
                to_int(tm_sec),
@@ -62,18 +62,18 @@ function psi\gmtime_r(int $ts) : array {
        );
 }
 
-extern int nanosleep(struct timespec *rqtp, struct timespec *rmtp);
+// extern int nanosleep(struct timespec *rqts, struct timespec *rmts);
 function psi\nanosleep(array $rq = NULL, array &$rm = NULL) : int {
-       let rqtp = arrval($rq);
-       let rmtp = calloc(1, struct timespec);
+       let rqts = arrval($rq);
+       let rmts = calloc(1, struct timespec);
        return to_int(nanosleep);
-       set $rm = to_array(*rmtp,
+       set $rm = to_array(*rmts,
                to_int(tv_sec),
                to_int(tv_nsec)
        );
 }
 
-extern clock_t times(struct tms *buf);
+// extern clock_t times(struct tms *buf);
 function psi\times(array &$tms = NULL) : int {
        let buf = calloc(1, struct tms);
        return to_int(times);
index 25abfcb..c79cc8e 100644 (file)
@@ -1,8 +1,7 @@
-extern int uname(struct utsname *u);
 function psi\uname(array &$u = NULL) : int {
-       let u = calloc(1, struct utsname);
+       let name = calloc(1, struct utsname);
        return to_int(uname);
-       set $u = to_array(*u,
+       set $u = to_array(*name,
                to_string(sysname),
                to_string(nodename),
                to_string(release),
index 5e66a45..44f8299 100644 (file)
@@ -224,8 +224,8 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
        for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
                if (!strcmp(type->name, stdtyp->type_name)) {
                        type->type = stdtyp->type_tag;
+                       return 1;
                }
-               return 1;
        }
 
        return 0;
@@ -404,6 +404,7 @@ static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args) {
                decl_arg *arg = args->args[i];
 
                if (!strcmp(var->name, arg->var->name)) {
+                       ZEND_ASSERT(!var->arg || var->arg == arg);
                        return var->arg = arg;
                }
        }
@@ -448,9 +449,14 @@ static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *r
        }
        set_var->arg = ref;
 
-       if (set->count && (set->func->type != PSI_T_TO_ARRAY || (ref_type->type != PSI_T_STRUCT && !ref->var->arg->var->pointer_level))) {
-               data->error(E_WARNING, "Inner `set` statement casts only work with to_array() casts on structs or pointers");
-               return 0;
+       if (set->count) {
+               int is_to_array = (set->func->type == PSI_T_TO_ARRAY);
+               int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level);
+               if (is_to_array && !is_pointer_to_struct) {
+                       data->error(E_WARNING, "Inner `set` statement casts only work with "
+                                       "to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name);
+                       return 0;
+               }
        }
 
        if (ref_type->type == PSI_T_STRUCT) {
@@ -459,11 +465,11 @@ static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *r
                        decl_var *sub_var = set->inner[i]->vars->vars[0];
                        decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var);
 
+                       set->inner[i]->outer.set = set;
                        if (sub_ref) {
                                if (!validate_set_value(data, set->inner[i], sub_ref, ref_type->strct->args)) {
                                        return 0;
                                }
-                               set->inner[i]->outer.set = set;
                        }
                }
        } else if (set->count == 1) {
@@ -471,6 +477,7 @@ static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *r
                decl_var *sub_var = set->inner[0]->vars->vars[0];
                decl_arg *sub_ref = locate_decl_var_arg(sub_var, ref_list);
 
+               set->inner[0]->outer.set = set;
                if (sub_ref) {
                        if (strcmp(sub_var->name, set_var->name)) {
                                data->error(E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
@@ -479,7 +486,6 @@ static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *r
                        if (!validate_set_value(data, set->inner[0], sub_ref, ref_list)) {
                                return 0;
                        }
-                       set->inner[0]->outer.set = set;
                }
        } else if (set->count > 1) {
                data->error(E_WARNING, "Inner `set` statement casts on pointers may only occur once");
@@ -625,10 +631,10 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
 
                                if (!strcmp(set_var->name, set_arg->var->name)) {
                                        check = 1;
+                                       set_var->arg = set_arg;
                                        if (!validate_set_value(data, set->val, set_arg, impl->decl->args)) {
                                                return 0;
                                        }
-                                       set_var->arg = set_arg;
                                        break;
                                }
                        }
@@ -1044,43 +1050,189 @@ static inline void dump_decl_arg(int fd, decl_arg *a) {
        dprintf(fd, " ");
        dump_decl_var(fd, a->var);
 }
+static inline void dump_level(int fd, unsigned level) {
+       dprintf(fd, "%.*s", level, "\t\t\t\t\t\t\t\t\t");
+}
+static inline void dump_impl_set_value(int fd, set_value *set, unsigned level) {
+       size_t i;
+
+       if (level > 1) {
+               /* only if not directly after `set ...` */
+               dump_level(fd, level);
+       }
+       dprintf(fd, "%s(", set->func->name);
+
+       for (i = 0; i < set->vars->count; ++i) {
+               decl_var *svar = set->vars->vars[i];
+               if (i) {
+                       dprintf(fd, ", ");
+               }
+               dump_decl_var(fd, svar);
+       }
+       if (set->inner) {
+               dprintf(fd, ",\n");
+               for (i = 0; i < set->count; ++i) {
+                       dump_impl_set_value(fd, set->inner[i], level+1);
+               }
+               /* only if inner stmts, i.e. with new lines, were dumped */
+               dump_level(fd, level);
+       }
+       if (level > 1) {
+               dprintf(fd, "),\n");
+       } else {
+               dprintf(fd, ");\n");
+       }
+}
 void PSI_ContextDump(PSI_Context *C, int fd)
 {
-       size_t i, j;
+       size_t i, j, k, l;
 
 #ifdef HAVE_LIBJIT
        if (C->ops == PSI_Libjit()) {
-               dprintf(fd, "#PSI(libjit)\n");
+               dprintf(fd, "// psi.engine=jit\n");
        }
 #endif
 #ifdef HAVE_LIBFFI
        if (C->ops == PSI_Libffi()) {
-               dprintf(fd, "#PSI(libffi)\n");
+               dprintf(fd, "// psi.engine=ffi\n");
        }
 #endif
+       dprintf(fd, "\n");
+
+       if (C->defs) {
+               for (i = 0; i < C->defs->count; ++i) {
+                       decl_typedef *tdef = C->defs->list[i];
+
+                       dprintf(fd, "typedef ");
+                       dump_decl_type(fd, tdef->type);
+                       dprintf(fd, " %s;\n", tdef->alias);
+               }
+               dprintf(fd, "\n");
+       }
+
+       if (C->structs) {
+               for (i = 0; i < C->structs->count; ++i) {
+                       decl_struct *strct = C->structs->list[i];
 
-       if (C->defs) for (i = 0; i < C->defs->count; ++i) {
-               decl_typedef *tdef = C->defs->list[i];
+                       dprintf(fd, "struct %s::(%zu) {\n", strct->name, strct->size);
+                       if (strct->args) for (j = 0; j < strct->args->count; ++j) {
+                               decl_arg *sarg = strct->args->args[j];
 
-               dprintf(fd, "typedef ");
-               dump_decl_type(fd, tdef->type);
-               dprintf(fd, " %s;\n", tdef->alias);
+                               dprintf(fd, "\t");
+                               dump_decl_arg(fd, sarg);
+                               dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos, sarg->layout->len);
+                       }
+                       dprintf(fd, "}\n");
+               }
+               dprintf(fd, "\n");
        }
-       if (C->structs) for (i = 0; i < C->structs->count; ++i) {
-               decl_struct *strct = C->structs->list[i];
-               decl_arg *sarg = NULL;
+       if (C->consts) {
+               for (i = 0; i < C->consts->count; ++i) {
+                       constant *cnst = C->consts->list[i];
 
-               dprintf(fd, "struct %s::(%zu) {\n", strct->name, strct->size);
-               for (j = 0; j < strct->args->count; ++j) {
-                       sarg = strct->args->args[j];
-                       dprintf(fd, "\t");
-                       dump_decl_arg(fd, sarg);
-                       dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos, sarg->layout->len);
+                       dprintf(fd, "const %s %s = ", cnst->type->name, cnst->name);
+                       if (cnst->val->type == PSI_T_QUOTED_STRING) {
+                               dprintf(fd, "\"%s\";\n", cnst->val->text);
+                       } else {
+                               dprintf(fd, "%s;\n", cnst->val->text);
+                       }
                }
-               dprintf(fd, "}\n");
+               dprintf(fd, "\n");
        }
+       if (C->decls) {
+               for (i = 0; i < C->decls->count; ++i) {
+                       decl *decl = C->decls->list[i];
+
+                       dprintf(fd, "%s ", decl->abi->convention);
+                       dump_decl_arg(fd, decl->func);
+                       dprintf(fd, "(");
+                       if (decl->args) for (j = 0; j < decl->args->count; ++j) {
+                               if (j) {
+                                       dprintf(fd, ", ");
+                               }
+                               dump_decl_arg(fd, decl->args->args[j]);
+                       }
+                       dprintf(fd, ");\n");
+               }
+               dprintf(fd, "\n");
+       }
+       if (C->impls) {
+               for (i = 0; i < C->impls->count; ++i) {
+                       impl *impl = C->impls->list[i];
 
-       dprintf(fd, "\n");
+                       dprintf(fd, "function %s(", impl->func->name);
+                       if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
+                               impl_arg *iarg = impl->func->args->args[j];
+
+                               dprintf(fd, "%s%s %s$%s",
+                                               j ? ", " : "",
+                                               iarg->type->name,
+                                               iarg->var->reference ? "&" : "",
+                                               iarg->var->name);
+                               if (iarg->def) {
+                                       dprintf(fd, " = %s", iarg->def->text);
+                               }
+                       }
+                       dprintf(fd, ") : %s%s {\n",
+                                       impl->func->return_reference ? "&":"",
+                                       impl->func->return_type->name);
+                       if (impl->stmts) {
+                               for (j = 0; j < impl->stmts->let.count; ++j) {
+                                       let_stmt *let = impl->stmts->let.list[j];
+
+                                       dprintf(fd, "\tlet %s", let->var->name);
+                                       if (let->val) {
+                                               dprintf(fd, " = %s", let->val->is_reference ? "&" : "");
+                                               if (let->val->func) {
+                                                       dprintf(fd, "%s(", let->val->func->name);
+                                                       if (let->val->func->alloc) {
+                                                               dprintf(fd, "%zu, ", let->val->func->alloc->n);
+                                                               dump_decl_type(fd, let->val->func->alloc->type);
+                                                       } else {
+                                                               dprintf(fd, "$%s", let->val->var->name);
+                                                       }
+                                                       dprintf(fd, ");\n");
+                                               } else {
+                                                       dprintf(fd, "NULL;\n");
+                                               }
+                                       }
+                               }
+                               for (j = 0; j < impl->stmts->ret.count; ++j) {
+                                       return_stmt *ret = impl->stmts->ret.list[j];
+
+                                       dprintf(fd, "\treturn ");
+                                       dump_impl_set_value(fd, ret->set, 1);
+                               }
+                               for (j = 0; j < impl->stmts->set.count; ++j) {
+                                       set_stmt *set = impl->stmts->set.list[j];
+
+                                       dprintf(fd, "\tset $%s = ", set->var->name);
+                                       dump_impl_set_value(fd, set->val, 1);
+                               }
+                               for (j = 0; j < impl->stmts->fre.count; ++j) {
+                                       free_stmt *fre = impl->stmts->fre.list[j];
+
+                                       dprintf(fd, "\tfree ");
+                                       for (k = 0; k < fre->calls->count; ++k) {
+                                               free_call *call = fre->calls->list[k];
+
+                                               if (k) {
+                                                       dprintf(fd, ", ");
+                                               }
+                                               dprintf(fd, "%s(", call->func);
+                                               for (l = 0; l < call->vars->count; ++l) {
+                                                       decl_var *fvar = call->vars->vars[l];
+
+                                                       dump_decl_var(fd, fvar);
+                                               }
+                                               dprintf(fd, ");\n");
+                                       }
+                               }
+                       }
+                       dprintf(fd, "}\n");
+               }
+               dprintf(fd, "\n");
+       }
 }
 
 void PSI_ContextDtor(PSI_Context *C)
index 737524f..0f2b4a0 100644 (file)
@@ -141,6 +141,7 @@ static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
        decl_arg *arg = calloc(1, sizeof(*arg));
        arg->type = type;
        arg->var = var;
+       var->arg = arg;
        return arg;
 }
 
index 81005f2..08478bc 100644 (file)
@@ -197,6 +197,7 @@ token_t PSI_ParserScan(PSI_Parser *P)
                'UINT32_T' {RETURN(PSI_T_UINT32);}
                'INT64_T' {RETURN(PSI_T_INT64);}
                'UINT64_T' {RETURN(PSI_T_UINT64);}
+               'UNSIGNED' {RETURN(PSI_T_UNSIGNED);}
                'STRING' {RETURN(PSI_T_STRING);}
                'ARRAY' {RETURN(PSI_T_ARRAY);}
                'FUNCTION' {RETURN(PSI_T_FUNCTION);}
index 3c07664..f5bea57 100644 (file)
 #define PSI_T_UINT32                          34
 #define PSI_T_INT64                           35
 #define PSI_T_UINT64                          36
-#define PSI_T_FUNCTION                        37
-#define PSI_T_REFERENCE                       38
-#define PSI_T_NULL                            39
-#define PSI_T_TRUE                            40
-#define PSI_T_FALSE                           41
-#define PSI_T_DOLLAR                          42
-#define PSI_T_CALLOC                          43
-#define PSI_T_ARRVAL                          44
-#define PSI_T_STRLEN                          45
-#define PSI_T_STRVAL                          46
-#define PSI_T_FLOATVAL                        47
-#define PSI_T_INTVAL                          48
-#define PSI_T_BOOLVAL                         49
-#define PSI_T_TO_ARRAY                        50
-#define PSI_T_TO_STRING                       51
-#define PSI_T_TO_INT                          52
-#define PSI_T_TO_FLOAT                        53
-#define PSI_T_TO_BOOL                         54
-#define PSI_T_MIXED                           55
-#define PSI_T_ARRAY                           56
-#define PSI_T_POINTER                         57
+#define PSI_T_UNSIGNED                        37
+#define PSI_T_FUNCTION                        38
+#define PSI_T_REFERENCE                       39
+#define PSI_T_NULL                            40
+#define PSI_T_TRUE                            41
+#define PSI_T_FALSE                           42
+#define PSI_T_DOLLAR                          43
+#define PSI_T_CALLOC                          44
+#define PSI_T_ARRVAL                          45
+#define PSI_T_STRLEN                          46
+#define PSI_T_STRVAL                          47
+#define PSI_T_FLOATVAL                        48
+#define PSI_T_INTVAL                          49
+#define PSI_T_BOOLVAL                         50
+#define PSI_T_TO_ARRAY                        51
+#define PSI_T_TO_STRING                       52
+#define PSI_T_TO_INT                          53
+#define PSI_T_TO_FLOAT                        54
+#define PSI_T_TO_BOOL                         55
+#define PSI_T_MIXED                           56
+#define PSI_T_ARRAY                           57
+#define PSI_T_POINTER                         58
index 345ab22..99054b6 100644 (file)
 %extra_argument {PSI_Parser *P}
 /* TOKEN is defined inside syntax_error */
 %syntax_error {
-       PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected token '%s'", TOKEN->text);
+       if (TOKEN) {
+               PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected token '%s'", TOKEN->text);
+       } else {
+               PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected end of input");
+       }
 }
 
 %nonassoc NAME.
@@ -162,7 +166,7 @@ decl_vars(vars) ::= decl_vars(vars_) COMMA decl_var(var). {
 %type decl_arg {decl_arg*}
 %destructor decl_arg {free_decl_arg($$);}
 decl_arg(arg_) ::= const_decl_type(type) decl_var(var). {
-       arg_ = var->arg = init_decl_arg(type, var);
+       arg_ = init_decl_arg(type, var);
 }
 /* void pointers need a specific rule */
 decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). {
@@ -170,7 +174,6 @@ decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). {
                init_decl_type(T->type, T->text),
                init_decl_var(N->text, p, 0)
        );
-       arg_->var->arg = arg_;
        free(T);
        free(N);
 }
@@ -179,7 +182,6 @@ decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). {
                init_decl_type(T->type, T->text),
                init_decl_var(N->text, p, 0)
        );
-       arg_->var->arg = arg_;
        free(T);
        free(N);
 }
@@ -227,6 +229,15 @@ decl_type(type_) ::= decl_type_token(T). {
        type_ = init_decl_type(T->type, T->text);
        free(T);
 }
+/* unsigned, urgh */
+decl_type(type_) ::= UNSIGNED NAME(T). {
+       type_ = init_decl_type(T->type, T->text);
+       type_->name = realloc(type_->name, T->size + sizeof("unsigned"));
+       memmove(type_->name + sizeof("unsigned"), type_->name, T->size);
+       memcpy(type_->name, "unsigned", sizeof("unsigned")-1);
+       type_->name[sizeof("unsigned")] = ' ';
+       type_->name[T->size + sizeof("unsigned")] = 0;
+}
 /* we have to support plain int here because we have it in our lexer rules */
 decl_type(type_) ::= INT(T). {
        type_ = init_decl_type(PSI_T_NAME, T->text);