flush
authorMichael Wallner <mike@php.net>
Thu, 5 Nov 2015 11:13:48 +0000 (12:13 +0100)
committerMichael Wallner <mike@php.net>
Thu, 5 Nov 2015 11:13:48 +0000 (12:13 +0100)
Makefile.frag
php_psi.h
src/libffi.c
src/libjit.c
src/module.c
src/parser.h
src/parser_proc.y
src/validator.c

index 0f572d1..1c42778 100644 (file)
@@ -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)
index f0e2ea2..2982402 100644 (file)
--- 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);
index 2c68fbf..897affb 100644 (file)
@@ -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 <ffi.h>
 
 #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) {
index 98ce029..9e43fd2 100644 (file)
@@ -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) {
index ac08a95..e3658a7 100644 (file)
@@ -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) {
index 1321f6c..28913f6 100644 (file)
@@ -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;
index 43ae161..efffcf7 100644 (file)
@@ -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);
index d4deddf..7bc2f70 100644 (file)
@@ -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 <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;
@@ -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];