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) {
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()) {
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) {
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)
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;
#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;
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
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;
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);
}
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);
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;
}
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) {
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;
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;
}
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) {
}
typedef struct PSI_Parser {
- decl_typedefs *defs;
- decls *decls;
- impls *impls;
- char *lib;
- char *fn;
+ PSI_DATA_MEMBERS;
FILE *fp;
unsigned flags;
unsigned errors;
#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);
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;
P->fp = fp;
P->fn = strdup(filename);
P->line = 1;
+ P->error = error;
P->flags = flags;
P->proc = PSI_ParserProcAlloc(malloc);
}
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;
}
MIXED = 'mixed';
VOID = 'void';
BOOL = 'bool';
+ CHAR = 'char';
+ SHORT = 'short';
INT = 'int';
+ LONG = 'long';
FLOAT = 'float';
DOUBLE = 'double';
SINT8 = 'sint8';
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);}
NAME {RETURN(PSI_T_NAME);}
NSNAME {RETURN(PSI_T_NSNAME);}
QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
- [^] {break;}
+ [^] {break;}
*/
}
return -1;
#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
%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.
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);
}
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);
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);
}
if (!ptr) {
/* FIXME: assume stdlib */
return 1;
- fprintf(stderr, "No import library defined;"
- " use 'lib \"<libname>\";' statement.\n");
} else if (!strchr(ptr, '/')) {
#ifdef DARWIN
len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
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;
}
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 <type> <basic_type>;' statement.\n",
+ V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
+ " Use 'typedef <type> <basic_type>;' statement",
type->name, arg->var->name);
+ return 0;
}
}
return 1;
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;
}
}
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;
}
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 */
}
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
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;
}
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;
#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;