From 9c72f6584bd95dd6e9c7dcb314a6583f7130362f Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 16 Oct 2015 11:31:00 +0200 Subject: [PATCH] flush --- src/compiler.c | 154 ++++++++++++++++++++++++++++++++++++++++++---- src/compiler.h | 6 +- src/module.c | 20 ++++-- src/parser.h | 63 ++++++++++++------- src/parser.re | 27 +++++--- src/parser_proc.h | 83 +++++++++++++------------ src/parser_proc.y | 19 +++++- src/validator.c | 89 +++++++++++++++++---------- src/validator.h | 6 +- 9 files changed, 333 insertions(+), 134 deletions(-) diff --git a/src/compiler.c b/src/compiler.c index 5e5ebde..f2821ca 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -38,6 +38,8 @@ void PSI_Compiler_Free(PSI_Compiler **C) typedef struct PSI_ClosureData { void *context; impl *impl; + jit_type_t signature; + zval return_value; } PSI_ClosureData; static inline PSI_ClosureData *PSI_ClosureDataAlloc(void *context, impl *impl) { @@ -60,12 +62,67 @@ static inline size_t impl_num_min_args(impl *impl) { return n; } -static void psi_jit_closure_handler(jit_type_t signature, void *result, void **args, void *user_data) +static inline jit_abi_t psi_jit_abi(const char *convention) { + return jit_abi_cdecl; +} +static inline jit_type_t psi_jit_type(token_t t) { + switch (t) { + case PSI_T_VOID: + return jit_type_void; + case PSI_T_SINT8: + return jit_type_sbyte; + case PSI_T_UINT8: + return jit_type_ubyte; + case PSI_T_SINT16: + return jit_type_short; + case PSI_T_UINT16: + return jit_type_ushort; + case PSI_T_SINT32: + return jit_type_int; + case PSI_T_UINT32: + return jit_type_uint; + case PSI_T_SINT64: + return jit_type_long; + case PSI_T_UINT64: + return jit_type_ulong; + case PSI_T_BOOL: + return jit_type_sys_bool; + case PSI_T_CHAR: + return jit_type_sys_char; + case PSI_T_SHORT: + return jit_type_sys_short; + case PSI_T_INT: + return jit_type_sys_int; + case PSI_T_LONG: + return jit_type_sys_long; + case PSI_T_FLOAT: + return jit_type_sys_float; + case PSI_T_DOUBLE: + return jit_type_sys_double; + default: + abort(); + } +} +static inline jit_type_t psi_jit_decl_type(decl_type *type) { + return psi_jit_type(real_decl_type(type)->type); +} +static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) { + if (darg->var->pointer_level) { + return jit_type_void_ptr; + } else { + return psi_jit_decl_type(darg->type); + } +} +static void psi_jit_closure_handler(jit_type_t _sig, void *result, void **_args, void *_data) { - zend_execute_data *execute_data = *(zend_execute_data **)args[0]; - zval *return_value = *(zval **)args[1]; - PSI_ClosureData *data = user_data; + zend_execute_data *execute_data = *(zend_execute_data **)_args[0]; + zval *return_value = *(zval **)_args[1]; + PSI_ClosureData *data = _data; impl_arg *iarg; + size_t i; + void **arg_ptr = NULL, **arg_prm = NULL; + impl_val ret_val, *arg_val = NULL; + jit_type_t signature, *sig_prm; if (!data->impl->func->args->count) { if (SUCCESS != zend_parse_parameters_none()) { @@ -85,12 +142,12 @@ static void psi_jit_closure_handler(jit_type_t signature, void *result, void **a Z_PARAM_BOOL(iarg->val.bval); } else if (PSI_T_INT == iarg->type->type) { if (iarg->def) { - iarg->val.lval = atol(iarg->def->text); + iarg->val.lval = zend_atol(iarg->def->text, strlen(iarg->def->text)); } Z_PARAM_LONG(iarg->val.lval); } else if (PSI_T_FLOAT == iarg->type->type) { if (iarg->def) { - iarg->val.dval = strtod(iarg->def->text, NULL); + iarg->val.dval = zend_strtod(iarg->def->text, NULL); } Z_PARAM_DOUBLE(iarg->val.dval); } else if (PSI_T_STRING == iarg->type->type) { @@ -104,8 +161,83 @@ static void psi_jit_closure_handler(jit_type_t signature, void *result, void **a error_code = ZPP_ERROR_FAILURE; break; } - goto nextarg; + iarg->_zv = _arg; + if (_i < _max_num_args) { + goto nextarg; + } ZEND_PARSE_PARAMETERS_END(); + + if (data->impl->decl->args->count) { + arg_ptr = malloc(data->impl->decl->args->count * sizeof(*arg_ptr)); + arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm)); + arg_val = malloc(data->impl->decl->args->count * sizeof(*arg_val)); + sig_prm = malloc(data->impl->decl->args->count * sizeof(*sig_prm)); + + for (i = 0; i < data->impl->decl->args->count; ++i) { + decl_arg *darg = data->impl->decl->args->args[i]; + impl_arg *iarg = darg->let->arg; + + switch (darg->let->val->func->type) { + case PSI_T_BOOLVAL: + if (iarg->type->type == PSI_T_BOOL) { + arg_val[i].bval = iarg->val.bval; + } else { + arg_val[i].bval = zend_is_true(iarg->_zv); + } + break; + case PSI_T_INTVAL: + if (iarg->type->type == PSI_T_INT) { + arg_val[i].lval = iarg->val.lval; + } else { + arg_val[i].lval = zval_get_long(iarg->_zv); + } + break; + case PSI_T_STRVAL: + if (iarg->type->type == PSI_T_STRING) { + arg_val[i].str.val = estrndup(iarg->val.str.val, iarg->val.str.len); + } else { + zend_string *zs = zval_get_string(iarg->_zv); + arg_val[i].str.val = estrndup(zs->val, zs->len); + zend_string_release(zs); + } + break; + case PSI_T_STRLEN: + if (iarg->type->type == PSI_T_STRING) { + arg_val[i].lval =iarg->val.str.len; + } else { + zend_string *zs = zval_get_string(iarg->_zv); + arg_val[i].lval = zs->len; + zend_string_release(zs); + } + break; + } + arg_ptr[i] = &arg_val[i]; + arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i]; + sig_prm[i] = psi_jit_decl_arg_type(darg); + } + } + + signature = jit_type_create_signature( + psi_jit_abi(data->impl->decl->abi->convention), + psi_jit_decl_arg_type(data->impl->decl->func), + sig_prm, + data->impl->decl->args->count, + 1); + jit_apply(signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val); + + switch (data->impl->stmts->ret.list[0]->func->type) { + case PSI_T_TO_STRING: + if (data->impl->decl->func->var->pointer_level) { + switch (real_decl_type(data->impl->decl->func->type)->type) { + case PSI_T_CHAR: + case PSI_T_SINT8: + case PSI_T_UINT8: + RETVAL_STRING(ret_val.str.val); + break; + } + } + break; + } } zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C) @@ -119,19 +251,17 @@ zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C) for (i = 0; i < C->impls->count; ++i) { zend_function_entry *zf; - volatile PSI_ClosureData *data; + PSI_ClosureData *data; if (!C->impls->list[i]->decl) { continue; } - signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1); zf = &zfe[j++]; data = PSI_ClosureDataAlloc(C->context, C->impls->list[i]); - zf->fname = C->impls->list[i]->func->name; + signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1); + zf->fname = C->impls->list[i]->func->name + (C->impls->list[i]->func->name[0] == '\\'); zf->handler = jit_closure_create(C->context, signature, &psi_jit_closure_handler, data); - fprintf(stderr, "Compiled closure for %s\n", zf->fname); - printf("Closuredata: %p of closure %p\n", data, zf->handler); } return zfe; diff --git a/src/compiler.h b/src/compiler.h index 1374d39..fcf2cf6 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -4,11 +4,7 @@ #include "validator.h" typedef struct PSI_Compiler { - decl_typedefs *defs; - decls *decls; - impls *impls; - char *lib; - char *fn; + PSI_DATA_MEMBERS; void *context; } PSI_Compiler; diff --git a/src/module.c b/src/module.c index 90a838d..69ec53d 100644 --- a/src/module.c +++ b/src/module.c @@ -24,6 +24,18 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("psi.directory", "psis", PHP_INI_ALL, OnUpdateString, directory, zend_psi_globals, psi_globals) PHP_INI_END(); +static void psi_error(int type, const char *msg, ...) +{ + char buf[0x1000]; + va_list argv; + + va_start(argv, msg); + vslprintf(buf, 0x1000, msg, argv); + va_end(argv); + + php_error(type, buf); +} + static int psi_select_dirent(const struct dirent *entry) { #ifndef FNM_CASEFOLD @@ -61,7 +73,7 @@ PHP_MINIT_FUNCTION(psi) php_error(E_WARNING, "Path to PSI file too long: %s/%s", PSI_G(directory), entries[i]->d_name); } - if (!PSI_ParserInit(&P, psi, 0)) { + if (!PSI_ParserInit(&P, psi, psi_error, 0)) { php_error(E_WARNING, "Failed to init PSI parser (%s): %s", psi, strerror(errno)); continue; @@ -85,10 +97,8 @@ PHP_MINIT_FUNCTION(psi) if (PSI_CompilerInit(&C, &V, ctx)) { zend_function_entry *closures = PSI_CompilerCompile(&C); - if (closures) { - if (SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) { - fprintf(stderr, "Failed to register functions!\n"); - } + if (closures && SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) { + psi_error(E_WARNING, "Failed to register functions!"); } //PSI_CompilerDtor(&C); } diff --git a/src/parser.h b/src/parser.h index 2aaab31..8506acd 100644 --- a/src/parser.h +++ b/src/parser.h @@ -35,6 +35,13 @@ static inline decl_type *init_decl_type(token_t type, char *name) { return t; } +static inline decl_type *real_decl_type(decl_type *type) { + while (type->real) { + type = type->real; + } + return type; +} + static inline void free_decl_type(decl_type *type) { free(type->name); free(type); @@ -102,12 +109,14 @@ static inline void free_decl_var(decl_var *var) { typedef struct decl_arg { decl_type *type; decl_var *var; + struct let_stmt *let; } decl_arg; static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) { decl_arg *arg = malloc(sizeof(*arg)); arg->type = type; arg->var = var; + arg->let = NULL; return arg; } @@ -288,19 +297,22 @@ static inline void free_impl_def_val(impl_def_val *def) { free(def); } +typedef union impl_val { + unsigned char bval; + zend_long lval; + double dval; + struct { + char *val; + size_t len; + } str; +} impl_val; + typedef struct impl_arg { impl_type *type; impl_var *var; impl_def_val *def; - union { - unsigned char bval; - zend_long lval; - double dval; - struct { - char *val; - size_t len; - } str; - } val; + impl_val val; + zval *_zv; } impl_arg; static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) { @@ -395,12 +407,12 @@ static inline void free_let_func(let_func *func) { typedef struct let_value { let_func *func; impl_var *var; - unsigned null_pointer_ref:1; + unsigned is_reference:1; } let_value; -static inline let_value *init_let_value(let_func *func, impl_var *var, int null_pointer_ref) { +static inline let_value *init_let_value(let_func *func, impl_var *var, int is_reference) { let_value *val = malloc(sizeof(*val)); - val->null_pointer_ref = null_pointer_ref; + val->is_reference = is_reference; val->func = func; val->var = var; return val; @@ -419,12 +431,14 @@ static inline void free_let_value(let_value *val) { typedef struct let_stmt { decl_var *var; let_value *val; + impl_arg *arg; } let_stmt; static inline let_stmt *init_let_stmt(decl_var *var, let_value *val) { let_stmt *let = malloc(sizeof(*let)); let->var = var; let->val = val; + let->arg = NULL; return let; } @@ -639,12 +653,19 @@ static void free_impls(impls *impls) { free(impls); } +#define PSI_ERROR 16 +#define PSI_WARNING 32 +typedef void (*psi_error_cb)(int type, const char *msg, ...); + typedef struct PSI_Data { - decl_typedefs *defs; - decls *decls; - impls *impls; - char *lib; - char *fn; +#define PSI_DATA_MEMBERS \ + decl_typedefs *defs; \ + decls *decls; \ + impls *impls; \ + char *lib; \ + char *fn; \ + psi_error_cb error + PSI_DATA_MEMBERS; } PSI_Data; static inline void PSI_DataExchange(PSI_Data *dest, PSI_Data *src) { @@ -671,11 +692,7 @@ static inline void PSI_DataDtor(PSI_Data *data) { } typedef struct PSI_Parser { - decl_typedefs *defs; - decls *decls; - impls *impls; - char *lib; - char *fn; + PSI_DATA_MEMBERS; FILE *fp; unsigned flags; unsigned errors; @@ -707,7 +724,7 @@ static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) { #define PSI_PARSER_DEBUG 0x1 -PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags); +PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags); void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...); size_t PSI_ParserFill(PSI_Parser *P, size_t n); token_t PSI_ParserScan(PSI_Parser *P); diff --git a/src/parser.re b/src/parser.re index 31ddfe1..4cabb45 100644 --- a/src/parser.re +++ b/src/parser.re @@ -9,7 +9,7 @@ void PSI_ParserProcFree(void*, void(*)(void*)); void PSI_ParserProc(void *, token_t, PSI_Token *, PSI_Parser *); void PSI_ParserProcTrace(FILE *, const char*); -PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags) +PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags) { FILE *fp; @@ -33,6 +33,7 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags) P->fp = fp; P->fn = strdup(filename); P->line = 1; + P->error = error; P->flags = flags; P->proc = PSI_ParserProcAlloc(malloc); @@ -46,14 +47,16 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags) } void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...) { - fprintf(stderr, "WARNING: Syntax error on line %zu in '%s'%s", ln, fn, msg ? ": ": "\n"); - if (msg) { - va_list argv; + char buf[0x1000] = {0}; + va_list argv; + + va_start(argv, msg); + vsnprintf(buf, 0x1000-1, msg, argv); + va_end(argv); + + P->error(PSI_WARNING, "PSI syntax error on line %zu in '%s'%s%s", + ln, fn, msg ? ": ": "", buf); - va_start(argv, msg); - vfprintf(stderr, msg, argv); - va_end(argv); - } ++P->errors; } @@ -180,7 +183,10 @@ token_t PSI_ParserScan(PSI_Parser *P) MIXED = 'mixed'; VOID = 'void'; BOOL = 'bool'; + CHAR = 'char'; + SHORT = 'short'; INT = 'int'; + LONG = 'long'; FLOAT = 'float'; DOUBLE = 'double'; SINT8 = 'sint8'; @@ -230,7 +236,10 @@ token_t PSI_ParserScan(PSI_Parser *P) MIXED {RETURN(PSI_T_MIXED);} VOID {RETURN(PSI_T_VOID);} BOOL {RETURN(PSI_T_BOOL);} + CHAR {RETURN(PSI_T_CHAR);} + SHORT {RETURN(PSI_T_SHORT);} INT {RETURN(PSI_T_INT);} + LONG {RETURN(PSI_T_LONG);} FLOAT {RETURN(PSI_T_FLOAT);} DOUBLE {RETURN(PSI_T_DOUBLE);} SINT8 {RETURN(PSI_T_SINT8);} @@ -262,7 +271,7 @@ token_t PSI_ParserScan(PSI_Parser *P) NAME {RETURN(PSI_T_NAME);} NSNAME {RETURN(PSI_T_NSNAME);} QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);} - [^] {break;} + [^] {break;} */ } return -1; diff --git a/src/parser_proc.h b/src/parser_proc.h index d8466df..d1ba3cf 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -8,43 +8,46 @@ #define PSI_T_RPAREN 8 #define PSI_T_COMMA 9 #define PSI_T_VOID 10 -#define PSI_T_INT 11 -#define PSI_T_FLOAT 12 -#define PSI_T_DOUBLE 13 -#define PSI_T_SINT8 14 -#define PSI_T_UINT8 15 -#define PSI_T_SINT16 16 -#define PSI_T_UINT16 17 -#define PSI_T_SINT32 18 -#define PSI_T_UINT32 19 -#define PSI_T_SINT64 20 -#define PSI_T_UINT64 21 -#define PSI_T_LBRACE 22 -#define PSI_T_RBRACE 23 -#define PSI_T_FUNCTION 24 -#define PSI_T_NSNAME 25 -#define PSI_T_COLON 26 -#define PSI_T_NULL 27 -#define PSI_T_NUMBER 28 -#define PSI_T_TRUE 29 -#define PSI_T_FALSE 30 -#define PSI_T_DOLLAR 31 -#define PSI_T_REFERENCE 32 -#define PSI_T_EQUALS 33 -#define PSI_T_LET 34 -#define PSI_T_STRLEN 35 -#define PSI_T_STRVAL 36 -#define PSI_T_INTVAL 37 -#define PSI_T_FLOATVAL 38 -#define PSI_T_BOOLVAL 39 -#define PSI_T_SET 40 -#define PSI_T_TO_STRING 41 -#define PSI_T_TO_INT 42 -#define PSI_T_TO_FLOAT 43 -#define PSI_T_TO_BOOL 44 -#define PSI_T_RET 45 -#define PSI_T_MIXED 46 -#define PSI_T_BOOL 47 -#define PSI_T_STRING 48 -#define PSI_T_ARRAY 49 -#define PSI_T_POINTER 50 +#define PSI_T_CHAR 11 +#define PSI_T_SHORT 12 +#define PSI_T_INT 13 +#define PSI_T_LONG 14 +#define PSI_T_FLOAT 15 +#define PSI_T_DOUBLE 16 +#define PSI_T_SINT8 17 +#define PSI_T_UINT8 18 +#define PSI_T_SINT16 19 +#define PSI_T_UINT16 20 +#define PSI_T_SINT32 21 +#define PSI_T_UINT32 22 +#define PSI_T_SINT64 23 +#define PSI_T_UINT64 24 +#define PSI_T_LBRACE 25 +#define PSI_T_RBRACE 26 +#define PSI_T_FUNCTION 27 +#define PSI_T_NSNAME 28 +#define PSI_T_COLON 29 +#define PSI_T_NULL 30 +#define PSI_T_NUMBER 31 +#define PSI_T_TRUE 32 +#define PSI_T_FALSE 33 +#define PSI_T_DOLLAR 34 +#define PSI_T_REFERENCE 35 +#define PSI_T_EQUALS 36 +#define PSI_T_LET 37 +#define PSI_T_STRLEN 38 +#define PSI_T_STRVAL 39 +#define PSI_T_INTVAL 40 +#define PSI_T_FLOATVAL 41 +#define PSI_T_BOOLVAL 42 +#define PSI_T_SET 43 +#define PSI_T_TO_STRING 44 +#define PSI_T_TO_INT 45 +#define PSI_T_TO_FLOAT 46 +#define PSI_T_TO_BOOL 47 +#define PSI_T_RET 48 +#define PSI_T_MIXED 49 +#define PSI_T_BOOL 50 +#define PSI_T_STRING 51 +#define PSI_T_ARRAY 52 +#define PSI_T_POINTER 53 diff --git a/src/parser_proc.y b/src/parser_proc.y index d99c96d..c619e55 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -14,7 +14,7 @@ %extra_argument {PSI_Parser *P} /* TOKEN is defined inside syntax_error */ %syntax_error { - PSI_ParserSyntaxError(P, P->fn, P->line, "Unexpected token '%s'.\n", TOKEN->text); + PSI_ParserSyntaxError(P, P->fn, P->line, "Unexpected token '%s'", TOKEN->text); } file ::= blocks. @@ -25,7 +25,7 @@ block ::= COMMENT. block ::= LIB(T) QUOTED_STRING(libname) EOS. { if (P->lib) { - PSI_ParserSyntaxError(P, P->fn, T->line, "Extra 'lib %s' statement has no effect.\n", libname->text); + PSI_ParserSyntaxError(P, P->fn, T->line, "Extra 'lib %s' statement has no effect", libname->text); } else { P->lib = strndup(libname->text + 1, libname->size - 2); } @@ -96,10 +96,22 @@ decl_type(type_) ::= VOID(T). { type_ = init_decl_type(T->type, T->text); free(T); } +decl_type(type_) ::= CHAR(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} +decl_type(type_) ::= SHORT(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} decl_type(type_) ::= INT(T). { type_ = init_decl_type(T->type, T->text); free(T); } +decl_type(type_) ::= LONG(T). { + type_ = init_decl_type(T->type, T->text); + free(T); +} decl_type(type_) ::= FLOAT(T). { type_ = init_decl_type(T->type, T->text); free(T); @@ -231,6 +243,9 @@ let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. { let_value(val) ::= let_func(func) LPAREN impl_var(var) RPAREN. { val = init_let_value(func, var, 0); } +let_value(val) ::= REFERENCE let_func(func) LPAREN impl_var(var) RPAREN. { + val = init_let_value(func, var, 1); +} let_value(val) ::= REFERENCE NULL. { val = init_let_value(NULL, NULL, 1); } diff --git a/src/validator.c b/src/validator.c index 5f6a6d3..4e38929 100644 --- a/src/validator.c +++ b/src/validator.c @@ -43,8 +43,6 @@ static int validate_lib(PSI_Validator *V) { if (!ptr) { /* FIXME: assume stdlib */ return 1; - fprintf(stderr, "No import library defined;" - " use 'lib \"\";' statement.\n"); } else if (!strchr(ptr, '/')) { #ifdef DARWIN len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr); @@ -52,13 +50,13 @@ static int validate_lib(PSI_Validator *V) { len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr); #endif if (MAXPATHLEN == len) { - fprintf(stderr, "Library name too long: '%s'\n", ptr); + V->error(PSI_WARNING, "Library name too long: '%s'", ptr); } lib[len] = 0; ptr = lib; } if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) { - fprintf(stderr, "Could not open library '%s': %s.\n", V->lib, dlerror()); + V->error(PSI_WARNING, "Could not open library '%s': %s.", V->lib, dlerror()); return 0; } return 1; @@ -79,12 +77,11 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { } static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) { if (type->type == PSI_T_NAME) { - size_t i; - if (!V->defs || !locate_decl_type_alias(V->defs, type)) { - fprintf(stderr, "Cannot use '%s' as type for '%s';" - " Use 'typedef ;' statement.\n", + V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';" + " Use 'typedef ;' statement", type->name, arg->var->name); + return 0; } } return 1; @@ -92,7 +89,7 @@ static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) { /* FIXME: check def->alias */ if (def->type->type == PSI_T_NAME) { - fprintf(stderr, "Type '%s' cannot be aliased to '%s'\n", + V->error(PSI_WARNING, "Type '%s' cannot be aliased to '%s'", def->type->name, def->alias); return 0; } @@ -111,10 +108,8 @@ static inline int validate_typedefs(PSI_Validator *V) { } static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func) { - void *dlptr; - if (!strcmp(func->var->name, "dlsym")) { - fprintf(stderr, "Cannot dlsym dlsym (sic!)\n"); + V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)"); return 0; } @@ -124,14 +119,14 @@ static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *fun decl->dlptr = dlsym(V->dlopened, func->var->name); if (!decl->dlptr) { - fprintf(stderr, "Failed to located symbol '%s': %s\n", + V->error(PSI_WARNING, "Failed to located symbol '%s': %s", func->var->name, dlerror()); } return 1; } static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { if (strcasecmp(abi->convention, "default")) { - fprintf(stderr, "Invalid calling convention: '%s'\n", abi->convention); + V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention); return 0; } /* FIXME */ @@ -213,6 +208,7 @@ static inline decl *locate_impl_decl(decls *decls, ret_stmt *ret) { } return NULL; } + static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) { /* okay, * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply @@ -222,18 +218,20 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * size_t i, j; ret_stmt *ret; decl *decl; - int *check; if (!stmts) { - fprintf(stderr, "Missing body for implementation %s!\n", impl->func->name); + V->error(PSI_WARNING, "Missing body for implementation %s!", + impl->func->name); return 0; } if (stmts->ret.count != 1) { if (stmts->ret.count > 1) { - fprintf(stderr, "Too many `ret` statements for implmentation %s; found %zu, exactly one is needed.\n", - impl->func->name, stmts->ret.count); + V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;" + "found %zu, exactly one is needed", + impl->func->name, stmts->ret.count); } else { - fprintf(stderr, "Missing `ret` statement for implementation %s.\n", impl->func->name); + V->error(PSI_WARNING, "Missing `ret` statement for implementation %s", + impl->func->name); } return 0; } @@ -241,31 +239,56 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * ret = stmts->ret.list[0]; decl = locate_impl_decl(V->decls, ret); if (!decl) { - fprintf(stderr, "Missing declaration for implementation %s.\n", impl->func->name); + V->error(PSI_WARNING, "Missing declaration for implementation %s", + impl->func->name); return 0; } /* check that we have a let stmt for every decl arg */ - check = calloc(decl->args->count, sizeof(int)); - for (i = 0; i < stmts->let.count; ++i) { - let_stmt *let = stmts->let.list[i]; + for (i = 0; i < decl->args->count; ++i) { + decl_arg *darg = decl->args->args[i]; + int check = 0; - for (j = 0; j < decl->args->count; ++j) { - if (!strcmp(decl->args->args[j]->var->name, let->var->name)) { - check[j] = 1; + for (j = 0; j < stmts->let.count; ++j) { + let_stmt *let = stmts->let.list[j]; + + if (!strcmp(let->var->name, darg->var->name)) { + darg->let = let; + check = 1; break; } } - } - for (i = 0; i < decl->args->count; ++i) { - if (!check[i]) { - fprintf(stderr, "Missing `let` statement for arg '%s %.*s%s' of declaration '%s' for implementation '%s'.\n", - decl->args->args[i]->type->name, (int) decl->args->args[i]->var->pointer_level, "*****", decl->args->args[i]->var->name, decl->func->var->name, impl->func->name); - free(check); + if (!check) { + V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%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; } } - free(check); + /* check that the let_value references a known variable or NULL */ + for (i = 0; i < stmts->let.count; ++i) { + let_stmt *let = stmts->let.list[i]; + int check = 0; + + if (let->val->var) { + 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)) { + let->arg = iarg; + check = 1; + break; + } + } + if (!check) { + V->error(PSI_WARNING, "Unknown value '$%s' of `let` statement" + " for variable '%s' of implementation '%s'", + let->val->var->name, let->var->name, impl->func->name); + return 0; + } + } + } impl->decl = decl; diff --git a/src/validator.h b/src/validator.h index f96111c..8b373f6 100644 --- a/src/validator.h +++ b/src/validator.h @@ -4,11 +4,7 @@ #include "parser.h" typedef struct PSI_Validator { - decl_typedefs *defs; - decls *decls; - impls *impls; - char *lib; - char *fn; + PSI_DATA_MEMBERS; void *dlopened; } PSI_Validator; -- 2.30.2