validation and marshaling of structs/unions
authorMichael Wallner <mike@php.net>
Mon, 12 Sep 2016 17:59:47 +0000 (19:59 +0200)
committerMichael Wallner <mike@php.net>
Tue, 18 Oct 2016 08:30:49 +0000 (10:30 +0200)
12 files changed:
m4/signal.m4
src/context.h
src/context_validate.c
src/engine.c
src/libffi.c
src/libjit.c
src/marshal.c
src/parser.h
src/parser.re
src/parser_proc.y
src/types/let_val.h
tests/parser/validate001.phpt

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