From 898c6dac30d12d7fe56662d66a8e73c340926d64 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Mon, 12 Sep 2016 19:59:47 +0200 Subject: [PATCH] validation and marshaling of structs/unions --- m4/signal.m4 | 2 +- src/context.h | 1 + src/context_validate.c | 111 ++++++++-- src/engine.c | 55 ++++- src/libffi.c | 82 +++++-- src/libjit.c | 89 ++++++-- src/marshal.c | 57 ++--- src/parser.h | 2 +- src/parser.re | 4 +- src/parser_proc.y | 400 +--------------------------------- src/types/let_val.h | 1 + tests/parser/validate001.phpt | 6 +- 12 files changed, 300 insertions(+), 510 deletions(-) diff --git a/m4/signal.m4 b/m4/signal.m4 index d16bf49..a9225ce 100644 --- a/m4/signal.m4 +++ b/m4/signal.m4 @@ -124,7 +124,7 @@ PSI_CHECK_SIGNAL() { ) PSI_FUNCTOR_TYPE(void sa_handler, [(int signo)]) - PSI_FUNCTOR_TYPE(void sa_sigaction, [(int signo, siginfo_t *info, void *context)]) + PSI_FUNCTOR_TYPE(void sa_sigaction, [(int signo, siginfo_t *info, ucontext_t *context)]) PSI_STRUCT(struct sigaction, [ sa_handler sa_handler, diff --git a/src/context.h b/src/context.h index d2ff1b3..98516ac 100644 --- a/src/context.h +++ b/src/context.h @@ -7,6 +7,7 @@ struct psi_parser; struct decl_callinfo; struct impl_vararg; +#define PSI_PRINT_POINTER_LEVEL(l) l,"************************" #define PSI_ERROR 16 #define PSI_WARNING 32 typedef void (*psi_context_error_func)(void *context, struct psi_token *token, int type, const char *msg, ...); diff --git a/src/context_validate.c b/src/context_validate.c index f7f517d..3e99e1b 100644 --- a/src/context_validate.c +++ b/src/context_validate.c @@ -17,6 +17,7 @@ #include "calc.h" #include "marshal.h" #include "engine.h" +#include "context.h" static int validate_lib(struct psi_data *data, void **dlopened) { char lib[MAXPATHLEN]; @@ -637,6 +638,13 @@ static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) { return NULL; } +static inline decl_arg *locate_union_member(decl_union *u, decl_var *var) { + if (u->args) { + return locate_decl_var_arg(var, u->args, NULL); + } + + return NULL; +} static inline constant *locate_num_exp_constant(num_exp *exp, constants *consts) { size_t i; @@ -831,12 +839,21 @@ static inline int validate_set_value_ex(struct psi_data *data, set_value *set, d } } - if (set->inner && ref_type->type == PSI_T_STRUCT) { + if (set->inner && (ref_type->type == PSI_T_STRUCT || ref_type->type == PSI_T_UNION)) { /* to_array(struct, to_...) */ if (!set->outer.set || set->outer.set->inner->vals != set->inner->vals) { for (i = 0; i < set->inner->count; ++i) { decl_var *sub_var = set->inner->vals[i]->vars->vars[0]; - decl_arg *sub_ref = locate_struct_member(ref_type->real.strct, sub_var); + decl_arg *sub_ref; + + switch (ref_type->type) { + case PSI_T_STRUCT: + sub_ref = locate_struct_member(ref_type->real.strct, sub_var); + break; + case PSI_T_UNION: + sub_ref = locate_union_member(ref_type->real.unn, sub_var); + break; + } if (sub_ref) { if (!validate_set_value_ex(data, set->inner->vals[i], sub_ref, ref_type->real.strct->args)) { @@ -860,7 +877,10 @@ static inline int validate_set_value_ex(struct psi_data *data, set_value *set, d } } } else if (set->inner && set->inner->count > 1) { - data->error(data, set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once"); + data->error(data, set->func->token, E_WARNING, + "Inner `set` statement casts on pointers may only occur once, " + "unless the outer type is a scruct or union, got '%s%.*s'", + ref_type->name, PSI_PRINT_POINTER_LEVEL(ref->var->pointer_level)); return 0; } @@ -964,29 +984,16 @@ static inline const char *locate_let_val_varname(let_val *val) { static inline int validate_let_func(struct psi_data *data, let_func *func, decl_var *let_var, impl *impl) { if (func->outer) { - decl_type *var_typ = real_decl_type(let_var->arg->type); - switch (var_typ->type) { - case PSI_T_STRUCT: - func->ref = locate_decl_arg(var_typ->real.strct->args, &func->var->name[1]); - break; - case PSI_T_UNION: - func->ref = locate_decl_arg(var_typ->real.unn->args, &func->var->name[1]); - break; - default: - data->error(data, let_var->token, PSI_WARNING, - "Inner let statement's values must refer to a structure type, got '%s' for '%s'", - real_decl_type(let_var->arg->type)->name, let_var->name); - return 0; - } } if (impl->func->args) { locate_impl_var_arg(func->var, impl->func->args); } if (!func->var->arg && !func->ref) { data->error(data, func->var->token, PSI_WARNING, - "Unknown variable '$%s' of `let` statement" + "Unknown variable '%s%s' of `let` statement" " for cast '%s' of implementation '%s'", + *func->var->name == '$' ? "" : "$", func->var->name, func->name, impl->func->name); return 0; } @@ -1004,13 +1011,17 @@ static inline int validate_let_func(struct psi_data *data, let_func *func, decl_ EMPTY_SWITCH_DEFAULT_CASE(); } - if (func->inner && func->ref) { + if (func->inner) { size_t i; decl_type *var_typ = real_decl_type(let_var->arg->type); + decl_args *sub_args; switch (var_typ->type) { case PSI_T_STRUCT: + sub_args = var_typ->real.strct->args; + break; case PSI_T_UNION: + sub_args = var_typ->real.unn->args; break; default: data->error(data, let_var->token, PSI_WARNING, @@ -1026,7 +1037,7 @@ static inline int validate_let_func(struct psi_data *data, let_func *func, decl_ decl_arg *sub_arg; if (name) { - sub_arg = locate_decl_arg(var_typ->real.strct->args, name); + sub_arg = locate_decl_arg(sub_args, name); } if (!name || !sub_arg) { data->error(data, let_var->token, PSI_WARNING, @@ -1118,15 +1129,36 @@ static inline int validate_let_val(struct psi_data *data, let_val *val, decl_var } if (val->data.callback->func->inner) { size_t i; + decl_type *var_typ = real_decl_type(let_var->arg->type); + decl_args *sub_args; + switch (var_typ->type) { + case PSI_T_STRUCT: + sub_args = var_typ->real.strct->args; + break; + case PSI_T_UNION: + sub_args = var_typ->real.unn->args; + break; + default: + data->error(data, let_var->token, PSI_WARNING, + "Inner let statement's values must refer to a structure type, got '%s' for '%s'", + real_decl_type(let_var->arg->type)->name, let_var->name); + return 0; + } for (i = 0; i < val->data.callback->func->inner->count; ++i) { let_val *inner = val->data.callback->func->inner->vals[i]; switch (inner->kind) { case PSI_LET_FUNC: inner->data.func->outer = val; + inner->data.func->ref = locate_decl_arg(sub_args, + &inner->data.func->var->name[1]); + break; + break; case PSI_LET_CALLBACK: inner->data.callback->func->outer = val; + inner->data.callback->func->ref = locate_decl_arg(sub_args, + &inner->data.callback->func->var->name[1]); break; } } @@ -1138,20 +1170,41 @@ static inline int validate_let_val(struct psi_data *data, let_val *val, decl_var case PSI_LET_FUNC: if (val->data.func->inner) { size_t i; + decl_type *var_typ = real_decl_type(let_var->arg->type); + decl_args *sub_args; + switch (var_typ->type) { + case PSI_T_STRUCT: + sub_args = var_typ->real.strct->args; + break; + case PSI_T_UNION: + sub_args = var_typ->real.unn->args; + break; + default: + data->error(data, let_var->token, PSI_WARNING, + "Inner let statement's values must refer to a structure type, got '%s' for '%s'", + real_decl_type(let_var->arg->type)->name, let_var->name); + return 0; + } for (i = 0; i < val->data.func->inner->count; ++i) { let_val *inner = val->data.func->inner->vals[i]; switch (inner->kind) { case PSI_LET_FUNC: inner->data.func->outer = val; + inner->data.func->ref = locate_decl_arg(sub_args, + &inner->data.func->var->name[1]); break; case PSI_LET_CALLBACK: inner->data.callback->func->outer = val; + inner->data.callback->func->ref = locate_decl_arg(sub_args, + &inner->data.callback->func->var->name[1]); break; } } } + val->data.func->var; + if (!validate_let_func(data, val->data.func, let_var, impl)) { return 0; } @@ -1165,10 +1218,11 @@ static inline int validate_impl_let_stmts(struct psi_data *data, impl *impl) { size_t i, j; /* we can have multiple let stmts */ - /* check that we have a decl arg for every let stmt */ + /* check that we have a decl arg and impl arg for every let stmt */ for (i = 0; i < impl->stmts->let.count; ++i) { let_stmt *let = impl->stmts->let.list[i]; decl_var *let_var; + impl_var *let_ivar = NULL; if (let->val && let->val->kind == PSI_LET_TMP) { let_var = let->val->data.var; @@ -1181,6 +1235,21 @@ static inline int validate_impl_let_stmts(struct psi_data *data, impl *impl) { " of implementation '%s'", let_var->name, impl->func->name); return 0; } + switch (let->val->kind) { + case PSI_LET_CALLBACK: + let_ivar = let->val->data.callback->func->var; + break; + case PSI_LET_FUNC: + let_ivar = let->val->data.func->var; + break; + default: + break; + } + if (let_ivar && !locate_impl_var_arg(let_ivar, impl->func->args)) { + data->error(data, let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement" + " of implementation '%s'", let_ivar->name, impl->func->name); + return 0; + } if (!validate_let_val(data, let->val, let->var, impl)) { return 0; diff --git a/src/engine.c b/src/engine.c index 37f9976..80a2eb5 100644 --- a/src/engine.c +++ b/src/engine.c @@ -207,17 +207,15 @@ static inline void *psi_do_calloc(let_calloc *alloc) return mem; } -static inline impl_val *psi_let_func(let_func *func, decl_arg *darg) { - return darg->ptr = func->handler(darg->ptr, darg->type, func->var->arg, &darg->mem); -} +static inline impl_val *psi_let_func(let_func *func, decl_arg *darg); -static inline void *psi_do_let(let_stmt *let) +static inline void *psi_let_val(let_val *val, decl_arg *darg) { - decl_arg *darg = let->var->arg; + ZEND_ASSERT(darg); - switch (let->val ? let->val->kind : PSI_LET_NULL) { + switch (val ? val->kind : PSI_LET_NULL) { case PSI_LET_TMP: - memcpy(darg->ptr, deref_impl_val(let->val->data.var->arg->let, let->val->data.var), sizeof(impl_val)); + memcpy(darg->ptr, deref_impl_val(val->data.var->arg->let, val->data.var), sizeof(impl_val)); break; case PSI_LET_NULL: if (darg->var->array_size) { @@ -228,29 +226,62 @@ static inline void *psi_do_let(let_stmt *let) } break; case PSI_LET_CALLOC: - darg->val.ptr = psi_do_calloc(let->val->data.alloc); + darg->val.ptr = psi_do_calloc(val->data.alloc); darg->mem = darg->val.ptr; break; case PSI_LET_CALLBACK: - darg->val.ptr = let->val->data.callback->decl->call.sym; + darg->val.ptr = val->data.callback->decl->call.sym; break; case PSI_LET_NUMEXP: - darg->val.zend.lval = psi_long_num_exp(let->val->data.num, NULL); + darg->val.zend.lval = psi_long_num_exp(val->data.num, NULL); break; case PSI_LET_FUNC: - if (!psi_let_func(let->val->data.func, darg)) { + if (!psi_let_func(val->data.func, darg)) { return NULL; } break; } - if (let->val && let->val->flags.one.is_reference) { + if (val && val->flags.one.is_reference) { return darg->let = &darg->ptr; } else { return darg->let = darg->ptr; } } +static inline impl_val *psi_let_func(let_func *func, decl_arg *darg) { + impl_arg *iarg = NULL; + + if (0 && func->inner) { + size_t i; + + for (i = 0; i < func->inner->count; ++i) { + let_val *inner = func->inner->vals[i]; + decl_arg *ref = NULL; + + switch (inner->kind) { + case PSI_LET_CALLBACK: + ref = inner->data.callback->func->ref; + break; + case PSI_LET_FUNC: + ref = inner->data.func->ref; + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + + psi_let_val(inner, ref); + } + } + + return darg->ptr = func->handler(darg->ptr, darg->type, func->var->arg, &darg->mem); + +} + +static inline void *psi_do_let(let_stmt *let) +{ + return psi_let_val(let->val, let->var->arg); +} + static inline void psi_do_return(zval *return_value, return_stmt *ret) { ret->set->func->handler(return_value, ret->set, ret->set->vars->vars[0]->arg->ptr); diff --git a/src/libffi.c b/src/libffi.c index 2dbe0bc..e2dc81f 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -7,7 +7,6 @@ #ifdef HAVE_LIBFFI #include "php_psi.h" -#include "ffi.h" #include "engine.h" #undef PACKAGE @@ -328,6 +327,37 @@ static void psi_ffi_init(struct psi_context *C) C->context = psi_ffi_context_init(NULL); } +static inline void psi_ffi_destroy_callbacks(struct psi_context *C, let_val *let_val) { + let_callback *cb; + let_func *fn = NULL; + + switch (let_val->kind) { + case PSI_LET_CALLBACK: + cb = let_val->data.callback; + + if (cb->decl && cb->decl->call.info) { + psi_ffi_call_free(cb->decl->call.info); + } + fn = cb->func; + /* no break */ + case PSI_LET_FUNC: + if (!fn) { + fn = let_val->data.func; + } + + if (fn->inner) { + size_t i; + + for (i = 0; i < fn->inner->count; ++i) { + psi_ffi_destroy_callbacks(C, fn->inner->vals[i]); + } + } + break; + default: + break; + } +} + static void psi_ffi_dtor(struct psi_context *C) { if (C->decls) { @@ -364,6 +394,41 @@ static void psi_ffi_dtor(struct psi_context *C) psi_ffi_context_free((void *) &C->context); } +static inline void psi_ffi_compile_callbacks(struct psi_context *C, let_val *let_val) { + struct psi_ffi_call *call; + let_callback *cb; + let_func *fn = NULL; + + switch (let_val->kind) { + case PSI_LET_CALLBACK: + cb = let_val->data.callback; + 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); + break; + } + + cb->decl->call.sym = call->code; + } + fn = cb->func; + /* no break */ + case PSI_LET_FUNC: + if (!fn) { + fn = let_val->data.func; + } + if (fn->inner) { + size_t i; + + for (i = 0; i < fn->inner->count; ++i) { + psi_ffi_compile_callbacks(C, fn->inner->vals[i]); + } + } + break; + default: + break; + } +} + static zend_function_entry *psi_ffi_compile(struct psi_context *C) { size_t c, i, j = 0; @@ -397,20 +462,7 @@ static zend_function_entry *psi_ffi_compile(struct psi_context *C) ++j; for (c = 0; c < impl->stmts->let.count; ++c) { - let_stmt *let = impl->stmts->let.list[c]; - - if (let->val && let->val->kind == PSI_LET_CALLBACK) { - let_callback *cb = let->val->data.callback; - - 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; - } - - cb->decl->call.sym = call->code; - } - } + psi_ffi_compile_callbacks(C, impl->stmts->let.list[c]->val); } } diff --git a/src/libjit.c b/src/libjit.c index b6022c5..de743a1 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -272,6 +272,37 @@ static void psi_jit_init(struct psi_context *C) C->context = psi_jit_context_init(NULL); } +static inline void psi_jit_destroy_callbacks(struct psi_context *C, let_val *let_val) { + let_callback *cb; + let_func *fn = NULL; + + switch (let_val->kind) { + case PSI_LET_CALLBACK: + cb = let_val->data.callback; + + if (cb->decl && cb->decl->call.info) { + psi_jit_call_free(cb->decl->call.info); + } + fn = cb->func; + /* no break */ + case PSI_LET_FUNC: + if (!fn) { + fn = let_val->data.func; + } + + if (fn->inner) { + size_t i; + + for (i = 0; i < fn->inner->count; ++i) { + psi_jit_destroy_callbacks(C, fn->inner->vals[i]); + } + } + break; + default: + break; + } +} + static void psi_jit_dtor(struct psi_context *C) { if (C->decls) { @@ -292,19 +323,46 @@ static void psi_jit_dtor(struct psi_context *C) impl *impl = C->impls->list[i]; for (j = 0; j < impl->stmts->let.count; ++j) { - let_stmt *let = impl->stmts->let.list[j]; + psi_jit_destroy_callbacks(C, impl->stmts->let.list[j]->val); + } + } + } + psi_jit_context_free((void *) &C->context); +} - if (let->val && let->val->kind == PSI_LET_CALLBACK) { - let_callback *cb = let->val->data.callback; +static inline void psi_jit_compile_callbacks(struct psi_context *C, let_val *let_val) { + struct psi_jit_call *call; + let_callback *cb; + let_func *fn = NULL; - if (cb->decl && cb->decl->call.info) { - psi_jit_call_free(cb->decl->call.info); - } - } + switch (let_val->kind) { + case PSI_LET_CALLBACK: + cb = let_val->data.callback; + if ((call = psi_jit_call_alloc(C, cb->decl))) { + if (!psi_jit_call_init_callback_closure(C, call, cb)) { + psi_jit_call_free(call); + break; } + + cb->decl->call.sym = call->closure; } + fn = cb->func; + /* no break */ + case PSI_LET_FUNC: + if (!fn) { + fn = let_val->data.func; + } + if (fn->inner) { + size_t i; + + for (i = 0; i < fn->inner->count; ++i) { + psi_jit_compile_callbacks(C, fn->inner->vals[i]); + } + } + break; + default: + break; } - psi_jit_context_free((void *) &C->context); } static zend_function_entry *psi_jit_compile(struct psi_context *C) @@ -343,20 +401,7 @@ static zend_function_entry *psi_jit_compile(struct psi_context *C) ++j; for (c = 0; c < impl->stmts->let.count; ++c) { - let_stmt *let = impl->stmts->let.list[c]; - - if (let->val && let->val->kind == PSI_LET_CALLBACK) { - let_callback *cb = let->val->data.callback; - - 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; - } - - cb->decl->call.sym = call->closure; - } - } + psi_jit_compile_callbacks(C, impl->stmts->let.list[c]->val); } } diff --git a/src/marshal.c b/src/marshal.c index 622db12..66b6ae6 100644 --- a/src/marshal.c +++ b/src/marshal.c @@ -298,7 +298,8 @@ void psi_from_zval_ex(impl_val **ptr, decl_arg *spec, token_t cast, zval *zv, vo switch (real->type) { default: ZEND_ASSERT(0); - /* no break */ + val->i64 = zval_get_long(zv); + break; case PSI_T_INT8: val->i8 = zval_get_long(zv); break; @@ -340,34 +341,22 @@ void psi_from_zval_ex(impl_val **ptr, decl_arg *spec, token_t cast, zval *zv, vo case PSI_T_STRUCT: *tmp = *ptr = psi_array_to_struct(real->real.strct, HASH_OF(zv)); break; - } -} - -void psi_from_zval(impl_val *mem, decl_arg *spec, zval *zv, void **tmp) -{ - decl_type *type = real_decl_type(spec->type); - - switch (type->type) { - case PSI_T_FUNCTION: - break; - case PSI_T_FLOAT: - mem->fval = (float) zval_get_double(zv); + case PSI_T_UNION: + *tmp = *ptr = psi_array_to_union(real->real.unn, HASH_OF(zv)); break; - case PSI_T_DOUBLE: - mem->dval = zval_get_double(zv); + case PSI_T_FUNCTION: + /*FIXME*/ + val->ptr = NULL; break; case PSI_T_VOID: - case PSI_T_INT8: - case PSI_T_UINT8: - if (spec->var->pointer_level) { + val->ptr = NULL; + if (Z_TYPE_P(zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), psi_object_get_class_entry())) { + *ptr = PSI_OBJ(zv, NULL)->data; + } else { zend_string *zs = zval_get_string(zv); - *tmp = mem->ptr = estrndup(zs->val, zs->len); + *tmp = val->ptr = estrndup(zs->val, zs->len); zend_string_release(zs); - break; } - /* no break */ - default: - mem->zend.lval = zval_get_long(zv); break; } } @@ -382,12 +371,12 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr) zval *entry = zend_hash_str_find_ind(arr, darg->var->name, strlen(darg->var->name)); if (entry) { - impl_val val; + impl_val val, *ptr = &val; void *tmp = NULL; - memset(&tmp, 0, sizeof(tmp)); - psi_from_zval(&val, darg, entry, &tmp); - memcpy(mem + darg->layout->pos, &val, darg->layout->len); + memset(&val, 0, sizeof(val)); + psi_from_zval_ex(&ptr, darg, /*FIXME*/0, entry, &tmp); + memcpy(mem + darg->layout->pos, ptr, darg->layout->len); if (tmp) { ((void **)(mem + s->size))[j++] = tmp; } @@ -405,11 +394,11 @@ void *psi_array_to_union(decl_union *u, HashTable *arr) { zval *entry = zend_hash_str_find_ind(arr, darg->var->name, strlen(darg->var->name)); if (entry) { - impl_val val; + impl_val val, *ptr = &val; void *tmp = NULL; - memset(&tmp, 0, sizeof(tmp)); - psi_from_zval(&val, darg, entry, &tmp); + memset(&val, 0, sizeof(val)); + psi_from_zval_ex(&ptr, darg, /*FIXME*/0, entry, &tmp); memcpy(mem, &val, darg->layout->len); if (tmp) { ((void **)(mem + u->size))[0] = tmp; @@ -440,7 +429,7 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) array_init(return_value); - if (t == PSI_T_STRUCT) { + if (t == PSI_T_STRUCT || t == PSI_T_UNION) { // decl_struct *s = real_decl_type(var->arg->type)->strct; if (set->inner && set->inner->count) { @@ -464,8 +453,8 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) } } } + return; } - return; } if (var->arg->var->array_size) { @@ -548,12 +537,10 @@ void psi_to_object(zval *return_value, set_value *set, impl_val *r_val) { decl_var *var = set->vars->vars[0]; impl_val *ret_val = deref_impl_val(r_val, var); - psi_object *obj; if ((intptr_t) ret_val->ptr > (intptr_t) 0) { object_init_ex(return_value, psi_object_get_class_entry()); - obj = PSI_OBJ(return_value, NULL); - obj->data = ret_val->ptr; + PSI_OBJ(return_value, NULL)->data = ret_val->ptr; } else { RETVAL_NULL(); } diff --git a/src/parser.h b/src/parser.h index 5851ee6..b5ec9f5 100644 --- a/src/parser.h +++ b/src/parser.h @@ -28,7 +28,7 @@ struct psi_parser { 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); +ssize_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); diff --git a/src/parser.re b/src/parser.re index 3cfe130..dcc76e3 100644 --- a/src/parser.re +++ b/src/parser.re @@ -55,7 +55,7 @@ struct psi_parser *psi_parser_init(struct psi_parser *P, const char *filename, p return P; } -size_t psi_parser_fill(struct psi_parser *P, size_t n) +ssize_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); @@ -91,7 +91,7 @@ size_t psi_parser_fill(struct psi_parser *P, size_t n) } } if (P->flags & PSI_PARSER_DEBUG) { - fprintf(stderr, "PSI> Fill: avail=%zu\n", P->lim - P->cur); + fprintf(stderr, "PSI> Fill: avail=%zd\n", P->lim - P->cur); } return P->lim - P->cur; } diff --git a/src/parser_proc.y b/src/parser_proc.y index b97d28f..4d96acb 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -13,24 +13,18 @@ #include "parser.h" } -%include {void psi_error(int, const char *, int, const char *, ...);} - - - +%include { void psi_error(int, const char *, int, const char *, ...); } %name psi_parser_proc_ %token_prefix PSI_T_ %token_type {struct psi_token *} %token_destructor {free($$);} %default_destructor {(void)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' at pos %u", TOKEN->text, TOKEN->col); } else { psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input"); }} +%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' at pos %u", TOKEN->text, TOKEN->col); } else { psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input"); } } %nonassoc NAME. %left PLUS MINUS. %left SLASH ASTERISK. %fallback NAME TEMP FREE SET LET RETURN CALLOC CALLBACK ZVAL LIB STRING. - %token_class const_type_token BOOL INT FLOAT STRING. %token_class decl_type_token FLOAT DOUBLE INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NAME. %token_class impl_def_val_token NULL NUMBER TRUE FALSE QUOTED_STRING. @@ -39,7 +33,6 @@ %token_class let_func_token ZVAL OBJVAL ARRVAL PATHVAL STRLEN STRVAL FLOATVAL INTVAL BOOLVAL. %token_class set_func_token TO_OBJECT TO_ARRAY TO_STRING TO_INT TO_FLOAT TO_BOOL ZVAL VOID. %token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY OBJECT CALLABLE. - %type decl_enum {decl_enum *} %destructor decl_enum {free_decl_enum($$);} %type decl_enum_items {decl_enum_items*} @@ -148,14 +141,11 @@ %type reference {char} %type indirection {unsigned} %type pointers {unsigned} - file ::= blocks. blocks ::= block. blocks ::= blocks block. - block ::= EOF. block ::= EOS. - block ::= LIB(token) QUOTED_STRING(libname) EOS. { if (P->psi.file.ln) { P->error(P, token, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text); @@ -168,11 +158,9 @@ block ::= LIB(token) QUOTED_STRING(libname) EOS. { block ::= decl(decl). { P->decls = add_decl(P->decls, decl); } - block ::= impl(impl). { P->impls = add_impl(P->impls, impl); } - block ::= decl_typedef(def). { P->defs = add_decl_typedef(P->defs, def); switch (def->type->type) { @@ -193,192 +181,116 @@ block ::= decl_typedef(def). { break; } } - block ::= constant(constant). { P->consts = add_constant(P->consts, constant); } - block ::= decl_struct(strct). { P->structs = add_decl_struct(P->structs, strct); } - block ::= decl_union(u). { P->unions = add_decl_union(P->unions, u); } - block ::= decl_enum(e). { P->enums = add_decl_enum(P->enums, e); } - optional_name(n) ::= . { n = NULL; } - optional_name(n) ::= NAME(N). { - n = N; } - enum_name(n) ::= ENUM(E) optional_name(N). { - if (N) { n = N; free(E); } else { char digest[17]; - 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. { - - - - e = init_decl_enum(N->text, list); e->token = N; } - decl_enum_items(l) ::= decl_enum_item(i). { - l = init_decl_enum_items(i); } decl_enum_items(l) ::= decl_enum_items(l_) COMMA decl_enum_item(i). { - - - l = add_decl_enum_item(l_, i); } - decl_enum_item(i) ::= NAME(N) EQUALS num_exp(num). { - - - i = init_decl_enum_item(N->text, num); i->token = N; } decl_enum_item(i) ::= NAME(N). { - i = init_decl_enum_item(N->text, NULL); i->token = N; } - union_name(n) ::= UNION(U) optional_name(N). { - - if (N) { n = N; free(U); } else { char digest[17]; - psi_token_hash(U, digest); n = psi_token_translit(psi_token_append(U, 1, digest), " ", "@"); } } - struct_name(n) ::= STRUCT(S) optional_name(N). { - - if (N) { n = N; free(S); } else { char digest[17]; - 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. { - - - args_ = args; } - decl_struct_args(args_) ::= decl_struct_args_block(args). { - args_ = args; } decl_struct_args(args_) ::= EOS. { - args_ = init_decl_args(NULL); } - decl_struct(strct) ::= STRUCT NAME(N) align_and_size(as) decl_struct_args(args). { - - - - strct = init_decl_struct(N->text, args); strct->align = as.pos; strct->size = as.len; strct->token = N; } - align_and_size(as) ::= . { as.pos = 0; as.len = 0; } align_and_size(as) ::= COLON COLON LPAREN NUMBER(A) COMMA NUMBER(S) RPAREN. { - - - - - - - as.pos = atol(A->text); as.len = atol(S->text); free(A); free(S); } - decl_union(u) ::= UNION NAME(N) align_and_size(as) decl_struct_args(args). { - - - - u = init_decl_union(N->text, args); u->align = as.pos; u->size = as.len; u->token = N; } - const_type(type_) ::= const_type_token(T). { - type_ = init_const_type(T->type, T->text); free(T); } - constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) EOS. { - - - - - - constant = init_constant(type, T->text, val); free(T); } - decl_typedef(def) ::= TYPEDEF(T) decl_typedef_body(def_) EOS. { - - - def = def_; def->token = T; } - 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_token_copy(N); def->type->real.strct = init_decl_struct(N->text, args); @@ -387,10 +299,6 @@ decl_typedef_body_ex(def) ::= struct_name(N) align_and_size(as) decl_struct_args def->type->real.strct->size = as.len; } 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_token_copy(N); def->type->real.unn = init_decl_union(N->text, args); @@ -399,55 +307,32 @@ decl_typedef_body_ex(def) ::= union_name(N) align_and_size(as) decl_struct_args_ def->type->real.unn->size = as.len; } 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_token_copy(e->token); def->type->real.enm = e; } - decl_typedef_body(def) ::= decl_typedef_body_ex(def_). { - def = def_; } - decl_typedef_body_fn_args(args) ::= LPAREN decl_args(args_) RPAREN. { - - - args = args_; } 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_token_copy(func_->token); def->type->real.func = init_decl(init_decl_abi("default"), func_, args); } decl_typedef_body(def) ::= decl_arg(arg). { - def = arg; } - decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) RPAREN EOS. { - - - - - - decl = init_decl(abi, func, args); } - decl_func(func) ::= decl_arg(arg). { - func = arg; } - decl_func(func) ::= VOID(T) NAME(N). { - - func = init_decl_arg( init_decl_type(T->type, T->text), init_decl_var(N->text, 0, 0) @@ -457,13 +342,6 @@ decl_func(func) ::= VOID(T) NAME(N). { func->token = N; } decl_typedef_body(def) ::= VOID(T) indirection(decl_i) LPAREN indirection(type_i) NAME(N) RPAREN decl_typedef_body_fn_args(args). { - - - - - - - decl_arg *func_ = init_decl_arg( init_decl_type(T->type, T->text), init_decl_var(N->text, decl_i, 0) @@ -471,7 +349,6 @@ decl_typedef_body(def) ::= VOID(T) indirection(decl_i) LPAREN indirection(type_i func_->type->token = T; func_->var->token = N; func_->token = N; - def = init_decl_arg( init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var) @@ -488,7 +365,6 @@ decl_typedef_body(def) ::= CONST VOID(T) pointers(decl_i) LPAREN indirection(typ func_->type->token = T; func_->var->token = N; func_->token = N; - def = init_decl_arg( init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var) @@ -497,61 +373,35 @@ decl_typedef_body(def) ::= CONST VOID(T) pointers(decl_i) LPAREN indirection(typ 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). { - abi = init_decl_abi(T->text); abi->token = T; } - decl_var(var) ::= indirection(p) NAME(T). { - - var = init_decl_var(T->text, p, 0); var->token = T; } decl_var(var) ::= indirection(p) NAME(T) LBRACKET NUMBER(D) RBRACKET. { - - - - - var = init_decl_var(T->text, p+1, atol(D->text)); var->token = T; free(D); } - decl_vars(vars) ::= decl_var(var). { - vars = init_decl_vars(var); } decl_vars(vars) ::= decl_vars(vars_) COMMA decl_var(var). { - - - vars = add_decl_var(vars_, var); } - decl_arg(arg_) ::= const_decl_type(type) decl_var(var). { - - arg_ = init_decl_arg(type, var); } decl_typedef_body(def) ::= const_decl_type(type_) indirection(decl_i) LPAREN indirection(type_i) NAME(N) RPAREN decl_typedef_body_fn_args(args). { - - - - - - - decl_arg *func_ = init_decl_arg( type_, init_decl_var(N->text, decl_i, 0) ); func_->var->token = N; func_->token = N; - def = init_decl_arg( init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var) @@ -560,12 +410,7 @@ decl_typedef_body(def) ::= const_decl_type(type_) indirection(decl_i) LPAREN ind 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). { - - - arg_ = init_decl_arg( init_decl_type(T->type, T->text), init_decl_var(N->text, p, 0) @@ -575,10 +420,6 @@ decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). { arg_->token = N; } decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { - - - - arg_ = init_decl_arg( init_decl_type(T->type, T->text), init_decl_var(N->text, p, 0) @@ -587,40 +428,25 @@ decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { arg_->var->token = N; arg_->token = N; } - decl_args ::= . decl_args ::= VOID. decl_args(args) ::= decl_arg(arg). { - args = init_decl_args(arg); } decl_args(args) ::= decl_args(args_) COMMA decl_arg(arg). { - - - args = add_decl_arg(args_, arg); } decl_args(args) ::= decl_args(args_) COMMA ELLIPSIS. { - - - args = args_; args->varargs = 1; } - struct_args(args) ::= struct_arg(arg). { - args = init_decl_args(arg); } struct_args(args) ::= struct_args(args_) struct_arg(arg). { - - args = add_decl_arg(args_, arg); } - struct_arg(arg_) ::= decl_typedef_body_ex(def) EOS. { - - arg_ = def; switch (def->type->type) { case PSI_T_STRUCT: @@ -641,37 +467,21 @@ struct_arg(arg_) ::= decl_typedef_body_ex(def) EOS. { } } struct_arg(arg) ::= decl_arg(arg_) struct_layout(layout_) EOS. { - - - arg_->layout = layout_; arg = arg_; } - struct_layout(layout) ::= . { layout = NULL; } struct_layout(layout) ::= COLON COLON LPAREN NUMBER(POS) COMMA NUMBER(SIZ) RPAREN. { - - - - - - - layout = init_decl_struct_layout(atol(POS->text), atol(SIZ->text)); free(POS); free(SIZ); } - - decl_scalar_type(type_) ::= CHAR(C). { - type_ = C; } decl_scalar_type(type_) ::= SHORT(S) decl_scalar_type_short(s). { - - if (s) { type_ = psi_token_cat(2, S, s); free(S); @@ -683,18 +493,13 @@ decl_scalar_type(type_) ::= SHORT(S) decl_scalar_type_short(s). { decl_scalar_type_short(s) ::= . { s = NULL; } - decl_scalar_type_short(s) ::= INT(I). { - s = I; } decl_scalar_type(type_) ::= INT(I). { - type_ = I; } decl_scalar_type(type_) ::= LONG(L) decl_scalar_type_long(l). { - - if (l) { type_ = psi_token_cat(2, L, l); free(L); @@ -707,12 +512,9 @@ decl_scalar_type_long(l) ::= . { l = NULL; } decl_scalar_type_long(l) ::= DOUBLE(D). { - l = D; } decl_scalar_type_long(l) ::= LONG(L) decl_scalar_type_long_long(ll). { - - if (ll) { l = psi_token_cat(2, L, ll); free(L); @@ -725,12 +527,9 @@ decl_scalar_type_long_long(ll) ::= . { ll = NULL; } decl_scalar_type_long_long(ll) ::= INT(I). { - ll = I; } decl_type(type_) ::= UNSIGNED(U) decl_scalar_type(N). { - - struct psi_token *T = psi_token_cat(2, U, N); type_ = init_decl_type(T->type, T->text); type_->token = T; @@ -738,8 +537,6 @@ decl_type(type_) ::= UNSIGNED(U) decl_scalar_type(N). { free(N); } decl_type(type_) ::= SIGNED(S) decl_scalar_type(N). { - - struct psi_token *T = psi_token_cat(2, S, N); type_ = init_decl_type(T->type, T->text); type_->token = T; @@ -747,298 +544,169 @@ decl_type(type_) ::= SIGNED(S) decl_scalar_type(N). { free(N); } decl_type(type_) ::= UNSIGNED(U). { - type_ = init_decl_type(PSI_T_NAME, U->text); type_->token = U; } decl_type(type_) ::= SIGNED(S). { - type_ = init_decl_type(PSI_T_NAME, S->text); type_->token = S; } decl_type(type_) ::= decl_scalar_type(N). { - type_ = init_decl_type(N->type, N->text); type_->token = N; } - decl_type(type_) ::= STRUCT(S) NAME(T). { - - type_ = init_decl_type(S->type, T->text); type_->token = T; free(S); } decl_type(type_) ::= UNION(U) NAME(T). { - - type_ = init_decl_type(U->type, T->text); type_->token = T; free(U); } decl_type(type_) ::= ENUM(E) NAME(T). { - - type_ = init_decl_type(E->type, T->text); type_->token = T; free(E); } decl_type(type_) ::= decl_type_token(T). { - type_ = init_decl_type(T->type, T->text); type_->token = T; } - - const_decl_type(type) ::= decl_type(type_). { - type = type_; } const_decl_type(type) ::= CONST decl_type(type_). { - - type = type_; } - impl(impl) ::= impl_func(func) LBRACE impl_stmts(stmts) RBRACE. { - - - - impl = init_impl(func, stmts); } - impl_func(func) ::= FUNCTION reference(r) NSNAME(NAME) impl_args(args) COLON impl_type(type). { - - - - - - func = init_impl_func(NAME->text, args, type, r); func->token = NAME; } - impl_def_val(def) ::= impl_def_val_token(T). { - def = init_impl_def_val(T->type, T->text); free(T); } - impl_var(var) ::= reference(r) DOLLAR_NAME(T). { - - var = init_impl_var(T->text, r); var->token = T; } - impl_arg(arg) ::= impl_type(type) impl_var(var). { - - arg = init_impl_arg(type, var, NULL); } impl_arg(arg) ::= impl_type(type) impl_var(var) EQUALS impl_def_val(def). { - - - - arg = init_impl_arg(type, var, def); } - impl_args(args) ::= LPAREN RPAREN. { - - args = NULL; } impl_args(args) ::= LPAREN impl_arg_list(args_) RPAREN. { - - - args = args_; } impl_args(args) ::= LPAREN impl_arg_list(args_) COMMA impl_vararg(va) RPAREN. { - - - - - args = args_; args->vararg.name = va; } - impl_vararg(va) ::= impl_type(type) reference(r) ELLIPSIS DOLLAR_NAME(T). { - - - - va = init_impl_arg(type, init_impl_var(T->text, r), NULL); free(T); } - impl_arg_list(args) ::= impl_arg(arg). { - args = init_impl_args(arg); } impl_arg_list(args) ::= impl_arg_list(args_) COMMA impl_arg(arg). { - - - args = add_impl_arg(args_, arg); } - impl_stmts(stmts) ::= impl_stmt(stmt). { - stmts = init_impl_stmts(stmt); } impl_stmts(stmts) ::= impl_stmts(stmts_) impl_stmt(stmt). { - - stmts = add_impl_stmt(stmts_, stmt); } - impl_stmt(stmt) ::= let_stmt(let). { - stmt = init_impl_stmt(PSI_T_LET, let); } impl_stmt(stmt) ::= set_stmt(set). { - stmt = init_impl_stmt(PSI_T_SET, set); } impl_stmt(stmt) ::= return_stmt(ret). { - stmt = init_impl_stmt(PSI_T_RETURN, ret); } impl_stmt(stmt) ::= free_stmt(free). { - stmt = init_impl_stmt(PSI_T_FREE, free); } - num_exp(exp) ::= num_exp_token(tok). { - exp = init_num_exp(tok->type, tok->text); exp->token = tok; } num_exp(exp) ::= decl_var(var). { - exp = init_num_exp(PSI_T_NAME, var); 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; exp_->operand = operand_; exp = exp_; free(operator_); } - let_stmt(let) ::= LET decl_var(var) EOS. { - - - let = init_let_stmt(var, init_let_val(PSI_LET_NULL, NULL)); } let_stmt(let) ::= LET decl_var(var) EQUALS reference(r) let_val(val) EOS. { - - - - - - val->flags.one.is_reference = r ? 1 : 0; let = init_let_stmt(var, val); } let_stmt(let) ::= TEMP decl_var(var) EQUALS decl_var(val) EOS. { - - - - - let = init_let_stmt(var, init_let_val(PSI_LET_TMP, val)); } - let_calloc(alloc) ::= num_exp(nmemb) COMMA num_exp(size). { - - - alloc = init_let_calloc(nmemb, size); } - let_func(func) ::= let_func_token(T) LPAREN impl_var(var) RPAREN. { - - - - func = init_let_func(T->type, T->text, var); free(T); } - let_vals(vals) ::= let_val(val). { - vals = init_let_vals(val); } let_vals(vals) ::= let_vals(vals_) COMMA let_val(val). { - - - vals = add_let_val(vals_, val); } - let_func(func) ::= let_func_token(T) LPAREN impl_var(var) COMMA let_vals(vals) RPAREN. { - - - - - - func = init_let_func(T->type, T->text, var); func->inner = vals; free(T); } - callback_arg_list ::= . callback_arg_list(args) ::= callback_args(args_). { - args = args_; } - callback_args(args) ::= set_value(val). { - args = init_set_values(val); } callback_args(args) ::= callback_args(args_) COMMA set_value(val). { - - - args = add_set_value(args_, val); } callback_rval(rval) ::= let_func_token(F). { - rval = F; } callback_rval(rval) ::= VOID(V). { - rval = V; } - let_val(val) ::= NULL. { - val = init_let_val(PSI_LET_NULL, NULL); } let_val(val) ::= num_exp(exp). { - val = init_let_val(PSI_LET_NUMEXP, exp); } let_val(val) ::= CALLOC LPAREN let_calloc(alloc) RPAREN. { - - - - val = init_let_val(PSI_LET_CALLOC, alloc); } let_val(val) ::= let_func(func_). { - val = init_let_val(PSI_LET_FUNC, func_); } let_val(val) ::= CALLBACK callback_rval(F) LPAREN impl_var(var) LPAREN callback_arg_list(args_) RPAREN RPAREN. { @@ -1046,51 +714,22 @@ let_val(val) ::= CALLBACK callback_rval(F) LPAREN impl_var(var) LPAREN callback_ init_let_func(F->type, F->text, var), args_)); free(F); } - set_stmt(set) ::= SET impl_var(var) EQUALS set_value(val) EOS. { - - - - - set = init_set_stmt(var, val); } - set_value(val) ::= set_func(func) LPAREN decl_var(var) RPAREN. { - - - - val = init_set_value(func, init_decl_vars(var)); } set_value(val) ::= set_func(func) LPAREN decl_var(var) COMMA num_exp(num_) RPAREN. { - - - - - - val = init_set_value(func, init_decl_vars(var)); val->num = num_; } set_value(val) ::= set_func(func_) LPAREN decl_var(var) COMMA ELLIPSIS(T) RPAREN. { - - - - - - free_set_func(func_); val = init_set_value(init_set_func(T->type, T->text), init_decl_vars(var)); val->func->token = T; } set_value(val) ::= set_func(func_) LPAREN decl_var(var) COMMA set_vals(vals) RPAREN. { - - - - - - val = vals; val->func = func_; val->vars = init_decl_vars(var); @@ -1101,87 +740,52 @@ set_value(val) ::= set_func(func_) LPAREN decl_var(var) COMMA num_exp(num_) COMM val->num = num_; val->vars = init_decl_vars(var); } - set_vals(vals) ::= set_value(val). { - vals = add_inner_set_value(init_set_value(NULL, NULL), val); } set_vals(vals) ::= set_vals(vals_) COMMA set_value(val). { - - - vals = add_inner_set_value(vals_, val); } - set_func(func) ::= set_func_token(T). { - func = init_set_func(T->type, T->text); func->token = T; } - return_stmt(ret) ::= RETURN(T) set_value(val) EOS. { - - - ret = init_return_stmt(val); ret->token = T; } - free_stmt(free) ::= FREE free_calls(calls) EOS. { - - - free = init_free_stmt(calls); } - free_calls(calls) ::= free_call(call). { - calls = init_free_calls(call); } free_calls(calls) ::= free_calls(calls_) COMMA free_call(call). { - - - calls = add_free_call(calls_, call); } - free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. { - - - - call = init_free_call(F->text, vars); call->token = F; } - impl_type(type_) ::= impl_type_token(T). { - type_ = init_impl_type(T->type, T->text); free(T); } - reference(r) ::= . { r = 0; } reference(r) ::= AMPERSAND. { - r = 1; } - indirection(i) ::= .{ i = 0; } indirection(i) ::= pointers(p). { - i = p; } - pointers(p) ::= ASTERISK. { - p = 1; } pointers(p) ::= pointers(p_) ASTERISK. { - - p = p_+1; } diff --git a/src/types/let_val.h b/src/types/let_val.h index 7d5acfd..e2827e2 100644 --- a/src/types/let_val.h +++ b/src/types/let_val.h @@ -13,6 +13,7 @@ enum let_val_kind { #define PSI_LET_REFERENCE 0x1; typedef struct let_val { enum let_val_kind kind; + decl_var *var; union { num_exp *num; let_calloc *alloc; diff --git a/tests/parser/validate001.phpt b/tests/parser/validate001.phpt index 7a0a862..378db8d 100644 --- a/tests/parser/validate001.phpt +++ b/tests/parser/validate001.phpt @@ -85,9 +85,9 @@ validate(true, "typedef int bar(int baz); \ntypedef int *(*foo)(bar bar);"); --EXPECTF-- ===TEST=== -Warning: PSI syntax error: Unexpected token ';' in %s001.psi on line 1 +Warning: PSI syntax error: Unexpected token ';' at pos 17 in %s001.psi on line 1 -Warning: PSI syntax error: Unexpected token 'int' in %s001.psi on line 1 +Warning: PSI syntax error: Unexpected token 'int' at pos 14 in %s001.psi on line 1 Warning: Type 'bar' cannot be aliased to struct 'foo' in %s001.psi on line 1 @@ -95,5 +95,5 @@ Warning: Cannot compute size of empty struct 'a' in %s001.psi on line 1 Warning: Unknown variable 'X' in numeric expression in %s001.psi on line 4 -Warning: PSI syntax error: Unexpected token '(' in %s001.psi on line 1 +Warning: PSI syntax error: Unexpected token '(' at pos 26 in %s001.psi on line 1 ===DONE=== -- 2.30.2