end
define psi_decl_type_dump_args_with_layout
call psi_decl_type_dump_args_with_layout(1, $arg0, 0)
- echo \n
+ echo \n
end
define psi_decl_union_dump
call psi_decl_union_dump(1, $arg0)
return (set && *set && (*set != '0' || set[1]));
}
+#include "php_network.h"
+
+static inline int psi_fdopen(const char *desc)
+{
+ int fd = -1;
+
+ if (desc) {
+ char *addr = strstr(desc, "://");
+
+ if (addr) {
+ addr += 3;
+ }
+ if (addr && *addr) {
+ struct sockaddr_storage sa = {0};
+ socklen_t ss = 0;
+ int rc = php_network_parse_network_address_with_port(addr,
+ strlen(addr), (struct sockaddr *) &sa, &ss);
+
+ if (SUCCESS == rc) {
+ int styp = strncmp(desc, "udp:", 4)
+ ? SOCK_STREAM
+ : SOCK_DGRAM;
+ int sfam = sa.ss_family == AF_INET6
+ ? ((struct sockaddr_in6 *) &sa)->sin6_family
+ : ((struct sockaddr_in *) &sa)->sin_family;
+
+ fd = socket(sfam, styp, 0);
+
+ if (fd > 0 && 0 != connect(fd, (struct sockaddr *) &sa, ss)) {
+ perror(desc);
+ close(fd);
+ fd = -1;
+ }
+ }
+ } else if (!strcmp(desc, "stdout")) {
+ fd = STDOUT_FILENO;
+ } else if (!strcmp(desc, "stderr")) {
+ fd = STDERR_FILENO;
+ } else if (!(fd = atoi(desc)) || -1 == fcntl(fd, F_GETFD)) {
+ fd = open(desc, O_WRONLY|O_APPEND|O_CREAT|O_CLOEXEC, 0664);
+ }
+ }
+ return fd;
+}
+
typedef struct psi_object {
void *data;
void (*dtor)(void *data);
#include "php.h"
#include "zend_exceptions.h"
-#include "ext/spl/spl_exceptions.h"
struct psi_call_frame_argument *psi_call_frame_argument_init(struct psi_impl_arg *spec,
impl_val *ival, zval *zptr, int is_vararg) {
while (psi_plist_get(frame->impl->stmts.ass, i++, &ass)) {
if (ass->kind == kind) {
if (!psi_assert_stmt_exec(ass, frame)) {
- char *message = psi_assert_stmt_message(ass);
- zend_throw_exception(kind == PSI_ASSERT_PRE
- ? spl_ce_InvalidArgumentException
- : spl_ce_UnexpectedValueException, message, 0);
- free(message);
+ psi_assert_stmt_throw(ass);
return FAILURE;
}
}
}
zc.name = zend_string_copy(c->name);
-
- switch (c->type ? c->type->type : c->val->type) {
- case PSI_T_BOOL:
- ZVAL_BOOL(&zc.value, c->val->ival.zend.bval);
- break;
- case PSI_T_INT:
- ZVAL_LONG(&zc.value, c->val->ival.zend.lval);
- break;
- case PSI_T_FLOAT:
- case PSI_T_DOUBLE:
- ZVAL_DOUBLE(&zc.value, c->val->ival.dval);
- break;
- case PSI_T_STRING:
- case PSI_T_QUOTED_STRING:
- ZVAL_NEW_STR(&zc.value, zend_string_copy(c->val->ival.zend.str));
- if (ZSTR_IS_INTERNED(Z_STR(zc.value))) {
- Z_TYPE_FLAGS(zc.value) = 0;
- }
- break;
- default:
- assert(0);
- break;
- }
+ psi_impl_def_val_get_zval(c->val, c->type ? c->type->type : PSI_T_MIXED , &zc.value);
zend_register_constant(&zc);
}
void psi_context_dump(struct psi_dump *dump, struct psi_context *C)
{
- size_t i;
-
PSI_DUMP(dump, "// psi.engine=%s\n// %lu files\n",
(char *) C->ops->query(C, PSI_CONTEXT_QUERY_SELF, NULL),
C->count);
#if 0
if (C->flags & PSI_DEBUG) {
+ size_t i;
+
for (i = 0; i < C->count; ++i) {
- psi_data_dump(fd, &C->data[i]);
+ psi_data_dump(dump, &C->data[i]);
}
}
#endif
"include once"
};
-#if PSI_CPP_DEBUG > 1
-static int dump_def(zval *p)
-{
- struct psi_cpp_macro_decl *decl = Z_PTR_P(p);
-
- if (decl) {
- dprintf(2, "PSI: CPP decl -> #define ");
- psi_cpp_macro_decl_dump(2, decl);
- dprintf(2, "\n");
- }
- return ZEND_HASH_APPLY_KEEP;
-}
-#endif
-
void psi_cpp_free(struct psi_cpp **cpp_ptr)
{
if (*cpp_ptr) {
struct psi_cpp *cpp = *cpp_ptr;
-#if PSI_CPP_DEBUG > 1
- zend_hash_apply(&cpp->defs, dump_def);
-#endif
*cpp_ptr = NULL;
zend_hash_destroy(&cpp->defs);
zend_hash_destroy(&cpp->once);
#include "data.h"
#ifndef PSI_CPP_DEBUG
-# define PSI_CPP_DEBUG 1
+# define PSI_CPP_DEBUG 0
#endif
struct psi_cpp {
void psi_cpp_tokiter_reset(struct psi_cpp *cpp);
bool psi_cpp_tokiter_seek(struct psi_cpp *cpp, size_t index);
#if PSI_CPP_DEBUG > 1
-void psi_cpp_tokiter_dump(int fd, struct psi_cpp *cpp);
+void psi_cpp_tokiter_dump(struct psi_dump *dump, struct psi_cpp *cpp);
#endif
struct psi_token *psi_cpp_tokiter_current(struct psi_cpp *cpp);
size_t psi_cpp_tokiter_index(struct psi_cpp *cpp);
#include "cpp.h"
#include "parser.h"
-void psi_cpp_tokiter_dump(int fd, struct psi_cpp *cpp)
+void psi_cpp_tokiter_dump(struct psi_dump *dump, struct psi_cpp *cpp)
{
size_t i = cpp->index;
struct psi_token *T;
i = 0;
}
while (psi_plist_get(cpp->tokens.iter, i, &T)) {
- dprintf(fd, "PSI: CPP tokens %5zu %c ", i, cpp->index == i ? '*' : ' ');
+ PSI_DUMP(dump, "PSI: CPP tokens %5zu %c ", i, cpp->index == i ? '*' : ' ');
if (T) {
- psi_token_dump(fd, T);
+ psi_token_dump(dump, T);
} else {
- dprintf(fd, "TOKEN deleted\n");
+ PSI_DUMP(dump, "TOKEN deleted\n");
}
if (i >= cpp->index + 40) {
- dprintf(fd, "PSI: CPP tokens .....\n");
+ PSI_DUMP(dump, "PSI: CPP tokens .....\n");
break;
}
++i;
#include "data.h"
#include "php_globals.h"
-#include "php_network.h"
#include <dlfcn.h>
#include <ctype.h>
data->flags = flags;
if (data->flags & PSI_DEBUG) {
- char *debug = getenv("PSI_DEBUG");
+ int fd = psi_fdopen(getenv("PSI_DEBUG"));
- if (debug) {
- int fd = -1;
- char *addr = strstr(debug, "://");
-
- if (addr) {
- addr += 3;
- }
- if (addr && *addr) {
- struct sockaddr_storage sa = {0};
- socklen_t ss = 0;
- int rc = php_network_parse_network_address_with_port(addr,
- strlen(addr), (struct sockaddr *) &sa, &ss);
-
- if (SUCCESS == rc) {
- int styp = strncmp(debug, "udp:", 4)
- ? SOCK_STREAM
- : SOCK_DGRAM;
- int sfam = sa.ss_family == AF_INET6
- ? ((struct sockaddr_in6 *) &sa)->sin6_family
- : ((struct sockaddr_in *) &sa)->sin_family;
-
- fd = socket(sfam, styp, 0);
-
- if (fd > 0 && 0 != connect(fd, (struct sockaddr *) &sa, ss)) {
- perror(debug);
- close(fd);
- fd = -1;
- }
- }
- } else if (!strcmp(debug, "stdout")) {
- fd = STDOUT_FILENO;
- } else if (!strcmp(debug, "stderr")) {
- fd = STDERR_FILENO;
- } else if (!(fd = atoi(debug))) {
- fd = open(debug, O_WRONLY|O_APPEND|O_CREAT|O_CLOEXEC, 0664);
- }
-
- if (fd > 0) {
- data->debug_fd = fd;
- } else {
- data->debug_fd = STDERR_FILENO;
- }
+ if (fd > 0) {
+ data->debug_fd = fd;
+ } else {
+ data->debug_fd = STDERR_FILENO;
}
}
}
while (psi_plist_get(D->unions, i++, &unn)) {
if (!psi_decl_type_is_anon(unn->name, "union")) {
- psi_decl_union_dump(fd, unn);
+ psi_decl_union_dump(dump, unn);
PSI_DUMP(dump, "\n");
}
}
#include "plist.h"
#include "validate.h"
-#define PSI_DEBUG 0x1
-#define PSI_SILENT 0x2
+#include "php_network.h"
#include <stdarg.h>
#include <dlfcn.h>
+#define PSI_DEBUG 0x1
+#define PSI_SILENT 0x2
+
#ifndef RTLD_NEXT
# define RTLD_NEXT ((void *) -1l)
#endif
} while(0)
#define PSI_DEBUG_DUMP(ctx, dump_func, ...) do { \
if ((ctx) && (PSI_DATA(ctx)->flags & PSI_DEBUG)) { \
- dump_func(PSI_DATA(ctx)->debug_fd, __VA_ARGS__); \
+ struct psi_dump dump_ = {{ .fd = PSI_DATA(ctx)->debug_fd}, \
+ .fun = (psi_dump_cb) dprintf}; \
+ dump_func(&dump_, __VA_ARGS__); \
} \
} while (0)
struct psi_data *psi_data_ctor_with_dtors(struct psi_data *data, psi_error_cb error, unsigned flags);
struct psi_data *psi_data_exchange(struct psi_data *dest, struct psi_data *src);
void psi_data_dtor(struct psi_data *data);
-void psi_data_dump(int fd, struct psi_data *data);
+void psi_data_dump(struct psi_dump *dump, struct psi_data *data);
#endif
void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...);
void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv);
-union psi_debug_ctx {
- FILE *stdio;
- int socket;
-};
-
#endif /* PSI_ERROR_H */
return psi_val_boolval(tmp, real_type, boolval);
}
-#if HAVE_INT128
-static inline char *psi_u128_to_buf(char *buf, unsigned __int128 u128)
-{
- for (*buf = 0; u128 > 0; u128 /= 10) {
- *--buf = ((u128 % 10) + '0') & 0xff;
- }
- return buf;
-}
-
-static inline char *psi_i128_to_buf(char *buf, __int128 i128)
-{
- if (i128 < 0) {
- char *res = psi_u128_to_buf(buf, ~((unsigned __int128) i128) + 1);
-
- *--res = '-';
- return res;
- }
- return psi_u128_to_buf(buf, i128);
-}
-
-# define RETVAL_LONG_STR(V, s) do {\
- char buf[0x30] = {0}; \
- if (s && V >= ZEND_LONG_MIN && V <= ZEND_LONG_MAX) { \
- RETVAL_LONG(V); \
- } else if (!s && V <= ZEND_LONG_MAX) { \
- RETVAL_LONG(V); \
- } else if (!s && V <= ZEND_ULONG_MAX) { \
- RETVAL_STRING(zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], V)); \
- } else if (s && V >= INT128_MIN && V <= INT128_MAX) { \
- RETVAL_STRING(psi_i128_to_buf(&buf[sizeof(buf) - 1], V)); \
- } else { \
- RETVAL_STRING(psi_u128_to_buf(&buf[sizeof(buf) - 1], V)); \
- } \
- } while (0)
-#else
-# define RETVAL_LONG_STR(V, s) do {\
- char buf[0x20] = {0}; \
- if (s && V >= ZEND_LONG_MIN && V <= ZEND_LONG_MAX) { \
- RETVAL_LONG(V); \
- } else if (!s && V <= ZEND_LONG_MAX) { \
- RETVAL_LONG(V); \
- } else { \
- RETVAL_STRING(zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], V)); \
- } \
- } while (0)
-#endif
/*
* set $ivar = to_int(*dvar)
*/
case PSI_T_INT32: RETVAL_LONG(v->i32); break;
case PSI_T_UINT32: RETVAL_LONG(v->u32); break;
case PSI_T_INT64: RETVAL_LONG(v->i64); break;
- case PSI_T_UINT64: RETVAL_LONG_STR(v->u64, 0); break;
+ case PSI_T_UINT64: RETVAL_LONG_DOUBLE_STR(v->u64,); break;
#ifdef HAVE_INT128
- case PSI_T_INT128: RETVAL_LONG_STR(v->i128, 1); break;
- case PSI_T_UINT128: RETVAL_LONG_STR(v->u128, 0); break;
+ case PSI_T_INT128: RETVAL_LONG_DOUBLE_STR(v->i128, is_signed=true); break;
+ case PSI_T_UINT128: RETVAL_LONG_DOUBLE_STR(v->u128,); break;
#endif
case PSI_T_FLOAT:
RETVAL_DOUBLE((double) v->fval);
struct psi_impl;
struct psi_impl_type;
+#if HAVE_INT128
+static inline char *psi_u128_to_buf(char *buf, unsigned __int128 u128)
+{
+ for (*buf = 0; u128 > 0; u128 /= 10) {
+ *--buf = ((u128 % 10) + '0') & 0xff;
+ }
+ return buf;
+}
+
+static inline char *psi_i128_to_buf(char *buf, __int128 i128)
+{
+ if (i128 < 0) {
+ char *res = psi_u128_to_buf(buf, ~((unsigned __int128) i128) + 1);
+
+ *--res = '-';
+ return res;
+ }
+ return psi_u128_to_buf(buf, i128);
+}
+#else
+# define psi_u128_to_buf(b,u) zend_print_ulong_to_buf(b,u)
+# define psi_i128_to_buf(b,i) zend_print_long_to_buf(b,i)
+#endif
+
+
+#define RETVAL_LONG_DOUBLE_STR(V, flags) ZVAL_LONG_DOUBLE_STR(return_value, V, flags)
+# define ZVAL_LONG_DOUBLE_STR(z, V, flags) do { \
+ char buf[0x20] = {0}; \
+ bool is_signed = false, persistent = false; \
+ flags; \
+ if (is_signed) { \
+ if (V >= ZEND_LONG_MIN && V <= ZEND_LONG_MAX) { \
+ ZVAL_LONG(z, V); \
+ } else if (V >= -(1L<<52) && V <= (1L<<53)) { \
+ ZVAL_DOUBLE(z, V); \
+ } else if (V < ZEND_LONG_MIN || V > ZEND_LONG_MAX) { \
+ ZVAL_STRING(z, psi_i128_to_buf(&buf[sizeof(buf) - 1], V)); \
+ } else { \
+ ZVAL_STRING(z, zend_print_long_to_buf(&buf[sizeof(buf) - 1], V)); \
+ } \
+ } else { \
+ if (V <= ZEND_LONG_MAX) { \
+ ZVAL_LONG(z, V); \
+ } else if (V <= (1L<<53)) { \
+ ZVAL_DOUBLE(z, V); \
+ } else if (V > ZEND_ULONG_MAX) { \
+ ZVAL_STRING(z, psi_u128_to_buf(&buf[sizeof(buf) - 1], V)); \
+ } else { \
+ ZVAL_STRING(z, zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], V)); \
+ } \
+ } \
+} while (0)
+
+
zend_long psi_zval_count(zval *zvalue);
zend_internal_arg_info *psi_internal_arginfo(struct psi_impl *impl);
int psi_internal_type(struct psi_impl_type *type);
{
php_stream *s;
zval *r = NULL;
- int fd = STDOUT_FILENO;
+ struct psi_dump dump = {.fun = php_stream_printf};
if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "|r!", &r)) {
return;
}
if (r) {
php_stream_from_zval(s, r);
-
- if (SUCCESS != php_stream_cast(s, PHP_STREAM_AS_FD | PHP_STREAM_CAST_INTERNAL, (void **)&fd, 1)) {
- RETURN_FALSE;
- }
+ dump.ctx.hn = s;
+ } else {
+ dump.ctx.hn = php_stream_open_wrapper("php://output", "w", REPORT_ERRORS, NULL);
}
- psi_context_dump(PSI_G(context), fd);
+ psi_context_dump(&dump, PSI_G(context));
}
ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate, 0, 0, 1)
size_t i = 0;
struct psi_token *tok;
- smart_str_append_printf(&str, "\nconst psi\\%s = ", name->val);
+ smart_str_append_printf(&str, "const psi\\%s = ", name->val);
if (scope->macro->exp) {
impl_val res = {0};
token_t typ = psi_num_exp_exec(scope->macro->exp, &res, NULL, scope->cpp);
scope.cpp = P->preproc;
flags = P->flags;
- //P->flags |= PSI_SILENT;
+ P->flags |= PSI_SILENT;
ZEND_HASH_FOREACH_STR_KEY_PTR(&P->preproc->defs, name, scope.macro)
{
T->file = zend_string_copy(file);
T->text = zend_string_init_interned(token_txt, token_len, 1);
#if PSI_DEBUG_TOKEN_ALLOC
- fprintf(stderr, "PSI: token_init %p\n", T);
+ PSI_DEBUG_PRINT(cpp->parser, "PSI: token_init %p\n", T);
#endif
return T;
}
if (*token_ptr) {
struct psi_token *token = *token_ptr;
#if PSI_DEBUG_TOKEN_ALLOC
- fprintf(stderr, "PSI: token_free %p\n", token);
+ PSI_DEBUG_PRINT(cpp->parser, "PSI: token_free %p\n", token);
#endif
*token_ptr = NULL;
zend_string_release(token->text);
*ptr = *src;
#if PSI_DEBUG_TOKEN_ALLOC
- fprintf(stderr, "PSI: token_copy %p <= %p\n", ptr, src);
+ PSI_DEBUG_PRINT(cpp->parser, "PSI: token_copy %p <= %p\n", ptr, src);
#endif
ptr->text = zend_string_copy(ptr->text);
ptr->file = zend_string_copy(ptr->file);
T->text = smart_str_extract(&text);
#if PSI_DEBUG_TOKEN_ALLOC
- fprintf(stderr, "PSI: token_cat %p\n", T);
+ PSI_DEBUG_PRINT(cpp->parser, "PSI: token_cat %p\n", T);
#endif
return T;
}
return psi_hash(digest_buf, t->file->val, loc_buf, (char *) NULL);
}
-void psi_token_dump(int fd, struct psi_token *t)
+void psi_token_dump(struct psi_dump *dump, struct psi_token *t)
{
size_t i;
- dprintf(fd, "TOKEN %p (%u) ", t, t->type);
+ PSI_DUMP(dump, "TOKEN %p (%u) ", t, t->type);
if (t->type == PSI_T_EOF) {
- dprintf(fd, "EOF");
+ PSI_DUMP(dump, "EOF");
} else {
- dprintf(fd, "\"");
+ PSI_DUMP(dump, "\"");
for (i = 0; i < t->text->len; ++i) {
switch (t->text->val[i]) {
case '\0':
- dprintf(fd, "\\0");
+ PSI_DUMP(dump, "\\0");
break;
case '\a':
- dprintf(fd, "\\a");
+ PSI_DUMP(dump, "\\a");
break;
case '\b':
- dprintf(fd, "\\b");
+ PSI_DUMP(dump, "\\b");
break;
case '\f':
- dprintf(fd, "\\f");
+ PSI_DUMP(dump, "\\f");
break;
case '\n':
- dprintf(fd, "\\n");
+ PSI_DUMP(dump, "\\n");
break;
case '\r':
- dprintf(fd, "\\r");
+ PSI_DUMP(dump, "\\r");
break;
case '\t':
- dprintf(fd, "\\t");
+ PSI_DUMP(dump, "\\t");
break;
case '\v':
- dprintf(fd, "\\v");
+ PSI_DUMP(dump, "\\v");
break;
case '"':
- dprintf(fd, "\\\"");
+ PSI_DUMP(dump, "\\\"");
break;
default:
if (isprint(t->text->val[i])) {
- dprintf(fd, "%c", t->text->val[i]);
+ PSI_DUMP(dump, "%c", t->text->val[i]);
} else {
- dprintf(fd, "\\x%02hhX", t->text->val[i]);
+ PSI_DUMP(dump, "\\x%02hhX", t->text->val[i]);
}
break;
}
}
- dprintf(fd, "\"");
+ PSI_DUMP(dump, "\"");
}
- dprintf(fd, " at col %u in %s on line %u\n", t->col, t->file->val, t->line);
+ PSI_DUMP(dump, " at col %u in %s on line %u\n", t->col, t->file->val, t->line);
}
return &indir[32 - MIN(32, pointer_level)];
}
+struct psi_dump;
+
struct psi_token {
token_t type;
unsigned line;
struct psi_token *psi_token_append(const char *sep, struct psi_token *T, unsigned argc, ...);
struct psi_token *psi_token_translit(struct psi_token *T, char *from, char *to);
uint64_t psi_token_hash(struct psi_token *t, char *digest_buf);
-void psi_token_dump(int fd, struct psi_token *t);
+void psi_token_dump(struct psi_dump *dump, struct psi_token *t);
void psi_token_free(struct psi_token **token);
#endif
#include "data.h"
#include "calc.h"
+#include "zend_smart_str.h"
+#include "zend_exceptions.h"
+#include "ext/spl/spl_exceptions.h"
+
struct psi_assert_stmt *psi_assert_stmt_init(enum psi_assert_kind kind, struct psi_num_exp *exp)
{
struct psi_assert_stmt *stmt = pecalloc(1, sizeof(*stmt), 1);
}
}
-void psi_assert_stmt_dump(int fd, struct psi_assert_stmt *stmt)
+void psi_assert_stmt_dump(struct psi_dump *dump, struct psi_assert_stmt *stmt)
{
- dprintf(fd, "\t%s_assert ", stmt->kind == PSI_ASSERT_PRE ? "pre" : "post");
- psi_num_exp_dump(fd, stmt->exp);
- dprintf(fd, ";\n");
+ PSI_DUMP(dump, "\t%s_assert ", stmt->kind == PSI_ASSERT_PRE ? "pre" : "post");
+ psi_num_exp_dump(dump, stmt->exp);
+ PSI_DUMP(dump, ";\n");
}
bool psi_assert_stmt_exec(struct psi_assert_stmt *stmt, struct psi_call_frame *frame)
return true;
}
-char *psi_assert_stmt_message(struct psi_assert_stmt *stmt)
+void psi_assert_stmt_throw(struct psi_assert_stmt *stmt)
{
- /* FIXME */
- struct stat sb;
- char *message, template[] = "psi.assert.XXXXXX";
- int fd = mkstemp(template);
-
- dprintf(fd, "Failed asserting that ");
- psi_num_exp_dump(fd, stmt->exp);
- fstat(fd, &sb);
- message = pemalloc(sb.st_size + 1, 1);
- lseek(fd, 0, SEEK_SET);
- read(fd, message, sb.st_size);
- close(fd);
- message[sb.st_size] = '\0';
- return message;
+ struct psi_dump dump;
+ smart_str str = {0};
+ zend_string *message;
+
+ dump.ctx.hn = &str;
+ dump.fun = (psi_dump_cb) smart_str_append_printf;
+
+ PSI_DUMP(&dump, "Failed asserting that ");
+ psi_num_exp_dump(&dump, stmt->exp);
+ smart_str_0(&str);
+ zend_throw_exception(stmt->kind == PSI_ASSERT_PRE
+ ? spl_ce_InvalidArgumentException
+ : spl_ce_UnexpectedValueException, str.s->val, 0);
+ smart_str_free(&str);
}
struct psi_assert_stmt *psi_assert_stmt_init(enum psi_assert_kind kind, struct psi_num_exp *exp);
bool psi_assert_stmt_exec(struct psi_assert_stmt *stmt, struct psi_call_frame *frame);
-void psi_assert_stmt_dump(int fd, struct psi_assert_stmt *stmt);
+void psi_assert_stmt_dump(struct psi_dump *dump, struct psi_assert_stmt *stmt);
void psi_assert_stmt_free(struct psi_assert_stmt **stmt);
bool psi_assert_stmts_validate(struct psi_data *data, struct psi_validate_scope *scope);
-char *psi_assert_stmt_message(struct psi_assert_stmt *stmt);
+void psi_assert_stmt_throw(struct psi_assert_stmt *stmt);
#endif
}
}
-void psi_const_dump(int fd, struct psi_const *cnst)
+void psi_const_dump(struct psi_dump *dump, struct psi_const *cnst)
{
- dprintf(fd, "const ");
+ PSI_DUMP(dump, "const ");
if (cnst->type) {
- psi_impl_type_dump(fd, cnst->type);
+ psi_impl_type_dump(dump, cnst->type);
}
- dprintf(fd, " %s = ", cnst->name->val);
- psi_impl_def_val_dump(fd, cnst->val);
- dprintf(fd, ";");
+ PSI_DUMP(dump, " %s = ", cnst->name->val);
+ psi_impl_def_val_dump(dump, cnst->val);
+ PSI_DUMP(dump, ";");
}
bool psi_const_validate(struct psi_data *data, struct psi_const *c,
struct psi_validate_scope *scope)
{
+ if (c->type) {
+ switch (c->type->type) {
+ case PSI_T_BOOL:
+ case PSI_T_INT:
+ case PSI_T_FLOAT:
+ case PSI_T_DOUBLE:
+ case PSI_T_STRING:
+ break;
+ default:
+ data->error(data, val->token, PSI_WARNING,
+ "Invalid default value type '%s', "
+ "expected one of bool, int, float/double or string.",
+ type->name->val);
+ return false;
+ }
+ }
if (!psi_impl_def_val_validate(data, c->val, c->type, scope)) {
return false;
}
struct psi_const *psi_const_init(struct psi_impl_type *type, zend_string *name,
struct psi_impl_def_val *val);
void psi_const_free(struct psi_const **constant_ptr);
-void psi_const_dump(int fd, struct psi_const *cnst);
+void psi_const_dump(struct psi_dump *dump, struct psi_const *cnst);
bool psi_const_validate(struct psi_data *data, struct psi_const *c,
struct psi_validate_scope *scope);
}
}
-void psi_cpp_exp_dump(int fd, struct psi_cpp_exp *exp)
+void psi_cpp_exp_dump(struct psi_dump *dump, struct psi_cpp_exp *exp)
{
- dprintf(fd, "#%s ", exp->token->text->val);
+ PSI_DUMP(dump, "#%s ", exp->token->text->val);
switch (exp->type) {
case PSI_T_WARNING:
case PSI_T_ERROR:
case PSI_T_UNDEF:
case PSI_T_IFDEF:
case PSI_T_IFNDEF:
- dprintf(fd, "%s", exp->data.tok->text->val);
+ PSI_DUMP(dump, "%s", exp->data.tok->text->val);
break;
case PSI_T_IMPORT:
case PSI_T_INCLUDE:
case PSI_T_INCLUDE_NEXT:
if (exp->data.tok->type == PSI_T_CPP_HEADER) {
- dprintf(fd, "<%s>", exp->data.tok->text->val);
+ PSI_DUMP(dump, "<%s>", exp->data.tok->text->val);
} else {
- dprintf(fd, "\"%s\"", exp->data.tok->text->val);
+ PSI_DUMP(dump, "\"%s\"", exp->data.tok->text->val);
}
break;
case PSI_T_DEFINE:
- psi_cpp_macro_decl_dump(fd, exp->data.decl);
+ psi_cpp_macro_decl_dump(dump, exp->data.decl);
break;
case PSI_T_IF:
case PSI_T_ELIF:
- psi_num_exp_dump(fd, exp->data.num);
+ psi_num_exp_dump(dump, exp->data.num);
break;
case PSI_T_ENDIF:
case PSI_T_ELSE:
assert(0);
break;
}
- dprintf(fd, "\n");
+ PSI_DUMP(dump, "\n");
}
struct psi_cpp_exp *psi_cpp_exp_init(token_t type, void *data);
void psi_cpp_exp_free(struct psi_cpp_exp **exp_ptr);
-void psi_cpp_exp_dump(int fd, struct psi_cpp_exp *exp);
+void psi_cpp_exp_dump(struct psi_dump *dump, struct psi_cpp_exp *exp);
void psi_cpp_exp_exec(struct psi_cpp_exp *exp, struct psi_cpp *cpp, struct psi_data *D);
#endif
}
}
-void psi_cpp_macro_call_dump(int fd, struct psi_cpp_macro_call *call)
+void psi_cpp_macro_call_dump(struct psi_dump *dump, struct psi_cpp_macro_call *call)
{
size_t i = 0;
struct psi_num_exp *num;
- dprintf(fd, "%s(", call->name->val);
+ PSI_DUMP(dump, "%s(", call->name->val);
while (psi_plist_get(call->args, i++, &num)) {
if (i > 1) {
- dprintf(fd, ", ");
+ PSI_DUMP(dump, ", ");
}
- psi_num_exp_dump(fd, num);
+ psi_num_exp_dump(dump, num);
}
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
}
struct psi_cpp_macro_call *psi_cpp_macro_call_copy(
struct psi_cpp_macro_call *call);
void psi_cpp_macro_call_free(struct psi_cpp_macro_call **call_ptr);
-void psi_cpp_macro_call_dump(int fd, struct psi_cpp_macro_call *call);
+void psi_cpp_macro_call_dump(struct psi_dump *dump, struct psi_cpp_macro_call *call);
#endif
}
}
-void psi_cpp_macro_decl_dump(int fd, struct psi_cpp_macro_decl *macro)
+void psi_cpp_macro_decl_dump(struct psi_dump *dump, struct psi_cpp_macro_decl *macro)
{
- dprintf(fd, "%s", macro->token->text->val);
+ PSI_DUMP(dump, "%s", macro->token->text->val);
if (macro->sig) {
size_t i = 0;
struct psi_token *tok;
- dprintf(fd, "(");
+ PSI_DUMP(dump, "(");
while (psi_plist_get(macro->sig, i++, &tok)) {
- dprintf(fd, "%s%s", i>1?",":"", tok->text->val);
+ PSI_DUMP(dump, "%s%s", i>1?",":"", tok->text->val);
}
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
}
if (macro->exp) {
- dprintf(fd, " ");
- psi_num_exp_dump(fd, macro->exp);
+ PSI_DUMP(dump, " ");
+ psi_num_exp_dump(dump, macro->exp);
assert(macro->tokens);
while (psi_plist_get(macro->tokens, i++, &tok)) {
switch (tok->type) {
case PSI_T_QUOTED_STRING:
- dprintf(fd, " \"%s\"", tok->text->val);
+ PSI_DUMP(dump, " \"%s\"", tok->text->val);
break;
case PSI_T_QUOTED_CHAR:
- dprintf(fd, " '%s'", tok->text->val);
+ PSI_DUMP(dump, " '%s'", tok->text->val);
break;
default:
- dprintf(fd, " %s", tok->text->val);
+ PSI_DUMP(dump, " %s", tok->text->val);
}
}
}
struct psi_cpp_macro_decl *psi_cpp_macro_decl_init(struct psi_plist *sig,
struct psi_plist *tokens, struct psi_num_exp *exp);
void psi_cpp_macro_decl_free(struct psi_cpp_macro_decl **macro_ptr);
-void psi_cpp_macro_decl_dump(int fd, struct psi_cpp_macro_decl *decl);
+void psi_cpp_macro_decl_dump(struct psi_dump *dump, struct psi_cpp_macro_decl *decl);
bool psi_cpp_macro_decl_equal(struct psi_cpp_macro_decl *d1, struct psi_cpp_macro_decl *d2);
#endif
}
}
-void psi_decl_dump(int fd, struct psi_decl *decl)
+void psi_decl_dump(struct psi_dump *dump, struct psi_decl *decl)
{
if (decl->abi) {
- psi_decl_abi_dump(fd, decl->abi);
+ psi_decl_abi_dump(dump, decl->abi);
}
- dprintf(fd, " ");
+ PSI_DUMP(dump, " ");
/* FIXME: functions returning arrays */
- psi_decl_arg_dump(fd, decl->func, 0);
- dprintf(fd, "(");
+ psi_decl_arg_dump(dump, decl->func, 0);
+ PSI_DUMP(dump, "(");
if (decl->args) {
size_t i;
struct psi_decl_arg *arg;
for (i = 0; psi_plist_get(decl->args, i, &arg); ++i) {
if (i) {
- dprintf(fd, ", ");
+ PSI_DUMP(dump, ", ");
}
- psi_decl_arg_dump(fd, arg, 0);
+ psi_decl_arg_dump(dump, arg, 0);
}
if (decl->varargs) {
- dprintf(fd, ", ...");
+ PSI_DUMP(dump, ", ...");
}
}
if (decl->func->var->array_size) {
- dprintf(fd, ")[%u]", decl->func->var->array_size);
+ PSI_DUMP(dump, ")[%u]", decl->func->var->array_size);
}
if (decl->redir) {
- dprintf(fd, ") __asm__ (\"%s\");", decl->redir->val);
+ PSI_DUMP(dump, ") __asm__ (\"%s\");", decl->redir->val);
} else {
- dprintf(fd, ");");
+ PSI_DUMP(dump, ");");
}
}
struct psi_decl *psi_decl_init(struct psi_decl_arg *func, struct psi_plist *args);
void psi_decl_free(struct psi_decl **d_ptr);
-void psi_decl_dump(int fd, struct psi_decl *decl);
+void psi_decl_dump(struct psi_dump *dump, struct psi_decl *decl);
bool psi_decl_validate(struct psi_data *data, struct psi_decl *decl, struct psi_validate_scope *scope);
bool psi_decl_validate_nodl(struct psi_data *data, struct psi_decl *decl, struct psi_validate_scope *scope);
}
}
-void psi_decl_abi_dump(int fd, struct psi_decl_abi *abi)
+void psi_decl_abi_dump(struct psi_dump *dump, struct psi_decl_abi *abi)
{
- dprintf(fd, "%s", abi->convention->val);
+ PSI_DUMP(dump, "%s", abi->convention->val);
}
static const char * const abi_ccs[] = {
struct psi_decl_abi *psi_decl_abi_init(zend_string *convention);
void psi_decl_abi_free(struct psi_decl_abi **abi_ptr);
-void psi_decl_abi_dump(int fd, struct psi_decl_abi *abi);
+void psi_decl_abi_dump(struct psi_dump *dump, struct psi_decl_abi *abi);
bool psi_decl_abi_validate(struct psi_data *data, struct psi_decl_abi *abi);
#endif
struct psi_decl_arg *psi_decl_arg_init(struct psi_decl_type *type, struct psi_decl_var *var);
void psi_decl_arg_free(struct psi_decl_arg **arg_ptr);
-void psi_decl_arg_dump(int fd, struct psi_decl_arg *arg, unsigned level);
+void psi_decl_arg_dump(struct psi_dump *dump, struct psi_decl_arg *arg, unsigned level);
bool psi_decl_arg_validate(struct psi_data *data, struct psi_decl_arg *arg, struct psi_validate_scope *scope);
bool psi_decl_arg_validate_typedef(struct psi_data *data, struct psi_decl_arg *def, struct psi_validate_scope *scope);
}
}
-void psi_decl_enum_dump(int fd, struct psi_decl_enum *e, unsigned level)
+void psi_decl_enum_dump(struct psi_dump *dump, struct psi_decl_enum *e, unsigned level)
{
- dprintf(fd, "enum %s {\n", e->name->val);
+ PSI_DUMP(dump, "enum %s {\n", e->name->val);
if (e->items) {
size_t i = 0;
struct psi_decl_enum_item *item;
while (psi_plist_get(e->items, i++, &item)) {
if (i > 1) {
- dprintf(fd, ",\n");
+ PSI_DUMP(dump, ",\n");
}
- dprintf(fd, "%s", psi_t_indent(level + 1));
- psi_decl_enum_item_dump(fd, item);
+ PSI_DUMP(dump, "%s", psi_t_indent(level + 1));
+ psi_decl_enum_item_dump(dump, item);
}
}
- dprintf(fd, "\n}");
+ PSI_DUMP(dump, "\n}");
}
bool psi_decl_enum_validate(struct psi_data *data, struct psi_decl_enum *e)
struct psi_decl_enum *psi_decl_enum_init(zend_string *name, struct psi_plist *l);
void psi_decl_enum_free(struct psi_decl_enum **e_ptr);
-void psi_decl_enum_dump(int fd, struct psi_decl_enum *e, unsigned level);
+void psi_decl_enum_dump(struct psi_dump *dump, struct psi_decl_enum *e, unsigned level);
bool psi_decl_enum_validate(struct psi_data *data, struct psi_decl_enum *e);
#endif
}
}
-void psi_decl_enum_item_dump(int fd, struct psi_decl_enum_item *item)
+void psi_decl_enum_item_dump(struct psi_dump *dump, struct psi_decl_enum_item *item)
{
- dprintf(fd, "%s", item->name->val);
+ PSI_DUMP(dump, "%s", item->name->val);
if (item->num && item->num != &item->inc) {
- dprintf(fd, " = ");
- psi_num_exp_dump(fd, item->num);
+ PSI_DUMP(dump, " = ");
+ psi_num_exp_dump(dump, item->num);
}
}
struct psi_decl_enum_item *psi_decl_enum_item_init(zend_string *name, struct psi_num_exp *num);
void psi_decl_enum_item_free(struct psi_decl_enum_item **i_ptr);
-void psi_decl_enum_item_dump(int fd, struct psi_decl_enum_item *item);
+void psi_decl_enum_item_dump(struct psi_dump *dump, struct psi_decl_enum_item *item);
bool psi_decl_enum_item_validate(struct psi_data *data, struct psi_decl_enum *enm, struct psi_decl_enum_item *item, size_t seq);
#endif
return true;
}
-void psi_decl_extvar_dump(int fd, struct psi_decl_extvar *evar)
+void psi_decl_extvar_dump(struct psi_dump *dump, struct psi_decl_extvar *evar)
{
- dprintf(fd, "extern ");
- psi_decl_arg_dump(fd, evar->arg, 0);
- dprintf(fd, ";\n");
+ PSI_DUMP(dump, "extern ");
+ psi_decl_arg_dump(dump, evar->arg, 0);
+ PSI_DUMP(dump, ";\n");
}
struct psi_decl *psi_decl_extvar_setter(struct psi_decl_extvar *evar)
void psi_decl_extvar_free(struct psi_decl_extvar **evar);
bool psi_decl_extvar_validate(struct psi_data *data, struct psi_decl_extvar *evar,
struct psi_validate_scope *scope);
-void psi_decl_extvar_dump(int fd, struct psi_decl_extvar *evar);
+void psi_decl_extvar_dump(struct psi_dump *dump, struct psi_decl_extvar *evar);
bool psi_decl_extvar_is_blacklisted(const char *name);
}
}
-void psi_decl_struct_dump(int fd, struct psi_decl_struct *strct)
+void psi_decl_struct_dump(struct psi_dump *dump, struct psi_decl_struct *strct)
{
- dprintf(fd, "struct %s::(%zu, %zu)", strct->name->val, strct->align,
+ PSI_DUMP(dump, "struct %s::(%zu, %zu)", strct->name->val, strct->align,
strct->size);
if (psi_plist_count(strct->args)) {
psi_decl_type_dump_args_with_layout(fd, strct->args, 0);
} else {
- dprintf(fd, ";");
+ PSI_DUMP(dump, ";");
}
}
struct psi_decl_struct *psi_decl_struct_init(zend_string *name, struct psi_plist *args);
void psi_decl_struct_free(struct psi_decl_struct **s_ptr);
-void psi_decl_struct_dump(int fd, struct psi_decl_struct *strct);
+void psi_decl_struct_dump(struct psi_dump *dump, struct psi_decl_struct *strct);
bool psi_decl_struct_validate(struct psi_data *data, struct psi_decl_struct *s, struct psi_validate_scope *scope);
{
size_t i = 0;
- dprintf(fd, " {\n");
+ PSI_DUMP(dump, " {\n");
if (args) {
struct psi_decl_arg *sarg;
++level;
while (psi_plist_get(args, i++, &sarg)) {
- dprintf(fd, "%s", psi_t_indent(level));
- psi_decl_arg_dump(fd, sarg, level);
+ PSI_DUMP(dump, "%s", psi_t_indent(level));
+ psi_decl_arg_dump(dump, sarg, level);
if (sarg->layout) {
if (sarg->layout->bfw) {
- dprintf(fd, ":%zu", sarg->layout->bfw->len);
+ PSI_DUMP(dump, ":%zu", sarg->layout->bfw->len);
}
- dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos,
+ PSI_DUMP(dump, "::(%zu, %zu);\n", sarg->layout->pos,
sarg->layout->len);
} else {
- dprintf(fd, ";\n");
+ PSI_DUMP(dump, ";\n");
}
}
--level;
}
- dprintf(fd, "%s", psi_t_indent(level));
- dprintf(fd, "}");
+ PSI_DUMP(dump, "%s", psi_t_indent(level));
+ PSI_DUMP(dump, "}");
}
-void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level)
+void psi_decl_type_dump(struct psi_dump *dump, struct psi_decl_type *t, unsigned level)
{
switch (t->type) {
case PSI_T_POINTER:
- dprintf(fd, "%s *", t->name->val);
+ PSI_DUMP(dump, "%s *", t->name->val);
return;
case PSI_T_ENUM:
- dprintf(fd, "enum ");
+ PSI_DUMP(dump, "enum ");
if (psi_decl_type_is_anon(t->name, "enum")) {
size_t i = 0, c = psi_plist_count(t->real.enm->items);
struct psi_decl_enum_item *item;
- dprintf(fd, "{\n");
+ PSI_DUMP(dump, "{\n");
++level;
while (psi_plist_get(t->real.enm->items, i++, &item)) {
- dprintf(fd, "%s", psi_t_indent(level));
- psi_decl_enum_item_dump(fd, item);
+ PSI_DUMP(dump, "%s", psi_t_indent(level));
+ psi_decl_enum_item_dump(dump, item);
if (i < c) {
- dprintf(fd, "%s\n", i < c ? "," : "");
+ PSI_DUMP(dump, "%s\n", i < c ? "," : "");
}
}
--level;
- dprintf(fd, "%s\n} ", psi_t_indent(level));
+ PSI_DUMP(dump, "%s\n} ", psi_t_indent(level));
return;
}
break;
case PSI_T_STRUCT:
- dprintf(fd, "struct ");
+ PSI_DUMP(dump, "struct ");
if (psi_decl_type_is_anon(t->name, "struct")) {
psi_decl_type_dump_args_with_layout(fd, t->real.strct->args, level);
return;
break;
case PSI_T_UNION:
- dprintf(fd, "union ");
+ PSI_DUMP(dump, "union ");
if (psi_decl_type_is_anon(t->name, "union")) {
psi_decl_type_dump_args_with_layout(fd, t->real.unn->args, level);
return;
break;
case PSI_T_FUNCTION:
- psi_decl_type_dump(fd, t->real.func->func->type, level);
+ psi_decl_type_dump(dump, t->real.func->func->type, level);
return;
default:
break;
}
- dprintf(fd, "%s", t->name->val);
+ PSI_DUMP(dump, "%s", t->name->val);
}
int psi_decl_type_is_weak(struct psi_decl_type *type)
struct psi_decl_type *psi_decl_type_init(token_t type, zend_string *name);
struct psi_decl_type *psi_decl_type_copy(struct psi_decl_type *src);
void psi_decl_type_free(struct psi_decl_type **type_ptr);
-void psi_decl_type_dump(int fd, struct psi_decl_type *t, unsigned level);
+void psi_decl_type_dump(struct psi_dump *dump, struct psi_decl_type *t, unsigned level);
bool psi_decl_type_validate(struct psi_data *data, struct psi_decl_type *type,
struct psi_decl_arg *def, struct psi_validate_scope *scope);
}
}
-void psi_decl_union_dump(int fd, struct psi_decl_union *unn)
+void psi_decl_union_dump(struct psi_dump *dump, struct psi_decl_union *unn)
{
- dprintf(fd, "union %s::(%zu, %zu)", unn->name->val, unn->align, unn->size);
+ PSI_DUMP(dump, "union %s::(%zu, %zu)", unn->name->val, unn->align, unn->size);
if (psi_plist_count(unn->args)) {
psi_decl_type_dump_args_with_layout(fd, unn->args, 0);
} else {
- dprintf(fd, ";");
+ PSI_DUMP(dump, ";");
}
}
struct psi_decl_union *psi_decl_union_init(zend_string *name, struct psi_plist *args);
void psi_decl_union_free(struct psi_decl_union **u_ptr);
-void psi_decl_union_dump(int fd, struct psi_decl_union *unn);
+void psi_decl_union_dump(struct psi_dump *dump, struct psi_decl_union *unn);
bool psi_decl_union_validate(struct psi_data *data, struct psi_decl_union *u, struct psi_validate_scope *scope);
}
}
-void psi_decl_var_dump(int fd, struct psi_decl_var *var)
+void psi_decl_var_dump(struct psi_dump *dump, struct psi_decl_var *var)
{
- dprintf(fd, "%s%s",
+ PSI_DUMP(dump, "%s%s",
psi_t_indirection(var->pointer_level - !!var->array_size),
var->name ? var->name->val : "/**/");
if (var->array_size && var->arg->type->type != PSI_T_FUNCTION) {
- dprintf(fd, "[%u]", var->array_size);
+ PSI_DUMP(dump, "[%u]", var->array_size);
}
}
struct psi_decl_var *psi_decl_var_init(zend_string *name, unsigned pl, unsigned as);
struct psi_decl_var *psi_decl_var_copy(struct psi_decl_var *src);
void psi_decl_var_free(struct psi_decl_var **var_ptr);
-void psi_decl_var_dump(int fd, struct psi_decl_var *var);
+void psi_decl_var_dump(struct psi_dump *dump, struct psi_decl_var *var);
bool psi_decl_var_validate(struct psi_data *data, struct psi_decl_var *dvar,
struct psi_validate_scope *scope);
}
}
-void psi_free_exp_dump(int fd, struct psi_free_exp *call)
+void psi_free_exp_dump(struct psi_dump *dump, struct psi_free_exp *call)
{
size_t l = 0, c = psi_plist_count(call->vars);
struct psi_decl_var *fvar;
- dprintf(fd, "%s(", call->func->val);
+ PSI_DUMP(dump, "%s(", call->func->val);
while (psi_plist_get(call->vars, l++, &fvar)) {
- psi_decl_var_dump(fd, fvar);
+ psi_decl_var_dump(dump, fvar);
if (l < c) {
- dprintf(fd, ", ");
+ PSI_DUMP(dump, ", ");
}
}
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
}
static inline struct psi_decl *locate_free_decl(struct psi_plist *decls,
struct psi_free_exp *psi_free_exp_init(zend_string *func, struct psi_plist *vars);
void psi_free_exp_free(struct psi_free_exp **f_ptr);
-void psi_free_exp_dump(int fd, struct psi_free_exp *call);
+void psi_free_exp_dump(struct psi_dump *dump, struct psi_free_exp *call);
bool psi_free_exp_validate(struct psi_data *data, struct psi_free_exp *fc, struct psi_validate_scope *scope);
}
}
-void psi_free_stmt_dump(int fd, struct psi_free_stmt *fre)
+void psi_free_stmt_dump(struct psi_dump *dump, struct psi_free_stmt *fre)
{
size_t i;
struct psi_free_exp *exp;
- dprintf(fd, "\tfree ");
+ PSI_DUMP(dump, "\tfree ");
for (i = 0; psi_plist_get(fre->exps, i, &exp); ++i) {
if (i) {
- dprintf(fd, ", ");
+ PSI_DUMP(dump, ", ");
}
- psi_free_exp_dump(fd, exp);
+ psi_free_exp_dump(dump, exp);
}
- dprintf(fd, ";\n");
+ PSI_DUMP(dump, ";\n");
}
bool psi_free_stmts_validate(struct psi_data *data, struct psi_validate_scope *scope)
struct psi_free_stmt *psi_free_stmt_init(struct psi_plist *calls);
void psi_free_stmt_free(struct psi_free_stmt **f_ptr);
-void psi_free_stmt_dump(int fd, struct psi_free_stmt *fre);
+void psi_free_stmt_dump(struct psi_dump *dump, struct psi_free_stmt *fre);
bool psi_free_stmts_validate(struct psi_data *data, struct psi_validate_scope *scope);
void psi_free_stmt_exec(struct psi_free_stmt *fre, struct psi_call_frame *frame);
}
}
-void psi_impl_dump(int fd, struct psi_impl *impl)
+void psi_impl_dump(struct psi_dump *dump, struct psi_impl *impl)
{
size_t i;
struct psi_return_stmt *ret;
struct psi_free_stmt *fre;
struct psi_assert_stmt *ass;
- psi_impl_func_dump(fd, impl->func);
- dprintf(fd, " {\n");
+ psi_impl_func_dump(dump, impl->func);
+ PSI_DUMP(dump, " {\n");
for (i = 0; psi_plist_get(impl->stmts.let, i, &let); ++i) {
- psi_let_stmt_dump(fd, let);
+ psi_let_stmt_dump(dump, let);
}
for (i = 0; psi_plist_get(impl->stmts.ass, i, &ass); ++i) {
- psi_assert_stmt_dump(fd, ass);
+ psi_assert_stmt_dump(dump, ass);
}
for (i = 0; psi_plist_get(impl->stmts.ret, i, &ret); ++i) {
- psi_return_stmt_dump(fd, ret);
+ psi_return_stmt_dump(dump, ret);
}
for (i = 0; psi_plist_get(impl->stmts.set, i, &set); ++i) {
- psi_set_stmt_dump(fd, set);
+ psi_set_stmt_dump(dump, set);
}
for (i = 0; psi_plist_get(impl->stmts.fre, i, &fre); ++i) {
- psi_free_stmt_dump(fd, fre);
+ psi_free_stmt_dump(dump, fre);
}
- dprintf(fd, "}\n");
+ PSI_DUMP(dump, "}\n");
}
bool psi_impl_validate(struct psi_data *data, struct psi_impl *impl,
struct psi_impl *psi_impl_init(struct psi_impl_func *func, struct psi_plist *stmts);
void psi_impl_free(struct psi_impl **impl_ptr);
-void psi_impl_dump(int fd, struct psi_impl *impl);
+void psi_impl_dump(struct psi_dump *dump, struct psi_impl *impl);
bool psi_impl_validate(struct psi_data *data, struct psi_impl *impl,
struct psi_validate_scope *scope);
}
}
-void psi_impl_arg_dump(int fd, struct psi_impl_arg *iarg, bool vararg)
+void psi_impl_arg_dump(struct psi_dump *dump, struct psi_impl_arg *iarg, bool vararg)
{
- psi_impl_type_dump(fd, iarg->type);
- dprintf(fd, " ");
- psi_impl_var_dump(fd, iarg->var, vararg);
+ psi_impl_type_dump(dump, iarg->type);
+ PSI_DUMP(dump, " ");
+ psi_impl_var_dump(dump, iarg->var, vararg);
if (iarg->def) {
- dprintf(fd, " = ");
- psi_impl_def_val_dump(fd, iarg->def);
+ PSI_DUMP(dump, " = ");
+ psi_impl_def_val_dump(dump, iarg->def);
}
}
struct psi_impl_arg *psi_impl_arg_init(struct psi_impl_type *type, struct psi_impl_var *var, struct psi_impl_def_val *def);
void psi_impl_arg_free(struct psi_impl_arg **arg_ptr);
-void psi_impl_arg_dump(int fd, struct psi_impl_arg *iarg, bool vararg);
+void psi_impl_arg_dump(struct psi_dump *dump, struct psi_impl_arg *iarg, bool vararg);
#endif
#include "php_psi_stdinc.h"
#include "data.h"
+#include "zend_smart_str.h"
+
#include <assert.h>
#include <math.h>
switch ((def->type = t)) {
case PSI_T_TRUE:
+ def->ival.zend.bval = 1;
+ /* no break */
case PSI_T_FALSE:
+ def->ityp = PSI_T_UINT8;
+ /* no break */
case PSI_T_NULL:
break;
case PSI_T_QUOTED_STRING:
}
}
+void psi_impl_def_val_get_zval(struct psi_impl_def_val *val, token_t typ, zval *zv)
+{
+ impl_val tmp = val->ival;
+
+ /* c->val has already been forced to the type of the containing constant or impl_arg */
+ switch (typ) {
+ case PSI_T_BOOL:
+ ZVAL_BOOL(zv, tmp.zend.bval);
+ break;
+ case PSI_T_INT:
+ ZVAL_LONG(zv, tmp.zend.lval);
+ break;
+ case PSI_T_FLOAT:
+ case PSI_T_DOUBLE:
+ is_double: ;
+ ZVAL_DOUBLE(zv, tmp.dval);
+ break;
+ case PSI_T_STRING:
+ is_string: ;
+ ZVAL_NEW_STR(zv, zend_string_copy(tmp.zend.str));
+ if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
+ Z_TYPE_FLAGS_P(zv) = 0;
+ }
+ break;
+ case PSI_T_MIXED:
+ switch (val->type) {
+ case PSI_T_NULL:
+ ZVAL_NULL(zv);
+ break;
+ case PSI_T_TRUE:
+ ZVAL_TRUE(zv);
+ break;
+ case PSI_T_FALSE:
+ ZVAL_FALSE(zv);
+ break;
+ case PSI_T_STRING:
+ goto is_string;
+ break;
+ case PSI_T_NUMBER:
+ switch (val->ityp) {
+ case PSI_T_INT8:
+ case PSI_T_UINT8:
+ case PSI_T_INT16:
+ case PSI_T_UINT16:
+ case PSI_T_INT32:
+ case PSI_T_UINT32:
+ psi_calc_cast(val->ityp, &tmp, PSI_T_INT64, &tmp);
+ /* no break */
+ case PSI_T_INT64:
+ ZVAL_LONG(zv, tmp.i64);
+ break;
+ case PSI_T_UINT64:
+ ZVAL_LONG_DOUBLE_STR(zv, tmp.u64, is_signed=false;persistent=true);
+ break;
+#if HAVE_INT128
+ case PSI_T_INT128:
+ ZVAL_LONG_DOUBLE_STR(zv, tmp.i128, is_signed=true;persistent=true);
+ break;
+ case PSI_T_UINT128:
+ ZVAL_LONG_DOUBLE_STR(zv, tmp.u128, is_signed=false;persistent=true);
+#endif
+ break;
+ case PSI_T_FLOAT:
+ ZVAL_DOUBLE(zv, tmp.fval);
+ break;
+ case PSI_T_DOUBLE:
+ goto is_double;
+ break;
+#if HAVE_LONG_DOUBLE
+ case PSI_T_LONG_DOUBLE:
+ ZVAL_DOUBLE(zv, tmp.ldval);
+ break;
+#endif
+ default:
+ assert(0);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+}
+/*
+token_t psi_impl_def_val_get_zend(struct psi_impl_def_val *val, impl_val *res)
+{
+ switch (val->type) {
+ case PSI_T_NULL:
+ return PSI_T_NULL;
+ case PSI_T_TRUE:
+ case PSI_T_FALSE:
+ res->zend.bval = val->ival.zend.bval;
+ return PSI_T_BOOL;
+ case PSI_T_STRING:
+ res->zend.str = val->ival.zend.str
+ ? zend_string_copy(val->ival.zend.str)
+ : zend_empty_string;
+ return PSI_T_STRING;
+ case PSI_T_NUMBER:
+ switch (val->ityp) {
+ case PSI_T_FLOAT:
+ res->dval = val->ival.fval;
+ return PSI_T_DOUBLE;
+ case PSI_T_DOUBLE:
+ res->dval = val->ival.dval;
+ return PSI_T_DOUBLE;
+#if HAVE_LONG_DOUBLE
+ case PSI_T_LONG_DOUBLE:
+ res->dval = val->ival.ldval;
+ return PSI_T_DOUBLE;
+#endif
+ default:
+ psi_calc_cast(val->ityp, &val->ival, PSI_T_INT64, res);
+ return PSI_T_INT;
+ }
+ break;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+*/
+
+static inline bool psi_impl_def_val_validate_impl_type(struct psi_data *data,
+ struct psi_impl_def_val *val, struct psi_impl_type *type,
+ struct psi_validate_scope *scope)
+{
+ switch (type->type) {
+ case PSI_T_BOOL:
+ switch (val->type) {
+ case PSI_T_TRUE:
+ case PSI_T_FALSE:
+ return true;
+ case PSI_T_STRING:
+ if (val->ival.zend.str
+ && *val->ival.zend.str->val
+ && *val->ival.zend.str->val != '0') {
+ zend_string_release(val->ival.zend.str);
+ val->ival.zend.bval = 1;
+ } else {
+ if (val->ival.zend.str) {
+ zend_string_release(val->ival.zend.str);
+ }
+ val->ival.zend.bval = 0;
+ }
+ val->ityp = PSI_T_UINT8;
+ return true;
+ default:
+ assert(0);
+ break;
+ }
+ break;
+ case PSI_T_INT:
+ if (val->type == PSI_T_STRING) {
+ zend_string *str = val->ival.zend.str;
+ switch (is_numeric_str_function(str, &val->ival.zend.lval, &val->ival.dval)) {
+ case IS_DOUBLE:
+ val->ival.zend.lval = zend_dval_to_lval_cap(val->ival.dval);
+ /* no break */
+ case IS_LONG:
+ break;
+ default:
+ val->ival.zend.lval = 0;
+ }
+ zend_string_release(str);
+ val->ityp = PSI_T_INT64;
+ return true;
+ }
+ psi_calc_cast(val->ityp, &val->ival, PSI_T_INT64, &val->ival);
+ val->type = val->ityp = PSI_T_INT64;
+ return true;
+ case PSI_T_FLOAT:
+ case PSI_T_DOUBLE:
+ if (val->type == PSI_T_STRING) {
+ zend_string *str = val->ival.zend.str;
+ switch (is_numeric_str_function(str, &val->ival.zend.lval, &val->ival.dval)) {
+ case IS_LONG:
+ val->ival.dval = val->ival.zend.lval;
+ /* no break */
+ case IS_DOUBLE:
+ break;
+ default:
+ val->ival.dval = 0;
+ }
+ zend_string_release(str);
+ val->type = val->ityp = PSI_T_DOUBLE;
+ return true;
+ }
+ psi_calc_cast(val->ityp, &val->ival, PSI_T_DOUBLE, &val->ival);
+ val->ityp = PSI_T_DOUBLE;
+ return true;
+ case PSI_T_STRING:
+ if (val->type == PSI_T_STRING) {
+ return true;
+ } else {
+ smart_str str = {0};
+
+ switch (val->ityp) {
+ CASE_IMPLVAL_NUM_PRINTF(smart_str_append_printf, &str, val->ival, false);
+ default:
+ assert(0);
+ }
+ val->ival.zend.str = smart_str_extract(&str);
+ val->type = PSI_T_STRING;
+ return true;
+ }
+ break;
+ default:
+ data->error(data, val->token, PSI_WARNING,
+ "Invalid default value type '%s', "
+ "expected one of bool, int, float/double or string.",
+ type->name->val);
+
+ }
+ return false;
+}
+
bool psi_impl_def_val_validate(struct psi_data *data,
struct psi_impl_def_val *val, struct psi_impl_type *type,
struct psi_validate_scope *scope)
{
+ /* NULL can be anything */
if (val->type == PSI_T_NULL) {
return true;
- } else if (val->type == PSI_T_NUMBER) {
+ }
+
+ /* a number can be anything */
+ if (val->type == PSI_T_NUMBER) {
if (!psi_num_exp_validate(data, val->data.num, scope)) {
return false;
}
+ val->ityp = psi_num_exp_exec(val->data.num, &val->ival, NULL, scope->cpp);
+ }
+
+ /* forced type, like `const <type> foo`, or function param `<type> $xyz` */
+ if (type) {
+ return psi_impl_def_val_validate_impl_type(data, val, type, scope);
+ }
+
+ switch (val->type) {
+ case PSI_T_NUMBER:
+ case PSI_T_NULL:
+ case PSI_T_TRUE:
+ case PSI_T_FALSE:
+ case PSI_T_STRING:
+ return true;
+ default:
+ assert(0);
+ break;
}
+ return false;
+/*
switch (type ? type->type : PSI_T_MIXED) {
case PSI_T_BOOL:
val->ival.zend.bval = val->type == PSI_T_TRUE ? 1 : 0;
return true;
break;
- /* macros */
+ // macros
case PSI_T_NUMBER:
if (val->type == PSI_T_NUMBER) {
token_t typ = psi_num_exp_exec(val->data.num, &val->ival, NULL, scope->cpp);
switch (typ) {
case PSI_T_FLOAT:
val->ival.dval = val->ival.fval;
- /* no break */
+ // no break
case PSI_T_DOUBLE:
val->type = PSI_T_FLOAT;
type->type = PSI_T_FLOAT;
val->ival.u64);
}
default:
- /* FIXME big integers */
+ // FIXME big integers
val->type = PSI_T_INT;
type->type = PSI_T_INT;
zend_string_release(type->name);
case PSI_T_STRING:
if (val->type == PSI_T_STRING) {
- return true;
+ return true; data->error(data, val->token, PSI_WARNING,
+ "Invalid default value type '%s', "
+ "expected one of bool, int, float, string.",
+ type ? type->name->val : "mixed");
+
}
break;
case PSI_T_MIXED:
- switch (val->type) {
- case PSI_T_TRUE:
- case PSI_T_FALSE:
- case PSI_T_NULL:
- case PSI_T_STRING:
- case PSI_T_FLOAT:
- case PSI_T_DOUBLE:
- case PSI_T_INT:
- return true;
- default:
- break;
- }
- if (val->type == PSI_T_NUMBER) {
- token_t typ = psi_num_exp_exec(val->data.num, &val->ival, NULL, scope->cpp);
- switch (typ) {
- case PSI_T_FLOAT:
-#if HAVE_LONG_DOUBLE
- case PSI_T_LONG_DOUBLE:
-#endif
- promote_double: ;
- psi_calc_cast(typ, &val->ival, PSI_T_DOUBLE, &val->ival);
- /* no break */
- case PSI_T_DOUBLE:
- val->type = PSI_T_DOUBLE;
- return true;
- case PSI_T_UINT64:
- if (val->ival.u64 > (uint64_t) ZEND_LONG_MAX) {
- if (val->ival.u64 > (1LU<<53)) {
- char buf[0x20];
-
- /* convert to string */
- char *res = zend_print_ulong_to_buf(buf + sizeof(buf) - 1, val->ival.u64);
- val->type = PSI_T_STRING;
- val->ival.zend.str = zend_string_init(res, buf + sizeof(buf) - 1 - res, 1);
-
- return true;
- }
- goto promote_double;
- }
- /* no break */
- default:
- psi_calc_cast(typ, &val->ival, PSI_T_INT64, &val->ival);
- /* no break */
- case PSI_T_INT64:
- val->type = PSI_T_INT;
- return true;
- }
}
- /* no break */
+ // no break
default:
- data->error(data, val->token, PSI_WARNING,
- "Invalid default value type '%s', "
- "expected one of bool, int, float, string.",
- type ? type->name->val : "mixed");
}
-
- return false;
+*/
}
-void psi_impl_def_val_dump(int fd, struct psi_impl_def_val *val) {
+void psi_impl_def_val_dump(struct psi_dump *dump, struct psi_impl_def_val *val) {
switch (val->type) {
case PSI_T_NULL:
- dprintf(fd, "NULL");
+ PSI_DUMP(dump, "NULL");
break;
case PSI_T_TRUE:
- dprintf(fd, "true");
+ PSI_DUMP(dump, "true");
break;
case PSI_T_FALSE:
- dprintf(fd, "false");
+ PSI_DUMP(dump, "false");
break;
case PSI_T_BOOL:
- dprintf(fd, "%s", val->ival.zend.bval ? "true" : "false");
+ PSI_DUMP(dump, "%s", val->ival.zend.bval ? "true" : "false");
break;
case PSI_T_INT:
- dprintf(fd, ZEND_LONG_FMT, val->ival.zend.lval);
+ PSI_DUMP(dump, ZEND_LONG_FMT, val->ival.zend.lval);
break;
case PSI_T_FLOAT:
case PSI_T_DOUBLE:
if (isinf(val->ival.dval)) {
- dprintf(fd, "\\INF");
+ PSI_DUMP(dump, "\\INF");
} else if (isnan(val->ival.dval)) {
- dprintf(fd, "\\NAN");
+ PSI_DUMP(dump, "\\NAN");
} else {
- dprintf(fd, "%" PRIdval, val->ival.dval);
+ PSI_DUMP(dump, "%" PRIdval, val->ival.dval);
}
break;
case PSI_T_STRING:
- dprintf(fd, "\"%s\"", val->ival.zend.str->val);
+ PSI_DUMP(dump, "\"%s\"", val->ival.zend.str->val);
break;
case PSI_T_NUMBER:
- psi_num_exp_dump(fd, val->data.num);
+ psi_num_exp_dump(dump, val->data.num);
break;
default:
assert(0);
}
+ PSI_DUMP(dump, "\t/* t=%d */ ", val->type);
}
struct psi_data;
struct psi_impl_type;
+struct psi_dump;
struct psi_impl_def_val {
struct psi_token *token;
union {
struct psi_num_exp *num;
} data;
+ token_t ityp;
impl_val ival;
};
struct psi_impl_def_val *psi_impl_def_val_init(token_t t, void *data);
void psi_impl_def_val_free(struct psi_impl_def_val **def_ptr);
-void psi_impl_def_val_dump(int fd, struct psi_impl_def_val *val);
+void psi_impl_def_val_dump(struct psi_dump *dump, struct psi_impl_def_val *val);
bool psi_impl_def_val_validate(struct psi_data *data, struct psi_impl_def_val *def,
struct psi_impl_type *cmp, struct psi_validate_scope *scope);
-
+token_t psi_impl_def_val_get_zend(struct psi_impl_def_val *val, impl_val *res);
#endif
return true;
}
-void psi_impl_func_dump(int fd, struct psi_impl_func *func)
+void psi_impl_func_dump(struct psi_dump *dump, struct psi_impl_func *func)
{
- dprintf(fd, "function %s(", func->name->val);
+ PSI_DUMP(dump, "function %s(", func->name->val);
if (func->args) {
size_t i = 0;
struct psi_impl_arg *iarg;
while (psi_plist_get(func->args, i++, &iarg)) {
if (i > 1) {
- dprintf(fd, ", ");
+ PSI_DUMP(dump, ", ");
}
- psi_impl_arg_dump(fd, iarg, false);
+ psi_impl_arg_dump(dump, iarg, false);
}
if (func->vararg) {
- dprintf(fd, ", ");
- psi_impl_arg_dump(fd, func->vararg, true);
+ PSI_DUMP(dump, ", ");
+ psi_impl_arg_dump(dump, func->vararg, true);
}
}
- dprintf(fd, ") : %s%s", func->return_reference ? "&" : "",
+ PSI_DUMP(dump, ") : %s%s", func->return_reference ? "&" : "",
func->return_type->name->val);
}
struct psi_impl_func *psi_impl_func_init(zend_string *name,
struct psi_plist *args, struct psi_impl_type *return_type);
void psi_impl_func_free(struct psi_impl_func **f_ptr);
-void psi_impl_func_dump(int fd, struct psi_impl_func *func);
+void psi_impl_func_dump(struct psi_dump *dump, struct psi_impl_func *func);
bool psi_impl_func_validate(struct psi_data *data, struct psi_impl_func *func,
struct psi_validate_scope *scope);
return t;
}
-void psi_impl_type_dump(int fd, struct psi_impl_type *type)
+void psi_impl_type_dump(struct psi_dump *dump, struct psi_impl_type *type)
{
- dprintf(fd, "%s", type->name->val);
+ PSI_DUMP(dump, "%s", type->name->val);
}
void psi_impl_type_free(struct psi_impl_type **type_ptr)
struct psi_impl_type *psi_impl_type_init(token_t type, zend_string *name);
void psi_impl_type_free(struct psi_impl_type **type_ptr);
-void psi_impl_type_dump(int fd, struct psi_impl_type *type);
+void psi_impl_type_dump(struct psi_dump *dump, struct psi_impl_type *type);
#endif
# define isnanl isnan
#endif
#if HAVE_LONG_DOUBLE
-# define CASE_IMPLVAL_LD_PRINTF(fun, to, ival) \
+# define CASE_IMPLVAL_LD_PRINTF(fun, to, ival, with_suffix) \
case PSI_T_LONG_DOUBLE: \
if (isinfl(ival.ldval)) { \
fun(to, "\\INF"); \
} else if (isnanl(ival.ldval)) { \
fun(to, "\\NAN"); \
} else { \
- fun(to, "%" PRIldval "L", ival.ldval); \
+ fun(to, "%" PRIldval "%s", ival.ldval, (with_suffix) ? "L" : ""); \
} \
break;
#else
# define CASE_IMPLVAL_LD_PRINTF(fun, to, ival)
#endif
-#define CASE_IMPLVAL_NUM_PRINTF(fun, to, ival) \
+#define CASE_IMPLVAL_FLOAT_PRINTF(fun, to, ival, with_suffix) \
+ CASE_IMPLVAL_LD_PRINTF(fun, to, ival, with_suffix); \
+ case PSI_T_FLOAT: \
+ if (isinf(ival.dval)) { \
+ fun(to, "\\INF"); \
+ } else if (isnan(ival.dval)) { \
+ fun(to, "\\NAN"); \
+ } else { \
+ fun(to, "%" PRIfval "%s", ival.dval, (with_suffix) ? "F" : ""); \
+ } \
+ break; \
+ case PSI_T_DOUBLE: \
+ if (isinf(ival.dval)) { \
+ fun(to, "\\INF"); \
+ } else if (isnan(ival.dval)) { \
+ fun(to, "\\NAN"); \
+ } else { \
+ fun(to, "%" PRIdval, ival.dval); \
+ } \
+ break
+
+#define CASE_IMPLVAL_INT_PRINTF(fun, to, ival, with_suffix) \
case PSI_T_INT8: \
fun(to, "%" PRId8, ival.i8); \
break; \
fun(to, "%" PRId32, ival.i32); \
break; \
case PSI_T_UINT32: \
- fun(to, "%" PRIu32 "U", ival.u32); \
+ fun(to, "%" PRIu32 "%s", ival.u32, (with_suffix) ? "U" : ""); \
break; \
case PSI_T_INT64: \
- fun(to, "%" PRId64 "L", ival.i64); \
+ fun(to, "%" PRId64 "%s", ival.i64, (with_suffix) ? "L" : ""); \
break; \
case PSI_T_UINT64: \
- fun(to, "%" PRIu64 "UL", ival.u64); \
- break; \
- case PSI_T_FLOAT: \
- if (isinf(ival.dval)) { \
- fun(to, "\\INF"); \
- } else if (isnan(ival.dval)) { \
- fun(to, "\\NAN"); \
- } else { \
- fun(to, "%" PRIfval "F", ival.dval); \
- } \
- break; \
- case PSI_T_DOUBLE: \
- if (isinf(ival.dval)) { \
- fun(to, "\\INF"); \
- } else if (isnan(ival.dval)) { \
- fun(to, "\\NAN"); \
- } else { \
- fun(to, "%" PRIdval, ival.dval); \
- } \
- break; \
- CASE_IMPLVAL_LD_PRINTF(fun, to, ival)
+ fun(to, "%" PRIu64 "%s", ival.u64, (with_suffix) ? "UL" : ""); \
+ break
+
+#define CASE_IMPLVAL_NUM_PRINTF(fun, to, ival, with_suffix) \
+ CASE_IMPLVAL_INT_PRINTF(fun, to, ival, with_suffix); \
+ CASE_IMPLVAL_FLOAT_PRINTF(fun, to, ival, with_suffix)
#endif
}
}
-void psi_impl_var_dump(int fd, struct psi_impl_var *var, bool vararg)
+void psi_impl_var_dump(struct psi_dump *dump, struct psi_impl_var *var, bool vararg)
{
- dprintf(fd, "%s%s%s",
+ PSI_DUMP(dump, "%s%s%s",
var->reference ? "&" : "",
vararg ? "..." : "",
var->name->val);
struct psi_impl_var *psi_impl_var_init(zend_string *name, bool is_reference);
struct psi_impl_var *psi_impl_var_copy(struct psi_impl_var *var);
void psi_impl_var_free(struct psi_impl_var **var_ptr);
-void psi_impl_var_dump(int fd, struct psi_impl_var *var, bool vararg);
+void psi_impl_var_dump(struct psi_dump *dump, struct psi_impl_var *var, bool vararg);
bool psi_impl_var_validate(struct psi_data *data, struct psi_impl_var *ivar,
struct psi_validate_scope *scope);
return true;
}
-void psi_let_callback_dump(int fd, struct psi_let_callback *callback,
+void psi_let_callback_dump(struct psi_dump *dump, struct psi_let_callback *callback,
unsigned level)
{
- dprintf(fd, "callback(");
+ PSI_DUMP(dump, "callback(");
if (callback->cb_args) {
size_t i = 0;
struct psi_decl_var *cb_arg;
while (psi_plist_get(callback->cb_args, i++, &cb_arg)) {
if (i > 1) {
- dprintf(fd, ", ");
+ PSI_DUMP(dump, ", ");
}
- psi_decl_var_dump(fd, cb_arg);
+ psi_decl_var_dump(dump, cb_arg);
}
}
- dprintf(fd, ") as %s(%s(",
+ PSI_DUMP(dump, ") as %s(%s(",
callback->func->name->val,
callback->func->var->name->val);
size_t i = 0, last = psi_plist_count(callback->args);
struct psi_set_exp *set;
- dprintf(fd, "\n");
+ PSI_DUMP(dump, "\n");
++level;
while (psi_plist_get(callback->args, i++, &set)) {
- psi_set_exp_dump(fd, set, level, i == last);
- dprintf(fd, "\n");
+ psi_set_exp_dump(dump, set, level, i == last);
+ PSI_DUMP(dump, "\n");
}
--level;
- dprintf(fd, "%s", psi_t_indent(level));
+ PSI_DUMP(dump, "%s", psi_t_indent(level));
}
- dprintf(fd, "))");
+ PSI_DUMP(dump, "))");
}
struct psi_let_callback *psi_let_callback_init(struct psi_let_func *func, struct psi_plist *args, struct psi_plist *cb_args);
void psi_let_callback_free(struct psi_let_callback **cb_ptr);
-void psi_let_callback_dump(int fd, struct psi_let_callback *cb, unsigned level);
+void psi_let_callback_dump(struct psi_dump *dump, struct psi_let_callback *cb, unsigned level);
bool psi_let_callback_validate(struct psi_data *data, struct psi_let_callback *cb, struct psi_validate_scope *scope);
#endif
}
}
-void psi_let_calloc_dump(int fd, struct psi_let_calloc *alloc)
+void psi_let_calloc_dump(struct psi_dump *dump, struct psi_let_calloc *alloc)
{
- dprintf(fd, "calloc(");
- psi_num_exp_dump(fd, alloc->nmemb);
- dprintf(fd, ", ");
- psi_num_exp_dump(fd, alloc->size);
- dprintf(fd, ")");
+ PSI_DUMP(dump, "calloc(");
+ psi_num_exp_dump(dump, alloc->nmemb);
+ PSI_DUMP(dump, ", ");
+ psi_num_exp_dump(dump, alloc->size);
+ PSI_DUMP(dump, ")");
}
struct psi_let_calloc *psi_let_calloc_init(struct psi_num_exp *nmemb, struct psi_num_exp *size);
void psi_let_calloc_free(struct psi_let_calloc **alloc_ptr);
-void psi_let_calloc_dump(int fd, struct psi_let_calloc *alloc);
+void psi_let_calloc_dump(struct psi_dump *dump, struct psi_let_calloc *alloc);
#endif
}
}
-void psi_let_exp_dump(int fd, struct psi_let_exp *val, unsigned level, int last)
+void psi_let_exp_dump(struct psi_dump *dump, struct psi_let_exp *val, unsigned level, int last)
{
if (level > 1) {
/* only if not directly after `set ...` */
- dprintf(fd, "%s", psi_t_indent(level));
+ PSI_DUMP(dump, "%s", psi_t_indent(level));
}
if (val->var) {
if (val->var->token) {
- psi_decl_var_dump(fd, val->var);
- dprintf(fd, " = ");
+ psi_decl_var_dump(dump, val->var);
+ PSI_DUMP(dump, " = ");
}
}
if (val->is_reference) {
- dprintf(fd, "&");
+ PSI_DUMP(dump, "&");
}
switch (val->kind) {
case PSI_LET_NULL:
- dprintf(fd, "NULL");
+ PSI_DUMP(dump, "NULL");
break;
case PSI_LET_TMP:
- psi_decl_var_dump(fd, val->data.var);
- dprintf(fd, "\t/* fqn=%s */", val->data.var->fqn->val);
+ psi_decl_var_dump(dump, val->data.var);
+ PSI_DUMP(dump, "\t/* fqn=%s */", val->data.var->fqn->val);
break;
case PSI_LET_CALLOC:
- psi_let_calloc_dump(fd, val->data.alloc);
+ psi_let_calloc_dump(dump, val->data.alloc);
break;
case PSI_LET_CALLBACK:
- psi_let_callback_dump(fd, val->data.callback, level);
+ psi_let_callback_dump(dump, val->data.callback, level);
break;
case PSI_LET_FUNC:
- psi_let_func_dump(fd, val->data.func, level);
+ psi_let_func_dump(dump, val->data.func, level);
break;
case PSI_LET_NUMEXP:
- psi_num_exp_dump(fd, val->data.num);
+ psi_num_exp_dump(dump, val->data.num);
break;
default:
}
if (val->var) {
- dprintf(fd, "\t/* fqn=%s */", val->var->fqn->val);
+ PSI_DUMP(dump, "\t/* fqn=%s */", val->var->fqn->val);
}
if (level > 1) {
if (!last) {
- dprintf(fd, ",");
+ PSI_DUMP(dump, ",");
}
} else {
- dprintf(fd, ";");
+ PSI_DUMP(dump, ";");
}
}
struct psi_let_exp *psi_let_exp_init(enum psi_let_exp_kind kind, void *data);
struct psi_let_exp *psi_let_exp_init_ex(struct psi_decl_var *var, enum psi_let_exp_kind kind, void *data);
void psi_let_exp_free(struct psi_let_exp **let_ptr);
-void psi_let_exp_dump(int fd, struct psi_let_exp *exp, unsigned level, int last);
+void psi_let_exp_dump(struct psi_dump *dump, struct psi_let_exp *exp, unsigned level, int last);
void *psi_let_exp_exec(struct psi_let_exp *exp, struct psi_decl_arg *darg, void *actual_location, size_t actual_size, struct psi_call_frame *frame);
bool psi_let_exp_validate(struct psi_data *data, struct psi_let_exp *exp, struct psi_validate_scope *scope);
}
}
-void psi_let_func_dump(int fd, struct psi_let_func *func, unsigned level)
+void psi_let_func_dump(struct psi_dump *dump, struct psi_let_func *func, unsigned level)
{
- dprintf(fd, "%s(%s\t/* fqn=%s */", func->name->val, func->var->name->val,
+ PSI_DUMP(dump, "%s(%s\t/* fqn=%s */", func->name->val, func->var->name->val,
func->var->fqn->val);
if (func->inner) {
size_t i = 0, count = psi_plist_count(func->inner);
struct psi_let_exp *inner;
- dprintf(fd, ",");
+ PSI_DUMP(dump, ",");
++level;
while (psi_plist_get(func->inner, i++, &inner)) {
- dprintf(fd, "\n");
- psi_let_exp_dump(fd, inner, level, i == count);
+ PSI_DUMP(dump, "\n");
+ psi_let_exp_dump(dump, inner, level, i == count);
}
--level;
- dprintf(fd, "\n");
- dprintf(fd, "%s", psi_t_indent(level));
+ PSI_DUMP(dump, "\n");
+ PSI_DUMP(dump, "%s", psi_t_indent(level));
}
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
}
static inline int validate_let_func_type(struct psi_data *data,
struct psi_let_func *psi_let_func_init(token_t type, zend_string *name, struct psi_impl_var *var);
void psi_let_func_free(struct psi_let_func **func_ptr);
-void psi_let_func_dump(int fd, struct psi_let_func *func, unsigned level);
+void psi_let_func_dump(struct psi_dump *dump, struct psi_let_func *func, unsigned level);
void *psi_let_func_exec(struct psi_let_exp *func_val, struct psi_let_func *func, struct psi_decl_arg *darg, struct psi_call_frame *frame);
bool psi_let_func_validate(struct psi_data *data, struct psi_let_func *func, struct psi_validate_scope *scope);
}
}
-void psi_let_stmt_dump(int fd, struct psi_let_stmt *let)
+void psi_let_stmt_dump(struct psi_dump *dump, struct psi_let_stmt *let)
{
- dprintf(fd, "\t%s ", let->exp->kind == PSI_LET_TMP ? "temp" : "let");
- psi_let_exp_dump(fd, let->exp, 1, 1);
- dprintf(fd, "\n");
+ PSI_DUMP(dump, "\t%s ", let->exp->kind == PSI_LET_TMP ? "temp" : "let");
+ psi_let_exp_dump(dump, let->exp, 1, 1);
+ PSI_DUMP(dump, "\n");
}
bool psi_let_stmts_validate(struct psi_data *data, struct psi_validate_scope *scope)
struct psi_let_stmt *psi_let_stmt_init(struct psi_let_exp *exp);
void psi_let_stmt_free(struct psi_let_stmt **stmt_ptr);
-void psi_let_stmt_dump(int fd, struct psi_let_stmt *stmt);
+void psi_let_stmt_dump(struct psi_dump *dump, struct psi_let_stmt *stmt);
void *psi_let_stmt_exec(struct psi_let_stmt *stmt, struct psi_call_frame *frame);
bool psi_let_stmts_validate(struct psi_data *data, struct psi_validate_scope *scope);
return list;
}
-void psi_num_exp_dump(int fd, struct psi_num_exp *exp)
+void psi_num_exp_dump(struct psi_dump *dump, struct psi_num_exp *exp)
{
switch (exp->op) {
case PSI_T_NUMBER:
- psi_number_dump(fd, exp->data.n);
+ psi_number_dump(dump, exp->data.n);
break;
case PSI_T_CAST:
- dprintf(fd, "(");
+ PSI_DUMP(dump, "(");
psi_decl_type_dump(1, exp->data.c.typ, 0);
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
break;
case PSI_T_NOT:
case PSI_T_TILDE:
unary:
- dprintf(fd, "%s", psi_num_exp_op_tok(exp->op));
- psi_num_exp_dump(fd, exp->data.u);
+ PSI_DUMP(dump, "%s", psi_num_exp_op_tok(exp->op));
+ psi_num_exp_dump(dump, exp->data.u);
break;
case PSI_T_LPAREN:
- dprintf(fd, "(");
- psi_num_exp_dump(fd, exp->data.u);
- dprintf(fd, ")");
+ PSI_DUMP(dump, "(");
+ psi_num_exp_dump(dump, exp->data.u);
+ PSI_DUMP(dump, ")");
break;
case PSI_T_PLUS:
case PSI_T_CMP_GE:
case PSI_T_RCHEVR:
case PSI_T_LCHEVR:
- psi_num_exp_dump(fd, exp->data.b.lhs);
- dprintf(fd, " %s ", psi_num_exp_op_tok(exp->op));
- psi_num_exp_dump(fd, exp->data.b.rhs);
+ psi_num_exp_dump(dump, exp->data.b.lhs);
+ PSI_DUMP(dump, " %s ", psi_num_exp_op_tok(exp->op));
+ psi_num_exp_dump(dump, exp->data.b.rhs);
break;
case PSI_T_IIF:
- psi_num_exp_dump(fd, exp->data.t.cond);
- dprintf(fd, " ? ");
- psi_num_exp_dump(fd, exp->data.t.truthy);
- dprintf(fd, " : ");
- psi_num_exp_dump(fd, exp->data.t.falsy);
+ psi_num_exp_dump(dump, exp->data.t.cond);
+ PSI_DUMP(dump, " ? ");
+ psi_num_exp_dump(dump, exp->data.t.truthy);
+ PSI_DUMP(dump, " : ");
+ psi_num_exp_dump(dump, exp->data.t.falsy);
break;
default:
struct psi_num_exp *psi_num_exp_copy(struct psi_num_exp *exp);
void psi_num_exp_copy_ctor(struct psi_num_exp **exp_ptr);
-void psi_num_exp_dump(int fd, struct psi_num_exp *exp);
+void psi_num_exp_dump(struct psi_dump *dump, struct psi_num_exp *exp);
bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp,
struct psi_validate_scope *scope);
return list;
}
-void psi_number_dump(int fd, struct psi_number *exp)
+void psi_number_dump(struct psi_dump *dump, struct psi_number *exp)
{
switch (exp->type) {
case PSI_T_DEFINED:
- CASE_IMPLVAL_NUM_PRINTF(dprintf, fd, exp->data.ival)
+ CASE_IMPLVAL_NUM_PRINTF(dump->fun, dump->ctx, exp->data.ival, 1);
case PSI_T_NULL:
- dprintf(fd, "NULL");
+ PSI_DUMP(dump, "NULL");
break;
case PSI_T_NUMBER:
case PSI_T_NSNAME:
case PSI_T_DEFINE:
case PSI_T_QUOTED_CHAR:
case PSI_T_CPP_HEADER:
- dprintf(fd, "%s", exp->data.numb->val);
+ PSI_DUMP(dump, "%s", exp->data.numb->val);
break;
case PSI_T_FUNCTION:
- psi_cpp_macro_call_dump(fd, exp->data.call);
+ psi_cpp_macro_call_dump(dump, exp->data.call);
break;
case PSI_T_CONST:
- dprintf(fd, "%s", exp->data.cnst->name->val);
+ PSI_DUMP(dump, "%s", exp->data.cnst->name->val);
break;
case PSI_T_ENUM:
- dprintf(fd, "%s", exp->data.enm->name->val);
+ PSI_DUMP(dump, "%s", exp->data.enm->name->val);
break;
case PSI_T_NAME:
- psi_decl_var_dump(fd, exp->data.dvar);
+ psi_decl_var_dump(dump, exp->data.dvar);
break;
case PSI_T_SIZEOF:
- dprintf(fd, "sizeof(");
- psi_decl_type_dump(fd, exp->data.dtyp, 0);
- dprintf(fd, ")");
+ PSI_DUMP(dump, "sizeof(");
+ psi_decl_type_dump(dump, exp->data.dtyp, 0);
+ PSI_DUMP(dump, ")");
break;
default:
assert(0);
case PSI_NUMBER_FLT:
switch (exp->flags & 0x0ff00) {
case PSI_NUMBER_F:
- case PSI_NUMBER_DF:
tmp.fval = strtof(exp->data.numb->val, NULL);
zend_string_release(exp->data.numb);
exp->type = PSI_T_FLOAT;
#endif
case PSI_NUMBER_DD:
default:
+ case PSI_NUMBER_DF:
tmp.dval = strtod(exp->data.numb->val, NULL);
zend_string_release(exp->data.numb);
exp->type = PSI_T_DOUBLE;
case PSI_T_UINT32:
case PSI_T_INT64:
case PSI_T_UINT64:
+#if HAVE_INT128
+ case PSI_T_INT128:
+ case PSI_T_UINT128:
+#endif
case PSI_T_FLOAT:
case PSI_T_DOUBLE:
#if HAVE_LONG_DOUBLE
*res = exp->data.ival;
if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
return PSI_T_UINT64;
-
+#if HAVE_INT128
+ case PSI_T_INT128:
+ *res = exp->data.ival;
+ //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi128, res->i128);
+ return PSI_T_INT128;
+ case PSI_T_UINT128:
+ *res = exp->data.ival;
+ //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu128, res->u128);
+ return PSI_T_UINT128;
+#endif
case PSI_T_FLOAT:
*res = exp->data.ival;
if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
struct psi_number *psi_number_init(token_t t, void *num, unsigned flags);
struct psi_number *psi_number_copy(struct psi_number *exp);
void psi_number_free(struct psi_number **exp_ptr);
-void psi_number_dump(int fd, struct psi_number *exp);
+void psi_number_dump(struct psi_dump *dump, struct psi_number *exp);
bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
struct psi_validate_scope *scope);
}
}
-void psi_return_exp_dump(int fd, struct psi_return_exp *exp)
+void psi_return_exp_dump(struct psi_dump *dump, struct psi_return_exp *exp)
{
if (exp->func) {
- psi_decl_var_dump(fd, exp->func);
- dprintf(fd, "(");
+ psi_decl_var_dump(dump, exp->func);
+ PSI_DUMP(dump, "(");
if (exp->args) {
size_t i = 0;
struct psi_decl_var *arg;
while (psi_plist_get(exp->args, i++, &arg)) {
if (i > 1) {
- dprintf(fd, ", ");
+ PSI_DUMP(dump, ", ");
}
- psi_decl_var_dump(fd, arg);
+ psi_decl_var_dump(dump, arg);
}
}
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
}
if (exp->set) {
if (exp->func) {
- dprintf(fd, " as ");
+ PSI_DUMP(dump, " as ");
}
- psi_set_exp_dump(fd, exp->set, 1, 1);
+ psi_set_exp_dump(dump, exp->set, 1, 1);
}
}
struct psi_return_exp *psi_return_exp_init(struct psi_decl_var *func,
struct psi_plist *args, struct psi_set_exp *set);
void psi_return_exp_free(struct psi_return_exp **exp_ptr);
-void psi_return_exp_dump(int fd, struct psi_return_exp *exp);
+void psi_return_exp_dump(struct psi_dump *dump, struct psi_return_exp *exp);
void psi_return_exp_exec(struct psi_return_exp *exp, zval *return_value,
struct psi_call_frame *frame);
bool psi_return_exp_validate(struct psi_data *data, struct psi_return_exp *exp,
}
}
-void psi_return_stmt_dump(int fd, struct psi_return_stmt *ret)
+void psi_return_stmt_dump(struct psi_dump *dump, struct psi_return_stmt *ret)
{
- dprintf(fd, "\treturn ");
- psi_return_exp_dump(fd, ret->exp);
- dprintf(fd, ";\n");
+ PSI_DUMP(dump, "\treturn ");
+ psi_return_exp_dump(dump, ret->exp);
+ PSI_DUMP(dump, ";\n");
}
bool psi_return_stmt_validate(struct psi_data *data,
struct psi_return_stmt *psi_return_stmt_init(struct psi_return_exp *exp);
void psi_return_stmt_free(struct psi_return_stmt **ret_ptr);
-void psi_return_stmt_dump(int fd, struct psi_return_stmt *ret);
+void psi_return_stmt_dump(struct psi_dump *dump, struct psi_return_stmt *ret);
void psi_return_stmt_exec(struct psi_return_stmt *ret, zval *return_value, struct psi_call_frame *frame);
bool psi_return_stmt_validate(struct psi_data *data, struct psi_validate_scope *impl);
}
}
-void psi_set_exp_dump(int fd, struct psi_set_exp *set, unsigned level, int last)
+void psi_set_exp_dump(struct psi_dump *dump, struct psi_set_exp *set, unsigned level, int last)
{
if (level > 1) {
/* only if not directly after `set ...` */
- dprintf(fd, "%s", psi_t_indent(level));
+ PSI_DUMP(dump, "%s", psi_t_indent(level));
}
if (set->var) {
/* parsed, or generated */
if (set->var->token) {
- dprintf(fd, "%s = ", set->var->name->val);
+ PSI_DUMP(dump, "%s = ", set->var->name->val);
}
}
switch (set->kind) {
case PSI_SET_FUNC:
- psi_set_func_dump(fd, set->data.func, level);
+ psi_set_func_dump(dump, set->data.func, level);
break;
case PSI_SET_NUMEXP:
- psi_num_exp_dump(fd, set->data.num);
+ psi_num_exp_dump(dump, set->data.num);
break;
default:
assert(0);
}
if (!last) {
- dprintf(fd, ",");
+ PSI_DUMP(dump, ",");
}
if (set->var) {
- dprintf(fd, "\t/* fqn=%s */", set->var->fqn->val);
+ PSI_DUMP(dump, "\t/* fqn=%s */", set->var->fqn->val);
}
}
struct psi_set_exp *psi_set_exp_init(enum psi_set_exp_kind kind, void *data);
void psi_set_exp_free(struct psi_set_exp **exp_ptr);
-void psi_set_exp_dump(int fd, struct psi_set_exp *set, unsigned level, int last);
+void psi_set_exp_dump(struct psi_dump *dump, struct psi_set_exp *set, unsigned level, int last);
void psi_set_exp_exec(struct psi_set_exp *val, struct psi_call_frame *frame);
void psi_set_exp_exec_ex(struct psi_set_exp *val, zval *zv, impl_val *iv, struct psi_call_frame *frame);
bool psi_set_exp_validate(struct psi_data *data, struct psi_set_exp *set, struct psi_validate_scope *scope);
}
}
-void psi_set_func_dump(int fd, struct psi_set_func *func, unsigned level)
+void psi_set_func_dump(struct psi_dump *dump, struct psi_set_func *func, unsigned level)
{
- dprintf(fd, "%s(", func->name->val);
- psi_decl_var_dump(fd, func->var);
- dprintf(fd, "\t/* fqn=%s */", func->var->fqn->val);
+ PSI_DUMP(dump, "%s(", func->name->val);
+ psi_decl_var_dump(dump, func->var);
+ PSI_DUMP(dump, "\t/* fqn=%s */", func->var->fqn->val);
if (func->inner && !func->recursive) {
size_t i = 0, count = psi_plist_count(func->inner);
struct psi_set_exp *inner;
- dprintf(fd, ",");
+ PSI_DUMP(dump, ",");
++level;
while (psi_plist_get(func->inner, i++, &inner)) {
- dprintf(fd, "\n");
- psi_set_exp_dump(fd, inner, level, i == count);
+ PSI_DUMP(dump, "\n");
+ psi_set_exp_dump(dump, inner, level, i == count);
}
--level;
}
if (func->recursive) {
- dprintf(fd, ", ...");
+ PSI_DUMP(dump, ", ...");
}
if (func->inner && !func->recursive) {
- dprintf(fd, "\n%s", psi_t_indent(level));
+ PSI_DUMP(dump, "\n%s", psi_t_indent(level));
}
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
}
static inline bool psi_set_func_validate_to_string(struct psi_data *data,
struct psi_set_func *psi_set_func_init(token_t type, zend_string *name, struct psi_decl_var *var);
void psi_set_func_free(struct psi_set_func **func_ptr);
-void psi_set_func_dump(int fd, struct psi_set_func *func, unsigned level);
+void psi_set_func_dump(struct psi_dump *dump, struct psi_set_func *func, unsigned level);
bool psi_set_func_validate(struct psi_data *data, struct psi_set_func *func,
struct psi_validate_scope *scope);
}
}
-void psi_set_stmt_dump(int fd, struct psi_set_stmt *set)
+void psi_set_stmt_dump(struct psi_dump *dump, struct psi_set_stmt *set)
{
- dprintf(fd, "\tset ");
- psi_set_exp_dump(fd, set->exp, 1, 1);
- dprintf(fd, ";\n");
+ PSI_DUMP(dump, "\tset ");
+ psi_set_exp_dump(dump, set->exp, 1, 1);
+ PSI_DUMP(dump, ";\n");
}
struct psi_set_stmt *psi_set_stmt_init(struct psi_set_exp *val);
void psi_set_stmt_free(struct psi_set_stmt **set_ptr);
-void psi_set_stmt_dump(int fd, struct psi_set_stmt *set);
+void psi_set_stmt_dump(struct psi_dump *dump, struct psi_set_stmt *set);
void psi_set_stmt_exec(struct psi_set_stmt *set, struct psi_call_frame *frame);
bool psi_set_stmts_validate(struct psi_data *data, struct psi_validate_scope *scope);