[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
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)
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)
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"
], [
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=""
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
])
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"
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)
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)
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)
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)])
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)])
--- /dev/null
+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
--- /dev/null
+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
)
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@:>@)])
--- /dev/null
+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
-
-extern void free(void *ptr);
+function psi\abs(int $i) : int {
+ let n = intval($i);
+ return to_int(abs);
+}
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,
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),
);
}
-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),
);
}
-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);
-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),
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;
decl_arg *arg = args->args[i];
if (!strcmp(var->name, arg->var->name)) {
+ ZEND_ASSERT(!var->arg || var->arg == arg);
return var->arg = arg;
}
}
}
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) {
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) {
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");
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");
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;
}
}
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)
decl_arg *arg = calloc(1, sizeof(*arg));
arg->type = type;
arg->var = var;
+ var->arg = arg;
return arg;
}
'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);}
#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
%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.
%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). {
init_decl_type(T->type, T->text),
init_decl_var(N->text, p, 0)
);
- arg_->var->arg = arg_;
free(T);
free(N);
}
init_decl_type(T->type, T->text),
init_decl_var(N->text, p, 0)
);
- arg_->var->arg = arg_;
free(T);
free(N);
}
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);