@cat >$@ <$<
install-headers: psi-build-headers
-clean: psi-clean-headers
+clean: psi-clean
.PHONY: psi-build-headers
psi-build-headers: $(PHP_PSI_HEADERS)
psi-clean-headers:
-rm -f $(PHP_PSI_HEADERS)
+.PHONY: psi-clean-sources
+psi-clean-sources:
+ -rm -f $(PHP_PSI_BUILDDIR)/src/*o
+ -rm -f $(PHP_PSI_SRCDIR)/src/parser.c $(PHP_PSI_SRCDIR)/src/parser_proc.c $(PHP_PSI_SRCDIR)/src/parser_proc.y
+
+.PHONY: psi-clean-aux
+psi-clean-aux:
+ -rm -f lempar.c lemon.c lemon
+
+.PHONY: psi-clean
+psi-clean: psi-clean-headers psi-clean-sources psi-clean-aux
+
+
lempar.c:
curl -sSo $@ "http://www.sqlite.org/src/raw/tool/lempar.c?name=3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7"
$(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.c
-$(PHP_PSI_SRCDIR)/src/%.c: $(PHP_PSI_SRCDIR)/src/parser.h $(PHP_PSI_SRCDIR)/src/parser_proc.h
- touch $@
-$(PHP_PSI_SRCDIR)/src/parser_proc.y: $(PHP_PSI_SRCDIR)/src/parser_def.h $(PHP_PSI_SRCDIR)/src/parser.h
+$(PHP_PSI_SRCDIR)/src/parser_proc.inc:
+$(PHP_PSI_SRCDIR)/src/parser_proc.y: $(PHP_PSI_SRCDIR)/src/parser_def.h $(PHP_PSI_SRCDIR)/src/parser_proc.inc
cat $(PHP_PSI_SRCDIR)/src/parser_proc.inc >$@
$(CPP) -P -DGENERATE $< >>$@
$(PHP_PSI_SRCDIR)/src/parser_proc.c: $(PHP_PSI_SRCDIR)/src/parser_proc.y $(LEMON)
$(LEMON) -c $<
-$(PHP_PSI_SRCDIR)/src/parser.re: $(PHP_PSI_SRCDIR)/src/parser.h $(PHP_PSI_SRCDIR)/src/parser_proc.h
+$(PHP_PSI_SRCDIR)/src/parser.re: $(PHP_PSI_SRCDIR)/src/parser_proc.h
touch $@
$(PHP_PSI_SRCDIR)/src/parser.c: $(PHP_PSI_SRCDIR)/src/parser.re
$(RE2C) -o $@ $<
PHP_ADD_INCLUDE($PHP_PSI_SRCDIR/src)
PHP_ADD_BUILD_DIR($PHP_PSI_BUILDDIR/src)
- PHP_PSI_HEADERS=`(cd $PHP_PSI_SRCDIR/src && echo *.h)`
- PHP_PSI_SOURCES= # parser* should come first
- PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/parser_proc.c src/parser.c"
- PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/libjit.c src/libffi.c src/engine.c"
- PHP_PSI_SOURCES="$PHP_PSI_SOURCES src/marshal.c src/calc.c src/module.c"
- PHP_PSI_SOURCES="$PHP_PSI_SOURCES `(cd $PHP_PSI_SRCDIR && echo src/context*.c)`"
+ PHP_PSI_HEADERS=`(cd $PHP_PSI_SRCDIR/src && ls *.h types/*.h)`
+ # parser* should come first
+ PHP_PSI_SOURCES=" \
+ src/parser_proc.c \
+ src/parser.c \
+ `(cd $PHP_PSI_SRCDIR && ls src/*.c | $EGREP -v '^src/parser')` \
+ "
PHP_NEW_EXTENSION(psi, $PHP_PSI_SOURCES, $ext_shared)
PHP_INSTALL_HEADERS(ext/psi, php_psi.h $PHP_PSI_HEADERS)
#include "context.h"
-void psi_error_wrapper(void *context, PSI_Token *t, int type, const char *msg, ...);
+void psi_error_wrapper(void *context, struct psi_token *t, int type, const char *msg, ...);
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);
ZEND_BEGIN_MODULE_GLOBALS(psi)
char *engine;
char *directory;
- PSI_Context context;
+ struct psi_context context;
ZEND_END_MODULE_GLOBALS(psi);
ZEND_EXTERN_MODULE_GLOBALS(psi);
#include <fnmatch.h>
-#include "php.h"
#include "php_scandir.h"
#include "php_psi.h"
#include "calc.h"
#include "libjit.h"
#include "libffi.h"
+#include "token.h"
+#include "parser.h"
+
#include "php_psi_types.h"
#include "php_psi_consts.h"
#include "php_psi_decls.h"
#include "php_psi_structs.h"
#include "php_psi_unions.h"
-PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error, unsigned flags)
+struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_ops *ops, psi_context_error_func error, unsigned flags)
{
- PSI_Data T;
+ struct psi_data T;
struct psi_predef_type *predef_type;
struct psi_predef_const *predef_const;
struct psi_predef_struct *predef_struct;
predef_decl = farg;
}
- PSI_ContextValidateData(PSI_DATA(C), &T);
+ psi_context_validate_data(PSI_DATA(C), &T);
C->count = 1;
C->data = malloc(sizeof(*C->data));
- PSI_DataExchange(C->data, &T);
+ psi_data_exchange(C->data, &T);
return C;
}
return 0 == fnmatch("*.psi", entry->d_name, FNM_CASEFOLD);
}
-void PSI_ContextBuild(PSI_Context *C, const char *paths)
+void psi_context_build(struct psi_context *C, const char *paths)
{
int i, n;
char *sep = NULL, *cpy = strdup(paths), *ptr = cpy;
if (n > 0) {
for (i = 0; i < n; ++i) {
char psi[MAXPATHLEN];
- PSI_Parser P;
+ struct psi_parser P;
if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) {
C->error(C, NULL, PSI_WARNING, "Path to PSI file too long: %s/%s",
ptr, entries[i]->d_name);
}
- if (!PSI_ParserInit(&P, psi, C->error, C->flags)) {
+ if (!psi_parser_init(&P, psi, C->error, C->flags)) {
C->error(C, NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s",
psi, strerror(errno));
continue;
}
- while (0 < PSI_ParserScan(&P)) {
- PSI_ParserParse(&P, PSI_TokenAlloc(&P));
+ while (0 < psi_parser_scan(&P)) {
+ psi_parser_parse(&P, psi_token_alloc(&P));
if (P.num == PSI_T_EOF) {
break;
}
}
- PSI_ParserParse(&P, NULL);
- PSI_ContextValidate(C, &P);
- PSI_ParserDtor(&P);
+ psi_parser_parse(&P, NULL);
+ psi_context_validate(C, &P);
+ psi_parser_dtor(&P);
}
}
} while (sep);
- if (PSI_ContextCompile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) {
+ if (psi_context_compile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) {
C->error(C, NULL, PSI_WARNING, "Failed to register functions!");
}
}
-zend_function_entry *PSI_ContextCompile(PSI_Context *C)
+zend_function_entry *psi_context_compile(struct psi_context *C)
{
size_t i;
zend_constant zc;
}
-void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va)
+void psi_context_call(struct psi_context *C, struct decl_callinfo *decl_call, struct impl_vararg *va)
{
C->ops->call(C, decl_call, va);
}
-void PSI_ContextDtor(PSI_Context *C)
+void psi_context_dtor(struct psi_context *C)
{
size_t i;
zend_function_entry *zfe;
if (C->data) {
for (i = 0; i < C->count; ++i) {
- PSI_DataDtor(&C->data[i]);
+ psi_data_dtor(&C->data[i]);
}
free(C->data);
}
memset(C, 0, sizeof(*C));
}
-void PSI_ContextFree(PSI_Context **C)
+void psi_context_free(struct psi_context **C)
{
if (*C) {
- PSI_ContextDtor(*C);
+ psi_context_dtor(*C);
free(*C);
*C = NULL;
}
#ifndef _PSI_CONTEXT_H
#define _PSI_CONTEXT_H
-#include "parser.h"
+struct psi_context;
+struct psi_token;
+struct psi_parser;
+struct decl_callinfo;
+struct impl_vararg;
#define PSI_ERROR 16
#define PSI_WARNING 32
-typedef void (*PSI_ContextErrorFunc)(void *context, PSI_Token *token, int type, const char *msg, ...);
+typedef void (*psi_context_error_func)(void *context, struct psi_token *token, int type, const char *msg, ...);
-typedef struct PSI_Context PSI_Context;
-typedef struct PSI_ContextOps PSI_ContextOps;
-struct PSI_ContextOps {
- void (*init)(PSI_Context *C);
- void (*dtor)(PSI_Context *C);
- zend_function_entry *(*compile)(PSI_Context *C);
- void (*call)(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va);
+struct psi_context_ops {
+ void (*init)(struct psi_context *C);
+ void (*dtor)(struct psi_context *C);
+ zend_function_entry *(*compile)(struct psi_context *C);
+ void (*call)(struct psi_context *C, struct decl_callinfo *decl_call, struct impl_vararg *va);
};
-struct PSI_Context {
+#include "data.h"
+
+struct psi_context {
PSI_DATA_MEMBERS;
void *context;
- struct PSI_ContextOps *ops;
+ struct psi_context_ops *ops;
zend_function_entry *closures;
- PSI_Data *data;
+ struct psi_data *data;
size_t count;
};
-PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error, unsigned flags);
-void PSI_ContextBuild(PSI_Context *C, const char *path);
-int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P);
-int PSI_ContextValidateData(PSI_Data *C, PSI_Data *D);
-zend_function_entry *PSI_ContextCompile(PSI_Context *C);
-void PSI_ContextCall(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va);
-void PSI_ContextDump(PSI_Context *C, int fd);
-void PSI_ContextDtor(PSI_Context *C);
-void PSI_ContextFree(PSI_Context **C);
+struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_ops *ops, psi_context_error_func error, unsigned flags);
+void psi_context_build(struct psi_context *C, const char *path);
+int psi_context_validate(struct psi_context *C, struct psi_parser *P);
+int psi_context_validate_data(struct psi_data *C, struct psi_data *D);
+zend_function_entry *psi_context_compile(struct psi_context *C);
+void psi_context_call(struct psi_context *C, struct decl_callinfo *decl_call, struct impl_vararg *va);
+void psi_context_dump(struct psi_context *C, int fd);
+void psi_context_dtor(struct psi_context *C);
+void psi_context_free(struct psi_context **C);
#endif
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include "php.h"
#include "php_psi.h"
+#include "types.h"
+
#include "libjit.h"
#include "libffi.h"
}
}
-void PSI_ContextDump(PSI_Context *C, int fd)
+void psi_context_dump(struct psi_context *C, int fd)
{
#ifdef HAVE_LIBJIT
- if (C->ops == PSI_Libjit()) {
+ if (C->ops == psi_libjit_ops()) {
dprintf(fd, "// psi.engine=jit\n");
}
#endif
#ifdef HAVE_LIBFFI
- if (C->ops == PSI_Libffi()) {
+ if (C->ops == psi_libffi_ops()) {
dprintf(fd, "// psi.engine=ffi\n");
}
#endif
#include "marshal.h"
#include "engine.h"
-static int validate_lib(PSI_Data *data, void **dlopened) {
+static int validate_lib(struct psi_data *data, void **dlopened) {
char lib[MAXPATHLEN];
const char *ptr = data->psi.file.ln;
size_t len;
return 0;
}
-static inline int validate_decl_nodl(PSI_Data *data, decl *decl);
-static inline int validate_decl_struct(PSI_Data *data, decl_struct *s);
-static inline int validate_decl_union(PSI_Data *data, decl_union *u);
-static inline int validate_decl_enum(PSI_Data *data, decl_enum *e);
+static inline int validate_decl_nodl(struct psi_data *data, decl *decl);
+static inline int validate_decl_struct(struct psi_data *data, decl_struct *s);
+static inline int validate_decl_union(struct psi_data *data, decl_union *u);
+static inline int validate_decl_enum(struct psi_data *data, decl_enum *e);
-static inline int validate_decl_type(PSI_Data *data, decl_type *type, decl_arg *def) {
+static inline int validate_decl_type(struct psi_data *data, decl_type *type, decl_arg *def) {
if (weak_decl_type(type)) {
if (!locate_decl_type_alias(data->defs, type)) {
return 0;
}
return 1;
}
-static inline int validate_decl_typedef(PSI_Data *data, decl_arg *def) {
+static inline int validate_decl_typedef(struct psi_data *data, decl_arg *def) {
if (!validate_decl_type(data, def->type, def)) {
const char *pre;
return 1;
}
-static inline int validate_constant(PSI_Data *data, constant *c) {
+static inline int validate_constant(struct psi_data *data, constant *c) {
/* FIXME */
return 1;
}
-static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) {
+static inline int validate_decl_arg(struct psi_data *data, decl_arg *arg) {
if (!validate_decl_type(data, arg->type, NULL)) {
data->error(data, arg->type->token, PSI_WARNING,
"Cannot use '%s' as type for '%s'",
psi_sort_struct_arg_cmp, psi_sort_struct_arg_swp);
}
-static inline int validate_decl_struct_darg(PSI_Data *data, decl_arg *darg, void *current) {
+static inline int validate_decl_struct_darg(struct psi_data *data, decl_arg *darg, void *current) {
decl_type *real = real_decl_type(darg->type);
/* pre-validate any structs/unions/enums */
return align;
}
-static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
+static inline int validate_decl_struct(struct psi_data *data, decl_struct *s) {
size_t i, pos, len, size, align;
if (!s->size && !s->args->count) {
return 1;
}
-static inline int validate_decl_union(PSI_Data *data, decl_union *u) {
+static inline int validate_decl_union(struct psi_data *data, decl_union *u) {
size_t i, pos, len, size = 0, align;
if (!u->size && !u->args->count) {
"stdcall",
"fastcall",
};
-static inline int validate_decl_abi(PSI_Data *data, decl_abi *abi) {
+static inline int validate_decl_abi(struct psi_data *data, decl_abi *abi) {
size_t i;
for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++i) {
}
return 0;
}
-static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_arg *func)
+static inline int validate_decl_func(struct psi_data *data, void *dl, decl *decl, decl_arg *func)
{
struct psi_func_redir *redir;
}
return 1;
}
-static inline int validate_decl_nodl(PSI_Data *data, decl *decl) {
+static inline int validate_decl_nodl(struct psi_data *data, decl *decl) {
if (!validate_decl_abi(data, decl->abi)) {
data->error(data, decl->abi->token, PSI_WARNING,
"Invalid calling convention: '%s'", decl->abi->token->text);
}
return 1;
}
-static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) {
+static inline int validate_decl(struct psi_data *data, void *dl, decl *decl) {
if (!validate_decl_nodl(data, decl)) {
return 0;
}
}
return NULL;
}
-static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
+static inline int validate_num_exp(struct psi_data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
if (exp->operand) {
switch (exp->operator) {
case PSI_T_PLUS:
}
}
-static inline int validate_decl_enum(PSI_Data *data, decl_enum *e) {
+static inline int validate_decl_enum(struct psi_data *data, decl_enum *e) {
size_t j;
if (!e->items || !e->items->count) {
}
}
}
-static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg *ref, decl_args *ref_list) {
+static inline int validate_set_value_ex(struct psi_data *data, set_value *set, decl_arg *ref, decl_args *ref_list) {
size_t i;
decl_type *ref_type;
decl_var *set_var = set->vars->vars[0];
return 1;
}
-static inline int validate_set_value(PSI_Data *data, set_value *set, ...) {
+static inline int validate_set_value(struct psi_data *data, set_value *set, ...) {
va_list argp;
decl_args args = {0};
int check;
return NULL;
}
-static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
+static inline int validate_impl_ret_stmt(struct psi_data *data, impl *impl) {
return_stmt *ret;
/* we must have exactly one ret stmt delcaring the native func to call */
return NULL;
}
-static inline int validate_let_func(PSI_Data *data, let_func *func, impl *impl) {
+static inline int validate_let_func(struct psi_data *data, let_func *func, impl *impl) {
if (impl->func->args) {
if (!locate_impl_var_arg(func->var, impl->func->args)) {
data->error(data, func->var->token, PSI_WARNING,
return 1;
}
-static inline int validate_let_callback(PSI_Data *data, decl_var *cb_var, let_callback *cb, impl *impl) {
+static inline int validate_let_callback(struct psi_data *data, decl_var *cb_var, let_callback *cb, impl *impl) {
size_t i;
decl *cb_func;
decl_type *cb_type = real_decl_type(cb_var->arg->type);
return 1;
}
-static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
+static inline int validate_impl_let_stmts(struct psi_data *data, impl *impl) {
size_t i, j;
/* we can have multiple let stmts */
return 1;
}
-static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
+static inline int validate_impl_set_stmts(struct psi_data *data, impl *impl) {
size_t i, j, k;
/* we can have any count of set stmts; processing out vars */
/* check that set stmts reference known variables */
return NULL;
}
-static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) {
+static inline int validate_impl_free_stmts(struct psi_data *data, impl *impl) {
size_t i, j, k, l;
/* we can have any count of free stmts; freeing any out vars */
for (i = 0; i < impl->stmts->fre.count; ++i) {
}
return 1;
}
-static inline int validate_impl_stmts(PSI_Data *data, impl *impl) {
+static inline int validate_impl_stmts(struct psi_data *data, impl *impl) {
if (!impl->stmts) {
data->error(data, impl->func->token, PSI_WARNING,
"Missing body for implementation %s!",
return 1;
}
-static inline int validate_impl_args(PSI_Data *data, impl *impl) {
+static inline int validate_impl_args(struct psi_data *data, impl *impl) {
int def = 0;
size_t i;
return 1;
}
-static inline int validate_impl(PSI_Data *data, impl *impl) {
+static inline int validate_impl(struct psi_data *data, impl *impl) {
if (!validate_impl_args(data, impl)) {
return 0;
}
}
-int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
+int psi_context_validate(struct psi_context *C, struct psi_parser *P)
{
- PSI_Data *D;
+ struct psi_data *D;
void *dlopened = NULL;
size_t i, count = C->count++, check_round, check_count;
decl_typedefs *check_defs = P->defs;
unsigned silent = C->flags & PSI_PARSER_SILENT;
C->data = realloc(C->data, C->count * sizeof(*C->data));
- D = PSI_DataExchange(&C->data[count], PSI_DATA(P));
+ D = psi_data_exchange(&C->data[count], PSI_DATA(P));
#define REVALIDATE(what) do { \
if (check_round && check_ ##what) { \
return 1;
}
-int PSI_ContextValidateData(PSI_Data *dest, PSI_Data *source)
+int psi_context_validate_data(struct psi_data *dest, struct psi_data *source)
{
size_t i;
int errors = 0;
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
+
+#include <string.h>
+
+#include "data.h"
+
+struct psi_data *psi_data_exchange(struct psi_data *dest, struct psi_data *src) {
+ if (!dest) {
+ dest = malloc(sizeof(*dest));
+ }
+ memcpy(dest, src, sizeof(*dest));
+ memset(src, 0, sizeof(*src));
+ return dest;
+}
+
+void psi_data_dtor(struct psi_data *data) {
+ if (data->consts) {
+ free_constants(data->consts);
+ }
+ if (data->defs) {
+ free_decl_typedefs(data->defs);
+ }
+ if (data->structs) {
+ free_decl_structs(data->structs);
+ }
+ if (data->unions) {
+ free_decl_unions(data->unions);
+ }
+ if (data->enums) {
+ free_decl_enums(data->enums);
+ }
+ if (data->decls) {
+ free_decls(data->decls);
+ }
+ if (data->impls) {
+ free_impls(data->impls);
+ }
+ free_decl_file(&data->psi.file);
+}
+
--- /dev/null
+#ifndef _PSI_DATA_H
+#define _PSI_DATA_H
+
+#include "types.h"
+
+#define PSI_DATA(D) ((struct psi_data *) (D))
+
+#define PSI_DATA_MEMBERS \
+ constants *consts; \
+ decl_typedefs *defs; \
+ decl_structs *structs; \
+ decl_unions *unions; \
+ decl_enums *enums; \
+ decls *decls; \
+ impls *impls; \
+ union { \
+ decl_file file; \
+ decl_libs libs; \
+ } psi; \
+ psi_error_cb error; \
+ unsigned errors; \
+ unsigned flags
+
+struct psi_data {
+ PSI_DATA_MEMBERS;
+};
+
+struct psi_data *psi_data_exchange(struct psi_data *dest, struct psi_data *src);
+void psi_data_dtor(struct psi_data *data);
+
+#endif
#include "calc.h"
#include "marshal.h"
-size_t psi_t_alignment(token_t t)
-{
-#define PSI_ALIGNOF(T) case PSI_T_## T: return ALIGNOF_## T ##_T;
- switch (t) {
- PSI_ALIGNOF(INT8);
- PSI_ALIGNOF(UINT8);
- PSI_ALIGNOF(INT16);
- PSI_ALIGNOF(UINT16);
- PSI_ALIGNOF(INT32);
- PSI_ALIGNOF(UINT32);
- PSI_ALIGNOF(INT64);
- PSI_ALIGNOF(UINT64);
- case PSI_T_FLOAT:
- return ALIGNOF_FLOAT;
- case PSI_T_DOUBLE:
- return ALIGNOF_DOUBLE;
- case PSI_T_POINTER:
- case PSI_T_FUNCTION:
- return ALIGNOF_VOID_P;
- case PSI_T_ENUM:
- return ALIGNOF_INT;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- return 0;
-}
-
-size_t psi_t_size(token_t t)
-{
-#define PSI_SIZEOF(T) case PSI_T_## T : return SIZEOF_## T ##_T;
- switch (t) {
- PSI_SIZEOF(INT8);
- PSI_SIZEOF(UINT8);
- PSI_SIZEOF(INT16);
- PSI_SIZEOF(UINT16);
- PSI_SIZEOF(INT32);
- PSI_SIZEOF(UINT32);
- PSI_SIZEOF(INT64);
- PSI_SIZEOF(UINT64);
- case PSI_T_FLOAT:
- return SIZEOF_FLOAT;
- case PSI_T_DOUBLE:
- return SIZEOF_DOUBLE;
- case PSI_T_POINTER:
- case PSI_T_FUNCTION:
- return SIZEOF_VOID_P;
- case PSI_T_ENUM:
- return SIZEOF_INT;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- return 0;
-}
int psi_internal_type(impl_type *type)
{
}
/* FIXME: check in validate_* that free functions return scalar */
- PSI_ContextCall(&PSI_G(context), &f->decl->call, NULL);
+ psi_context_call(&PSI_G(context), &f->decl->call, NULL);
}
}
}
}
- PSI_ContextCall(&PSI_G(context), &impl->decl->call, va);
+ psi_context_call(&PSI_G(context), &impl->decl->call, va);
psi_do_return(return_value, impl->stmts->ret.list[0]);
for (i = 0; i < impl->stmts->set.count; ++i) {
#ifndef _PSI_ENGINE_H
#define _PSI_ENGINE_H
-size_t psi_t_alignment(token_t t);
-size_t psi_t_size(token_t t);
-
static inline size_t psi_align(size_t s, size_t a) {
return ((s - 1) | (a - 1)) + 1;
}
#ifdef HAVE_LIBFFI
#include "php_psi.h"
-#include "libffi.h"
+#include "ffi.h"
#include "engine.h"
#undef PACKAGE
static inline ffi_type *psi_ffi_decl_arg_type(decl_arg *darg);
-typedef struct PSI_LibffiContext {
+struct psi_ffi_context {
ffi_cif signature;
ffi_type *params[2];
-} PSI_LibffiContext;
+};
-typedef struct PSI_LibffiCall {
+struct psi_ffi_call {
void *code;
ffi_closure *closure;
ffi_cif signature;
void *params[1]; /* [type1, type2, NULL, arg1, arg2] ... */
-} PSI_LibffiCall;
+};
static inline ffi_abi psi_ffi_abi(const char *convention) {
return FFI_DEFAULT_ABI;
}
-static inline PSI_LibffiCall *PSI_LibffiCallAlloc(PSI_Context *C, decl *decl) {
+static inline struct psi_ffi_call *psi_ffi_call_alloc(struct psi_context *C, decl *decl) {
int rc;
size_t i, c = decl->args ? decl->args->count : 0;
- PSI_LibffiCall *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
+ struct psi_ffi_call *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
for (i = 0; i < c; ++i) {
call->params[i] = psi_ffi_decl_arg_type(decl->args->args[i]);
return call;
}
-static inline ffi_status PSI_LibffiCallInitClosure(PSI_Context *C, PSI_LibffiCall *call, impl *impl) {
- PSI_LibffiContext *context = C->context;
+static inline ffi_status psi_ffi_call_init_closure(struct psi_context *C, struct psi_ffi_call *call, impl *impl) {
+ struct psi_ffi_context *context = C->context;
return psi_ffi_prep_closure(&call->closure, &call->code, &context->signature, psi_ffi_handler, impl);
}
-static inline ffi_status PSI_LibffiCallInitCallbackClosure(PSI_Context *C, PSI_LibffiCall *call, let_callback *cb) {
+static inline ffi_status psi_ffi_call_init_callback_closure(struct psi_context *C, struct psi_ffi_call *call, let_callback *cb) {
return psi_ffi_prep_closure(&call->closure, &call->code, &call->signature, psi_ffi_callback, cb);
}
-static inline void PSI_LibffiCallFree(PSI_LibffiCall *call) {
+static inline void psi_ffi_call_free(struct psi_ffi_call *call) {
if (call->closure) {
psi_ffi_closure_free(call->closure);
}
}
-static inline PSI_LibffiContext *PSI_LibffiContextInit(PSI_LibffiContext *L) {
+static inline struct psi_ffi_context *psi_ffi_context_init(struct psi_ffi_context *L) {
ffi_status rc;
if (!L) {
return L;
}
-static inline void PSI_LibffiContextFree(PSI_LibffiContext **L) {
+static inline void psi_ffi_context_free(struct psi_ffi_context **L) {
if (*L) {
free(*L);
*L = NULL;
}
}
-static void psi_ffi_init(PSI_Context *C)
+static void psi_ffi_init(struct psi_context *C)
{
- C->context = PSI_LibffiContextInit(NULL);
+ C->context = psi_ffi_context_init(NULL);
}
-static void psi_ffi_dtor(PSI_Context *C)
+static void psi_ffi_dtor(struct psi_context *C)
{
if (C->decls) {
size_t i;
decl *decl = C->decls->list[i];
if (decl->call.info) {
- PSI_LibffiCallFree(decl->call.info);
+ psi_ffi_call_free(decl->call.info);
}
}
let_callback *cb = let->val->data.callback;
if (cb->decl && cb->decl->call.info) {
- PSI_LibffiCallFree(cb->decl->call.info);
+ psi_ffi_call_free(cb->decl->call.info);
}
}
}
}
}
- PSI_LibffiContextFree((void *) &C->context);
+ psi_ffi_context_free((void *) &C->context);
}
-static zend_function_entry *psi_ffi_compile(PSI_Context *C)
+static zend_function_entry *psi_ffi_compile(struct psi_context *C)
{
size_t c, i, j = 0;
zend_function_entry *zfe;
zfe = calloc(C->impls->count + 1, sizeof(*zfe));
for (i = 0; i < C->impls->count; ++i) {
zend_function_entry *zf = &zfe[j];
- PSI_LibffiCall *call;
+ struct psi_ffi_call *call;
impl *impl = C->impls->list[i];
if (!impl->decl) {
continue;
}
- if ((call = PSI_LibffiCallAlloc(C, impl->decl))) {
- if (FFI_OK != PSI_LibffiCallInitClosure(C, call, impl)) {
- PSI_LibffiCallFree(call);
+ if ((call = psi_ffi_call_alloc(C, impl->decl))) {
+ if (FFI_OK != psi_ffi_call_init_closure(C, call, impl)) {
+ psi_ffi_call_free(call);
continue;
}
}
if (let->val && let->val->kind == PSI_LET_CALLBACK) {
let_callback *cb = let->val->data.callback;
- if ((call = PSI_LibffiCallAlloc(C, cb->decl))) {
- if (FFI_OK != PSI_LibffiCallInitCallbackClosure(C, call, cb)) {
- PSI_LibffiCallFree(call);
+ if ((call = psi_ffi_call_alloc(C, cb->decl))) {
+ if (FFI_OK != psi_ffi_call_init_callback_closure(C, call, cb)) {
+ psi_ffi_call_free(call);
continue;
}
continue;
}
- PSI_LibffiCallAlloc(C, decl);
+ psi_ffi_call_alloc(C, decl);
}
return zfe;
}
-static void psi_ffi_call(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va) {
- PSI_LibffiCall *call = decl_call->info;
+static void psi_ffi_call(struct psi_context *C, decl_callinfo *decl_call, impl_vararg *va) {
+ struct psi_ffi_call *call = decl_call->info;
if (va) {
ffi_status rc;
}
}
-static PSI_ContextOps ops = {
+static struct psi_context_ops ops = {
psi_ffi_init,
psi_ffi_dtor,
psi_ffi_compile,
psi_ffi_call,
};
-PSI_ContextOps *PSI_Libffi(void)
+struct psi_context_ops *psi_libffi_ops(void)
{
return &ops;
}
#include "context.h"
#ifdef HAVE_LIBFFI
-PSI_ContextOps *PSI_Libffi(void);
+struct psi_context_ops *psi_libffi_ops(void);
#endif
#endif
}
}
-typedef struct PSI_LibjitContext {
+struct psi_jit_context {
jit_context_t jit;
jit_type_t signature;
struct {
- struct PSI_LibjitData **list;
+ struct psi_jit_data **list;
size_t count;
} data;
-} PSI_LibjitContext;
+};
-typedef struct PSI_LibjitCall {
+struct psi_jit_call {
void *closure;
jit_type_t signature;
void *params[1]; /* [type1, type2, NULL, arg1, arg2] ... */
-} PSI_LibjitCall;
+};
-typedef struct PSI_LibjitData {
- PSI_LibjitContext *context;
+struct psi_jit_data {
+ struct psi_jit_context *context;
impl *impl;
zend_internal_arg_info *arginfo;
-} PSI_LibjitData;
+};
-static inline PSI_LibjitCall *PSI_LibjitCallAlloc(PSI_Context *C, decl *decl) {
+static inline struct psi_jit_call *psi_jit_call_alloc(struct psi_context *C, decl *decl) {
size_t i, c = decl->args ? decl->args->count : 0;
- PSI_LibjitCall *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
+ struct psi_jit_call *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
for (i = 0; i < c; ++i) {
call->params[i] = psi_jit_decl_arg_type(decl->args->args[i]);
return call;
}
-static inline void *PSI_LibjitCallInitClosure(PSI_Context *C, PSI_LibjitCall *call, impl *impl) {
- PSI_LibjitContext *context = C->context;
+static inline void *psi_jit_call_init_closure(struct psi_context *C, struct psi_jit_call *call, impl *impl) {
+ struct psi_jit_context *context = C->context;
return call->closure = jit_closure_create(context->jit, context->signature,
&psi_jit_handler, impl);
}
-static inline void *PSI_LibjitCallInitCallbackClosure(PSI_Context *C, PSI_LibjitCall *call, let_callback *cb) {
- PSI_LibjitContext *context = C->context;
+static inline void *psi_jit_call_init_callback_closure(struct psi_context *C, struct psi_jit_call *call, let_callback *cb) {
+ struct psi_jit_context *context = C->context;
return call->closure = jit_closure_create(context->jit, call->signature,
&psi_jit_callback, cb);
}
-static inline void PSI_LibjitCallFree(PSI_LibjitCall *call) {
+static inline void psi_jit_call_free(struct psi_jit_call *call) {
jit_type_free(call->signature);
free(call);
}
-static inline PSI_LibjitContext *PSI_LibjitContextInit(PSI_LibjitContext *L) {
+static inline struct psi_jit_context *psi_jit_context_init(struct psi_jit_context *L) {
jit_type_t params[] = {
jit_type_void_ptr,
jit_type_void_ptr
return L;
}
-static inline void PSI_LibjitContextDtor(PSI_LibjitContext *L) {
+static inline void psi_jit_context_dtor(struct psi_jit_context *L) {
jit_type_free(L->signature);
jit_context_destroy(L->jit);
}
-static inline void PSI_LibjitContextFree(PSI_LibjitContext **L) {
+static inline void psi_jit_context_free(struct psi_jit_context **L) {
if (*L) {
- PSI_LibjitContextDtor(*L);
+ psi_jit_context_dtor(*L);
free(*L);
*L = NULL;
}
}
-static void psi_jit_init(PSI_Context *C)
+static void psi_jit_init(struct psi_context *C)
{
- C->context = PSI_LibjitContextInit(NULL);
+ C->context = psi_jit_context_init(NULL);
}
-static void psi_jit_dtor(PSI_Context *C)
+static void psi_jit_dtor(struct psi_context *C)
{
if (C->decls) {
size_t i;
decl *decl = C->decls->list[i];
if (decl->call.info) {
- PSI_LibjitCallFree(decl->call.info);
+ psi_jit_call_free(decl->call.info);
}
}
}
let_callback *cb = let->val->data.callback;
if (cb->decl && cb->decl->call.info) {
- PSI_LibjitCallFree(cb->decl->call.info);
+ psi_jit_call_free(cb->decl->call.info);
}
}
}
}
}
- PSI_LibjitContextFree((void *) &C->context);
+ psi_jit_context_free((void *) &C->context);
}
-static zend_function_entry *psi_jit_compile(PSI_Context *C)
+static zend_function_entry *psi_jit_compile(struct psi_context *C)
{
size_t c, i, j = 0;
zend_function_entry *zfe;
- PSI_LibjitContext *ctx = C->context;
+ struct psi_jit_context *ctx = C->context;
if (!C->impls) {
return NULL;
for (i = 0; i < C->impls->count; ++i) {
zend_function_entry *zf = &zfe[j];
- PSI_LibjitCall *call;
+ struct psi_jit_call *call;
impl *impl = C->impls->list[i];
if (!impl->decl) {
continue;
}
- if ((call = PSI_LibjitCallAlloc(C, impl->decl))) {
- if (!PSI_LibjitCallInitClosure(C, call, impl)) {
- PSI_LibjitCallFree(call);
+ if ((call = psi_jit_call_alloc(C, impl->decl))) {
+ if (!psi_jit_call_init_closure(C, call, impl)) {
+ psi_jit_call_free(call);
continue;
}
}
if (let->val && let->val->kind == PSI_LET_CALLBACK) {
let_callback *cb = let->val->data.callback;
- if ((call = PSI_LibjitCallAlloc(C, cb->decl))) {
- if (!PSI_LibjitCallInitCallbackClosure(C, call, cb)) {
- PSI_LibjitCallFree(call);
+ if ((call = psi_jit_call_alloc(C, cb->decl))) {
+ if (!psi_jit_call_init_callback_closure(C, call, cb)) {
+ psi_jit_call_free(call);
continue;
}
continue;
}
- PSI_LibjitCallAlloc(C, decl);
+ psi_jit_call_alloc(C, decl);
}
jit_context_build_end(ctx->jit);
return zfe;
}
-static void psi_jit_call(PSI_Context *C, decl_callinfo *decl_call, impl_vararg *va) {
- PSI_LibjitCall *call = decl_call->info;
+static void psi_jit_call(struct psi_context *C, decl_callinfo *decl_call, impl_vararg *va) {
+ struct psi_jit_call *call = decl_call->info;
if (va) {
jit_type_t signature;
}
}
-static PSI_ContextOps ops = {
+static struct psi_context_ops ops = {
psi_jit_init,
psi_jit_dtor,
psi_jit_compile,
psi_jit_call,
};
-PSI_ContextOps *PSI_Libjit(void)
+struct psi_context_ops *psi_libjit_ops(void)
{
return &ops;
}
#include "context.h"
#ifdef HAVE_LIBJIT
-PSI_ContextOps *PSI_Libjit(void);
+struct psi_context_ops *psi_libjit_ops(void);
#endif
#endif
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "zend_operators.h"
#include "php_psi.h"
+#include "token.h"
+#include "parser.h"
#if HAVE_LIBJIT
# include "libjit.h"
return psi_class_entry;
}
-void psi_error_wrapper(void *context, PSI_Token *t, int type, const char *msg, ...)
+void psi_error_wrapper(void *context, struct psi_token *t, int type, const char *msg, ...)
{
va_list argv;
const char *fn = NULL;
RETURN_FALSE;
}
}
- PSI_ContextDump(&PSI_G(context), fd);
+ psi_context_dump(&PSI_G(context), fd);
}
ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate, 0, 0, 1)
ZEND_END_ARG_INFO();
static PHP_FUNCTION(psi_validate) {
zend_string *file;
- PSI_Parser P;
+ struct psi_parser P;
if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file)) {
return;
}
- if (!PSI_ParserInit(&P, file->val, psi_error_wrapper, 0)) {
+ if (!psi_parser_init(&P, file->val, psi_error_wrapper, 0)) {
RETURN_FALSE;
}
- while (0 < PSI_ParserScan(&P)) {
- PSI_ParserParse(&P, PSI_TokenAlloc(&P));
+ while (0 < psi_parser_scan(&P)) {
+ psi_parser_parse(&P, psi_token_alloc(&P));
if (P.num == PSI_T_EOF) {
break;
}
}
- PSI_ParserParse(&P, NULL);
+ psi_parser_parse(&P, NULL);
- if (0 == PSI_ContextValidateData(NULL, PSI_DATA(&P)) && !P.errors) {
+ if (0 == psi_context_validate_data(NULL, PSI_DATA(&P)) && !P.errors) {
RETVAL_TRUE;
} else {
RETVAL_FALSE;
}
- PSI_ParserDtor(&P);
+ psi_parser_dtor(&P);
}
static PHP_MINIT_FUNCTION(psi)
{
- PSI_ContextOps *ops = NULL;
+ struct psi_context_ops *ops = NULL;
zend_class_entry ce = {0};
unsigned flags = psi_check_env("PSI_DEBUG") ? PSI_PARSER_DEBUG : (
psi_check_env("PSI_SILENT") ? PSI_PARSER_SILENT : 0);
#ifdef HAVE_LIBJIT
if (!strcasecmp(PSI_G(engine), "jit")) {
- ops = PSI_Libjit();
+ ops = psi_libjit_ops();
} else
#endif
#ifdef HAVE_LIBFFI
- ops = PSI_Libffi();
+ ops = psi_libffi_ops();
#endif
if (!ops) {
return FAILURE;
}
- PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper, flags);
- PSI_ContextBuild(&PSI_G(context), PSI_G(directory));
+ psi_context_init(&PSI_G(context), ops, psi_error_wrapper, flags);
+ psi_context_build(&PSI_G(context), PSI_G(directory));
if (psi_check_env("PSI_DUMP")) {
- PSI_ContextDump(&PSI_G(context), STDOUT_FILENO);
+ psi_context_dump(&PSI_G(context), STDOUT_FILENO);
}
return SUCCESS;
static PHP_MSHUTDOWN_FUNCTION(psi)
{
- PSI_ContextDtor(&PSI_G(context));
+ psi_context_dtor(&PSI_G(context));
UNREGISTER_INI_ENTRIES();
#include <stdarg.h>
#include <string.h>
-#include <Zend/zend_types.h>
-#include <Zend/zend_API.h> /* fcall */
-
#include "parser_proc.h"
#define BSIZE 256
-#define PSI_T_POINTER PSI_T_ASTERISK
-#define PSI_T_LONG_DOUBLE (PSI_T_DOUBLE << 16)
-
-typedef int token_t;
-
-size_t psi_t_alignment(token_t);
-size_t psi_t_size(token_t);
-
-typedef struct PSI_Token {
- token_t type;
- unsigned size, line, col;
- char *text, *file;
- char buf[1];
-} PSI_Token;
-
-static inline PSI_Token *PSI_TokenCopy(PSI_Token *src);
-
-typedef struct zend_fcall {
- zend_fcall_info fci;
- zend_fcall_info_cache fcc;
-} zend_fcall;
-
-typedef union impl_val {
- char cval;
- int8_t i8;
- uint8_t u8;
- short sval;
- int16_t i16;
- uint16_t u16;
- int ival;
- int32_t i32;
- uint32_t u32;
- long lval;
- int64_t i64;
- uint64_t u64;
- float fval;
- double dval;
-#ifdef HAVE_LONG_DOUBLE
- long double ldval;
-#endif
- union {
- zend_bool bval;
- zend_long lval;
- zend_string *str;
- zend_fcall *cb;
- } zend;
- void *ptr;
-} impl_val;
-
-typedef struct decl_type {
- PSI_Token *token;
- char *name;
- token_t type;
- union {
- struct decl_arg *def;
- struct decl_struct *strct;
- struct decl_union *unn;
- struct decl_enum *enm;
- struct decl *func;
- } real;
-} decl_type;
-
-static inline decl_type *init_decl_type(token_t type, const char *name) {
- decl_type *t = calloc(1, sizeof(*t));
- t->type = type;
- t->name = strdup(name);
- return t;
-}
-
-static inline int weak_decl_type(decl_type *type) {
- switch (type->type) {
- case PSI_T_CHAR:
- case PSI_T_SHORT:
- case PSI_T_INT:
- case PSI_T_LONG:
- case PSI_T_NAME:
- return type->type;
- default:
- return 0;
- }
-}
-
-static inline void free_decl(struct decl *decl);
-static inline void free_decl_type(decl_type *type) {
- if (type->token) {
- free(type->token);
- }
- if (type->type == PSI_T_FUNCTION) {
- free_decl(type->real.func);
- }
- free(type->name);
- free(type);
-}
-
-typedef struct decl_var {
- PSI_Token *token;
- char *name;
- unsigned pointer_level;
- unsigned array_size;
- struct decl_arg *arg;
-} decl_var;
-
-static inline decl_var *init_decl_var(const char *name, unsigned pl, unsigned as) {
- decl_var *v = calloc(1, sizeof(*v));
- v->name = (char *) strdup((const char *) name);
- v->pointer_level = pl;
- v->array_size = as;
- return v;
-}
-
-static inline decl_var *copy_decl_var(decl_var *src) {
- decl_var *dest = calloc(1, sizeof(*dest));
-
- memcpy(dest, src, sizeof(*dest));
- dest->name = strdup(dest->name);
- if (dest->token) {
- dest->token = PSI_TokenCopy(dest->token);
- }
- return dest;
-}
-
-static inline void free_decl_var(decl_var *var) {
- if (var->token) {
- free(var->token);
- }
- free(var->name);
- free(var);
-}
-
-typedef struct decl_struct_layout {
- size_t pos;
- size_t len;
-} decl_struct_layout;
-
-static inline decl_struct_layout *init_decl_struct_layout(size_t pos, size_t len) {
- decl_struct_layout *l = calloc(1, sizeof(*l));
- ZEND_ASSERT(pos+len);
- l->pos = pos;
- l->len = len;
- return l;
-}
-
-static inline void free_decl_struct_layout(decl_struct_layout *l) {
- free(l);
-}
-
-typedef struct decl_arg {
- PSI_Token *token;
- decl_type *type;
- decl_var *var;
- decl_struct_layout *layout;
- impl_val val;
- void *ptr;
- void *let;
- void *mem;
-} decl_arg;
-
-static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
- decl_arg *arg = calloc(1, sizeof(*arg));
- arg->token = var->token;
- arg->type = type;
- arg->var = var;
- var->arg = arg;
- arg->ptr = &arg->val;
- arg->let = arg->ptr;
- return arg;
-}
-
-static inline void free_decl_arg(decl_arg *arg) {
- if (arg->token && arg->token != arg->var->token) {
- free(arg->token);
- }
- free_decl_type(arg->type);
- free_decl_var(arg->var);
- if (arg->layout) {
- free_decl_struct_layout(arg->layout);
- }
- free(arg);
-}
-
-static inline decl_type *real_decl_type(decl_type *type) {
- while (weak_decl_type(type)) {
- type = type->real.def->type;
- }
- return type;
-}
-
-typedef struct decl_typedefs {
- size_t count;
- decl_arg **list;
-} decl_typedefs;
-
-static inline decl_typedefs *add_decl_typedef(decl_typedefs *defs, decl_arg *def) {
- if (!defs) {
- defs = calloc(1, sizeof(*defs));
- }
- defs->list = realloc(defs->list, ++defs->count * sizeof(*defs->list));
- defs->list[defs->count-1] = def;
- return defs;
-}
-
-static void free_decl_typedefs(decl_typedefs *defs) {
- size_t i;
-
- for (i = 0; i < defs->count; ++i) {
- free_decl_arg(defs->list[i]);
- }
- free(defs->list);
- free(defs);
-}
-
-typedef struct decl_vars {
- decl_var **vars;
- size_t count;
-} decl_vars;
-
-static inline decl_vars *init_decl_vars(decl_var *var) {
- decl_vars *vars = calloc(1, sizeof(*vars));
- if (var) {
- vars->count = 1;
- vars->vars = calloc(1, sizeof(*vars->vars));
- vars->vars[0] = var;
- }
- return vars;
-}
-
-static inline decl_vars *add_decl_var(decl_vars *vars, decl_var *var) {
- vars->vars = realloc(vars->vars, ++vars->count * sizeof(*vars->vars));
- vars->vars[vars->count-1] = var;
- return vars;
-}
-
-static inline void free_decl_vars(decl_vars *vars) {
- size_t i;
-
- for (i = 0; i < vars->count; ++i) {
- free_decl_var(vars->vars[i]);
- }
- free(vars->vars);
- free(vars);
-}
-
-typedef struct decl_args {
- decl_arg **args;
- size_t count;
- unsigned varargs:1;
-} decl_args;
-
-static inline decl_args *init_decl_args(decl_arg *arg) {
- decl_args *args = calloc(1, sizeof(*args));
- if (arg) {
- args->count = 1;
- args->args = calloc(1, sizeof(*args->args));
- args->args[0] = arg;
- }
- return args;
-}
-
-static inline decl_args *add_decl_arg(decl_args *args, decl_arg *arg) {
- args->args = realloc(args->args, ++args->count * sizeof(*args->args));
- args->args[args->count-1] = arg;
- return args;
-}
-
-static inline void free_decl_args(decl_args *args) {
- size_t i;
-
- for (i = 0; i < args->count; ++i) {
- free_decl_arg(args->args[i]);
- }
- free(args->args);
- free(args);
-}
-
-typedef struct decl_abi {
- PSI_Token *token;
- char *convention;
-} decl_abi;
-
-static inline decl_abi *init_decl_abi(const char *convention) {
- decl_abi *abi = calloc(1, sizeof(*abi));
- abi->convention = strdup(convention);
- return abi;
-}
-
-static inline void free_decl_abi(decl_abi *abi) {
- if (abi->token) {
- free(abi->token);
- }
- free(abi->convention);
- free(abi);
-}
-
-typedef struct decl_callinfo {
- void *sym;
- void *info;
- size_t argc;
- void **args;
- void **rval;
-} decl_callinfo;
-
-typedef struct decl {
- decl_abi *abi;
- decl_arg *func;
- decl_args *args;
- struct impl *impl;
- decl_callinfo call;
-} decl;
-
-static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) {
- decl *d = calloc(1, sizeof(*d));
- d->abi = abi;
- d->func = func;
- d->args = args;
- return d;
-}
-
-static inline void free_decl(decl *d) {
- free_decl_abi(d->abi);
- free_decl_arg(d->func);
- if (d->args) {
- free_decl_args(d->args);
- }
- free(d);
-}
-
-typedef struct decls {
- size_t count;
- decl **list;
-} decls;
-
-static inline decls *add_decl(decls *decls, decl *decl) {
- if (!decls) {
- decls = calloc(1, sizeof(*decls));
- }
- decls->list = realloc(decls->list, ++decls->count * sizeof(*decls->list));
- decls->list[decls->count-1] = decl;
- return decls;
-}
-
-static inline void free_decls(decls *decls) {
- size_t i;
-
- for (i = 0; i < decls->count; ++i) {
- free_decl(decls->list[i]);
- }
- free(decls->list);
- free(decls);
-}
-
-
-typedef struct decl_struct {
- PSI_Token *token;
- char *name;
- decl_args *args;
- size_t size;
- size_t align;
- struct {
- void *type;
- void (*dtor)(void *type);
- } engine;
-} decl_struct;
-
-static inline decl_struct *init_decl_struct(const char *name, decl_args *args) {
- decl_struct *s = calloc(1, sizeof(*s));
- s->name = strdup(name);
- s->args = args;
- return s;
-}
-
-static inline void free_decl_struct(decl_struct *s) {
- if (s->token) {
- free(s->token);
- }
- if (s->args) {
- free_decl_args(s->args);
- }
- if (s->engine.type && s->engine.dtor) {
- s->engine.dtor(s->engine.type);
- }
- free(s->name);
- free(s);
-}
-
-typedef struct decl_structs {
- size_t count;
- decl_struct **list;
-} decl_structs;
-
-static inline decl_structs *add_decl_struct(decl_structs *ss, decl_struct *s) {
- if (!ss) {
- ss = calloc(1, sizeof(*ss));
- }
- ss->list = realloc(ss->list, ++ss->count * sizeof(*ss->list));
- ss->list[ss->count-1] = s;
- return ss;
-}
-
-static inline void free_decl_structs(decl_structs *ss) {
- size_t i;
-
- for (i = 0; i < ss->count; ++i) {
- free_decl_struct(ss->list[i]);
- }
- free(ss->list);
- free(ss);
-}
-
-typedef struct decl_union {
- PSI_Token *token;
- char *name;
- decl_args *args;
- size_t size;
- size_t align;
-} decl_union;
-
-static inline decl_union *init_decl_union(const char *name, decl_args *args) {
- decl_union *u = calloc(1, sizeof(*u));
- u->name = strdup(name);
- u->args = args;
- return u;
-}
-
-static inline void free_decl_union(decl_union *u) {
- if (u->token) {
- free(u->token);
- }
- if (u->args) {
- free_decl_args(u->args);
- }
- free(u->name);
- free(u);
-}
-
-typedef struct decl_unions {
- decl_union **list;
- size_t count;
-} decl_unions;
-
-static inline decl_unions *add_decl_union(decl_unions *uu, decl_union *u) {
- if (!uu) {
- uu = calloc(1, sizeof(*uu));
- }
- uu->list = realloc(uu->list, ++uu->count * sizeof(*uu->list));
- uu->list[uu->count-1] = u;
- return uu;
-}
-
-static inline void free_decl_unions(decl_unions *uu) {
- size_t i;
-
- for (i = 0; i < uu->count; ++i) {
- free_decl_union(uu->list[i]);
- }
- free(uu->list);
- free(uu);
-}
-
-typedef struct impl_type {
- char *name;
- token_t type;
-} impl_type;
-
-static inline impl_type *init_impl_type(token_t type, const char *name) {
- impl_type *t = calloc(1, sizeof(*t));
-
- t->type = type;
- t->name = strdup(name);
- return t;
-}
-
-static inline void free_impl_type(impl_type *type) {
- free(type->name);
- free(type);
-}
-
-typedef struct impl_var {
- PSI_Token *token;
- char *name;
- struct impl_arg *arg;
- unsigned reference:1;
-} impl_var;
-
-static inline impl_var *init_impl_var(const char *name, int is_reference) {
- impl_var *var = calloc(1, sizeof(*var));
- var->name = strdup(name);
- var->reference = is_reference;
- return var;
-}
-
-static inline impl_var *copy_impl_var(impl_var *var) {
- impl_var *cpy = malloc(sizeof(*cpy));
-
- memcpy(cpy, var, sizeof(*cpy));
- cpy->name = strdup(cpy->name);
- if (cpy->token) {
- cpy->token = PSI_TokenCopy(cpy->token);
- }
- return cpy;
-}
-
-static inline void free_impl_var(impl_var *var) {
- if (var->token) {
- free(var->token);
- }
- free(var->name);
- free(var);
-}
-
-typedef struct impl_def_val {
- token_t type;
- char *text;
-} impl_def_val;
-
-static inline impl_def_val *init_impl_def_val(token_t t, const char *text) {
- impl_def_val *def = calloc(1, sizeof(*def));
- def->type = t;
- def->text = strdup(text);
- return def;
-}
-
-static inline void free_impl_def_val(impl_def_val *def) {
- free(def->text);
- free(def);
-}
-
-typedef struct const_type {
- token_t type;
- char *name;
-} const_type;
-
-static inline const_type *init_const_type(token_t type, const char *name) {
- const_type *ct = calloc(1, sizeof(*ct));
- ct->type = type;
- ct->name = strdup(name);
- return ct;
-}
-
-static inline void free_const_type(const_type *type) {
- free(type->name);
- free(type);
-}
-
-typedef struct constant {
- const_type *type;
- char *name;
- impl_def_val *val;
-} constant;
-
-static inline constant *init_constant(const_type *type, const char *name, impl_def_val *val) {
- constant *c = calloc(1, sizeof(*c));
- c->type = type;
- c->name = strdup(name);
- c->val = val;
- return c;
-}
-
-static inline void free_constant(constant *constant) {
- free_const_type(constant->type);
- free(constant->name);
- free_impl_def_val(constant->val);
- free(constant);
-}
-
-typedef struct constants {
- size_t count;
- constant **list;
-} constants;
-
-static inline constants *add_constant(constants *constants, constant *constant) {
- if (!constants) {
- constants = calloc(1, sizeof(*constants));
- }
- constants->list = realloc(constants->list, ++constants->count * sizeof(*constants->list));
- constants->list[constants->count-1] = constant;
- return constants;
-}
-
-static inline void free_constants(constants *c) {
- size_t i;
-
- for (i = 0; i < c->count; ++i) {
- free_constant(c->list[i]);
- }
- free(c->list);
- free(c);
-}
-
-typedef struct impl_arg {
- impl_type *type;
- impl_var *var;
- impl_def_val *def;
- impl_val val;
- zval *_zv;
-} impl_arg;
-
-static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) {
- impl_arg *arg = calloc(1, sizeof(*arg));
- arg->type = type;
- arg->var = var;
- arg->var->arg = arg;
- arg->def = def;
- return arg;
-}
-
-static inline void free_impl_arg(impl_arg *arg) {
- free_impl_type(arg->type);
- free_impl_var(arg->var);
- if (arg->def) {
- free_impl_def_val(arg->def);
- }
- free(arg);
-}
-
-typedef struct impl_vararg {
- impl_arg *name;
- struct impl_args *args;
- token_t *types;
- impl_val *values;
- void **free_list;
-} impl_vararg;
-
-typedef struct impl_args {
- impl_arg **args;
- size_t count;
- impl_vararg vararg;
-} impl_args;
-
-static inline impl_args *init_impl_args(impl_arg *arg) {
- impl_args *args = calloc(1, sizeof(*args));
- if (arg) {
- args->count = 1;
- args->args = calloc(1, sizeof(*args->args));
- args->args[0] = arg;
- }
- return args;
-}
-
-static inline impl_args *add_impl_arg(impl_args *args, impl_arg *arg) {
- args->args = realloc(args->args, ++args->count * sizeof(*args->args));
- args->args[args->count-1] = arg;
- return args;
-}
-
-static inline void free_impl_args(impl_args *args) {
- size_t i;
-
- for (i = 0; i < args->count; ++i) {
- free_impl_arg(args->args[i]);
- }
- if (args->vararg.name) {
- free_impl_arg(args->vararg.name);
- }
- free(args->args);
- free(args);
-}
-
-typedef struct impl_func {
- PSI_Token *token;
- char *name;
- impl_args *args;
- impl_type *return_type;
- unsigned return_reference:1;
-} impl_func;
-
-static inline impl_func *init_impl_func(char *name, impl_args *args, impl_type *type, int ret_reference) {
- impl_func *func = calloc(1, sizeof(*func));
- func->name = strdup(name);
- func->args = args ? args : init_impl_args(NULL);
- func->return_type = type;
- func->return_reference = ret_reference;
- return func;
-}
-
-static inline void free_impl_func(impl_func *f) {
- if (f->token) {
- free(f->token);
- }
- free_impl_type(f->return_type);
- free_impl_args(f->args);
- free(f->name);
- free(f);
-}
-
-typedef struct num_exp {
- PSI_Token *token;
- token_t t;
- union {
- char *numb;
- constant *cnst;
- decl_var *dvar;
- struct decl_enum_item *enm;
- } u;
- token_t operator;
- int (*calculator)(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res);
- struct num_exp *operand;
-} num_exp;
-
-static inline num_exp *init_num_exp(token_t t, void *num) {
- num_exp *exp = calloc(1, sizeof(*exp));
- switch (exp->t = t) {
- case PSI_T_NUMBER:
- case PSI_T_NSNAME:
- exp->u.numb = strdup(num);
- break;
- case PSI_T_NAME:
- exp->u.dvar = num;
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- return exp;
-}
-
-static inline num_exp *copy_num_exp(num_exp *exp) {
- decl_var *dvar;
- num_exp *num = calloc(1, sizeof(*num));
-
- memcpy(num, exp, sizeof(*num));
-
- if (num->token) {
- num->token = PSI_TokenCopy(num->token);
- }
- if (num->operand) {
- num->operand = copy_num_exp(num->operand);
- }
- switch (num->t) {
- case PSI_T_NUMBER:
- case PSI_T_NSNAME:
- num->u.numb = strdup(num->u.numb);
- break;
- case PSI_T_NAME:
- dvar = init_decl_var(num->u.dvar->name, num->u.dvar->pointer_level, num->u.dvar->array_size);
- dvar->arg = num->u.dvar->arg;
- if (num->u.dvar->token) {
- dvar->token = PSI_TokenCopy(num->u.dvar->token);
- }
- num->u.dvar = dvar;
- break;
- }
- return num;
-}
-
-static inline void free_num_exp(num_exp *exp) {
- if (exp->token) {
- free(exp->token);
- }
- switch (exp->t) {
- case PSI_T_NUMBER:
- free(exp->u.numb);
- break;
- case PSI_T_NSNAME:
- break;
- case PSI_T_NAME:
- free_decl_var(exp->u.dvar);
- break;
- case PSI_T_ENUM:
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- if (exp->operand) {
- free_num_exp(exp->operand);
- }
- free(exp);
-}
-
-typedef struct decl_enum_item {
- PSI_Token *token;
- char *name;
- num_exp *num;
- num_exp inc;
- struct decl_enum_item *prev;
-} decl_enum_item;
-
-static inline decl_enum_item *init_decl_enum_item(const char *name, num_exp *num) {
- decl_enum_item *i = calloc(1, sizeof(*i));
-
- i->name = strdup(name);
- i->num = num;
- return i;
-}
-
-static inline void free_decl_enum_item(decl_enum_item *i) {
- if (i->token) {
- free(i->token);
- }
- if (i->num && i->num != &i->inc) {
- free_num_exp(i->num);
- }
- free(i->name);
- free(i);
-}
-
-typedef struct decl_enum_items {
- decl_enum_item **list;
- size_t count;
-} decl_enum_items;
-
-static inline decl_enum_items *init_decl_enum_items(decl_enum_item *i) {
- decl_enum_items *l = calloc(1, sizeof(*l));
-
- if (i) {
- l->count = 1;
- l->list = calloc(1, sizeof(*l->list));
- l->list[0] = i;
- }
- return l;
-}
-
-static inline decl_enum_items *add_decl_enum_item(decl_enum_items *l, decl_enum_item *i) {
- l->list = realloc(l->list, sizeof(*l->list) * (l->count + 1));
- l->list[l->count] = i;
- if (l->count) {
- i->prev = l->list[l->count - 1];
- }
- ++l->count;
- return l;
-}
-
-static inline void free_decl_enum_items(decl_enum_items *l) {
- if (l->list) {
- size_t j;
-
- for (j = 0; j < l->count; ++j) {
- free_decl_enum_item(l->list[j]);
- }
- free(l->list);
- }
- free(l);
-}
-
-typedef struct decl_enum {
- PSI_Token *token;
- char *name;
- decl_enum_items *items;
-} decl_enum;
-
-static inline decl_enum *init_decl_enum(const char *name, decl_enum_items *l) {
- decl_enum *e = calloc(1, sizeof(*e));
-
- e->name = strdup(name);
- e->items = l;
- return e;
-}
-
-static inline void free_decl_enum(decl_enum *e) {
- if (e->token) {
- free(e->token);
- }
- if (e->items) {
- free_decl_enum_items(e->items);
- }
- free(e->name);
- free(e);
-}
-
-typedef struct decl_enums {
- decl_enum **list;
- size_t count;
-} decl_enums;
+#include "token.h"
+#include "types.h"
+#include "data.h"
-static inline decl_enums* add_decl_enum(decl_enums *es, decl_enum *e) {
- if (!es) {
- es = calloc(1, sizeof(*es));
- }
- es->list = realloc(es->list, ++es->count * sizeof(*es->list));
- es->list[es->count-1] = e;
- return es;
-}
-
-static inline void free_decl_enums(decl_enums *es) {
- if (es->list) {
- size_t j;
-
- for (j = 0; j < es->count; ++j) {
- free_decl_enum(es->list[j]);
- }
- }
- free(es->list);
- free(es);
-}
-
-typedef struct let_calloc {
- num_exp *nmemb;
- num_exp *size;
-} let_calloc;
-
-static inline let_calloc *init_let_calloc(num_exp *nmemb, num_exp *size) {
- let_calloc *alloc = calloc(1, sizeof(*alloc));
- alloc->nmemb = nmemb;
- alloc->size = size;
- return alloc;
-}
-
-static inline void free_let_calloc(let_calloc *alloc) {
- free_num_exp(alloc->nmemb);
- free_num_exp(alloc->size);
- free(alloc);
-}
-
-typedef struct let_callback {
- struct let_func *func;
- struct set_values *args;
- decl *decl;
-} let_callback;
-
-static inline void free_let_func(struct let_func *func);
-static inline void free_set_values(struct set_values *vals);
-static inline let_callback *init_let_callback(struct let_func *func, struct set_values *args) {
- let_callback *cb = calloc(1, sizeof(*cb));
-
- cb->func = func;
- cb->args = args;
- return cb;
-}
-
-static inline void free_let_callback(let_callback *cb) {
- free_let_func(cb->func);
- free_set_values(cb->args);
- free(cb);
-}
-
-typedef impl_val *(*let_func_handler)(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
-
-typedef struct let_func {
- token_t type;
- char *name;
- impl_var *var;
- let_func_handler handler;
-} let_func;
-
-static inline let_func *init_let_func(token_t type, const char *name, impl_var *var) {
- let_func *func = calloc(1, sizeof(*func));
- func->type = type;
- func->name = strdup(name);
- func->var = var;
- return func;
-}
-
-static inline void free_let_func(let_func *func) {
- free_impl_var(func->var);
- free(func->name);
- free(func);
-}
-
-enum let_val_kind {
- PSI_LET_NULL,
- PSI_LET_NUMEXP,
- PSI_LET_CALLOC,
- PSI_LET_CALLBACK,
- PSI_LET_FUNC,
- PSI_LET_TMP,
-};
-#define PSI_LET_REFERENCE 0x1;
-typedef struct let_val {
- enum let_val_kind kind;
- union {
- num_exp *num;
- let_calloc *alloc;
- let_callback *callback;
- let_func *func;
- decl_var *var;
- } data;
- union {
- struct {
- unsigned is_reference:1;
- } one;
- unsigned all;
- } flags;
-} let_val;
-
-static inline let_val *init_let_val(enum let_val_kind kind, void *data) {
- let_val *let = calloc(1, sizeof(*let));
- switch (let->kind = kind) {
- case PSI_LET_NULL:
- break;
- case PSI_LET_NUMEXP:
- let->data.num = data;
- break;
- case PSI_LET_CALLOC:
- let->data.alloc = data;
- break;
- case PSI_LET_CALLBACK:
- let->data.callback = data;
- break;
- case PSI_LET_FUNC:
- let->data.func = data;
- break;
- case PSI_LET_TMP:
- let->data.var = data;
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- return let;
-}
-
-static inline void free_let_val(let_val *let) {
- switch (let->kind) {
- case PSI_LET_NULL:
- break;
- case PSI_LET_NUMEXP:
- free_num_exp(let->data.num);
- break;
- case PSI_LET_CALLOC:
- free_let_calloc(let->data.alloc);
- break;
- case PSI_LET_CALLBACK:
- free_let_callback(let->data.callback);
- break;
- case PSI_LET_FUNC:
- free_let_func(let->data.func);
- break;
- case PSI_LET_TMP:
- free_decl_var(let->data.var);
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- free(let);
-}
-
-typedef struct let_stmt {
- decl_var *var;
- let_val *val;
-} let_stmt;
-
-static inline let_stmt *init_let_stmt(decl_var *var, let_val *val) {
- let_stmt *let = calloc(1, sizeof(*let));
- let->var = var;
- let->val = val;
- return let;
-}
-
-static inline void free_let_stmt(let_stmt *stmt) {
- if (stmt->val) {
- if (stmt->val->kind == PSI_LET_TMP && stmt->var->arg) {
- free_decl_arg(stmt->var->arg);
- }
- free_let_val(stmt->val);
- }
- free_decl_var(stmt->var);
- free(stmt);
-}
-
-struct set_value;
-
-typedef struct set_func {
- PSI_Token *token;
- token_t type;
- char *name;
- void (*handler)(zval *, struct set_value *set, impl_val *ret_val);
-} set_func;
-
-static inline set_func *init_set_func(token_t type, const char *name) {
- set_func *func = calloc(1, sizeof(*func));
- func->type = type;
- func->name = strdup(name);
- return func;
-}
-
-static inline void free_set_func(set_func *func) {
- if (func->token) {
- free(func->token);
- }
- free(func->name);
- free(func);
-}
-
-typedef struct set_value {
- set_func *func;
- decl_vars *vars;
- num_exp *num;
- struct {
- struct set_value *set;
- impl_val *val;
- } outer;
- struct set_values *inner;
-} set_value;
-
-typedef struct set_values {
- set_value **vals;
- size_t count;
-} set_values;
-
-
-static inline set_value *init_set_value(set_func *func, decl_vars *vars) {
- set_value *val = calloc(1, sizeof(*val));
- val->func = func;
- val->vars = vars;
- return val;
-}
-
-static inline set_values *add_set_value(set_values *vals, set_value *val);
-static inline set_value *add_inner_set_value(set_value *val, set_value *inner) {
- val->inner = add_set_value(val->inner, inner);
- inner->outer.set = val;
- return val;
-}
-
-static inline void free_set_value(set_value *val) {
- if (val->func) {
- free_set_func(val->func);
- }
- if (val->vars) {
- free_decl_vars(val->vars);
- }
- if (val->inner && (!val->outer.set || val->outer.set->inner != val->inner)) {
- free_set_values(val->inner);
- }
- if (val->num) {
- free_num_exp(val->num);
- }
- free(val);
-}
-
-static inline set_values *init_set_values(set_value *val) {
- set_values *vals = calloc(1, sizeof(*vals));
- if (val) {
- vals->count = 1;
- vals->vals = calloc(1, sizeof(val));
- vals->vals[0] = val;
- }
- return vals;
-}
-
-static inline set_values *add_set_value(set_values *vals, set_value *val) {
- if (!vals) {
- vals = calloc(1, sizeof(*vals));
- }
- vals->vals = realloc(vals->vals, ++vals->count * sizeof(val));
- vals->vals[vals->count-1] = val;
- return vals;
-}
-
-static inline void free_set_values(set_values *vals) {
- if (vals->vals) {
- size_t i;
-
- for (i = 0; i < vals->count; ++i) {
- free_set_value(vals->vals[i]);
- }
- free(vals->vals);
- }
- free(vals);
-}
-
-typedef struct set_stmt {
- impl_var *var;
- set_value *val;
- impl_arg *arg;
-} set_stmt;
-
-static inline set_stmt *init_set_stmt(impl_var *var, set_value *val) {
- set_stmt *set = calloc(1, sizeof(*set));
- set->var = var;
- set->val = val;
- return set;
-}
-
-static inline void free_set_stmt(set_stmt *set) {
- free_impl_var(set->var);
- free_set_value(set->val);
- free(set);
-}
-
-typedef struct return_stmt {
- PSI_Token *token;
- set_value *set;
- decl_arg *decl;
-} return_stmt;
-
-static inline return_stmt *init_return_stmt(set_value *val) {
- return_stmt *ret = calloc(1, sizeof(*ret));
- ret->set = val;
- return ret;
-}
-
-static inline void free_return_stmt(return_stmt *ret) {
- if (ret->token) {
- free(ret->token);
- }
- free_set_value(ret->set);
- free(ret);
-}
-
-typedef struct free_call {
- PSI_Token *token;
- char *func;
- decl_vars *vars;
- decl *decl;
-} free_call;
-
-static inline free_call *init_free_call(const char *func, decl_vars *vars) {
- free_call *f = calloc(1, sizeof(*f));
- f->func = strdup(func);
- f->vars = vars;
- return f;
-}
-
-static inline void free_free_call(free_call *f) {
- if (f->token) {
- free(f->token);
- }
- free(f->func);
- free_decl_vars(f->vars);
- free(f);
-}
-
-typedef struct free_calls {
- free_call **list;
- size_t count;
-} free_calls;
-
-static inline free_calls *init_free_calls(free_call *f) {
- free_calls *fcs = calloc(1, sizeof(*fcs));
- if (f) {
- fcs->count = 1;
- fcs->list = calloc(1, sizeof(*fcs->list));
- fcs->list[0] = f;
- }
- return fcs;
-}
-
-static inline void free_free_calls(free_calls *fcs) {
- size_t i;
-
- for (i = 0; i < fcs->count; ++i) {
- free_free_call(fcs->list[i]);
- }
- free(fcs->list);
- free(fcs);
-}
-
-static inline free_calls *add_free_call(free_calls *fcs, free_call *f) {
- fcs->list = realloc(fcs->list, ++fcs->count * sizeof(*fcs->list));
- fcs->list[fcs->count-1] = f;
- return fcs;
-}
-
-typedef struct free_stmt {
- free_calls *calls;
-} free_stmt;
-
-static inline free_stmt *init_free_stmt(free_calls *calls) {
- free_stmt *f = calloc(1, sizeof(*f));
- f->calls = calls;
- return f;
-}
-
-static inline void free_free_stmt(free_stmt *f) {
- free_free_calls(f->calls);
- free(f);
-}
-
-typedef struct impl_stmt {
- token_t type;
- union {
- let_stmt *let;
- set_stmt *set;
- return_stmt *ret;
- free_stmt *fre;
- void *ptr;
- } s;
-} impl_stmt;
-
-static inline impl_stmt *init_impl_stmt(token_t type, void *ptr) {
- impl_stmt *stmt = calloc(1, sizeof(*stmt));
- stmt->type = type;
- stmt->s.ptr = ptr;
- return stmt;
-}
-
-static inline void free_impl_stmt(impl_stmt *stmt) {
- switch (stmt->type) {
- case PSI_T_LET:
- free_let_stmt(stmt->s.let);
- break;
- case PSI_T_SET:
- free_set_stmt(stmt->s.set);
- break;
- case PSI_T_RETURN:
- free_return_stmt(stmt->s.ret);
- break;
- case PSI_T_FREE:
- free_free_stmt(stmt->s.fre);
- break;
- }
- free(stmt);
-}
-
-typedef struct impl_stmts {
- struct {
- return_stmt **list;
- size_t count;
- } ret;
- struct {
- let_stmt **list;
- size_t count;
- } let;
- struct {
- set_stmt **list;
- size_t count;
- } set;
- struct {
- free_stmt **list;
- size_t count;
- } fre;
-} impl_stmts;
-
-static inline void *add_impl_stmt_ex(void *list, size_t count, void *stmt) {
- list = realloc(list, count * sizeof(list));
- ((void **)list)[count-1] = stmt;
- return list;
-}
-
-static inline impl_stmts *add_impl_stmt(impl_stmts *stmts, impl_stmt *stmt) {
- switch (stmt->type) {
- case PSI_T_RETURN:
- stmts->ret.list = add_impl_stmt_ex(stmts->ret.list, ++stmts->ret.count, stmt->s.ret);
- break;
- case PSI_T_LET:
- stmts->let.list = add_impl_stmt_ex(stmts->let.list, ++stmts->let.count, stmt->s.let);
- break;
- case PSI_T_SET:
- stmts->set.list = add_impl_stmt_ex(stmts->set.list, ++stmts->set.count, stmt->s.set);
- break;
- case PSI_T_FREE:
- stmts->fre.list = add_impl_stmt_ex(stmts->fre.list, ++stmts->fre.count, stmt->s.fre);
- break;
- }
- free(stmt);
- return stmts;
-}
-
-static inline impl_stmts *init_impl_stmts(impl_stmt *stmt) {
- impl_stmts *stmts = calloc(1, sizeof(*stmts));
- return add_impl_stmt(stmts, stmt);
-}
-
-static inline void free_impl_stmts(impl_stmts *stmts) {
- size_t i;
-
- for (i = 0; i < stmts->let.count; ++i) {
- free_let_stmt(stmts->let.list[i]);
- }
- free(stmts->let.list);
- for (i = 0; i < stmts->ret.count; ++i) {
- free_return_stmt(stmts->ret.list[i]);
- }
- free(stmts->ret.list);
- for (i = 0; i < stmts->set.count; ++i) {
- free_set_stmt(stmts->set.list[i]);
- }
- free(stmts->set.list);
- for (i = 0; i < stmts->fre.count; ++i) {
- free_free_stmt(stmts->fre.list[i]);
- }
- free(stmts->fre.list);
- free(stmts);
-}
-
-typedef struct impl {
- impl_func *func;
- impl_stmts *stmts;
- decl *decl;
-} impl;
-
-static inline impl *init_impl(impl_func *func, impl_stmts *stmts) {
- impl *i = calloc(1, sizeof(*i));
- i->func = func;
- i->stmts = stmts;
- return i;
-}
-
-static inline void free_impl(impl *impl) {
- free_impl_func(impl->func);
- free_impl_stmts(impl->stmts);
- free(impl);
-}
-
-typedef struct impls {
- size_t count;
- impl **list;
-} impls;
-
-static inline impls *add_impl(impls *impls, impl *impl) {
- if (!impls) {
- impls = calloc(1, sizeof(*impls));
- }
- impls->list = realloc(impls->list, ++impls->count * sizeof(*impls->list));
- impls->list[impls->count-1] = impl;
- return impls;
-}
-
-static void free_impls(impls *impls) {
- size_t i;
-
- for (i = 0; i < impls->count; ++i) {
- free_impl(impls->list[i]);
- }
- free(impls->list);
- free(impls);
-}
-
-typedef struct decl_file {
- char *ln;
- char *fn;
-} decl_file;
-
-static inline void free_decl_file(decl_file *file) {
- if (file->ln) {
- free(file->ln);
- }
- if (file->fn) {
- free(file->fn);
- }
- memset(file, 0, sizeof(*file));
-}
-
-typedef struct decl_libs {
- void **dl;
- size_t count;
-} decl_libs;
-
-static inline void free_decl_libs(decl_libs *libs) {
- if (libs->dl) {
- size_t i;
- for (i = 0; i < libs->count; ++i) {
- if (libs->dl[i]) {
- dlclose(libs->dl[i]);
- }
- }
- free(libs->dl);
- }
- memset(libs, 0, sizeof(*libs));
-}
-
-static inline void add_decl_lib(decl_libs *libs, void *dlopened) {
- libs->dl = realloc(libs->dl, ++libs->count * sizeof(*libs->dl));
- libs->dl[libs->count-1] = dlopened;
-}
-
-static inline impl_val *deref_impl_val(impl_val *ret_val, decl_var *var) {
- unsigned i;
-
- ZEND_ASSERT(var->arg->var != var);
-#if 0
- fprintf(stderr, "deref: %s pl=%u:%u as=%u:%u %p\n",
- var->name, var->pointer_level, var->arg->var->pointer_level,
- var->array_size, var->arg->var->array_size, ret_val);
-#endif
- for (i = 0; i < var->pointer_level; ++i) {
-#if 0
- fprintf(stderr, "-- %p %p %p\n", ret_val, *(void**)ret_val, ret_val->ptr);
-#endif
- ret_val = *(void **) ret_val;
- }
- return ret_val;
-}
-
-static inline impl_val *enref_impl_val(void *ptr, decl_var *var) {
- impl_val *val, *val_ptr;
- unsigned i;
-
- ZEND_ASSERT(var->arg->var == var);
-#if 0
- fprintf(stderr, "enref: %s pl=%u:%u as=%u:%u\n",
- var->name, var->pointer_level, var->arg->var->pointer_level,
- var->array_size, var->arg->var->array_size);
-#endif
- if (!var->pointer_level ){//&& real_decl_type(var->arg->type)->type != PSI_T_STRUCT) {
- return ptr;
- }
-
- val = val_ptr = calloc(var->pointer_level + 1, sizeof(void *));
- for (i = !var->arg->var->array_size; i < var->pointer_level; ++i) {
-#if 0
- fprintf(stderr, "++\n");
-#endif
- val_ptr->ptr = (void **) val_ptr + 1;
- val_ptr = val_ptr->ptr;
- }
- val_ptr->ptr = ptr;
- return val;
-}
-
-static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_ptr, impl_val **to_free) {
- void *ptr = (char *) struct_ptr + set_arg->layout->pos;
-#if 0
- fprintf(stderr, "struct member %s: %p\n", set_arg->var->name, ptr);
-#endif
- return ptr;
-}
-
-
-#define PSI_ERROR 16
-#define PSI_WARNING 32
-typedef void (*psi_error_cb)(void *context, PSI_Token *token, int type, const char *msg, ...);
-
-#define PSI_DATA(D) ((PSI_Data *) (D))
-#define PSI_DATA_MEMBERS \
- constants *consts; \
- decl_typedefs *defs; \
- decl_structs *structs; \
- decl_unions *unions; \
- decl_enums *enums; \
- decls *decls; \
- impls *impls; \
- union { \
- decl_file file; \
- decl_libs libs; \
- } psi; \
- psi_error_cb error; \
- unsigned errors; \
- unsigned flags
-typedef struct PSI_Data {
- PSI_DATA_MEMBERS;
-} PSI_Data;
-
-static inline PSI_Data *PSI_DataExchange(PSI_Data *dest, PSI_Data *src) {
- if (!dest) {
- dest = malloc(sizeof(*dest));
- }
- memcpy(dest, src, sizeof(*dest));
- memset(src, 0, sizeof(*src));
- return dest;
-}
-
-static inline void PSI_DataDtor(PSI_Data *data) {
- if (data->consts) {
- free_constants(data->consts);
- }
- if (data->defs) {
- free_decl_typedefs(data->defs);
- }
- if (data->structs) {
- free_decl_structs(data->structs);
- }
- if (data->unions) {
- free_decl_unions(data->unions);
- }
- if (data->enums) {
- free_decl_enums(data->enums);
- }
- if (data->decls) {
- free_decls(data->decls);
- }
- if (data->impls) {
- free_impls(data->impls);
- }
- free_decl_file(&data->psi.file);
-}
-
-typedef struct PSI_Parser {
+struct psi_parser {
PSI_DATA_MEMBERS;
FILE *fp;
token_t num;
void *proc;
unsigned line, col;
char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE];
-} PSI_Parser;
-
-static inline size_t PSI_TokenAllocSize(size_t token_len, size_t fname_len) {
- return sizeof(PSI_Token) + token_len + fname_len + 2;
-}
-
-static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) {
- PSI_Token *T;
- size_t token_len, fname_len;
- token_t token_typ;
-
- if (P->cur < P->tok) {
- return NULL;
- }
-
- token_typ = P->num;
- token_len = P->cur - P->tok;
- fname_len = strlen(P->psi.file.fn);
-
- T = calloc(1, PSI_TokenAllocSize(token_len, fname_len));
- T->type = token_typ;
- T->size = token_len;
- T->text = &T->buf[0];
- T->file = &T->buf[token_len + 1];
- T->line = P->line;
- T->col = P->col;
-
- memcpy(T->text, P->tok, token_len);
- memcpy(T->file, P->psi.file.fn, fname_len);
-
- return T;
-}
-
-static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) {
- size_t strct_len = PSI_TokenAllocSize(src->size, strlen(src->file));
- PSI_Token *ptr = malloc(strct_len);
-
- memcpy(ptr, src, strct_len);
-
- ptr->text = &ptr->buf[0];
- ptr->file = &ptr->buf[ptr->size + 1];
-
- return ptr;
-}
-
-static inline PSI_Token *PSI_TokenCat(unsigned argc, ...) {
- va_list argv;
- unsigned i;
- PSI_Token *T = NULL;
-
- va_start(argv, argc);
- for (i = 0; i < argc; ++i) {
- PSI_Token *arg = va_arg(argv, PSI_Token *);
-
- if (T) {
- size_t token_len = T->size, fname_len = strlen(T->file);
-
- T = realloc(T, PSI_TokenAllocSize(T->size += arg->size + 1, fname_len));
- T->text = &T->buf[0];
- T->file = &T->buf[T->size + 1];
- T->buf[token_len] = ' ';
- memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
- memcpy(&T->buf[token_len + 1], arg->text, arg->size + 1);
- } else {
- T = PSI_TokenCopy(arg);
- T->type = PSI_T_NAME;
- }
- }
- va_end(argv);
-
- return T;
-}
-
-static inline PSI_Token *PSI_TokenAppend(PSI_Token *T, unsigned argc, ...) {
- va_list argv;
- unsigned i;
-
- va_start(argv, argc);
- for (i = 0; i < argc; ++i) {
- char *str = va_arg(argv, char *);
- size_t str_len = strlen(str), token_len = T->size, fname_len = strlen(T->file);
-
- T = realloc(T, PSI_TokenAllocSize(T->size += str_len + 1, fname_len));
- T->text = &T->buf[0];
- T->file = &T->buf[T->size + 1];
- T->buf[token_len] = ' ';
- memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
- memcpy(&T->buf[token_len + 1], str, str_len + 1);
- }
- va_end(argv);
-
- return T;
-}
-
-char *php_strtr(char *str, size_t len, char *str_from, char *str_to, size_t trlen);
-static inline PSI_Token *PSI_TokenTranslit(PSI_Token *T, char *from, char *to) {
- php_strtr(T->text, T->size, from, to, MIN(strlen(from), strlen(to)));
- return T;
-}
-
-static inline uint64_t psi_hash(char *digest_buf, ...)
-{
- uint64_t hash = 5381;
- uint8_t c;
- const uint8_t *ptr;
- va_list argv;
-
- va_start(argv, digest_buf);
- while ((ptr = va_arg(argv, const uint8_t *))) {
- while ((c = *ptr++)) {
- hash = ((hash << 5) + hash) + c;
- }
- }
- va_end(argv);
-
- if (digest_buf) {
- sprintf(digest_buf, "%" PRIx64, hash);
- }
-
- return hash;
-}
-
-static inline uint64_t PSI_TokenHash(PSI_Token *t, char *digest_buf) {
- char loc_buf[48];
-
- sprintf(loc_buf, "%u%u", t->line, t->col);
- return psi_hash(digest_buf, t->file, loc_buf, NULL);
-}
+};
#define PSI_PARSER_DEBUG 0x1
#define PSI_PARSER_SILENT 0x2
-PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags);
-void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...);
-size_t PSI_ParserFill(PSI_Parser *P, size_t n);
-token_t PSI_ParserScan(PSI_Parser *P);
-void PSI_ParserParse(PSI_Parser *P, PSI_Token *src);
-void PSI_ParserDtor(PSI_Parser *P);
-void PSI_ParserFree(PSI_Parser **P);
+struct psi_parser *psi_parser_init(struct psi_parser *P, const char *filename, psi_error_cb error, unsigned flags);
+void psi_parser_syntax_error(struct psi_parser *P, const char *fn, size_t ln, const char *msg, ...);
+size_t psi_parser_fill(struct psi_parser *P, size_t n);
+token_t psi_parser_scan(struct psi_parser *P);
+void psi_parser_parse(struct psi_parser *P, struct psi_token *src);
+void psi_parser_dtor(struct psi_parser *P);
+void psi_parser_free(struct psi_parser **P);
#endif
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
+
#include <stddef.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
-#include "parser.h"
#include "parser_proc.h"
-void *PSI_ParserProcAlloc(void*(unsigned long));
-void PSI_ParserProcFree(void*, void(*)(void*));
-void PSI_ParserProc(void *, token_t, PSI_Token *, PSI_Parser *);
-void PSI_ParserProcTrace(FILE *, const char*);
+#include "parser.h"
+
+void *psi_parser_proc_Alloc(void*(unsigned long));
+void psi_parser_proc_Free(void*, void(*)(void*));
+void psi_parser_proc_(void *, token_t, struct psi_token *, struct psi_parser *);
+void psi_parser_proc_Trace(FILE *, const char*);
-PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags)
+struct psi_parser *psi_parser_init(struct psi_parser *P, const char *filename, psi_error_cb error, unsigned flags)
{
FILE *fp;
P->line = 1;
P->error = error;
P->flags = flags;
- P->proc = PSI_ParserProcAlloc(malloc);
+ P->proc = psi_parser_proc_Alloc(malloc);
if (flags & PSI_PARSER_DEBUG) {
- PSI_ParserProcTrace(stderr, "PSI> ");
+ psi_parser_proc_Trace(stderr, "PSI> ");
}
- PSI_ParserFill(P, 0);
+ psi_parser_fill(P, 0);
return P;
}
-size_t PSI_ParserFill(PSI_Parser *P, size_t n)
+size_t psi_parser_fill(struct psi_parser *P, size_t n)
{
if (P->flags & PSI_PARSER_DEBUG) {
fprintf(stderr, "PSI> Fill: n=%zu\n", n);
return P->lim - P->cur;
}
-void PSI_ParserParse(PSI_Parser *P, PSI_Token *T)
+void psi_parser_parse(struct psi_parser *P, struct psi_token *T)
{
if (T) {
- PSI_ParserProc(P->proc, T->type, T, P);
+ psi_parser_proc_(P->proc, T->type, T, P);
} else {
- PSI_ParserProc(P->proc, 0, NULL, P);
+ psi_parser_proc_(P->proc, 0, NULL, P);
}
}
-void PSI_ParserDtor(PSI_Parser *P)
+void psi_parser_dtor(struct psi_parser *P)
{
- PSI_ParserProcFree(P->proc, free);
+ psi_parser_proc_Free(P->proc, free);
if (P->fp) {
fclose(P->fp);
}
- PSI_DataDtor((PSI_Data *) P);
+ psi_data_dtor(PSI_DATA(P));
memset(P, 0, sizeof(*P));
}
-void PSI_ParserFree(PSI_Parser **P)
+void psi_parser_free(struct psi_parser **P)
{
if (*P) {
- PSI_ParserDtor(*P);
+ psi_parser_dtor(*P);
free(*P);
*P = NULL;
}
++P->line; \
goto label
-token_t PSI_ParserScan(PSI_Parser *P)
+token_t psi_parser_scan(struct psi_parser *P)
{
for (;;) {
ADDCOLS;
re2c:define:YYCURSOR = P->cur;
re2c:define:YYLIMIT = P->lim;
re2c:define:YYMARKER = P->mrk;
- re2c:define:YYFILL = "{ if (!PSI_ParserFill(P,@@)) RETURN(PSI_T_EOF); }";
+ re2c:define:YYFILL = "{ if (!psi_parser_fill(P,@@)) RETURN(PSI_T_EOF); }";
re2c:yyfill:parameter = 0;
B = [^a-zA-Z0-9_];
#define DEF(dn, dv)
#define LET(nt, rule)
#define PARSE(nt, rule) \
- static void COUNTED(nt) (PSI_Parser *P rule)
+ static void COUNTED(nt) (struct psi_parser *P rule)
#define PARSE_NAMED(nt, nt_name, rule) \
- static void COUNTED(nt) (PSI_Parser *P NAMED(nt, nt_name) rule)
+ static void COUNTED(nt) (struct psi_parser *P NAMED(nt, nt_name) rule)
#define PARSE_TYPED(nt, nt_name, rule) \
- static void COUNTED(nt) (PSI_Parser *P TYPED(nt, nt_name) rule)
+ static void COUNTED(nt) (struct psi_parser *P TYPED(nt, nt_name) rule)
#define TOKEN(t)
-#define NAMED(t, name) , PSI_Token *name
+#define NAMED(t, name) , struct psi_token *name
#define TYPED(t, name) , TOKEN_TYPE_NAME(t) name
#define TOKEN_TYPE_NAME(token) _##token##_type
#define TOKEN_TYPE(token, type) typedef type TOKEN_TYPE_NAME(token);
void psi_error(int, const char *, int, const char *, ...);
})
-DEF(%name, PSI_ParserProc)
+DEF(%name, psi_parser_proc_)
DEF(%token_prefix, PSI_T_)
-DEF(%token_type, {PSI_Token *})
+DEF(%token_type, {struct psi_token *})
DEF(%token_destructor, {free($$);})
DEF(%default_destructor, {(void)P;})
-DEF(%extra_argument, {PSI_Parser *P})
+DEF(%extra_argument, {struct psi_parser *P})
/* TOKEN is defined inside syntax_error */
DEF(%syntax_error, {
} else {
char digest[17];
- PSI_TokenHash(E, digest);
- n = PSI_TokenTranslit(PSI_TokenAppend(E, 1, digest), " ", "@");
+ psi_token_hash(E, digest);
+ n = psi_token_translit(psi_token_append(E, 1, digest), " ", "@");
}
}
} else {
char digest[17];
- PSI_TokenHash(U, digest);
- n = PSI_TokenTranslit(PSI_TokenAppend(U, 1, digest), " ", "@");
+ psi_token_hash(U, digest);
+ n = psi_token_translit(psi_token_append(U, 1, digest), " ", "@");
}
}
} else {
char digest[17];
- PSI_TokenHash(S, digest);
- n = PSI_TokenTranslit(PSI_TokenAppend(S, 1, digest), " ", "@");
+ psi_token_hash(S, digest);
+ n = psi_token_translit(psi_token_append(S, 1, digest), " ", "@");
}
}
TYPED(decl_struct_args_block, args)
TYPED(decl_var, var)) {
def = init_decl_arg(init_decl_type(PSI_T_STRUCT, N->text), var);
- def->type->token = PSI_TokenCopy(N);
+ def->type->token = psi_token_copy(N);
def->type->real.strct = init_decl_struct(N->text, args);
def->type->real.strct->token = N;
def->type->real.strct->align = as.pos;
TYPED(decl_struct_args_block, args)
TYPED(decl_var, var)) {
def = init_decl_arg(init_decl_type(PSI_T_UNION, N->text), var);
- def->type->token = PSI_TokenCopy(N);
+ def->type->token = psi_token_copy(N);
def->type->real.unn = init_decl_union(N->text, args);
def->type->real.unn->token = N;
def->type->real.unn->align = as.pos;
NAMED(NAME, ALIAS)) {
def = init_decl_arg(init_decl_type(PSI_T_ENUM, e->name), init_decl_var(ALIAS->text, 0, 0));
def->var->token = ALIAS;
- def->type->token = PSI_TokenCopy(e->token);
+ def->type->token = psi_token_copy(e->token);
def->type->real.enm = e;
}
TYPED(decl_func, func_)
TYPED(decl_typedef_body_fn_args, args)) {
def = init_decl_arg(init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var));
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
PARSE_TYPED(decl_typedef_body, def,
copy_decl_var(func_->var)
);
def->var->pointer_level = type_i;
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
PARSE_TYPED(decl_typedef_body, def,
copy_decl_var(func_->var)
);
def->var->pointer_level = type_i;
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
copy_decl_var(func_->var)
);
def->var->pointer_level = type_i;
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
NAMED(SHORT, S)
NAMED(decl_scalar_type_short, s)) {
if (s) {
- type_ = PSI_TokenCat(2, S, s);
+ type_ = psi_token_cat(2, S, s);
free(S);
free(s);
} else {
NAMED(LONG, L)
NAMED(decl_scalar_type_long, l)) {
if (l) {
- type_ = PSI_TokenCat(2, L, l);
+ type_ = psi_token_cat(2, L, l);
free(L);
free(l);
} else {
NAMED(LONG, L)
NAMED(decl_scalar_type_long_long, ll)) {
if (ll) {
- l = PSI_TokenCat(2, L, ll);
+ l = psi_token_cat(2, L, ll);
free(L);
free(ll);
} else {
PARSE_TYPED(decl_type, type_,
NAMED(UNSIGNED, U)
NAMED(decl_scalar_type, N)) {
- PSI_Token *T = PSI_TokenCat(2, U, N);
+ struct psi_token *T = psi_token_cat(2, U, N);
type_ = init_decl_type(T->type, T->text);
type_->token = T;
free(U);
PARSE_TYPED(decl_type, type_,
NAMED(SIGNED, S)
NAMED(decl_scalar_type, N)) {
- PSI_Token *T = PSI_TokenCat(2, S, N);
+ struct psi_token *T = psi_token_cat(2, S, N);
type_ = init_decl_type(T->type, T->text);
type_->token = T;
free(S);
PARSE_TYPED(num_exp, exp,
TYPED(decl_var, var)) {
exp = init_num_exp(PSI_T_NAME, var);
- exp->token = PSI_TokenCopy(var->token);
+ exp->token = psi_token_copy(var->token);
}
PARSE_TYPED(num_exp, exp,
TYPED(num_exp, exp_)
%include {
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
+
#include <stddef.h>
#include <assert.h>
#include <stdlib.h>
%include {
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
+
#include <stddef.h>
#include <assert.h>
#include <stdlib.h>
#include "parser.h"
}
%include { void psi_error(int, const char *, int, const char *, ...); }
-%name PSI_ParserProc
+%name psi_parser_proc_
%token_prefix PSI_T_
-%token_type {PSI_Token *}
+%token_type {struct psi_token *}
%token_destructor {free($$);}
%default_destructor {(void)P;}
-%extra_argument {PSI_Parser *P}
+%extra_argument {struct psi_parser *P}
%syntax_error { ++P->errors; if (TOKEN && TOKEN->type != PSI_T_EOF) { psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s'", TOKEN->text); } else { psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input"); } }
%nonassoc NAME.
%left PLUS MINUS.
free(E);
} else {
char digest[17];
- PSI_TokenHash(E, digest);
- n = PSI_TokenTranslit(PSI_TokenAppend(E, 1, digest), " ", "@");
+ psi_token_hash(E, digest);
+ n = psi_token_translit(psi_token_append(E, 1, digest), " ", "@");
}
}
decl_enum(e) ::= enum_name(N) LBRACE decl_enum_items(list) RBRACE. {
free(U);
} else {
char digest[17];
- PSI_TokenHash(U, digest);
- n = PSI_TokenTranslit(PSI_TokenAppend(U, 1, digest), " ", "@");
+ psi_token_hash(U, digest);
+ n = psi_token_translit(psi_token_append(U, 1, digest), " ", "@");
}
}
struct_name(n) ::= STRUCT(S) optional_name(N). {
free(S);
} else {
char digest[17];
- PSI_TokenHash(S, digest);
- n = PSI_TokenTranslit(PSI_TokenAppend(S, 1, digest), " ", "@");
+ psi_token_hash(S, digest);
+ n = psi_token_translit(psi_token_append(S, 1, digest), " ", "@");
}
}
decl_struct_args_block(args_) ::= LBRACE struct_args(args) RBRACE. {
}
decl_typedef_body_ex(def) ::= struct_name(N) align_and_size(as) decl_struct_args_block(args) decl_var(var). {
def = init_decl_arg(init_decl_type(PSI_T_STRUCT, N->text), var);
- def->type->token = PSI_TokenCopy(N);
+ def->type->token = psi_token_copy(N);
def->type->real.strct = init_decl_struct(N->text, args);
def->type->real.strct->token = N;
def->type->real.strct->align = as.pos;
}
decl_typedef_body_ex(def) ::= union_name(N) align_and_size(as) decl_struct_args_block(args) decl_var(var). {
def = init_decl_arg(init_decl_type(PSI_T_UNION, N->text), var);
- def->type->token = PSI_TokenCopy(N);
+ def->type->token = psi_token_copy(N);
def->type->real.unn = init_decl_union(N->text, args);
def->type->real.unn->token = N;
def->type->real.unn->align = as.pos;
decl_typedef_body_ex(def) ::= decl_enum(e) NAME(ALIAS). {
def = init_decl_arg(init_decl_type(PSI_T_ENUM, e->name), init_decl_var(ALIAS->text, 0, 0));
def->var->token = ALIAS;
- def->type->token = PSI_TokenCopy(e->token);
+ def->type->token = psi_token_copy(e->token);
def->type->real.enm = e;
}
decl_typedef_body(def) ::= decl_typedef_body_ex(def_). {
}
decl_typedef_body(def) ::= decl_func(func_) decl_typedef_body_fn_args(args). {
def = init_decl_arg(init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var));
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
decl_typedef_body(def) ::= decl_arg(arg). {
copy_decl_var(func_->var)
);
def->var->pointer_level = type_i;
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
decl_typedef_body(def) ::= CONST VOID(T) pointers(decl_i) LPAREN indirection(type_i) NAME(N) RPAREN decl_typedef_body_fn_args(args). {
copy_decl_var(func_->var)
);
def->var->pointer_level = type_i;
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
decl_abi(abi) ::= NAME(T). {
copy_decl_var(func_->var)
);
def->var->pointer_level = type_i;
- def->type->token = PSI_TokenCopy(func_->token);
+ def->type->token = psi_token_copy(func_->token);
def->type->real.func = init_decl(init_decl_abi("default"), func_, args);
}
decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). {
}
decl_scalar_type(type_) ::= SHORT(S) decl_scalar_type_short(s). {
if (s) {
- type_ = PSI_TokenCat(2, S, s);
+ type_ = psi_token_cat(2, S, s);
free(S);
free(s);
} else {
}
decl_scalar_type(type_) ::= LONG(L) decl_scalar_type_long(l). {
if (l) {
- type_ = PSI_TokenCat(2, L, l);
+ type_ = psi_token_cat(2, L, l);
free(L);
free(l);
} else {
}
decl_scalar_type_long(l) ::= LONG(L) decl_scalar_type_long_long(ll). {
if (ll) {
- l = PSI_TokenCat(2, L, ll);
+ l = psi_token_cat(2, L, ll);
free(L);
free(ll);
} else {
ll = I;
}
decl_type(type_) ::= UNSIGNED(U) decl_scalar_type(N). {
- PSI_Token *T = PSI_TokenCat(2, U, N);
+ struct psi_token *T = psi_token_cat(2, U, N);
type_ = init_decl_type(T->type, T->text);
type_->token = T;
free(U);
free(N);
}
decl_type(type_) ::= SIGNED(S) decl_scalar_type(N). {
- PSI_Token *T = PSI_TokenCat(2, S, N);
+ struct psi_token *T = psi_token_cat(2, S, N);
type_ = init_decl_type(T->type, T->text);
type_->token = T;
free(S);
}
num_exp(exp) ::= decl_var(var). {
exp = init_num_exp(PSI_T_NAME, var);
- exp->token = PSI_TokenCopy(var->token);
+ exp->token = psi_token_copy(var->token);
}
num_exp(exp) ::= num_exp(exp_) num_exp_op_token(operator_) num_exp(operand_). {
exp_->operator = operator_->type;
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/param.h>
+
+#include "parser_proc.h"
+#include "token.h"
+#include "parser.h"
+
+size_t psi_token_alloc_size(size_t token_len, size_t fname_len) {
+ return sizeof(struct psi_token) + token_len + fname_len + 2;
+}
+
+struct psi_token *psi_token_alloc(struct psi_parser *P) {
+ struct psi_token *T;
+ size_t token_len, fname_len;
+ token_t token_typ;
+
+ if (P->cur < P->tok) {
+ return NULL;
+ }
+
+ token_typ = P->num;
+ token_len = P->cur - P->tok;
+ fname_len = strlen(P->psi.file.fn);
+
+ T = calloc(1, psi_token_alloc_size(token_len, fname_len));
+ T->type = token_typ;
+ T->size = token_len;
+ T->text = &T->buf[0];
+ T->file = &T->buf[token_len + 1];
+ T->line = P->line;
+ T->col = P->col;
+
+ memcpy(T->text, P->tok, token_len);
+ memcpy(T->file, P->psi.file.fn, fname_len);
+
+ return T;
+}
+
+struct psi_token *psi_token_copy(struct psi_token *src) {
+ size_t strct_len = psi_token_alloc_size(src->size, strlen(src->file));
+ struct psi_token *ptr = malloc(strct_len);
+
+ memcpy(ptr, src, strct_len);
+
+ ptr->text = &ptr->buf[0];
+ ptr->file = &ptr->buf[ptr->size + 1];
+
+ return ptr;
+}
+
+struct psi_token *psi_token_cat(unsigned argc, ...) {
+ va_list argv;
+ unsigned i;
+ struct psi_token *T = NULL;
+
+ va_start(argv, argc);
+ for (i = 0; i < argc; ++i) {
+ struct psi_token *arg = va_arg(argv, struct psi_token *);
+
+ if (T) {
+ size_t token_len = T->size, fname_len = strlen(T->file);
+
+ T = realloc(T, psi_token_alloc_size(T->size += arg->size + 1, fname_len));
+ T->text = &T->buf[0];
+ T->file = &T->buf[T->size + 1];
+ T->buf[token_len] = ' ';
+ memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
+ memcpy(&T->buf[token_len + 1], arg->text, arg->size + 1);
+ } else {
+ T = psi_token_copy(arg);
+ T->type = PSI_T_NAME;
+ }
+ }
+ va_end(argv);
+
+ return T;
+}
+
+struct psi_token *psi_token_append(struct psi_token *T, unsigned argc, ...) {
+ va_list argv;
+ unsigned i;
+
+ va_start(argv, argc);
+ for (i = 0; i < argc; ++i) {
+ char *str = va_arg(argv, char *);
+ size_t str_len = strlen(str), token_len = T->size, fname_len = strlen(T->file);
+
+ T = realloc(T, psi_token_alloc_size(T->size += str_len + 1, fname_len));
+ T->text = &T->buf[0];
+ T->file = &T->buf[T->size + 1];
+ T->buf[token_len] = ' ';
+ memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
+ memcpy(&T->buf[token_len + 1], str, str_len + 1);
+ }
+ va_end(argv);
+
+ return T;
+}
+
+char *php_strtr(char *str, size_t len, char *str_from, char *str_to, size_t trlen);
+struct psi_token *psi_token_translit(struct psi_token *T, char *from, char *to) {
+ php_strtr(T->text, T->size, from, to, MIN(strlen(from), strlen(to)));
+ return T;
+}
+
+static inline uint64_t psi_hash(char *digest_buf, ...)
+{
+ uint64_t hash = 5381;
+ uint8_t c;
+ const uint8_t *ptr;
+ va_list argv;
+
+ va_start(argv, digest_buf);
+ while ((ptr = va_arg(argv, const uint8_t *))) {
+ while ((c = *ptr++)) {
+ hash = ((hash << 5) + hash) + c;
+ }
+ }
+ va_end(argv);
+
+ if (digest_buf) {
+ sprintf(digest_buf, "%" PRIx64, hash);
+ }
+
+ return hash;
+}
+
+uint64_t psi_token_hash(struct psi_token *t, char *digest_buf) {
+ char loc_buf[48];
+
+ sprintf(loc_buf, "%u%u", t->line, t->col);
+ return psi_hash(digest_buf, t->file, loc_buf, NULL);
+}
--- /dev/null
+#ifndef _PSI_TOKEN_H
+#define _PSI_TOKEN_H
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include "parser_proc.h"
+
+#define PSI_T_POINTER PSI_T_ASTERISK
+#define PSI_T_LONG_DOUBLE (PSI_T_DOUBLE << 16)
+
+typedef int token_t;
+
+static inline size_t psi_t_alignment(token_t t)
+{
+#define PSI_ALIGNOF(T) case PSI_T_## T: return ALIGNOF_## T ##_T;
+ switch (t) {
+ PSI_ALIGNOF(INT8);
+ PSI_ALIGNOF(UINT8);
+ PSI_ALIGNOF(INT16);
+ PSI_ALIGNOF(UINT16);
+ PSI_ALIGNOF(INT32);
+ PSI_ALIGNOF(UINT32);
+ PSI_ALIGNOF(INT64);
+ PSI_ALIGNOF(UINT64);
+ case PSI_T_FLOAT:
+ return ALIGNOF_FLOAT;
+ case PSI_T_DOUBLE:
+ return ALIGNOF_DOUBLE;
+ case PSI_T_POINTER:
+ case PSI_T_FUNCTION:
+ return ALIGNOF_VOID_P;
+ case PSI_T_ENUM:
+ return ALIGNOF_INT;
+ default:
+ assert(0);
+ }
+ return 0;
+}
+
+static inline size_t psi_t_size(token_t t)
+{
+#define PSI_SIZEOF(T) case PSI_T_## T : return SIZEOF_## T ##_T;
+ switch (t) {
+ PSI_SIZEOF(INT8);
+ PSI_SIZEOF(UINT8);
+ PSI_SIZEOF(INT16);
+ PSI_SIZEOF(UINT16);
+ PSI_SIZEOF(INT32);
+ PSI_SIZEOF(UINT32);
+ PSI_SIZEOF(INT64);
+ PSI_SIZEOF(UINT64);
+ case PSI_T_FLOAT:
+ return SIZEOF_FLOAT;
+ case PSI_T_DOUBLE:
+ return SIZEOF_DOUBLE;
+ case PSI_T_POINTER:
+ case PSI_T_FUNCTION:
+ return SIZEOF_VOID_P;
+ case PSI_T_ENUM:
+ return SIZEOF_INT;
+ default:
+ assert(0);
+ }
+ return 0;
+}
+
+struct psi_token {
+ token_t type;
+ unsigned size, line, col;
+ char *text, *file;
+ char buf[1];
+};
+
+struct psi_parser;
+
+struct psi_token *psi_token_alloc(struct psi_parser *P);
+size_t psi_token_alloc_size(size_t token_len, size_t fname_len);
+struct psi_token *psi_token_copy(struct psi_token *src);
+struct psi_token *psi_token_cat(unsigned argc, ...);
+struct psi_token *psi_token_append(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);
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_H
+#define _PSI_TYPES_H
+
+#include "Zend/zend_API.h"
+typedef struct zend_fcall {
+ zend_fcall_info fci;
+ zend_fcall_info_cache fcc;
+} zend_fcall;
+
+#include "token.h"
+
+#include "types/impl_val.h"
+#include "types/decl_type.h"
+#include "types/decl_var.h"
+#include "types/decl_struct_layout.h"
+#include "types/decl_arg.h"
+#include "types/decl_typedefs.h"
+#include "types/decl_vars.h"
+#include "types/decl_args.h"
+#include "types/decl_abi.h"
+#include "types/decl_callinfo.h"
+#include "types/decl.h"
+#include "types/decls.h"
+#include "types/decl_struct.h"
+#include "types/decl_structs.h"
+#include "types/decl_union.h"
+#include "types/decl_unions.h"
+#include "types/impl_type.h"
+#include "types/impl_var.h"
+#include "types/impl_def_val.h"
+#include "types/const_type.h"
+#include "types/constant.h"
+#include "types/constants.h"
+#include "types/impl_arg.h"
+#include "types/impl_args.h"
+#include "types/impl_func.h"
+#include "types/num_exp.h"
+#include "types/decl_enum_item.h"
+#include "types/decl_enum_items.h"
+#include "types/decl_enum.h"
+#include "types/decl_enums.h"
+#include "types/let_calloc.h"
+#include "types/let_callback.h"
+#include "types/let_func.h"
+#include "types/let_val.h"
+#include "types/let_stmt.h"
+#include "types/set_func.h"
+#include "types/set_value.h"
+#include "types/set_values.h"
+#include "types/set_stmt.h"
+#include "types/return_stmt.h"
+#include "types/free_call.h"
+#include "types/free_calls.h"
+#include "types/free_stmt.h"
+#include "types/impl_stmt.h"
+#include "types/impl_stmts.h"
+#include "types/impl.h"
+#include "types/impls.h"
+#include "types/decl_file.h"
+#include "types/decl_libs.h"
+
+
+static inline int weak_decl_type(decl_type *type) {
+ switch (type->type) {
+ case PSI_T_CHAR:
+ case PSI_T_SHORT:
+ case PSI_T_INT:
+ case PSI_T_LONG:
+ case PSI_T_NAME:
+ return type->type;
+ default:
+ return 0;
+ }
+}
+
+static inline decl_type *real_decl_type(decl_type *type) {
+ while (weak_decl_type(type)) {
+ type = type->real.def->type;
+ }
+ return type;
+}
+
+static inline impl_val *deref_impl_val(impl_val *ret_val, decl_var *var) {
+ unsigned i;
+
+ ZEND_ASSERT(var->arg->var != var);
+#if 0
+ fprintf(stderr, "deref: %s pl=%u:%u as=%u:%u %p\n",
+ var->name, var->pointer_level, var->arg->var->pointer_level,
+ var->array_size, var->arg->var->array_size, ret_val);
+#endif
+ for (i = 0; i < var->pointer_level; ++i) {
+#if 0
+ fprintf(stderr, "-- %p %p %p\n", ret_val, *(void**)ret_val, ret_val->ptr);
+#endif
+ ret_val = *(void **) ret_val;
+ }
+ return ret_val;
+}
+
+static inline impl_val *enref_impl_val(void *ptr, decl_var *var) {
+ impl_val *val, *val_ptr;
+ unsigned i;
+
+ ZEND_ASSERT(var->arg->var == var);
+#if 0
+ fprintf(stderr, "enref: %s pl=%u:%u as=%u:%u\n",
+ var->name, var->pointer_level, var->arg->var->pointer_level,
+ var->array_size, var->arg->var->array_size);
+#endif
+ if (!var->pointer_level ){//&& real_decl_type(var->arg->type)->type != PSI_T_STRUCT) {
+ return ptr;
+ }
+
+ val = val_ptr = calloc(var->pointer_level + 1, sizeof(void *));
+ for (i = !var->arg->var->array_size; i < var->pointer_level; ++i) {
+#if 0
+ fprintf(stderr, "++\n");
+#endif
+ val_ptr->ptr = (void **) val_ptr + 1;
+ val_ptr = val_ptr->ptr;
+ }
+ val_ptr->ptr = ptr;
+ return val;
+}
+
+static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_ptr, impl_val **to_free) {
+ void *ptr = (char *) struct_ptr + set_arg->layout->pos;
+#if 0
+ fprintf(stderr, "struct member %s: %p\n", set_arg->var->name, ptr);
+#endif
+ return ptr;
+}
+
+
+#define PSI_ERROR 16
+#define PSI_WARNING 32
+typedef void (*psi_error_cb)(void *context, struct psi_token *token, int type, const char *msg, ...);
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_CONST_TYPE_H
+#define _PSI_TYPES_CONST_TYPE_H
+
+typedef struct const_type {
+ token_t type;
+ char *name;
+} const_type;
+
+static inline const_type *init_const_type(token_t type, const char *name) {
+ const_type *ct = calloc(1, sizeof(*ct));
+ ct->type = type;
+ ct->name = strdup(name);
+ return ct;
+}
+
+static inline void free_const_type(const_type *type) {
+ free(type->name);
+ free(type);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_CONSTANT_H
+#define _PSI_TYPES_CONSTANT_H
+
+typedef struct constant {
+ const_type *type;
+ char *name;
+ impl_def_val *val;
+} constant;
+
+static inline constant *init_constant(const_type *type, const char *name, impl_def_val *val) {
+ constant *c = calloc(1, sizeof(*c));
+ c->type = type;
+ c->name = strdup(name);
+ c->val = val;
+ return c;
+}
+
+static inline void free_constant(constant *constant) {
+ free_const_type(constant->type);
+ free(constant->name);
+ free_impl_def_val(constant->val);
+ free(constant);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_CONSTANTS_H
+#define _PSI_TYPES_CONSTANTS_H
+
+typedef struct constants {
+ size_t count;
+ constant **list;
+} constants;
+
+static inline constants *add_constant(constants *constants, constant *constant) {
+ if (!constants) {
+ constants = calloc(1, sizeof(*constants));
+ }
+ constants->list = realloc(constants->list, ++constants->count * sizeof(*constants->list));
+ constants->list[constants->count-1] = constant;
+ return constants;
+}
+
+static inline void free_constants(constants *c) {
+ size_t i;
+
+ for (i = 0; i < c->count; ++i) {
+ free_constant(c->list[i]);
+ }
+ free(c->list);
+ free(c);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_H
+#define _PSI_TYPES_DECL_H
+
+typedef struct decl {
+ decl_abi *abi;
+ decl_arg *func;
+ decl_args *args;
+ struct impl *impl;
+ decl_callinfo call;
+} decl;
+
+static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) {
+ decl *d = calloc(1, sizeof(*d));
+ d->abi = abi;
+ d->func = func;
+ d->args = args;
+ return d;
+}
+
+static inline void free_decl(decl *d) {
+ free_decl_abi(d->abi);
+ free_decl_arg(d->func);
+ if (d->args) {
+ free_decl_args(d->args);
+ }
+ free(d);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_ABI_H
+#define _PSI_TYPES_DECL_ABI_H
+
+typedef struct decl_abi {
+ struct psi_token *token;
+ char *convention;
+} decl_abi;
+
+static inline decl_abi *init_decl_abi(const char *convention) {
+ decl_abi *abi = calloc(1, sizeof(*abi));
+ abi->convention = strdup(convention);
+ return abi;
+}
+
+static inline void free_decl_abi(decl_abi *abi) {
+ if (abi->token) {
+ free(abi->token);
+ }
+ free(abi->convention);
+ free(abi);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_ARG_H
+#define _PSI_TYPES_DECL_ARG_H
+
+typedef struct decl_arg {
+ struct psi_token *token;
+ decl_type *type;
+ decl_var *var;
+ decl_struct_layout *layout;
+ impl_val val;
+ void *ptr;
+ void *let;
+ void *mem;
+} decl_arg;
+
+static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
+ decl_arg *arg = calloc(1, sizeof(*arg));
+ arg->token = var->token;
+ arg->type = type;
+ arg->var = var;
+ var->arg = arg;
+ arg->ptr = &arg->val;
+ arg->let = arg->ptr;
+ return arg;
+}
+
+static inline void free_decl_arg(decl_arg *arg) {
+ if (arg->token && arg->token != arg->var->token) {
+ free(arg->token);
+ }
+ free_decl_type(arg->type);
+ free_decl_var(arg->var);
+ if (arg->layout) {
+ free_decl_struct_layout(arg->layout);
+ }
+ free(arg);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_ARGS_H
+#define _PSI_TYPES_DECL_ARGS_H
+
+typedef struct decl_args {
+ decl_arg **args;
+ size_t count;
+ unsigned varargs:1;
+} decl_args;
+
+static inline decl_args *init_decl_args(decl_arg *arg) {
+ decl_args *args = calloc(1, sizeof(*args));
+ if (arg) {
+ args->count = 1;
+ args->args = calloc(1, sizeof(*args->args));
+ args->args[0] = arg;
+ }
+ return args;
+}
+
+static inline decl_args *add_decl_arg(decl_args *args, decl_arg *arg) {
+ args->args = realloc(args->args, ++args->count * sizeof(*args->args));
+ args->args[args->count-1] = arg;
+ return args;
+}
+
+static inline void free_decl_args(decl_args *args) {
+ size_t i;
+
+ for (i = 0; i < args->count; ++i) {
+ free_decl_arg(args->args[i]);
+ }
+ free(args->args);
+ free(args);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_CALLINFO_H
+#define _PSI_TYPES_DECL_CALLINFO_H
+
+typedef struct decl_callinfo {
+ void *sym;
+ void *info;
+ size_t argc;
+ void **args;
+ void **rval;
+} decl_callinfo;
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_ENUM_H
+#define _PSI_TYPES_DECL_ENUM_H
+
+typedef struct decl_enum {
+ struct psi_token *token;
+ char *name;
+ decl_enum_items *items;
+} decl_enum;
+
+static inline decl_enum *init_decl_enum(const char *name, decl_enum_items *l) {
+ decl_enum *e = calloc(1, sizeof(*e));
+
+ e->name = strdup(name);
+ e->items = l;
+ return e;
+}
+
+static inline void free_decl_enum(decl_enum *e) {
+ if (e->token) {
+ free(e->token);
+ }
+ if (e->items) {
+ free_decl_enum_items(e->items);
+ }
+ free(e->name);
+ free(e);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_ENUM_ITEM_H
+#define _PSI_TYPES_DECL_ENUM_ITEM_H
+
+typedef struct decl_enum_item {
+ struct psi_token *token;
+ char *name;
+ num_exp *num;
+ num_exp inc;
+ struct decl_enum_item *prev;
+} decl_enum_item;
+
+static inline decl_enum_item *init_decl_enum_item(const char *name, num_exp *num) {
+ decl_enum_item *i = calloc(1, sizeof(*i));
+
+ i->name = strdup(name);
+ i->num = num;
+ return i;
+}
+
+static inline void free_decl_enum_item(decl_enum_item *i) {
+ if (i->token) {
+ free(i->token);
+ }
+ if (i->num && i->num != &i->inc) {
+ free_num_exp(i->num);
+ }
+ free(i->name);
+ free(i);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_ENUM_ITEMS_H
+#define _PSI_TYPES_DECL_ENUM_ITEMS_H
+
+typedef struct decl_enum_items {
+ decl_enum_item **list;
+ size_t count;
+} decl_enum_items;
+
+static inline decl_enum_items *init_decl_enum_items(decl_enum_item *i) {
+ decl_enum_items *l = calloc(1, sizeof(*l));
+
+ if (i) {
+ l->count = 1;
+ l->list = calloc(1, sizeof(*l->list));
+ l->list[0] = i;
+ }
+ return l;
+}
+
+static inline decl_enum_items *add_decl_enum_item(decl_enum_items *l, decl_enum_item *i) {
+ l->list = realloc(l->list, sizeof(*l->list) * (l->count + 1));
+ l->list[l->count] = i;
+ if (l->count) {
+ i->prev = l->list[l->count - 1];
+ }
+ ++l->count;
+ return l;
+}
+
+static inline void free_decl_enum_items(decl_enum_items *l) {
+ if (l->list) {
+ size_t j;
+
+ for (j = 0; j < l->count; ++j) {
+ free_decl_enum_item(l->list[j]);
+ }
+ free(l->list);
+ }
+ free(l);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_ENUMS_H
+#define _PSI_TYPES_DECL_ENUMS_H
+
+typedef struct decl_enums {
+ decl_enum **list;
+ size_t count;
+} decl_enums;
+
+static inline decl_enums* add_decl_enum(decl_enums *es, decl_enum *e) {
+ if (!es) {
+ es = calloc(1, sizeof(*es));
+ }
+ es->list = realloc(es->list, ++es->count * sizeof(*es->list));
+ es->list[es->count-1] = e;
+ return es;
+}
+
+static inline void free_decl_enums(decl_enums *es) {
+ if (es->list) {
+ size_t j;
+
+ for (j = 0; j < es->count; ++j) {
+ free_decl_enum(es->list[j]);
+ }
+ }
+ free(es->list);
+ free(es);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_FILE_H
+#define _PSI_TYPES_DECL_FILE_H
+
+typedef struct decl_file {
+ char *ln;
+ char *fn;
+} decl_file;
+
+static inline void free_decl_file(decl_file *file) {
+ if (file->ln) {
+ free(file->ln);
+ }
+ if (file->fn) {
+ free(file->fn);
+ }
+ memset(file, 0, sizeof(*file));
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_LIBS_H
+#define _PSI_TYPES_DECL_LIBS_H
+
+typedef struct decl_libs {
+ void **dl;
+ size_t count;
+} decl_libs;
+
+static inline void free_decl_libs(decl_libs *libs) {
+ if (libs->dl) {
+ size_t i;
+ for (i = 0; i < libs->count; ++i) {
+ if (libs->dl[i]) {
+ dlclose(libs->dl[i]);
+ }
+ }
+ free(libs->dl);
+ }
+ memset(libs, 0, sizeof(*libs));
+}
+
+static inline void add_decl_lib(decl_libs *libs, void *dlopened) {
+ libs->dl = realloc(libs->dl, ++libs->count * sizeof(*libs->dl));
+ libs->dl[libs->count-1] = dlopened;
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_STRUCT_H
+#define _PSI_TYPES_DECL_STRUCT_H
+
+typedef struct decl_struct {
+ struct psi_token *token;
+ char *name;
+ decl_args *args;
+ size_t size;
+ size_t align;
+ struct {
+ void *type;
+ void (*dtor)(void *type);
+ } engine;
+} decl_struct;
+
+static inline decl_struct *init_decl_struct(const char *name, decl_args *args) {
+ decl_struct *s = calloc(1, sizeof(*s));
+ s->name = strdup(name);
+ s->args = args;
+ return s;
+}
+
+static inline void free_decl_struct(decl_struct *s) {
+ if (s->token) {
+ free(s->token);
+ }
+ if (s->args) {
+ free_decl_args(s->args);
+ }
+ if (s->engine.type && s->engine.dtor) {
+ s->engine.dtor(s->engine.type);
+ }
+ free(s->name);
+ free(s);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_STRUCT_LAYOUT_H
+#define _PSI_TYPES_DECL_STRUCT_LAYOUT_H
+
+typedef struct decl_struct_layout {
+ size_t pos;
+ size_t len;
+} decl_struct_layout;
+
+static inline decl_struct_layout *init_decl_struct_layout(size_t pos, size_t len) {
+ decl_struct_layout *l = calloc(1, sizeof(*l));
+ ZEND_ASSERT(pos+len);
+ l->pos = pos;
+ l->len = len;
+ return l;
+}
+
+static inline void free_decl_struct_layout(decl_struct_layout *l) {
+ free(l);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_STRUCTS_H
+#define _PSI_TYPES_DECL_STRUCTS_H
+
+typedef struct decl_structs {
+ size_t count;
+ decl_struct **list;
+} decl_structs;
+
+static inline decl_structs *add_decl_struct(decl_structs *ss, decl_struct *s) {
+ if (!ss) {
+ ss = calloc(1, sizeof(*ss));
+ }
+ ss->list = realloc(ss->list, ++ss->count * sizeof(*ss->list));
+ ss->list[ss->count-1] = s;
+ return ss;
+}
+
+static inline void free_decl_structs(decl_structs *ss) {
+ size_t i;
+
+ for (i = 0; i < ss->count; ++i) {
+ free_decl_struct(ss->list[i]);
+ }
+ free(ss->list);
+ free(ss);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_TYPE_H
+#define _PSI_TYPES_DECL_TYPE_H
+
+#include "parser_proc.h"
+
+typedef struct decl_type {
+ struct psi_token *token;
+ char *name;
+ token_t type;
+ union {
+ struct decl_arg *def;
+ struct decl_struct *strct;
+ struct decl_union *unn;
+ struct decl_enum *enm;
+ struct decl *func;
+ } real;
+} decl_type;
+
+static inline decl_type *init_decl_type(token_t type, const char *name) {
+ decl_type *t = calloc(1, sizeof(*t));
+ t->type = type;
+ t->name = strdup(name);
+ return t;
+}
+
+static inline void free_decl(struct decl *decl);
+static inline void free_decl_type(decl_type *type) {
+ if (type->token) {
+ free(type->token);
+ }
+ if (type->type == PSI_T_FUNCTION) {
+ free_decl(type->real.func);
+ }
+ free(type->name);
+ free(type);
+}
+
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_TYPEDEFS_H
+#define _PSI_TYPES_DECL_TYPEDEFS_H
+
+typedef struct decl_typedefs {
+ size_t count;
+ decl_arg **list;
+} decl_typedefs;
+
+static inline decl_typedefs *add_decl_typedef(decl_typedefs *defs, decl_arg *def) {
+ if (!defs) {
+ defs = calloc(1, sizeof(*defs));
+ }
+ defs->list = realloc(defs->list, ++defs->count * sizeof(*defs->list));
+ defs->list[defs->count-1] = def;
+ return defs;
+}
+
+static inline void free_decl_typedefs(decl_typedefs *defs) {
+ size_t i;
+
+ for (i = 0; i < defs->count; ++i) {
+ free_decl_arg(defs->list[i]);
+ }
+ free(defs->list);
+ free(defs);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_UNION_H
+
+typedef struct decl_union {
+ struct psi_token *token;
+ char *name;
+ decl_args *args;
+ size_t size;
+ size_t align;
+} decl_union;
+
+static inline decl_union *init_decl_union(const char *name, decl_args *args) {
+ decl_union *u = calloc(1, sizeof(*u));
+ u->name = strdup(name);
+ u->args = args;
+ return u;
+}
+
+static inline void free_decl_union(decl_union *u) {
+ if (u->token) {
+ free(u->token);
+ }
+ if (u->args) {
+ free_decl_args(u->args);
+ }
+ free(u->name);
+ free(u);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_UNOINS_H
+#define _PSI_TYPES_DECL_UNOINS_H
+
+typedef struct decl_unions {
+ decl_union **list;
+ size_t count;
+} decl_unions;
+
+static inline decl_unions *add_decl_union(decl_unions *uu, decl_union *u) {
+ if (!uu) {
+ uu = calloc(1, sizeof(*uu));
+ }
+ uu->list = realloc(uu->list, ++uu->count * sizeof(*uu->list));
+ uu->list[uu->count-1] = u;
+ return uu;
+}
+
+static inline void free_decl_unions(decl_unions *uu) {
+ size_t i;
+
+ for (i = 0; i < uu->count; ++i) {
+ free_decl_union(uu->list[i]);
+ }
+ free(uu->list);
+ free(uu);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_VAR_H
+#define _PSI_TYPES_DECL_VAR_H
+
+typedef struct decl_var {
+ struct psi_token *token;
+ char *name;
+ unsigned pointer_level;
+ unsigned array_size;
+ struct decl_arg *arg;
+} decl_var;
+
+static inline decl_var *init_decl_var(const char *name, unsigned pl, unsigned as) {
+ decl_var *v = calloc(1, sizeof(*v));
+ v->name = (char *) strdup((const char *) name);
+ v->pointer_level = pl;
+ v->array_size = as;
+ return v;
+}
+
+static inline decl_var *copy_decl_var(decl_var *src) {
+ decl_var *dest = calloc(1, sizeof(*dest));
+
+ memcpy(dest, src, sizeof(*dest));
+ dest->name = strdup(dest->name);
+ if (dest->token) {
+ dest->token = psi_token_copy(dest->token);
+ }
+ return dest;
+}
+
+static inline void free_decl_var(decl_var *var) {
+ if (var->token) {
+ free(var->token);
+ }
+ free(var->name);
+ free(var);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECL_VARS_H
+#define _PSI_TYPES_DECL_VARS_H
+
+typedef struct decl_vars {
+ decl_var **vars;
+ size_t count;
+} decl_vars;
+
+static inline decl_vars *init_decl_vars(decl_var *var) {
+ decl_vars *vars = calloc(1, sizeof(*vars));
+ if (var) {
+ vars->count = 1;
+ vars->vars = calloc(1, sizeof(*vars->vars));
+ vars->vars[0] = var;
+ }
+ return vars;
+}
+
+static inline decl_vars *add_decl_var(decl_vars *vars, decl_var *var) {
+ vars->vars = realloc(vars->vars, ++vars->count * sizeof(*vars->vars));
+ vars->vars[vars->count-1] = var;
+ return vars;
+}
+
+static inline void free_decl_vars(decl_vars *vars) {
+ size_t i;
+
+ for (i = 0; i < vars->count; ++i) {
+ free_decl_var(vars->vars[i]);
+ }
+ free(vars->vars);
+ free(vars);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_DECLS_H
+#define _PSI_TYPES_DECLS_H
+
+typedef struct decls {
+ size_t count;
+ decl **list;
+} decls;
+
+static inline decls *add_decl(decls *decls, decl *decl) {
+ if (!decls) {
+ decls = calloc(1, sizeof(*decls));
+ }
+ decls->list = realloc(decls->list, ++decls->count * sizeof(*decls->list));
+ decls->list[decls->count-1] = decl;
+ return decls;
+}
+
+static inline void free_decls(decls *decls) {
+ size_t i;
+
+ for (i = 0; i < decls->count; ++i) {
+ free_decl(decls->list[i]);
+ }
+ free(decls->list);
+ free(decls);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_FREE_CALL_H
+#define _PSI_TYPES_FREE_CALL_H
+
+typedef struct free_call {
+ struct psi_token *token;
+ char *func;
+ decl_vars *vars;
+ decl *decl;
+} free_call;
+
+static inline free_call *init_free_call(const char *func, decl_vars *vars) {
+ free_call *f = calloc(1, sizeof(*f));
+ f->func = strdup(func);
+ f->vars = vars;
+ return f;
+}
+
+static inline void free_free_call(free_call *f) {
+ if (f->token) {
+ free(f->token);
+ }
+ free(f->func);
+ free_decl_vars(f->vars);
+ free(f);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_FREE_CALLS_H
+#define _PSI_TYPES_FREE_CALLS_H
+
+typedef struct free_calls {
+ free_call **list;
+ size_t count;
+} free_calls;
+
+static inline free_calls *init_free_calls(free_call *f) {
+ free_calls *fcs = calloc(1, sizeof(*fcs));
+ if (f) {
+ fcs->count = 1;
+ fcs->list = calloc(1, sizeof(*fcs->list));
+ fcs->list[0] = f;
+ }
+ return fcs;
+}
+
+static inline void free_free_calls(free_calls *fcs) {
+ size_t i;
+
+ for (i = 0; i < fcs->count; ++i) {
+ free_free_call(fcs->list[i]);
+ }
+ free(fcs->list);
+ free(fcs);
+}
+
+static inline free_calls *add_free_call(free_calls *fcs, free_call *f) {
+ fcs->list = realloc(fcs->list, ++fcs->count * sizeof(*fcs->list));
+ fcs->list[fcs->count-1] = f;
+ return fcs;
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_FREE_STMT_H
+#define _PSI_TYPES_FREE_STMT_H
+
+typedef struct free_stmt {
+ free_calls *calls;
+} free_stmt;
+
+static inline free_stmt *init_free_stmt(free_calls *calls) {
+ free_stmt *f = calloc(1, sizeof(*f));
+ f->calls = calls;
+ return f;
+}
+
+static inline void free_free_stmt(free_stmt *f) {
+ free_free_calls(f->calls);
+ free(f);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_H
+#define _PSI_TYPES_IMPL_H
+
+typedef struct impl {
+ impl_func *func;
+ impl_stmts *stmts;
+ decl *decl;
+} impl;
+
+static inline impl *init_impl(impl_func *func, impl_stmts *stmts) {
+ impl *i = calloc(1, sizeof(*i));
+ i->func = func;
+ i->stmts = stmts;
+ return i;
+}
+
+static inline void free_impl(impl *impl) {
+ free_impl_func(impl->func);
+ free_impl_stmts(impl->stmts);
+ free(impl);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_ARG_H
+#define _PSI_TYPES_IMPL_ARG_H
+
+typedef struct impl_arg {
+ impl_type *type;
+ impl_var *var;
+ impl_def_val *def;
+ impl_val val;
+ zval *_zv;
+} impl_arg;
+
+typedef struct impl_vararg {
+ impl_arg *name;
+ struct impl_args *args;
+ token_t *types;
+ impl_val *values;
+ void **free_list;
+} impl_vararg;
+
+static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) {
+ impl_arg *arg = calloc(1, sizeof(*arg));
+ arg->type = type;
+ arg->var = var;
+ arg->var->arg = arg;
+ arg->def = def;
+ return arg;
+}
+
+static inline void free_impl_arg(impl_arg *arg) {
+ free_impl_type(arg->type);
+ free_impl_var(arg->var);
+ if (arg->def) {
+ free_impl_def_val(arg->def);
+ }
+ free(arg);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_ARGS_H
+#define _PSI_TYPES_IMPL_ARGS_H
+
+typedef struct impl_args {
+ impl_arg **args;
+ size_t count;
+ impl_vararg vararg;
+} impl_args;
+
+static inline impl_args *init_impl_args(impl_arg *arg) {
+ impl_args *args = calloc(1, sizeof(*args));
+ if (arg) {
+ args->count = 1;
+ args->args = calloc(1, sizeof(*args->args));
+ args->args[0] = arg;
+ }
+ return args;
+}
+
+static inline impl_args *add_impl_arg(impl_args *args, impl_arg *arg) {
+ args->args = realloc(args->args, ++args->count * sizeof(*args->args));
+ args->args[args->count-1] = arg;
+ return args;
+}
+
+static inline void free_impl_args(impl_args *args) {
+ size_t i;
+
+ for (i = 0; i < args->count; ++i) {
+ free_impl_arg(args->args[i]);
+ }
+ if (args->vararg.name) {
+ free_impl_arg(args->vararg.name);
+ }
+ free(args->args);
+ free(args);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_DEF_VAL_H
+#define _PSI_TYPES_IMPL_DEF_VAL_H
+
+typedef struct impl_def_val {
+ token_t type;
+ char *text;
+} impl_def_val;
+
+static inline impl_def_val *init_impl_def_val(token_t t, const char *text) {
+ impl_def_val *def = calloc(1, sizeof(*def));
+ def->type = t;
+ def->text = strdup(text);
+ return def;
+}
+
+static inline void free_impl_def_val(impl_def_val *def) {
+ free(def->text);
+ free(def);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_FUNC_H
+#define _PSI_TYPES_IMPL_FUNC_H
+
+typedef struct impl_func {
+ struct psi_token *token;
+ char *name;
+ impl_args *args;
+ impl_type *return_type;
+ unsigned return_reference:1;
+} impl_func;
+
+static inline impl_func *init_impl_func(char *name, impl_args *args, impl_type *type, int ret_reference) {
+ impl_func *func = calloc(1, sizeof(*func));
+ func->name = strdup(name);
+ func->args = args ? args : init_impl_args(NULL);
+ func->return_type = type;
+ func->return_reference = ret_reference;
+ return func;
+}
+
+static inline void free_impl_func(impl_func *f) {
+ if (f->token) {
+ free(f->token);
+ }
+ free_impl_type(f->return_type);
+ free_impl_args(f->args);
+ free(f->name);
+ free(f);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_STMT_H
+#define _PSI_TYPES_IMPL_STMT_H
+
+typedef struct impl_stmt {
+ token_t type;
+ union {
+ let_stmt *let;
+ set_stmt *set;
+ return_stmt *ret;
+ free_stmt *fre;
+ void *ptr;
+ } s;
+} impl_stmt;
+
+static inline impl_stmt *init_impl_stmt(token_t type, void *ptr) {
+ impl_stmt *stmt = calloc(1, sizeof(*stmt));
+ stmt->type = type;
+ stmt->s.ptr = ptr;
+ return stmt;
+}
+
+static inline void free_impl_stmt(impl_stmt *stmt) {
+ switch (stmt->type) {
+ case PSI_T_LET:
+ free_let_stmt(stmt->s.let);
+ break;
+ case PSI_T_SET:
+ free_set_stmt(stmt->s.set);
+ break;
+ case PSI_T_RETURN:
+ free_return_stmt(stmt->s.ret);
+ break;
+ case PSI_T_FREE:
+ free_free_stmt(stmt->s.fre);
+ break;
+ }
+ free(stmt);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_STMTS_H
+#define _PSI_TYPES_IMPL_STMTS_H
+
+typedef struct impl_stmts {
+ struct {
+ return_stmt **list;
+ size_t count;
+ } ret;
+ struct {
+ let_stmt **list;
+ size_t count;
+ } let;
+ struct {
+ set_stmt **list;
+ size_t count;
+ } set;
+ struct {
+ free_stmt **list;
+ size_t count;
+ } fre;
+} impl_stmts;
+
+static inline void *add_impl_stmt_ex(void *list, size_t count, void *stmt) {
+ list = realloc(list, count * sizeof(list));
+ ((void **)list)[count-1] = stmt;
+ return list;
+}
+
+static inline impl_stmts *add_impl_stmt(impl_stmts *stmts, impl_stmt *stmt) {
+ switch (stmt->type) {
+ case PSI_T_RETURN:
+ stmts->ret.list = add_impl_stmt_ex(stmts->ret.list, ++stmts->ret.count, stmt->s.ret);
+ break;
+ case PSI_T_LET:
+ stmts->let.list = add_impl_stmt_ex(stmts->let.list, ++stmts->let.count, stmt->s.let);
+ break;
+ case PSI_T_SET:
+ stmts->set.list = add_impl_stmt_ex(stmts->set.list, ++stmts->set.count, stmt->s.set);
+ break;
+ case PSI_T_FREE:
+ stmts->fre.list = add_impl_stmt_ex(stmts->fre.list, ++stmts->fre.count, stmt->s.fre);
+ break;
+ }
+ free(stmt);
+ return stmts;
+}
+
+static inline impl_stmts *init_impl_stmts(impl_stmt *stmt) {
+ impl_stmts *stmts = calloc(1, sizeof(*stmts));
+ return add_impl_stmt(stmts, stmt);
+}
+
+static inline void free_impl_stmts(impl_stmts *stmts) {
+ size_t i;
+
+ for (i = 0; i < stmts->let.count; ++i) {
+ free_let_stmt(stmts->let.list[i]);
+ }
+ free(stmts->let.list);
+ for (i = 0; i < stmts->ret.count; ++i) {
+ free_return_stmt(stmts->ret.list[i]);
+ }
+ free(stmts->ret.list);
+ for (i = 0; i < stmts->set.count; ++i) {
+ free_set_stmt(stmts->set.list[i]);
+ }
+ free(stmts->set.list);
+ for (i = 0; i < stmts->fre.count; ++i) {
+ free_free_stmt(stmts->fre.list[i]);
+ }
+ free(stmts->fre.list);
+ free(stmts);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_TYPE_H
+#define _PSI_TYPES_IMPL_TYPE_H
+
+typedef struct impl_type {
+ char *name;
+ token_t type;
+} impl_type;
+
+static inline impl_type *init_impl_type(token_t type, const char *name) {
+ impl_type *t = calloc(1, sizeof(*t));
+
+ t->type = type;
+ t->name = strdup(name);
+ return t;
+}
+
+static inline void free_impl_type(impl_type *type) {
+ free(type->name);
+ free(type);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_VAL_H
+#define _PSI_TYPES_IMPL_VAL_H
+
+#include "Zend/zend_types.h"
+
+typedef union impl_val {
+ char cval;
+ int8_t i8;
+ uint8_t u8;
+ short sval;
+ int16_t i16;
+ uint16_t u16;
+ int ival;
+ int32_t i32;
+ uint32_t u32;
+ long lval;
+ int64_t i64;
+ uint64_t u64;
+ float fval;
+ double dval;
+#ifdef HAVE_LONG_DOUBLE
+ long double ldval;
+#endif
+ union {
+ zend_bool bval;
+ zend_long lval;
+ zend_string *str;
+ zend_fcall *cb;
+ } zend;
+ void *ptr;
+} impl_val;
+
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPL_VAR_H
+#define _PSI_TYPES_IMPL_VAR_H
+
+typedef struct impl_var {
+ struct psi_token *token;
+ char *name;
+ struct impl_arg *arg;
+ unsigned reference:1;
+} impl_var;
+
+static inline impl_var *init_impl_var(const char *name, int is_reference) {
+ impl_var *var = calloc(1, sizeof(*var));
+ var->name = strdup(name);
+ var->reference = is_reference;
+ return var;
+}
+
+static inline impl_var *copy_impl_var(impl_var *var) {
+ impl_var *cpy = malloc(sizeof(*cpy));
+
+ memcpy(cpy, var, sizeof(*cpy));
+ cpy->name = strdup(cpy->name);
+ if (cpy->token) {
+ cpy->token = psi_token_copy(cpy->token);
+ }
+ return cpy;
+}
+
+static inline void free_impl_var(impl_var *var) {
+ if (var->token) {
+ free(var->token);
+ }
+ free(var->name);
+ free(var);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_IMPLS_H
+#define _PSI_TYPES_IMPLS_H
+
+typedef struct impls {
+ size_t count;
+ impl **list;
+} impls;
+
+static inline impls *add_impl(impls *impls, impl *impl) {
+ if (!impls) {
+ impls = calloc(1, sizeof(*impls));
+ }
+ impls->list = realloc(impls->list, ++impls->count * sizeof(*impls->list));
+ impls->list[impls->count-1] = impl;
+ return impls;
+}
+
+static inline void free_impls(impls *impls) {
+ size_t i;
+
+ for (i = 0; i < impls->count; ++i) {
+ free_impl(impls->list[i]);
+ }
+ free(impls->list);
+ free(impls);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_LET_CALLBACK_H
+#define _PSI_TYPES_LET_CALLBACK_H
+
+typedef struct let_callback {
+ struct let_func *func;
+ struct set_values *args;
+ decl *decl;
+} let_callback;
+
+static inline void free_let_func(struct let_func *func);
+static inline void free_set_values(struct set_values *vals);
+static inline let_callback *init_let_callback(struct let_func *func, struct set_values *args) {
+ let_callback *cb = calloc(1, sizeof(*cb));
+
+ cb->func = func;
+ cb->args = args;
+ return cb;
+}
+
+static inline void free_let_callback(let_callback *cb) {
+ free_let_func(cb->func);
+ free_set_values(cb->args);
+ free(cb);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_LET_CALLOC_H
+#define _PSI_TYPES_LET_CALLOC_H
+
+typedef struct let_calloc {
+ num_exp *nmemb;
+ num_exp *size;
+} let_calloc;
+
+static inline let_calloc *init_let_calloc(num_exp *nmemb, num_exp *size) {
+ let_calloc *alloc = calloc(1, sizeof(*alloc));
+ alloc->nmemb = nmemb;
+ alloc->size = size;
+ return alloc;
+}
+
+static inline void free_let_calloc(let_calloc *alloc) {
+ free_num_exp(alloc->nmemb);
+ free_num_exp(alloc->size);
+ free(alloc);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_LET_FUNC_H
+#define _PSI_TYPES_LET_FUNC_H
+
+typedef impl_val *(*let_func_handler)(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+
+typedef struct let_func {
+ token_t type;
+ char *name;
+ impl_var *var;
+ let_func_handler handler;
+} let_func;
+
+static inline let_func *init_let_func(token_t type, const char *name, impl_var *var) {
+ let_func *func = calloc(1, sizeof(*func));
+ func->type = type;
+ func->name = strdup(name);
+ func->var = var;
+ return func;
+}
+
+static inline void free_let_func(let_func *func) {
+ free_impl_var(func->var);
+ free(func->name);
+ free(func);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_LET_STMT_H
+#define _PSI_TYPES_LET_STMT_H
+
+typedef struct let_stmt {
+ decl_var *var;
+ let_val *val;
+} let_stmt;
+
+static inline let_stmt *init_let_stmt(decl_var *var, let_val *val) {
+ let_stmt *let = calloc(1, sizeof(*let));
+ let->var = var;
+ let->val = val;
+ return let;
+}
+
+static inline void free_let_stmt(let_stmt *stmt) {
+ if (stmt->val) {
+ if (stmt->val->kind == PSI_LET_TMP && stmt->var->arg) {
+ free_decl_arg(stmt->var->arg);
+ }
+ free_let_val(stmt->val);
+ }
+ free_decl_var(stmt->var);
+ free(stmt);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_LET_VAL_H
+#define _PSI_TYPES_LET_VAL_H
+
+
+enum let_val_kind {
+ PSI_LET_NULL,
+ PSI_LET_NUMEXP,
+ PSI_LET_CALLOC,
+ PSI_LET_CALLBACK,
+ PSI_LET_FUNC,
+ PSI_LET_TMP,
+};
+#define PSI_LET_REFERENCE 0x1;
+typedef struct let_val {
+ enum let_val_kind kind;
+ union {
+ num_exp *num;
+ let_calloc *alloc;
+ let_callback *callback;
+ let_func *func;
+ decl_var *var;
+ } data;
+ union {
+ struct {
+ unsigned is_reference:1;
+ } one;
+ unsigned all;
+ } flags;
+} let_val;
+
+static inline let_val *init_let_val(enum let_val_kind kind, void *data) {
+ let_val *let = calloc(1, sizeof(*let));
+ switch (let->kind = kind) {
+ case PSI_LET_NULL:
+ break;
+ case PSI_LET_NUMEXP:
+ let->data.num = data;
+ break;
+ case PSI_LET_CALLOC:
+ let->data.alloc = data;
+ break;
+ case PSI_LET_CALLBACK:
+ let->data.callback = data;
+ break;
+ case PSI_LET_FUNC:
+ let->data.func = data;
+ break;
+ case PSI_LET_TMP:
+ let->data.var = data;
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+ return let;
+}
+
+static inline void free_let_val(let_val *let) {
+ switch (let->kind) {
+ case PSI_LET_NULL:
+ break;
+ case PSI_LET_NUMEXP:
+ free_num_exp(let->data.num);
+ break;
+ case PSI_LET_CALLOC:
+ free_let_calloc(let->data.alloc);
+ break;
+ case PSI_LET_CALLBACK:
+ free_let_callback(let->data.callback);
+ break;
+ case PSI_LET_FUNC:
+ free_let_func(let->data.func);
+ break;
+ case PSI_LET_TMP:
+ free_decl_var(let->data.var);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+ free(let);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_NUM_EXP
+#define _PSI_TYPES_NUM_EXP
+
+typedef struct num_exp {
+ struct psi_token *token;
+ token_t t;
+ union {
+ char *numb;
+ constant *cnst;
+ decl_var *dvar;
+ struct decl_enum_item *enm;
+ } u;
+ token_t operator;
+ int (*calculator)(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res);
+ struct num_exp *operand;
+} num_exp;
+
+static inline num_exp *init_num_exp(token_t t, void *num) {
+ num_exp *exp = calloc(1, sizeof(*exp));
+ switch (exp->t = t) {
+ case PSI_T_NUMBER:
+ case PSI_T_NSNAME:
+ exp->u.numb = strdup(num);
+ break;
+ case PSI_T_NAME:
+ exp->u.dvar = num;
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+ return exp;
+}
+
+static inline num_exp *copy_num_exp(num_exp *exp) {
+ decl_var *dvar;
+ num_exp *num = calloc(1, sizeof(*num));
+
+ memcpy(num, exp, sizeof(*num));
+
+ if (num->token) {
+ num->token = psi_token_copy(num->token);
+ }
+ if (num->operand) {
+ num->operand = copy_num_exp(num->operand);
+ }
+ switch (num->t) {
+ case PSI_T_NUMBER:
+ case PSI_T_NSNAME:
+ num->u.numb = strdup(num->u.numb);
+ break;
+ case PSI_T_NAME:
+ dvar = init_decl_var(num->u.dvar->name, num->u.dvar->pointer_level, num->u.dvar->array_size);
+ dvar->arg = num->u.dvar->arg;
+ if (num->u.dvar->token) {
+ dvar->token = psi_token_copy(num->u.dvar->token);
+ }
+ num->u.dvar = dvar;
+ break;
+ }
+ return num;
+}
+
+static inline void free_num_exp(num_exp *exp) {
+ if (exp->token) {
+ free(exp->token);
+ }
+ switch (exp->t) {
+ case PSI_T_NUMBER:
+ free(exp->u.numb);
+ break;
+ case PSI_T_NSNAME:
+ break;
+ case PSI_T_NAME:
+ free_decl_var(exp->u.dvar);
+ break;
+ case PSI_T_ENUM:
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+ if (exp->operand) {
+ free_num_exp(exp->operand);
+ }
+ free(exp);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_RETURN_STMT_H
+#define _PSI_TYPES_RETURN_STMT_H
+
+typedef struct return_stmt {
+ struct psi_token *token;
+ set_value *set;
+ decl_arg *decl;
+} return_stmt;
+
+static inline return_stmt *init_return_stmt(set_value *val) {
+ return_stmt *ret = calloc(1, sizeof(*ret));
+ ret->set = val;
+ return ret;
+}
+
+static inline void free_return_stmt(return_stmt *ret) {
+ if (ret->token) {
+ free(ret->token);
+ }
+ free_set_value(ret->set);
+ free(ret);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_SET_FUNC_H
+#define _PSI_TYPES_SET_FUNC_H
+
+struct set_value;
+
+typedef struct set_func {
+ struct psi_token *token;
+ token_t type;
+ char *name;
+ void (*handler)(zval *, struct set_value *set, impl_val *ret_val);
+} set_func;
+
+static inline set_func *init_set_func(token_t type, const char *name) {
+ set_func *func = calloc(1, sizeof(*func));
+ func->type = type;
+ func->name = strdup(name);
+ return func;
+}
+
+static inline void free_set_func(set_func *func) {
+ if (func->token) {
+ free(func->token);
+ }
+ free(func->name);
+ free(func);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_SET_STMT_H
+#define _PSI_TYPES_SET_STMT_H
+
+typedef struct set_stmt {
+ impl_var *var;
+ set_value *val;
+ impl_arg *arg;
+} set_stmt;
+
+static inline set_stmt *init_set_stmt(impl_var *var, set_value *val) {
+ set_stmt *set = calloc(1, sizeof(*set));
+ set->var = var;
+ set->val = val;
+ return set;
+}
+
+static inline void free_set_stmt(set_stmt *set) {
+ free_impl_var(set->var);
+ free_set_value(set->val);
+ free(set);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_SET_VALUE_H
+#define _PSI_TYPES_SET_VALUE_H
+
+typedef struct set_value {
+ set_func *func;
+ decl_vars *vars;
+ num_exp *num;
+ struct {
+ struct set_value *set;
+ impl_val *val;
+ } outer;
+ struct set_values *inner;
+} set_value;
+
+static inline set_value *init_set_value(set_func *func, decl_vars *vars) {
+ set_value *val = calloc(1, sizeof(*val));
+ val->func = func;
+ val->vars = vars;
+ return val;
+}
+
+static inline struct set_values *add_set_value(struct set_values *vals, struct set_value *val);
+static inline set_value *add_inner_set_value(set_value *val, set_value *inner) {
+ val->inner = add_set_value(val->inner, inner);
+ inner->outer.set = val;
+ return val;
+}
+
+static inline void free_set_value(set_value *val) {
+ if (val->func) {
+ free_set_func(val->func);
+ }
+ if (val->vars) {
+ free_decl_vars(val->vars);
+ }
+ if (val->inner && (!val->outer.set || val->outer.set->inner != val->inner)) {
+ free_set_values(val->inner);
+ }
+ if (val->num) {
+ free_num_exp(val->num);
+ }
+ free(val);
+}
+
+#endif
--- /dev/null
+#ifndef _PSI_TYPES_SET_VALUES_H
+#define _PSI_TYPES_SET_VALUES_H
+
+typedef struct set_values {
+ struct set_value **vals;
+ size_t count;
+} set_values;
+
+static inline set_values *init_set_values(struct set_value *val) {
+ set_values *vals = calloc(1, sizeof(*vals));
+ if (val) {
+ vals->count = 1;
+ vals->vals = calloc(1, sizeof(val));
+ vals->vals[0] = val;
+ }
+ return vals;
+}
+
+static inline set_values *add_set_value(set_values *vals, struct set_value *val) {
+ if (!vals) {
+ vals = calloc(1, sizeof(*vals));
+ }
+ vals->vals = realloc(vals->vals, ++vals->count * sizeof(val));
+ vals->vals[vals->count-1] = val;
+ return vals;
+}
+
+static inline void free_set_values(set_values *vals) {
+ if (vals->vals) {
+ size_t i;
+
+ for (i = 0; i < vals->count; ++i) {
+ free_set_value(vals->vals[i]);
+ }
+ free(vals->vals);
+ }
+ free(vals);
+}
+
+#endif