From: Michael Wallner Date: Fri, 27 Nov 2015 12:21:30 +0000 (+0100) Subject: flush X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=commitdiff_plain;h=4b5ceb304b924c50eaf8263ad394493ff806fed4 flush --- diff --git a/config.m4 b/config.m4 index c4eb578..e7d1e1f 100644 --- 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) diff --git a/m4/psi_decl.m4 b/m4/psi_decl.m4 index 9b2d3eb..a08197e 100644 --- a/m4/psi_decl.m4 +++ b/m4/psi_decl.m4 @@ -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" ], [ diff --git a/m4/psi_macro.m4 b/m4/psi_macro.m4 index 439098f..0de4fdf 100644 --- a/m4/psi_macro.m4 +++ b/m4/psi_macro.m4 @@ -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="" diff --git a/m4/psi_struct.m4 b/m4/psi_struct.m4 index f0d273e..3255c94 100644 --- a/m4/psi_struct.m4 +++ b/m4/psi_struct.m4 @@ -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" diff --git a/m4/psi_type.m4 b/m4/psi_type.m4 index 2cd9191..d1e0fbf 100644 --- a/m4/psi_type.m4 +++ b/m4/psi_type.m4 @@ -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) diff --git a/m4/stdlib.m4 b/m4/stdlib.m4 index c84d44d..e521d43 100644 --- a/m4/stdlib.m4 +++ b/m4/stdlib.m4 @@ -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 index 0000000..7ae010e --- /dev/null +++ b/m4/sys_select.m4 @@ -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 index 0000000..331bd16 --- /dev/null +++ b/m4/sys_socket.m4 @@ -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 diff --git a/m4/sys_time.m4 b/m4/sys_time.m4 index 861fa41..758ca79 100644 --- a/m4/sys_time.m4 +++ b/m4/sys_time.m4 @@ -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 index 0000000..475779f --- /dev/null +++ b/m4/sys_utsname.m4 @@ -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 diff --git a/psi.d/stdlib.psi b/psi.d/stdlib.psi index 6044d41..2400614 100644 --- a/psi.d/stdlib.psi +++ b/psi.d/stdlib.psi @@ -1,2 +1,4 @@ - -extern void free(void *ptr); +function psi\abs(int $i) : int { + let n = intval($i); + return to_int(abs); +} diff --git a/psi.d/time.psi b/psi.d/time.psi index e01bd1b..a8082c6 100644 --- a/psi.d/time.psi +++ b/psi.d/time.psi @@ -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); diff --git a/psi.d/uname.psi b/psi.d/uname.psi index 25abfcb..c79cc8e 100644 --- a/psi.d/uname.psi +++ b/psi.d/uname.psi @@ -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), diff --git a/src/context.c b/src/context.c index 5e66a45..44f8299 100644 --- a/src/context.c +++ b/src/context.c @@ -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) diff --git a/src/parser.h b/src/parser.h index 737524f..0f2b4a0 100644 --- a/src/parser.h +++ b/src/parser.h @@ -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; } diff --git a/src/parser.re b/src/parser.re index 81005f2..08478bc 100644 --- a/src/parser.re +++ b/src/parser.re @@ -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);} diff --git a/src/parser_proc.h b/src/parser_proc.h index 3c07664..f5bea57 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -34,24 +34,25 @@ #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 diff --git a/src/parser_proc.y b/src/parser_proc.y index 345ab22..99054b6 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -15,7 +15,11 @@ %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);