From d60f4bbdd315ddf42dbafeff0fd3d87d2e7a51f7 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Thu, 5 Nov 2015 12:13:48 +0100 Subject: [PATCH] flush --- Makefile.frag | 3 + php_psi.h | 10 ++- src/libffi.c | 15 ++++- src/libjit.c | 4 +- src/module.c | 152 ++++++++++++++++++++++++++++------------------ src/parser.h | 102 ++++++++++++++++++++----------- src/parser_proc.y | 49 ++++++++++++--- src/validator.c | 63 ++++++++++--------- 8 files changed, 255 insertions(+), 143 deletions(-) diff --git a/Makefile.frag b/Makefile.frag index 0f572d1..1c42778 100644 --- a/Makefile.frag +++ b/Makefile.frag @@ -1,6 +1,7 @@ # provide headers in builddir, so they do not end up in /usr/include/ext/psi/src PHP_PSI_HEADERS := $(addprefix $(PHP_PSI_BUILDDIR)/,$(PHP_PSI_HEADERS)) +PHP_PSI_SOURCES := $(addprefix $(PHP_PSI_SRCDIR)/,$(PHP_PSI_SOURCES)) $(PHP_PSI_BUILDDIR)/%.h: $(PHP_PSI_SRCDIR)/src/%.h @cat >$@ <$< @@ -24,6 +25,8 @@ lemon.c: ./lemon: lemon.c | lempar.c $(CC) -o $@ $< +$(PHP_PSI_SRCDIR)/src/%.c: $(PHP_PSI_BUILDDIR)/parser.h + touch $@ $(PHP_PSI_SRCDIR)/src/parser_proc.y: $(PHP_PSI_BUILDDIR)/parser.h touch $@ $(PHP_PSI_SRCDIR)/src/parser_proc.c: $(PHP_PSI_SRCDIR)/src/parser_proc.y $(LEMON) diff --git a/php_psi.h b/php_psi.h index f0e2ea2..2982402 100644 --- a/php_psi.h +++ b/php_psi.h @@ -23,15 +23,19 @@ extern zend_module_entry psi_module_entry; #include "parser.h" void psi_error(int type, const char *msg, ...); + size_t psi_t_alignment(token_t t); size_t psi_t_size(token_t t); size_t psi_t_align(token_t t, size_t s); + int psi_internal_type(impl_type *type); zend_internal_arg_info *psi_internal_arginfo(impl *impl); size_t psi_num_min_args(impl *impl); -void psi_to_int(impl_val *ret_val, decl_arg *func, zval *return_value); -void psi_to_double(impl_val *ret_val, decl_arg *func, zval *return_value); -void psi_to_string(impl_val *ret_val, decl_arg *func, zval *return_value); + +void psi_to_int(zval *return_value, token_t t, impl_val *ret_val, decl_var *var); +void psi_to_double(zval *return_value, token_t t, impl_val *ret_val, decl_var *var); +void psi_to_string(zval *return_value, token_t t, impl_val *ret_val, decl_var *var); + ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl); impl_val *psi_do_let(decl_arg *darg); void psi_do_set(zval *return_value, set_func *func, decl_vars *vars); diff --git a/src/libffi.c b/src/libffi.c index 2c68fbf..897affb 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -2,6 +2,13 @@ #include "php_psi.h" #include "libffi.h" +#undef PACKAGE +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION + #include #ifndef PSI_HAVE_FFI_CLOSURE_ALLOC @@ -117,7 +124,7 @@ typedef struct PSI_LibffiData { static inline PSI_LibffiData *PSI_LibffiDataAlloc(PSI_LibffiContext *context, impl *impl) { ffi_status rc; - size_t i, c = impl->decl->args->count; + size_t i, c = impl->decl->args ? impl->decl->args->count : 0; PSI_LibffiData *data = malloc(sizeof(*data) + c * sizeof(ffi_type *)); data->context = context; @@ -211,7 +218,7 @@ static void handler(ffi_cif *_sig, void *_result, void **_args, void *_data) return; } - if (data->impl->decl->args->count) { + if (data->impl->decl->args) { arg_ptr = malloc(data->impl->decl->args->count * sizeof(*arg_ptr)); arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm)); @@ -233,7 +240,9 @@ static void handler(ffi_cif *_sig, void *_result, void **_args, void *_data) for (i = 0; i < data->impl->stmts->set.count; ++i) { set_stmt *set = data->impl->stmts->set.list[i]; - psi_do_set(set->arg->_zv, set->val->func, set->val->vars); + if (set->arg->_zv) { + psi_do_set(set->arg->_zv, set->val->func, set->val->vars); + } } for (i = 0; i < data->impl->stmts->fre.count; ++i) { diff --git a/src/libjit.c b/src/libjit.c index 98ce029..9e43fd2 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -178,7 +178,9 @@ static void handler(jit_type_t _sig, void *result, void **_args, void *_data) for (i = 0; i < data->impl->stmts->set.count; ++i) { set_stmt *set = data->impl->stmts->set.list[i]; - psi_do_set(set->arg->_zv, set->val->func, set->val->vars); + if (set->arg->_zv) { + psi_do_set(set->arg->_zv, set->val->func, set->val->vars); + } } for (i = 0; i < data->impl->stmts->fre.count; ++i) { diff --git a/src/module.c b/src/module.c index ac08a95..e3658a7 100644 --- a/src/module.c +++ b/src/module.c @@ -94,35 +94,47 @@ size_t psi_num_min_args(impl *impl) return n; } -void psi_to_int(impl_val *ret_val, decl_arg *func, zval *return_value) +void psi_to_int(zval *return_value, token_t t, impl_val *ret_val, decl_var *var) { - switch (real_decl_type(func->type)->type) { + switch (t) { case PSI_T_FLOAT: + RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval); + convert_to_long(return_value); + break; case PSI_T_DOUBLE: - RETVAL_DOUBLE(deref_impl_val(0, ret_val, func)->dval); + RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval); convert_to_long(return_value); break; default: - RETVAL_LONG(deref_impl_val(0, ret_val, func)->lval); + RETVAL_LONG(deref_impl_val(ret_val, var)->lval); } } -void psi_to_double(impl_val *ret_val, decl_arg *func, zval *return_value) +void psi_to_double(zval *return_value, token_t t, impl_val *ret_val, decl_var *var) { - RETVAL_DOUBLE(deref_impl_val(0, ret_val, func)->dval); + switch (t) { + case PSI_T_FLOAT: + RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval); + break; + case PSI_T_DOUBLE: + RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval); + break; + default: + RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->lval); + break; + } } -void psi_to_string(impl_val *ret_val, decl_arg *func, zval *return_value) +void psi_to_string(zval *return_value, token_t t, impl_val *ret_val, decl_var *var) { - switch (real_decl_type(func->type)->type) { + switch (t) { case PSI_T_CHAR: case PSI_T_SINT8: case PSI_T_UINT8: - if (!func->var->pointer_level) { - char chr = ret_val->lval; - RETVAL_STRINGL(&chr, 1); + if (var->pointer_level == var->arg->var->pointer_level) { + RETVAL_STRINGL(&ret_val->cval, 1); } else { - ret_val = deref_impl_val(1, ret_val, func); + ret_val = deref_impl_val(ret_val, var); if (ret_val->ptr) { RETVAL_STRING(ret_val->ptr); } else { @@ -131,12 +143,15 @@ void psi_to_string(impl_val *ret_val, decl_arg *func, zval *return_value) } break; case PSI_T_FLOAT: + RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval); + convert_to_string(return_value); + break; case PSI_T_DOUBLE: - RETVAL_DOUBLE(deref_impl_val(0, ret_val, func)->dval); + RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval); convert_to_string(return_value); break; default: - RETVAL_LONG(deref_impl_val(0, ret_val, func)->lval); + RETVAL_LONG(deref_impl_val(ret_val, var)->lval); convert_to_string(return_value); break; } @@ -302,7 +317,7 @@ void psi_from_zval(impl_val *mem, decl_arg *spec, zval *zv, void **tmp) break; } default: - mem->lval = zval_get_long(zv); + mem->zend.lval = zval_get_long(zv); break; } } @@ -315,7 +330,6 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr) for (i = 0; i < s->args->count; ++i) { decl_struct_layout *layout = &s->layout[i]; decl_arg *darg = s->args->args[i]; - decl_type *type = real_decl_type(darg->type); zval *entry = zend_hash_str_find_ind(arr, darg->var->name, strlen(darg->var->name)); if (entry) { @@ -333,19 +347,17 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr) return mem; } -void psi_to_array(impl_val *ret_val, decl_arg *func, zval *return_value) +void psi_to_array(zval *return_value, token_t t, impl_val *ret_val, decl_var *var) { zval ele; unsigned i; impl_val tmp; - decl_type *type = real_decl_type(func->type); - token_t t = type->type; array_init(return_value); if (t == PSI_T_STRUCT) { - decl_struct *s = type->strct; - ret_val = deref_impl_val(func->var->pointer_level, ret_val, func); + decl_struct *s = real_decl_type(var->arg->type)->strct; + ret_val = deref_impl_val(ret_val, var); ZEND_ASSERT(s); for (i = 0; i < s->args->count; ++i) { @@ -358,25 +370,32 @@ void psi_to_array(impl_val *ret_val, decl_arg *func, zval *return_value) memset(&tmp, 0, sizeof(tmp)); memcpy(&tmp, ptr, layout.len); switch (real_decl_type(darg->type)->type) { + case PSI_T_CHAR: + if (darg->var->pointer_level) { + psi_to_string(&ztmp, real_decl_type(darg->type)->type, &tmp, darg->var); + break; + } + /* nobreak */ case PSI_T_INT: case PSI_T_LONG: - psi_to_int(&tmp, darg, &ztmp); - break; - case PSI_T_CHAR: - psi_to_string(&tmp, darg, &ztmp); + psi_to_int(&ztmp, real_decl_type(darg->type)->type, &tmp, darg->var); break; - EMPTY_SWITCH_DEFAULT_CASE(); + default: + printf("t=%d\n", real_decl_type(darg->type)->type); + abort(); } add_assoc_zval(return_value, darg->var->name, &ztmp); } return; } - ret_val = deref_impl_val(0, ret_val, func); - for (i = 0; i < func->var->array_size; ++i) { + ret_val = deref_impl_val(ret_val, var); + for (i = 0; i < var->arg->var->array_size; ++i) { impl_val *ptr = iterate(ret_val, t, i, &tmp); switch (t) { case PSI_T_FLOAT: + ZVAL_DOUBLE(&ele, (double) ptr->fval); + break; case PSI_T_DOUBLE: ZVAL_DOUBLE(&ele, ptr->dval); break; @@ -405,15 +424,15 @@ ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) } if (PSI_T_BOOL == iarg->type->type) { if (iarg->def) { - iarg->val.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0; + iarg->val.zend.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0; } - Z_PARAM_BOOL(iarg->val.bval); - } else if (PSI_T_INT == iarg->type->type) { + Z_PARAM_BOOL(iarg->val.zend.bval); + } else if (PSI_T_INT == iarg->type->type || PSI_T_LONG == iarg->type->type) { if (iarg->def) { - iarg->val.lval = zend_atol(iarg->def->text, strlen(iarg->def->text)); + iarg->val.zend.lval = zend_atol(iarg->def->text, strlen(iarg->def->text)); } - Z_PARAM_LONG(iarg->val.lval); - } else if (PSI_T_FLOAT == iarg->type->type) { + Z_PARAM_LONG(iarg->val.zend.lval); + } else if (PSI_T_FLOAT == iarg->type->type || PSI_T_DOUBLE == iarg->type->type) { if (iarg->def) { iarg->val.dval = zend_strtod(iarg->def->text, NULL); } @@ -425,11 +444,11 @@ ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) str.len = strlen(iarg->def->text) - 2; str.val = &iarg->def->text[1]; } - Z_PARAM_STR_EX(iarg->val.str, 1, 0); - if (iarg->val.str) { - zend_string_addref(iarg->val.str); + Z_PARAM_STR_EX(iarg->val.zend.str, 1, 0); + if (iarg->val.zend.str) { + zend_string_addref(iarg->val.zend.str); } else if (iarg->def) { - iarg->val.str = zend_string_init(str.val, str.len, 0); + iarg->val.zend.str = zend_string_init(str.val, str.len, 0); } } else if (PSI_T_ARRAY == iarg->type->type) { /* handled as _zv in let or set */ @@ -447,17 +466,35 @@ ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl) return SUCCESS; } +void *psi_do_calloc(let_calloc *alloc) +{ + decl_type *type = real_decl_type(alloc->type); + size_t size; + + if (type->type == PSI_T_STRUCT) { + /* psi_do_clean expects a NULL pointer after the struct */ + size = decl_struct_size(type->strct) + sizeof(void *); + } else { + size = psi_t_size(type->type); + } + + return ecalloc(alloc->n, size); +} + impl_val *psi_do_let(decl_arg *darg) { impl_val *arg_val = &darg->let->out; impl_arg *iarg = darg->let->arg; if (!iarg) { - /* + /* let foo = calloc(1, long); * let foo = NULL; * let foo; */ - if (darg->var->array_size) { + if (darg->let->val->func->type == PSI_T_CALLOC) { + arg_val->ptr = psi_do_calloc(darg->let->val->func->alloc); + darg->let->mem = arg_val->ptr; + } else if (darg->var->array_size) { arg_val->ptr = ecalloc(darg->var->array_size, sizeof(*arg_val)); darg->let->mem = arg_val->ptr; } else { @@ -465,26 +502,27 @@ impl_val *psi_do_let(decl_arg *darg) } return arg_val; } + switch (darg->let->val->func->type) { case PSI_T_BOOLVAL: if (iarg->type->type == PSI_T_BOOL) { - arg_val->cval = iarg->val.cval; + arg_val->cval = iarg->val.zend.bval; } else { arg_val->cval = zend_is_true(iarg->_zv); } break; case PSI_T_INTVAL: - if (iarg->type->type == PSI_T_INT) { - arg_val->lval = iarg->val.lval; + if (iarg->type->type == PSI_T_INT || iarg->type->type == PSI_T_LONG) { + arg_val->lval = iarg->val.zend.lval; } else { arg_val->lval = zval_get_long(iarg->_zv); } break; case PSI_T_STRVAL: if (iarg->type->type == PSI_T_STRING) { - arg_val->ptr = estrdup(iarg->val.str->val); + arg_val->ptr = estrdup(iarg->val.zend.str->val); darg->let->mem = arg_val->ptr; - zend_string_release(iarg->val.str); + zend_string_release(iarg->val.zend.str); } else { zend_string *zs = zval_get_string(iarg->_zv); arg_val->ptr = estrdup(zs->val); @@ -494,18 +532,14 @@ impl_val *psi_do_let(decl_arg *darg) break; case PSI_T_STRLEN: if (iarg->type->type == PSI_T_STRING) { - arg_val->lval = iarg->val.str->len; - zend_string_release(iarg->val.str); + arg_val->lval = iarg->val.zend.str->len; + zend_string_release(iarg->val.zend.str); } else { zend_string *zs = zval_get_string(iarg->_zv); arg_val->lval = zs->len; zend_string_release(zs); } break; - case PSI_T_CALLOC: - arg_val->ptr = calloc(1, darg->let->val->func->size); - darg->let->mem = arg_val->ptr; - break; case PSI_T_ARRVAL: if (iarg->type->type == PSI_T_ARRAY) { decl_type *type = real_decl_type(darg->type); @@ -533,10 +567,10 @@ void psi_do_set(zval *return_value, set_func *func, decl_vars *vars) switch (func->type) { case PSI_T_TO_STRING: - psi_to_string(val, vars->vars[0]->arg, return_value); + psi_to_string(return_value, real_decl_type(vars->vars[0]->arg->type)->type, val, vars->vars[0]); break; case PSI_T_TO_ARRAY: - psi_to_array(val, vars->vars[0]->arg, return_value); + psi_to_array(return_value, real_decl_type(vars->vars[0]->arg->type)->type, val, vars->vars[0]); break; EMPTY_SWITCH_DEFAULT_CASE(); } @@ -546,13 +580,13 @@ void psi_do_return(impl *impl, impl_val *ret_val, zval *return_value) { switch (impl->stmts->ret.list[0]->func->type) { case PSI_T_TO_STRING: - psi_to_string(ret_val, impl->decl->func, return_value); + psi_to_string(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, impl->decl->func->var); break; case PSI_T_TO_INT: - psi_to_int(ret_val, impl->decl->func, return_value); + psi_to_int(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, impl->decl->func->var); break; case PSI_T_TO_ARRAY: - psi_to_array(ret_val, impl->decl->func, return_value); + psi_to_array(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, impl->decl->func->var); break; EMPTY_SWITCH_DEFAULT_CASE(); } @@ -581,14 +615,14 @@ void psi_do_clean(impl *impl) switch (iarg->type->type) { case PSI_T_STRING: - if (iarg->val.str) { - zend_string_release(iarg->val.str); + if (iarg->val.zend.str) { + zend_string_release(iarg->val.zend.str); } break; } } - for (i = 0; i < impl->decl->args->count; ++i) { + if (impl->decl->args) for (i = 0; i < impl->decl->args->count; ++i) { decl_arg *darg = impl->decl->args->args[i]; if (darg->let && darg->let->mem) { diff --git a/src/parser.h b/src/parser.h index 1321f6c..28913f6 100644 --- a/src/parser.h +++ b/src/parser.h @@ -57,7 +57,7 @@ typedef struct decl_typedef { } decl_typedef; static inline decl_typedef *init_decl_typedef(char *name, decl_type *type) { - decl_typedef *t = malloc(sizeof(*t)); + decl_typedef *t = calloc(1, sizeof(*t)); t->alias = strdup(name); t->type = type; return t; @@ -101,7 +101,7 @@ typedef struct decl_var { } decl_var; static inline decl_var *init_decl_var(char *name, unsigned pl, unsigned as) { - decl_var *v = malloc(sizeof(*v)); + decl_var *v = calloc(1, sizeof(*v)); v->name = (char *) strdup((const char *) name); v->pointer_level = pl; v->array_size = as; @@ -120,7 +120,7 @@ typedef struct decl_arg { } decl_arg; static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) { - decl_arg *arg = malloc(sizeof(*arg)); + decl_arg *arg = calloc(1, sizeof(*arg)); arg->type = type; arg->var = var; arg->let = NULL; @@ -139,9 +139,9 @@ typedef struct decl_vars { } decl_vars; static inline decl_vars *init_decl_vars(decl_var *var) { - decl_vars *vars = malloc(sizeof(*vars)); + decl_vars *vars = calloc(1, sizeof(*vars)); vars->count = 1; - vars->vars = malloc(sizeof(*vars->vars)); + vars->vars = calloc(1, sizeof(*vars->vars)); vars->vars[0] = var; return vars; } @@ -168,9 +168,9 @@ typedef struct decl_args { } decl_args; static inline decl_args *init_decl_args(decl_arg *arg) { - decl_args *args = malloc(sizeof(*args)); + decl_args *args = calloc(1, sizeof(*args)); args->count = 1; - args->args = malloc(sizeof(*args->args)); + args->args = calloc(1, sizeof(*args->args)); args->args[0] = arg; return args; } @@ -196,7 +196,7 @@ typedef struct decl_abi { } decl_abi; static inline decl_abi *init_decl_abi(char *convention) { - decl_abi *abi = malloc(sizeof(*abi)); + decl_abi *abi = calloc(1, sizeof(*abi)); abi->convention = strdup(convention); return abi; } @@ -214,7 +214,7 @@ typedef struct decl { } decl; static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) { - decl *d = malloc(sizeof(*d)); + decl *d = calloc(1, sizeof(*d)); d->abi = abi; d->func = func; d->args = args; @@ -314,22 +314,30 @@ static inline void free_decl_structs(decl_structs *ss) { } typedef union impl_val { - unsigned char bval; char cval; + int8_t i8; short sval; + int16_t i16; int ival; + int32_t i32; + long lval; + int64_t i64; float fval; double dval; - zend_long lval; - zend_string *str; + union { + zend_bool bval; + zend_long lval; + zend_string *str; + } zend; void *ptr; + uint8_t _dbg[sizeof(void *)]; } impl_val; -static inline impl_val *deref_impl_val(unsigned level, impl_val *ret_val, decl_arg *darg) { +static inline impl_val *deref_impl_val(impl_val *ret_val, decl_var *var) { unsigned i; - for (i = level; i < darg->var->pointer_level && ret_val->ptr; ++i) { - ret_val = *(void **)ret_val; + for (i = 0; i < var->arg->var->pointer_level; ++i) { + ret_val = *(void **) ret_val; } return ret_val; } @@ -340,7 +348,7 @@ typedef struct impl_type { } impl_type; static inline impl_type *init_impl_type(token_t type, char *name) { - impl_type *t = malloc(sizeof(*t)); + impl_type *t = calloc(1, sizeof(*t)); t->type = type; t->name = (char *) strdup((const char *) name); @@ -358,7 +366,7 @@ typedef struct impl_var { } impl_var; static inline impl_var *init_impl_var(char *name, int is_reference) { - impl_var *var = malloc(sizeof(*var)); + impl_var *var = calloc(1, sizeof(*var)); var->name = (char *) strdup((const char *) name); var->reference = is_reference; return var; @@ -375,7 +383,7 @@ typedef struct impl_def_val { } impl_def_val; static inline impl_def_val *init_impl_def_val(PSI_Token *T) { - impl_def_val *def = malloc(sizeof(*def)); + impl_def_val *def = calloc(1, sizeof(*def)); def->type = T->type; def->text = strdup(T->text); return def; @@ -395,7 +403,7 @@ typedef struct impl_arg { } impl_arg; static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) { - impl_arg *arg = malloc(sizeof(*arg)); + impl_arg *arg = calloc(1, sizeof(*arg)); arg->type = type; arg->var = var; arg->def = def; @@ -417,8 +425,8 @@ typedef struct impl_args { } impl_args; static inline impl_args *init_impl_args(impl_arg *arg) { - impl_args *args = malloc(sizeof(*args)); - args->args = malloc(sizeof(*args->args)); + impl_args *args = calloc(1, sizeof(*args)); + args->args = calloc(1, sizeof(*args->args)); if (arg) { args->count = 1; args->args[0] = arg; @@ -453,7 +461,7 @@ typedef struct impl_func { } impl_func; static inline impl_func *init_impl_func(char *name, impl_args *args, impl_type *type, int ret_reference) { - impl_func *func = malloc(sizeof(*func)); + impl_func *func = calloc(1, sizeof(*func)); func->name = strdup(name); func->args = args ? args : init_impl_args(NULL); func->return_type = type; @@ -468,21 +476,41 @@ static inline void free_impl_func(impl_func *f) { free(f); } +typedef struct let_calloc { + size_t n; + decl_type *type; +} let_calloc; + +static inline let_calloc *init_let_calloc(long n, decl_type *type) { + let_calloc *alloc = calloc(1, sizeof(*alloc)); + alloc->n = n; + alloc->type = type; + return alloc; +} + +static inline void free_let_calloc(let_calloc *alloc) { + free_decl_type(alloc->type); + free(alloc); +} + typedef struct let_func { token_t type; char *name; - size_t size; + let_calloc *alloc; } let_func; -static inline let_func *init_let_func(token_t type, char *name, size_t size) { - let_func *func = malloc(sizeof(*func)); +static inline let_func *init_let_func(token_t type, char *name, let_calloc *alloc) { + let_func *func = calloc(1, sizeof(*func)); func->type = type; func->name = strdup(name); - func->size = size; + func->alloc = alloc; return func; } static inline void free_let_func(let_func *func) { + if (func->alloc) { + free_let_calloc(func->alloc); + } free(func->name); free(func); } @@ -494,7 +522,7 @@ typedef struct let_value { } let_value; static inline let_value *init_let_value(let_func *func, impl_var *var, int is_reference) { - let_value *val = malloc(sizeof(*val)); + let_value *val = calloc(1, sizeof(*val)); val->is_reference = is_reference; val->func = func; val->var = var; @@ -541,7 +569,7 @@ typedef struct set_func { } set_func; static inline set_func *init_set_func(token_t type, char *name) { - set_func *func = malloc(sizeof(*func)); + set_func *func = calloc(1, sizeof(*func)); func->type = type; func->name = (char *) strdup((const char *) name); return func; @@ -558,7 +586,7 @@ typedef struct set_value { } set_value; static inline set_value *init_set_value(set_func *func, decl_vars *vars) { - set_value *val = malloc(sizeof(*val)); + set_value *val = calloc(1, sizeof(*val)); val->func = func; val->vars = vars; return val; @@ -577,7 +605,7 @@ typedef struct set_stmt { } set_stmt; static inline set_stmt *init_set_stmt(impl_var *var, set_value *val) { - set_stmt *set = malloc(sizeof(*set)); + set_stmt *set = calloc(1, sizeof(*set)); set->var = var; set->val = val; return set; @@ -595,7 +623,7 @@ typedef struct return_stmt { } return_stmt; static inline return_stmt *init_return_stmt(set_func *func, decl_var *decl) { - return_stmt *ret = malloc(sizeof(*ret)); + return_stmt *ret = calloc(1, sizeof(*ret)); ret->func = func; ret->decl = decl; return ret; @@ -612,7 +640,7 @@ typedef struct free_stmt { } free_stmt; static inline free_stmt *init_free_stmt(decl_vars *vars) { - free_stmt *free_ = malloc(sizeof(*free_)); + free_stmt *free_ = calloc(1, sizeof(*free_)); free_->vars = vars; return free_; } @@ -634,7 +662,7 @@ typedef struct impl_stmt { } impl_stmt; static inline impl_stmt *init_impl_stmt(token_t type, void *ptr) { - impl_stmt *stmt = malloc(sizeof(*stmt)); + impl_stmt *stmt = calloc(1, sizeof(*stmt)); stmt->type = type; stmt->s.ptr = ptr; return stmt; @@ -736,7 +764,7 @@ typedef struct impl { } impl; static inline impl *init_impl(impl_func *func, impl_stmts *stmts) { - impl *i = malloc(sizeof(*i)); + impl *i = calloc(1, sizeof(*i)); i->func = func; i->stmts = stmts; return i; @@ -778,7 +806,7 @@ typedef struct const_type { } const_type; static inline const_type *init_const_type(token_t type, const char *name) { - const_type *ct = malloc(sizeof(*ct)); + const_type *ct = calloc(1, sizeof(*ct)); ct->type = type; ct->name = strdup(name); return ct; @@ -796,7 +824,7 @@ typedef struct constant { } constant; static inline constant *init_constant(const_type *type, char *name, impl_def_val *val) { - constant *c = malloc(sizeof(*c)); + constant *c = calloc(1, sizeof(*c)); c->type = type; c->name = strdup(name); c->val = val; @@ -901,7 +929,7 @@ static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) { token_len = P->cur - P->tok; - T = malloc(sizeof(*T) + token_len); + T = calloc(1, sizeof(*T) + token_len); T->type = P->num; T->line = P->line; T->size = token_len; diff --git a/src/parser_proc.y b/src/parser_proc.y index 43ae161..efffcf7 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -54,11 +54,14 @@ block ::= decl_struct(strct). { } %type decl_struct {decl_struct*} +%destructor decl_struct {free_decl_struct($$);} decl_struct(strct) ::= STRUCT NAME(N) LBRACE struct_args(args) RBRACE. { strct = init_decl_struct(N->text, args); + free(N); } %type const_type {const_type*} +%destructor const_type {free_const_type($$);} const_type(type_) ::= BOOL(T). { type_ = init_const_type(T->type, T->text); free(T); @@ -76,12 +79,14 @@ const_type(type_) ::= STRING(T). { free(T); } %type constant {constant*} +%destructor constant {free_constant($$);} constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) EOS. { constant = init_constant(type, T->text, val); free(T); } %type decl_typedef {decl_typedef*} +%destructor decl_typedef {free_decl_typedef($$);} decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, type); free(ALIAS); @@ -99,17 +104,20 @@ decl_typedef(def) ::= TYPEDEF decl_struct(s) NAME(ALIAS) EOS. { } %type decl {decl*} +%destructor decl {free_decl($$);} decl(decl) ::= decl_abi(abi) decl_arg(func) LPAREN decl_args(args) RPAREN EOS. { decl = init_decl(abi, func, args); } %type decl_abi {decl_abi*} +%destructor decl_abi {free_decl_abi($$);} decl_abi(abi) ::= NAME(T). { abi = init_decl_abi(T->text); free(T); } %type decl_var {decl_var*} +%destructor decl_var {free_decl_var($$);} decl_var(var) ::= NAME(T). { var = init_decl_var(T->text, 0, 0); free(T); @@ -130,6 +138,7 @@ decl_var(var) ::= pointers(p) NAME(T) LBRACKET NUMBER(D) RBRACKET. { } %type decl_vars {decl_vars*} +%destructor decl_vars {free_decl_vars($$);} decl_vars(vars) ::= decl_var(var). { vars = init_decl_vars(var); } @@ -138,11 +147,13 @@ decl_vars(vars) ::= decl_vars(vars_) COMMA decl_var(var). { } %type decl_arg {decl_arg*} -decl_arg(arg) ::= decl_type(type) decl_var(var). { - arg = init_decl_arg(type, var); +%destructor decl_arg {free_decl_arg($$);} +decl_arg(arg_) ::= decl_type(type) decl_var(var). { + arg_ = var->arg = init_decl_arg(type, var); } %type decl_args {decl_args*} +%destructor decl_args {free_decl_args($$);} decl_args ::= VOID. decl_args(args) ::= decl_arg(arg). { args = init_decl_args(arg); @@ -151,6 +162,7 @@ decl_args(args) ::= decl_args(args_) COMMA decl_arg(arg). { args = add_decl_arg(args_, arg); } %type struct_args {decl_args*} +%destructor struct_args {free_decl_args($$);} struct_args(args) ::= decl_arg(arg) EOS. { args = init_decl_args(arg); } @@ -159,6 +171,7 @@ struct_args(args) ::= struct_args(args_) decl_arg(arg) EOS. { } %type decl_type {decl_type*} +%destructor decl_type {free_decl_type($$);} decl_type(type_) ::= VOID(T). { type_ = init_decl_type(T->type, T->text); free(T); @@ -235,6 +248,7 @@ impl(impl) ::= impl_func(func) LBRACE impl_stmts(stmts) RBRACE. { } %type impl_func {impl_func*} +%destructor impl_func {free_impl_func($$);} impl_func(func) ::= FUNCTION NSNAME(NAME) impl_args(args) COLON impl_type(type). { func = init_impl_func(NAME->text, args, type, 0); free(NAME); @@ -245,6 +259,7 @@ impl_func(func) ::= FUNCTION REFERENCE NSNAME(NAME) impl_args(args) COLON impl_t } %type impl_def_val {impl_def_val*} +%destructor impl_def_val {free_impl_def_val($$);} impl_def_val(def) ::= NULL(T). { def = init_impl_def_val(T); free(T); @@ -267,6 +282,7 @@ impl_def_val(def) ::= QUOTED_STRING(T). { } %type impl_var {impl_var*} +%destructor impl_var {free_impl_var($$);} impl_var(var) ::= DOLLAR NAME(T). { var = init_impl_var(T->text, 0); free(T); @@ -277,6 +293,7 @@ impl_var(var) ::= REFERENCE DOLLAR NAME(T). { } %type impl_arg {impl_arg*} +%destructor impl_arg {free_impl_arg($$);} impl_arg(arg) ::= impl_type(type) impl_var(var). { arg = init_impl_arg(type, var, NULL); } @@ -285,6 +302,7 @@ impl_arg(arg) ::= impl_type(type) impl_var(var) EQUALS impl_def_val(def). { } %type impl_args {impl_args*} +%destructor impl_args {free_impl_args($$);} impl_args(args) ::= LPAREN RPAREN. { args = NULL; } @@ -292,6 +310,7 @@ impl_args(args) ::= LPAREN impl_arg_list(args_) RPAREN. { args = args_; } %type impl_arg_list {impl_args*} +%destructor impl_arg_list {free_impl_args($$);} impl_arg_list(args) ::= impl_arg(arg). { args = init_impl_args(arg); } @@ -324,6 +343,7 @@ impl_stmt(stmt) ::= free_stmt(free). { } %type let_stmt {let_stmt*} +%destructor let_stmt {free_let_stmt($$);} let_stmt(let) ::= LET decl_var(var) EOS. { let = init_let_stmt(var, NULL); } @@ -332,13 +352,15 @@ let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. { } %type let_value {let_value*} +%destructor let_value {free_let_value($$);} let_value(val) ::= CALLOC(F) LPAREN NUMBER(N) COMMA decl_type(t) RPAREN. { val = init_let_value( init_let_func(F->type, F->text, - atol(N->text) * psi_t_size(real_decl_type(t)->type) + init_let_calloc( + atol(N->text), t + ) ), NULL, 0 ); - free_decl_type(t); free(F); free(N); } @@ -356,42 +378,46 @@ let_value(val) ::= NULL. { } %type let_func {let_func*} +%destructor let_func {free_let_func($$);} let_func(func) ::= STRLEN(T). { - func = init_let_func(T->type, T->text, 0); + func = init_let_func(T->type, T->text, NULL); free(T); } let_func(func) ::= STRVAL(T). { - func = init_let_func(T->type, T->text, 0); + func = init_let_func(T->type, T->text, NULL); free(T); } let_func(func) ::= INTVAL(T). { - func = init_let_func(T->type, T->text, 0); + func = init_let_func(T->type, T->text, NULL); free(T); } let_func(func) ::= FLOATVAL(T). { - func = init_let_func(T->type, T->text, 0); + func = init_let_func(T->type, T->text, NULL); free(T); } let_func(func) ::= BOOLVAL(T). { - func = init_let_func(T->type, T->text, 0); + func = init_let_func(T->type, T->text, NULL); free(T); } let_func(func) ::= ARRVAL(T). { - func = init_let_func(T->type, T->text, 0); + func = init_let_func(T->type, T->text, NULL); free(T); } %type set_stmt {set_stmt*} +%destructor set_stmt {free_set_stmt($$);} set_stmt(set) ::= SET impl_var(var) EQUALS set_value(val) EOS. { set = init_set_stmt(var, val); } %type set_value {set_value*} +%destructor set_value {free_set_value($$);} set_value(val) ::= set_func(func) LPAREN decl_vars(vars) RPAREN. { val = init_set_value(func, vars); } %type set_func {set_func*} +%destructor set_func {free_set_func($$);} set_func(func) ::= TO_ARRAY(T). { func = init_set_func(T->type, T->text); free(T); @@ -418,16 +444,19 @@ set_func(func) ::= VOID(T). { } %type return_stmt {return_stmt*} +%destructor return_stmt {free_return_stmt($$);} return_stmt(ret) ::= RETURN set_func(func) LPAREN decl_var(var) RPAREN EOS. { ret = init_return_stmt(func, var); } %type free_stmt {free_stmt*} +%destructor free_stmt {free_free_stmt($$);} free_stmt(free) ::= FREE decl_vars(vars) EOS. { free = init_free_stmt(vars); } %type impl_type {impl_type*} +%destructor impl_type {free_impl_type($$);} impl_type(type_) ::= VOID(T). { type_ = init_impl_type(T->type, T->text); free(T); diff --git a/src/validator.c b/src/validator.c index d4deddf..7bc2f70 100644 --- a/src/validator.c +++ b/src/validator.c @@ -92,21 +92,15 @@ static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type } return 0; } -static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) { +static inline int validate_decl_type(PSI_Validator *V, decl_type *type) { switch (type->type) { case PSI_T_NAME: if (!V->defs || !locate_decl_type_alias(V->defs, type)) { - V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';" - " Use 'typedef ;' statement", - type->name, arg->var->name); return 0; } - return validate_decl_type(V, arg, type->real); + return validate_decl_type(V, type->real); case PSI_T_STRUCT: if (!V->structs || !locate_decl_type_struct(V->structs, type)) { - V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';" - " Use 'typedef struct ;' statement", - type->name, arg->var->name); return 0; } break; @@ -133,26 +127,6 @@ static inline int validate_typedefs(PSI_Validator *V) { return 1; } -static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func) -{ - if (!strcmp(func->var->name, "dlsym")) { - V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)"); - return 0; - } - - if (!validate_decl_type(V, func, func->type)) { - return 0; - } -#ifndef RTLD_NEXT -# define RTLD_NEXT ((void *) -1l) -#endif - decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name); - if (!decl->dlptr) { - V->error(PSI_WARNING, "Failed to located symbol '%s': %s", - func->var->name, dlerror()); - } - return 1; -} static const char * const abi_ccs[] = { "default", /* \ */ "extern", /* > - all the same */ @@ -163,7 +137,7 @@ static const char * const abi_ccs[] = { static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { size_t i; - for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++ i) { + for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++i) { if (strcasecmp(abi->convention, abi_ccs[i])) { return 1; } @@ -172,7 +146,9 @@ static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { return 0; } static inline int validate_decl_arg(PSI_Validator *V, decl_arg *arg) { - if (!validate_decl_type(V, arg, arg->type)) { + if (!validate_decl_type(V, arg->type)) { + V->error(PSI_WARNING, "Cannot use '%s' as type for '%s'", + arg->type->name, arg->var->name); return 0; } return 1; @@ -187,6 +163,26 @@ static inline int validate_decl_args(PSI_Validator *V, decl_args *args) { } return 1; } +static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func) +{ + if (!strcmp(func->var->name, "dlsym")) { + V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)"); + return 0; + } + + if (!validate_decl_arg(V, func)) { + return 0; + } +#ifndef RTLD_NEXT +# define RTLD_NEXT ((void *) -1l) +#endif + decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name); + if (!decl->dlptr) { + V->error(PSI_WARNING, "Failed to located symbol '%s': %s", + func->var->name, dlerror()); + } + return 1; +} static inline int validate_decl(PSI_Validator *V, decl *decl) { if (!validate_decl_abi(V, decl->abi)) { return 0; @@ -344,6 +340,13 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * let_stmt *let = stmts->let.list[i]; int check = 0; + if (let->val && let->val->func && let->val->func->alloc) { + if (!validate_decl_type(V, let->val->func->alloc->type)) { + V->error(PSI_WARNING, "Cannot use '%s' as type for calloc in `let` statement", + let->val->func->alloc->type->name); + return 0; + } + } if (let->val && let->val->var) { if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) { impl_arg *iarg = impl->func->args->args[j]; -- 2.30.2