X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fvalidator.c;h=d4deddf5e0717574e183216ea92bdfb54d14078d;hp=5a6f5d96de0782acad1f0aa451262a8bf1fc1cab;hb=22b4a95d8fd6525e4539f843ba5bebb9a56e89f2;hpb=be3ceffdd27422aae6ba44d31d868fb12d08957a diff --git a/src/validator.c b/src/validator.c index 5a6f5d9..d4deddf 100644 --- a/src/validator.c +++ b/src/validator.c @@ -6,6 +6,8 @@ #include +#include "php.h" +#include "php_psi.h" #include "validator.h" PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P) @@ -61,6 +63,7 @@ static int validate_lib(PSI_Validator *V) { } return 1; } + static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { size_t i; @@ -75,14 +78,38 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { } return 0; } +static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) { + size_t i; + + if (type->strct) { + return 1; + } + for (i = 0; i < structs->count; ++i) { + if (!strcmp(structs->list[i]->name, type->name)) { + type->strct = structs->list[i]; + return 1; + } + } + return 0; +} static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) { - if (type->type == PSI_T_NAME) { + switch (type->type) { + case PSI_T_NAME: if (!V->defs || !locate_decl_type_alias(V->defs, type)) { V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';" - " Use 'typedef ;' statement", + " Use 'typedef ;' statement", + type->name, arg->var->name); + return 0; + } + return validate_decl_type(V, arg, type->real); + case PSI_T_STRUCT: + if (!V->structs || !locate_decl_type_struct(V->structs, type)) { + V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';" + " Use 'typedef struct ;' statement", type->name, arg->var->name); return 0; } + break; } return 1; } @@ -116,8 +143,10 @@ static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *fun if (!validate_decl_type(V, func, func->type)) { return 0; } - - decl->dlptr = dlsym(V->dlopened, func->var->name); +#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()); @@ -142,17 +171,17 @@ static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention); return 0; } -static inline int validate_decl_arg(PSI_Validator *V, decl *decl, decl_arg *arg) { +static inline int validate_decl_arg(PSI_Validator *V, decl_arg *arg) { if (!validate_decl_type(V, arg, arg->type)) { return 0; } return 1; } -static inline int validate_decl_args(PSI_Validator *V, decl *decl, decl_args *args) { +static inline int validate_decl_args(PSI_Validator *V, decl_args *args) { size_t i; for (i = 0; i < args->count; ++i) { - if (!validate_decl_arg(V, decl, args->args[i])) { + if (!validate_decl_arg(V, args->args[i])) { return 0; } } @@ -165,7 +194,7 @@ static inline int validate_decl(PSI_Validator *V, decl *decl) { if (!validate_decl_func(V, decl, decl->func)) { return 0; } - if (decl->args && !validate_decl_args(V, decl, decl->args)) { + if (decl->args && !validate_decl_args(V, decl->args)) { return 0; } return 1; @@ -180,6 +209,39 @@ static inline int validate_decls(PSI_Validator *V) { } return 1; } +static inline int validate_struct(PSI_Validator *V, decl_struct *s) { + size_t i; + + if (!validate_decl_args(V, s->args)) { + return 0; + } + + s->layout = calloc(s->args->count, sizeof(*s->layout)); + for (i = 0; i < s->args->count; ++i) { + decl_arg *darg = s->args->args[i]; + decl_type *type = real_decl_type(darg->type); + token_t t = darg->var->pointer_level ? PSI_T_POINTER : type->type; + + if (i) { + decl_struct_layout *l = &s->layout[i-1]; + s->layout[i].pos = psi_t_align(t, l->pos + l->len); + } else { + s->layout[i].pos = 0; + } + s->layout[i].len = psi_t_size(t); + } + return 1; +} +static inline int validate_structs(PSI_Validator *V) { + size_t i; + + for (i = 0; i < V->structs->count; ++i) { + if (!validate_struct(V, V->structs->list[i])) { + return 0; + } + } + return 1; +} static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) { /* FIXME */ @@ -238,7 +300,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * if (stmts->ret.count != 1) { if (stmts->ret.count > 1) { V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;" - "found %zu, exactly one is needed", + " found %zu, exactly one is needed", impl->func->name, stmts->ret.count); } else { V->error(PSI_WARNING, "Missing `ret` statement for implementation %s", @@ -256,7 +318,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * } /* check that we have a let stmt for every decl arg */ - for (i = 0; i < decl->args->count; ++i) { + if (decl->args) for (i = 0; i < decl->args->count; ++i) { decl_arg *darg = decl->args->args[i]; int check = 0; @@ -271,7 +333,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * } if (!check) { V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'" - "of declaration '%s' for implementation '%s'", + " of declaration '%s' for implementation '%s'", darg->type->name, (int) darg->var->pointer_level, "*****", darg->var->name, decl->func->var->name, impl->func->name); return 0; @@ -282,8 +344,8 @@ 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->var) { - for (j = 0; j < impl->func->args->count; ++j) { + 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]; if (!strcmp(let->val->var->name, iarg->var->name)) { @@ -305,7 +367,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * set_stmt *set = stmts->set.list[i]; int check = 0; - for (j = 0; j < impl->func->args->count; ++j) { + if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) { impl_arg *iarg = impl->func->args->args[j]; if (!strcmp(set->var->name, iarg->var->name)) { @@ -325,7 +387,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * decl_var *set_var = set->val->vars->vars[j]; check = 0; - for (k = 0; k < decl->args->count; ++k) { + if (decl->args) for (k = 0; k < decl->args->count; ++k) { decl_arg *set_arg = decl->args->args[k]; if (!strcmp(set_var->name, set_arg->var->name)) { @@ -354,7 +416,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * if (!strcmp(free_var->name, decl->func->var->name)) { continue; } - for (k = 0; k < decl->args->count; ++k) { + if (decl->args) for (k = 0; k < decl->args->count; ++k) { decl_arg *free_arg = decl->args->args[k]; if (!strcmp(free_var->name, free_arg->var->name)) { @@ -406,10 +468,13 @@ int PSI_ValidatorValidate(PSI_Validator *V) if (V->defs && !validate_typedefs(V)) { return 0; } + if (V->structs && !validate_structs(V)) { + return 0; + } if (V->decls && !validate_decls(V)) { return 0; } - if (V->impls && !validate_impls(V)) { + if (!V->impls || !validate_impls(V)) { return 0; } return 1;