# 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 >$@ <$<
./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)
#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);
#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 <ffi.h>
#ifndef PSI_HAVE_FFI_CLOSURE_ALLOC
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;
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));
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) {
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) {
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 {
}
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;
}
break;
}
default:
- mem->lval = zval_get_long(zv);
+ mem->zend.lval = zval_get_long(zv);
break;
}
}
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) {
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) {
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;
}
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);
}
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 */
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 {
}
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);
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);
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();
}
{
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();
}
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) {
} 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;
} 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;
} 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;
} 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;
}
} 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;
}
} 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;
}
} 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;
}
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;
}
} 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);
} 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;
} 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;
} 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;
} 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;
} 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;
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);
}
} 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;
} 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;
} 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;
} 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;
} 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;
} 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_;
}
} 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;
} 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;
} 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;
} 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;
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;
}
%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);
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);
}
%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);
}
%type decl_vars {decl_vars*}
+%destructor decl_vars {free_decl_vars($$);}
decl_vars(vars) ::= decl_var(var). {
vars = init_decl_vars(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);
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);
}
}
%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);
}
%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);
}
%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);
}
%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);
}
%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);
}
}
%type impl_args {impl_args*}
+%destructor impl_args {free_impl_args($$);}
impl_args(args) ::= LPAREN RPAREN. {
args = NULL;
}
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);
}
}
%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);
}
}
%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);
}
}
%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);
}
%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);
}
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 <type> <alias>;' 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 <name> <alias>;' statement",
- type->name, arg->var->name);
return 0;
}
break;
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 */
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;
}
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;
}
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;
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];