From: Michael Wallner Date: Fri, 30 Oct 2015 09:16:28 +0000 (+0100) Subject: flush X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=commitdiff_plain;h=22b4a95d8fd6525e4539f843ba5bebb9a56e89f2 flush --- diff --git a/php_psi.h b/php_psi.h index 0889801..f0e2ea2 100644 --- a/php_psi.h +++ b/php_psi.h @@ -23,7 +23,9 @@ 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); diff --git a/src/module.c b/src/module.c index 3e7de89..ee1230f 100644 --- a/src/module.c +++ b/src/module.c @@ -145,12 +145,16 @@ void psi_to_string(impl_val *ret_val, decl_arg *func, zval *return_value) size_t psi_t_alignment(token_t t) { size_t align; -# define PSI_TAS_D(T) struct TAS_ ##T { \ +#define PSI_TAS_D(T) struct PSI_TAS_ ##T { \ char c; \ - ##T x; \ + T x; \ } -# define PSI_TAS_C(T) align = offsetof(struct TAS_ ##T, x) -# define PSI_TAS_CASE(T) { \ +#define PSI_TAS_P(T) struct PSI_TAS_ ## T ## _pointer { \ + char c; \ + T *x; \ +} +#define PSI_TAS_C(T) align = offsetof(struct PSI_TAS_ ##T, x) +#define PSI_TAS_CASE(T) { \ PSI_TAS_D(T); \ PSI_TAS_C(T); \ } @@ -197,8 +201,19 @@ size_t psi_t_alignment(token_t t) case PSI_T_DOUBLE: PSI_TAS_CASE(double); break; + case PSI_T_SIZE_T: + PSI_TAS_CASE(size_t); + break; + case PSI_T_POINTER: + { + PSI_TAS_P(char); + PSI_TAS_C(char_pointer); + } + break; EMPTY_SWITCH_DEFAULT_CASE(); } + + return align; } size_t psi_t_size(token_t t) @@ -240,6 +255,12 @@ size_t psi_t_size(token_t t) case PSI_T_DOUBLE: size = sizeof(double); break; + case PSI_T_SIZE_T: + size = sizeof(size_t); + break; + case PSI_T_POINTER: + size = sizeof(char *); + break; EMPTY_SWITCH_DEFAULT_CASE(); } return size; diff --git a/src/parser.h b/src/parser.h index 8df41ea..a39d15e 100644 --- a/src/parser.h +++ b/src/parser.h @@ -221,7 +221,9 @@ static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) { static inline void free_decl(decl *d) { free_decl_abi(d->abi); free_decl_arg(d->func); - free_decl_args(d->args); + if (d->args) { + free_decl_args(d->args); + } free(d); } @@ -268,7 +270,9 @@ static inline decl_struct *init_decl_struct(char *name, decl_args *args) { } static inline void free_decl_struct(decl_struct *s) { - free_decl_args(s->args); + if (s->args) { + free_decl_args(s->args); + } free(s->name); free(s); } diff --git a/src/parser.re b/src/parser.re index c134ffd..0bca5b0 100644 --- a/src/parser.re +++ b/src/parser.re @@ -189,6 +189,7 @@ token_t PSI_ParserScan(PSI_Parser *P) LONG = 'long'; FLOAT = 'float'; DOUBLE = 'double'; + SIZE_T = 'size_t'; SINT8 = 'sint8'; UINT8 = 'uint8'; SINT16 = 'sint16'; @@ -249,6 +250,7 @@ token_t PSI_ParserScan(PSI_Parser *P) LONG {RETURN(PSI_T_LONG);} FLOAT {RETURN(PSI_T_FLOAT);} DOUBLE {RETURN(PSI_T_DOUBLE);} + SIZE_T {RETURN(PSI_T_SIZE_T);} SINT8 {RETURN(PSI_T_SINT8);} UINT8 {RETURN(PSI_T_UINT8);} SINT16 {RETURN(PSI_T_SINT16);} diff --git a/src/parser_proc.h b/src/parser_proc.h index bdc0b45..a427b08 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -25,36 +25,37 @@ #define PSI_T_SHORT 25 #define PSI_T_LONG 26 #define PSI_T_DOUBLE 27 -#define PSI_T_SINT8 28 -#define PSI_T_UINT8 29 -#define PSI_T_SINT16 30 -#define PSI_T_UINT16 31 -#define PSI_T_SINT32 32 -#define PSI_T_UINT32 33 -#define PSI_T_SINT64 34 -#define PSI_T_UINT64 35 -#define PSI_T_FUNCTION 36 -#define PSI_T_COLON 37 -#define PSI_T_REFERENCE 38 -#define PSI_T_NULL 39 -#define PSI_T_TRUE 40 -#define PSI_T_FALSE 41 -#define PSI_T_DOLLAR 42 -#define PSI_T_LET 43 -#define PSI_T_CALLOC 44 -#define PSI_T_STRLEN 45 -#define PSI_T_STRVAL 46 -#define PSI_T_INTVAL 47 -#define PSI_T_FLOATVAL 48 -#define PSI_T_BOOLVAL 49 -#define PSI_T_SET 50 -#define PSI_T_TO_ARRAY 51 -#define PSI_T_TO_STRING 52 -#define PSI_T_TO_INT 53 -#define PSI_T_TO_FLOAT 54 -#define PSI_T_TO_BOOL 55 -#define PSI_T_RETURN 56 -#define PSI_T_FREE 57 -#define PSI_T_MIXED 58 -#define PSI_T_ARRAY 59 -#define PSI_T_POINTER 60 +#define PSI_T_SIZE_T 28 +#define PSI_T_SINT8 29 +#define PSI_T_UINT8 30 +#define PSI_T_SINT16 31 +#define PSI_T_UINT16 32 +#define PSI_T_SINT32 33 +#define PSI_T_UINT32 34 +#define PSI_T_SINT64 35 +#define PSI_T_UINT64 36 +#define PSI_T_FUNCTION 37 +#define PSI_T_COLON 38 +#define PSI_T_REFERENCE 39 +#define PSI_T_NULL 40 +#define PSI_T_TRUE 41 +#define PSI_T_FALSE 42 +#define PSI_T_DOLLAR 43 +#define PSI_T_LET 44 +#define PSI_T_CALLOC 45 +#define PSI_T_STRLEN 46 +#define PSI_T_STRVAL 47 +#define PSI_T_INTVAL 48 +#define PSI_T_FLOATVAL 49 +#define PSI_T_BOOLVAL 50 +#define PSI_T_SET 51 +#define PSI_T_TO_ARRAY 52 +#define PSI_T_TO_STRING 53 +#define PSI_T_TO_INT 54 +#define PSI_T_TO_FLOAT 55 +#define PSI_T_TO_BOOL 56 +#define PSI_T_RETURN 57 +#define PSI_T_FREE 58 +#define PSI_T_MIXED 59 +#define PSI_T_ARRAY 60 +#define PSI_T_POINTER 61 diff --git a/src/parser_proc.y b/src/parser_proc.y index d368914..59477ba 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -42,6 +42,9 @@ block ::= impl(impl). { } block ::= decl_typedef(def). { P->defs = add_decl_typedef(P->defs, def); + if (def->type->strct) { + P->structs = add_decl_struct(P->structs, def->type->strct); + } } block ::= constant(constant). { P->consts = add_constant(P->consts, constant); @@ -89,6 +92,11 @@ decl_typedef(def) ::= TYPEDEF STRUCT(S) NAME(N) NAME(ALIAS) EOS. { free(S); free(N); } +decl_typedef(def) ::= TYPEDEF decl_struct(s) NAME(ALIAS) EOS. { + def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, s->name)); + def->type->strct = s; + free(ALIAS); +} %type decl {decl*} decl(decl) ::= decl_abi(abi) decl_arg(func) LPAREN decl_args(args) RPAREN EOS. { @@ -179,6 +187,10 @@ decl_type(type_) ::= DOUBLE(T). { type_ = init_decl_type(T->type, T->text); free(T); } +decl_type(type_) ::= SIZE_T(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} decl_type(type_) ::= SINT8(T). { type_ = init_decl_type(T->type, T->text); free(T); diff --git a/src/validator.c b/src/validator.c index 19956b7..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) @@ -141,7 +143,9 @@ static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *fun 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", @@ -214,15 +218,17 @@ static inline int validate_struct(PSI_Validator *V, decl_struct *s) { s->layout = calloc(s->args->count, sizeof(*s->layout)); for (i = 0; i < s->args->count; ++i) { - decl_type *t = real_decl_type(s->args->args[i]->type); + 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->type, l->pos + l->size); + 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->type); + s->layout[i].len = psi_t_size(t); } return 1; } @@ -230,7 +236,7 @@ static inline int validate_structs(PSI_Validator *V) { size_t i; for (i = 0; i < V->structs->count; ++i) { - if (!validate_struct(V->structs->list[i])) { + if (!validate_struct(V, V->structs->list[i])) { return 0; } } @@ -294,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", @@ -312,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; @@ -327,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; @@ -339,7 +345,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * int check = 0; if (let->val && let->val->var) { - 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(let->val->var->name, iarg->var->name)) { @@ -361,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)) { @@ -381,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)) { @@ -410,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)) {