X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fvalidator.c;h=5a6f5d96de0782acad1f0aa451262a8bf1fc1cab;hp=4e38929e1d42f9411468af53676f7b8b49233e9b;hb=be3ceffdd27422aae6ba44d31d868fb12d08957a;hpb=4a49fe2f8eb21cdeabb06acec7a0395b6708d911 diff --git a/src/validator.c b/src/validator.c index 4e38929..5a6f5d9 100644 --- a/src/validator.c +++ b/src/validator.c @@ -124,13 +124,23 @@ static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *fun } return 1; } +static const char * const abi_ccs[] = { + "default", /* \ */ + "extern", /* > - all the same */ + "cdecl", /* / */ + "stdcall", + "fastcall", +}; static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { - if (strcasecmp(abi->convention, "default")) { - V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention); - return 0; + size_t i; + + for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++ i) { + if (strcasecmp(abi->convention, abi_ccs[i])) { + return 1; + } } - /* FIXME */ - return 1; + 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) { if (!validate_decl_type(V, arg, arg->type)) { @@ -198,7 +208,7 @@ static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *fu } return 1; } -static inline decl *locate_impl_decl(decls *decls, ret_stmt *ret) { +static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) { size_t i; for (i = 0; i < decls->count; ++i) { @@ -213,10 +223,11 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * /* okay, * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one - * - we can have any count of set stmts; processing out vars, etc. + * - we can have any count of set stmts; processing out vars + * - we can have any count of free stmts; freeing any out vars */ - size_t i, j; - ret_stmt *ret; + size_t i, j, k; + return_stmt *ret; decl *decl; if (!stmts) { @@ -289,6 +300,78 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * } } } + /* check that set stmts reference known variables */ + for (i = 0; i < stmts->set.count; ++i) { + set_stmt *set = stmts->set.list[i]; + int check = 0; + + 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)) { + set->arg = iarg; + check = 1; + break; + } + } + if (!check) { + V->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement" + " of implementation '%s'", + set->var->name, impl->func->name); + return 0; + } + + for (j = 0; j < set->val->vars->count; ++j) { + decl_var *set_var = set->val->vars->vars[j]; + + check = 0; + 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)) { + check = 1; + set_var->arg = set_arg; + break; + } + } + + if (!check) { + V->error(PSI_WARNING, "Unknown value '%s' of `set` statement" + " for variable '$%s' of implementation '%s'", + set_var->name, set->arg->var->name, impl->func->name); + return 0; + } + } + } + /* check free stmts */ + for (i = 0; i < stmts->fre.count; ++i) { + free_stmt *fre = stmts->fre.list[i]; + + for (j = 0; j < fre->vars->count; ++j) { + decl_var *free_var = fre->vars->vars[j]; + int check = 0; + + if (!strcmp(free_var->name, decl->func->var->name)) { + continue; + } + 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)) { + check = 1; + free_var->arg = free_arg; + break; + } + } + + if (!check) { + V->error(PSI_WARNING, "Unknown variable '%s' of `free` statement" + " of implementation '%s'", + free_var->name, impl->func->name); + return 0; + } + } + } impl->decl = decl;