From 19f0eb5807fb8d0f3aa305f2476f094e66a02709 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 5 Jan 2016 15:53:46 +0100 Subject: [PATCH] better errors --- php_psi.h | 4 ++- psi.d/stdio.psi | 1 + src/context.c | 79 +++++++++++++++++++++++++++-------------------- src/context.h | 2 +- src/module.c | 19 +++++++++--- src/parser.h | 76 +++++++++++++++++++++++++++++++++++---------- src/parser.re | 16 +--------- src/parser_proc.y | 55 ++++++++++++++++----------------- 8 files changed, 150 insertions(+), 102 deletions(-) diff --git a/php_psi.h b/php_psi.h index f5859e3..31e6565 100644 --- a/php_psi.h +++ b/php_psi.h @@ -20,7 +20,9 @@ extern zend_module_entry psi_module_entry; #include "context.h" -void psi_error(int type, const char *msg, ...); +void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...); +void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...); +void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv); static inline int psi_check_env(const char *var) { char *set = getenv(var); diff --git a/psi.d/stdio.psi b/psi.d/stdio.psi index 685d6c8..43987de 100644 --- a/psi.d/stdio.psi +++ b/psi.d/stdio.psi @@ -70,3 +70,4 @@ function psi\printf(string $fmt, mixed ...$args) : int { let format = strval($fmt); return to_int(printf); } + diff --git a/src/context.c b/src/context.c index 64fce37..a75368e 100644 --- a/src/context.c +++ b/src/context.c @@ -212,13 +212,13 @@ static int validate_lib(PSI_Data *data, void **dlopened) { } else if (!strchr(ptr, '/')) { len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX); if (MAXPATHLEN == len) { - data->error(PSI_WARNING, "Library name too long: '%s'", ptr); + data->error(NULL, PSI_WARNING, "Library name too long: '%s'", ptr); } lib[len] = 0; ptr = lib; } if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) { - data->error(PSI_WARNING, "Could not open library '%s': %s.", + data->error(NULL, PSI_WARNING, "Could not open library '%s': %s.", data->psi.file.ln, dlerror()); return 0; } @@ -284,7 +284,8 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) { } static inline int validate_decl_typedef(PSI_Data *data, decl_typedef *def) { if (!validate_decl_type(data, def->type)) { - data->error(PSI_WARNING, "Type '%s' cannot be aliased to %s'%s'", + data->error(def->token, PSI_WARNING, + "Type '%s' cannot be aliased to %s'%s'", def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",def->alias); return 0; } @@ -299,10 +300,9 @@ static inline int validate_constant(PSI_Data *data, constant *c) { static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) { if (!validate_decl_type(data, arg->type)) { - data->error(PSI_WARNING, "Cannot use '%s'(%d) as type for decl var '%s'" - " in %s on line %zu at col %zu", - arg->type->name, arg->type->type, arg->var->name, - arg->type->token->file, arg->type->token->line, arg->type->token->col); + data->error(arg->type->token, PSI_WARNING, + "Cannot use '%s'(%d) as type for decl var '%s'", + arg->type->name, arg->type->type, arg->var->name); return 0; } return 1; @@ -367,7 +367,6 @@ static inline int validate_decl_abi(PSI_Data *data, decl_abi *abi) { return 1; } } - data->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention); return 0; } static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_arg *func) @@ -375,7 +374,7 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ struct psi_func_redir *redir; if (!strcmp(func->var->name, "dlsym")) { - data->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)"); + data->error(func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)"); return 0; } @@ -393,7 +392,8 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ #endif decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name); if (!decl->call.sym) { - data->error(PSI_WARNING, "Failed to locate symbol '%s': %s", + data->error(func->token, PSI_WARNING, + "Failed to locate symbol '%s': %s", func->var->name, dlerror()); } } @@ -402,6 +402,8 @@ static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_ static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) { if (!validate_decl_abi(data, decl->abi)) { + data->error(decl->abi->token, PSI_WARNING, + "Invalid calling convention: '%s'", decl->abi->token->text); return 0; } if (!validate_decl_func(data, dl, decl, decl->func)) { @@ -480,14 +482,14 @@ static inline int validate_num_exp(PSI_Data *data, decl_args *dargs, decl_arg *f switch (exp->t) { case PSI_T_NAME: if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) { - data->error(PSI_WARNING, "Unknown variable '%s' in numeric expression", + data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression", exp->u.dvar->name); return 0; } return 1; case PSI_T_NSNAME: if (!locate_num_exp_constant(exp, data->consts)) { - data->error(PSI_WARNING, "Unknown constant '%s' in numeric expression", + data->error(exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression", exp->u.numb); return 0; } @@ -545,14 +547,14 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg decl_var *set_var = set->vars->vars[0]; if (!validate_set_value_handler(set)) { - data->error(PSI_WARNING, "Invalid cast '%s'", set->func->name); + data->error(set->func->token, PSI_WARNING, "Invalid cast '%s'", set->func->name); return 0; } for (i = 0; i < set->vars->count; ++i) { decl_var *svar = set->vars->vars[i]; if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) { - data->error(PSI_WARNING, "Unknown variable '%s'", svar->name); + data->error(svar->token, PSI_WARNING, "Unknown variable '%s'", svar->name); return 0; } } @@ -567,7 +569,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level); if (!is_to_array && !is_pointer_to_struct) { - data->error(E_WARNING, "Inner `set` statement casts only work with " + data->error(set->func->token, E_WARNING, "Inner `set` statement casts only work with " "to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name); return 0; } @@ -599,7 +601,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg set->inner[0]->outer.set = set; if (sub_ref) { if (strcmp(sub_var->name, set_var->name)) { - data->error(E_WARNING, "Inner `set` statement casts on pointers must reference the same variable"); + data->error(sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable"); return 0; } if (!validate_set_value_ex(data, set->inner[0], sub_ref, ref_list)) { @@ -607,7 +609,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg } } } else if (set->count > 1) { - data->error(E_WARNING, "Inner `set` statement casts on pointers may only occur once"); + data->error(set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once"); return 0; } @@ -649,11 +651,13 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { /* and which type cast to apply */ if (impl->stmts->ret.count != 1) { if (impl->stmts->ret.count > 1) { - data->error(PSI_WARNING, "Too many `return` statements for implmentation %s;" + data->error(impl->stmts->ret.list[1]->token, PSI_WARNING, + "Too many `return` statements for implmentation %s;" " found %zu, exactly one is needed", impl->func->name, impl->stmts->ret.count); } else { - data->error(PSI_WARNING, "Missing `return` statement for implementation %s", + data->error(impl->func->token, PSI_WARNING, + "Missing `return` statement for implementation %s", impl->func->name); } return 0; @@ -662,8 +666,9 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { ret = impl->stmts->ret.list[0]; if (!(impl->decl = locate_impl_decl(data->decls, ret))) { - data->error(PSI_WARNING, "Missing declaration for implementation %s", - impl->func->name); + data->error(ret->token, PSI_WARNING, + "Missing declaration '%s' for `return` statment for implementation %s", + ret->set->vars->vars[0]->name, impl->func->name); return 0; } @@ -693,7 +698,7 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { } if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) { - data->error(PSI_WARNING, "Unknown variable '%s' in `let` statement" + data->error(let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement" " of implementation '%s'", let_var->name, impl->func->name); return 0; } @@ -740,7 +745,7 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { } } if (!check) { - data->error(PSI_WARNING, "Unknown value '$%s' of `let` statement" + data->error(let->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement" " for variable '%s' of implementation '%s'", let->val->data.func->var->name, let->var->name, impl->func->name); return 0; @@ -764,7 +769,8 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) { } } if (!check) { - data->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'" + data->error(impl->func->token, 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, impl->decl->func->var->name, impl->func->name); @@ -792,7 +798,7 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { } } if (!check) { - data->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement" + data->error(set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement" " of implementation '%s'", set->var->name, impl->func->name); return 0; @@ -835,7 +841,7 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { } if (!check) { - data->error(PSI_WARNING, "Unknown value '%s' of `set` statement" + data->error(set_var->token, 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; @@ -869,12 +875,15 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { /* first find the decl of the free func */ if (!locate_free_decl(data->decls, free_call)) { - data->error(PSI_WARNING, "Unknown function '%s' in `free` statement" - " of implementation '%s'", free_call->func, impl->func->name); + data->error(free_call->token, PSI_WARNING, + "Missing declaration '%s' in `free` statement" + " of implementation '%s'", + free_call->func, impl->func->name); return 0; } if (!impl->decl->args) { - data->error(PSI_WARNING, "Declaration '%s' of implementation '%s'" + data->error(free_call->token, PSI_WARNING, + "Declaration '%s' of implementation '%s'" " does not have any arguments to free", impl->decl->func->var->name, impl->func->name); } @@ -895,7 +904,8 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { } if (!check) { - data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement" + data->error(free_var->token, PSI_WARNING, + "Unknown variable '%s' of `free` statement" " of implementation '%s'", free_var->name, impl->func->name); return 0; @@ -907,7 +917,8 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { } static inline int validate_impl_stmts(PSI_Data *data, impl *impl) { if (!impl->stmts) { - data->error(PSI_WARNING, "Missing body for implementation %s!", + data->error(impl->func->token, PSI_WARNING, + "Missing body for implementation %s!", impl->func->name); return 0; } @@ -1164,11 +1175,11 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths) PSI_Parser P; if (MAXPATHLEN <= slprintf(psi, MAXPATHLEN, "%s/%s", ptr, entries[i]->d_name)) { - C->error(PSI_WARNING, "Path to PSI file too long: %s/%s", + C->error(NULL, PSI_WARNING, "Path to PSI file too long: %s/%s", ptr, entries[i]->d_name); } if (!PSI_ParserInit(&P, psi, C->error, flags)) { - C->error(PSI_WARNING, "Failed to init PSI parser (%s): %s", + C->error(NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s", psi, strerror(errno)); continue; } @@ -1198,7 +1209,7 @@ void PSI_ContextBuild(PSI_Context *C, const char *paths) if (PSI_ContextCompile(C) && SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) { - C->error(PSI_WARNING, "Failed to register functions!"); + C->error(NULL, PSI_WARNING, "Failed to register functions!"); } free(cpy); diff --git a/src/context.h b/src/context.h index a010eee..c8416a5 100644 --- a/src/context.h +++ b/src/context.h @@ -5,7 +5,7 @@ #define PSI_ERROR 16 #define PSI_WARNING 32 -typedef void (*PSI_ContextErrorFunc)(int type, const char *msg, ...); +typedef void (*PSI_ContextErrorFunc)(PSI_Token *token, int type, const char *msg, ...); typedef struct PSI_Context PSI_Context; typedef struct PSI_ContextOps PSI_ContextOps; diff --git a/src/module.c b/src/module.c index 321ab63..39d1291 100644 --- a/src/module.c +++ b/src/module.c @@ -33,16 +33,25 @@ PHP_INI_END(); static zend_object_handlers psi_object_handlers; static zend_class_entry *psi_class_entry; -void psi_error(int type, const char *msg, ...) +void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...) { - char buf[0x1000]; va_list argv; va_start(argv, msg); - vslprintf(buf, 0x1000, msg, argv); + psi_verror(type, t?t->file:"Unknown", t?*t->line:0, msg, argv); va_end(argv); +} +void psi_error(int type, const char *fn, unsigned ln, const char *msg, ...) +{ + va_list argv; - php_error(type, buf); + va_start(argv, msg); + psi_verror(type, fn, ln, msg, argv); + va_end(argv); +} +void psi_verror(int type, const char *fn, unsigned ln, const char *msg, va_list argv) +{ + zend_error_cb(type, fn, ln, msg, argv); } size_t psi_t_alignment(token_t t) @@ -1172,7 +1181,7 @@ PHP_MINIT_FUNCTION(psi) return FAILURE; } - PSI_ContextInit(&PSI_G(context), ops, psi_error); + PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper); PSI_ContextBuild(&PSI_G(context), PSI_G(directory)); if (psi_check_env("PSI_DUMP")) { diff --git a/src/parser.h b/src/parser.h index 014509d..aadb31c 100644 --- a/src/parser.h +++ b/src/parser.h @@ -21,7 +21,7 @@ size_t psi_t_size(token_t); typedef struct PSI_Token { token_t type; - size_t size, line, col; + unsigned size, *line; char *text, *file; char buf[1]; } PSI_Token; @@ -81,6 +81,7 @@ static inline void free_decl_type(decl_type *type) { } typedef struct decl_typedef { + PSI_Token *token; char *alias; decl_type *type; } decl_typedef; @@ -93,6 +94,9 @@ static inline decl_typedef *init_decl_typedef(const char *name, decl_type *type) } static inline void free_decl_typedef(decl_typedef *t) { + if (t->token) { + free(t->token); + } free(t->alias); free_decl_type(t->type); free(t); @@ -123,6 +127,7 @@ static void free_decl_typedefs(decl_typedefs *defs) { } typedef struct decl_var { + PSI_Token *token; char *name; unsigned pointer_level; unsigned array_size; @@ -138,6 +143,9 @@ static inline decl_var *init_decl_var(const char *name, unsigned pl, unsigned as } static inline void free_decl_var(decl_var *var) { + if (var->token) { + free(var->token); + } free(var->name); free(var); } @@ -160,6 +168,7 @@ static inline void free_decl_struct_layout(decl_struct_layout *l) { } typedef struct decl_arg { + PSI_Token *token; decl_type *type; decl_var *var; decl_struct_layout *layout; @@ -171,6 +180,7 @@ typedef struct decl_arg { static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) { decl_arg *arg = calloc(1, sizeof(*arg)); + arg->token = var->token; arg->type = type; arg->var = var; var->arg = arg; @@ -251,6 +261,7 @@ static inline void free_decl_args(decl_args *args) { } typedef struct decl_abi { + PSI_Token *token; char *convention; } decl_abi; @@ -261,6 +272,9 @@ static inline decl_abi *init_decl_abi(const char *convention) { } static inline void free_decl_abi(decl_abi *abi) { + if (abi->token) { + free(abi->token); + } free(abi->convention); free(abi); } @@ -323,6 +337,7 @@ static inline void free_decls(decls *decls) { } typedef struct decl_struct { + PSI_Token *token; char *name; decl_args *args; size_t size; @@ -336,6 +351,9 @@ static inline decl_struct *init_decl_struct(const char *name, decl_args *args) { } static inline void free_decl_struct(decl_struct *s) { + if (s->token) { + free(s->token); + } if (s->args) { free_decl_args(s->args); } @@ -386,6 +404,7 @@ static inline void free_impl_type(impl_type *type) { } typedef struct impl_var { + PSI_Token *token; char *name; unsigned reference:1; } impl_var; @@ -398,6 +417,9 @@ static inline impl_var *init_impl_var(const char *name, int is_reference) { } static inline void free_impl_var(impl_var *var) { + if (var->token) { + free(var->token); + } free(var->name); free(var); } @@ -550,6 +572,7 @@ static inline void free_impl_args(impl_args *args) { } typedef struct impl_func { + PSI_Token *token; char *name; impl_args *args; impl_type *return_type; @@ -566,6 +589,9 @@ static inline impl_func *init_impl_func(char *name, impl_args *args, impl_type * } static inline void free_impl_func(impl_func *f) { + if (f->token) { + free(f->token); + } free_impl_type(f->return_type); free_impl_args(f->args); free(f->name); @@ -573,6 +599,7 @@ static inline void free_impl_func(impl_func *f) { } typedef struct num_exp { + PSI_Token *token; token_t t; union { char *numb; @@ -600,6 +627,9 @@ static inline num_exp *init_num_exp(token_t t, void *num) { } static inline void free_num_exp(num_exp *exp) { + if (exp->token) { + free(exp->token); + } switch (exp->t) { case PSI_T_NUMBER: free(exp->u.numb); @@ -750,6 +780,7 @@ static inline void free_let_stmt(let_stmt *stmt) { struct set_value; typedef struct set_func { + PSI_Token *token; token_t type; char *name; void (*handler)(zval *, struct set_value *set, impl_val *ret_val); @@ -763,6 +794,9 @@ static inline set_func *init_set_func(token_t type, const char *name) { } static inline void free_set_func(set_func *func) { + if (func->token) { + free(func->token); + } free(func->name); free(func); } @@ -827,6 +861,7 @@ static inline void free_set_stmt(set_stmt *set) { } typedef struct return_stmt { + PSI_Token *token; set_value *set; decl_arg *decl; } return_stmt; @@ -838,13 +873,15 @@ static inline return_stmt *init_return_stmt(set_value *val) { } static inline void free_return_stmt(return_stmt *ret) { - //free_set_func(ret->func); - //free_decl_var(ret->decl); + if (ret->token) { + free(ret->token); + } free_set_value(ret->set); free(ret); } typedef struct free_call { + PSI_Token *token; char *func; decl_vars *vars; decl *decl; @@ -858,6 +895,9 @@ static inline free_call *init_free_call(const char *func, decl_vars *vars) { } static inline void free_free_call(free_call *f) { + if (f->token) { + free(f->token); + } free(f->func); free_decl_vars(f->vars); free(f); @@ -1135,7 +1175,7 @@ static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_pt #define PSI_ERROR 16 #define PSI_WARNING 32 -typedef void (*psi_error_cb)(int type, const char *msg, ...); +typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...); #define PSI_DATA(D) ((PSI_Data *) (D)) #define PSI_DATA_MEMBERS \ @@ -1184,11 +1224,9 @@ static inline void PSI_DataDtor(PSI_Data *data) { typedef struct PSI_Parser { PSI_DATA_MEMBERS; FILE *fp; - unsigned flags; - unsigned errors; - void *proc; - size_t line, col; token_t num; + void *proc; + unsigned flags, errors, line, col; char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE]; } PSI_Parser; @@ -1205,33 +1243,37 @@ static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) { token_len = P->cur - P->tok; fname_len = strlen(P->psi.file.fn); - T = calloc(1, sizeof(*T) + token_len + fname_len + 1); + T = calloc(1, sizeof(*T) + token_len + fname_len + sizeof(unsigned) + 2); T->type = token_typ; T->size = token_len; - T->line = P->line; - T->col = P->col; - T->file = &T->buf[0]; - T->text = &T->buf[fname_len + 1]; + T->text = &T->buf[0]; + T->file = &T->buf[token_len + 1]; + T->line = (void *) &T->buf[fname_len + token_len + 2]; - memcpy(T->file, P->psi.file.fn, fname_len); memcpy(T->text, P->tok, token_len); + memcpy(T->file, P->psi.file.fn, fname_len); + memcpy(T->line, &P->line, sizeof(unsigned)); return T; } static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) { size_t fname_len = strlen(src->file); - size_t strct_len = sizeof(*src) + src->size + fname_len + 1; + size_t strct_len = sizeof(*src) + src->size + fname_len + sizeof(unsigned) + 2; PSI_Token *ptr = malloc(strct_len); memcpy(ptr, src, strct_len); - ptr->file = &ptr->buf[0]; - ptr->text = &ptr->buf[fname_len + 1]; + ptr->text = &ptr->buf[0]; + ptr->file = &ptr->buf[ptr->size + 1]; return ptr; } +static inline const char *PSI_TokenLocation(PSI_Token *t) { + return t ? t->file : ":0:0"; +} + #define PSI_PARSER_DEBUG 0x1 PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags); diff --git a/src/parser.re b/src/parser.re index 69e76c8..3375a0b 100644 --- a/src/parser.re +++ b/src/parser.re @@ -47,20 +47,6 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb err return P; } -void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...) { - 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); - - ++P->errors; -} - size_t PSI_ParserFill(PSI_Parser *P, size_t n) { if (P->flags & PSI_PARSER_DEBUG) { @@ -214,7 +200,7 @@ void PSI_ParserFree(PSI_Parser **P) #define RETURN(t) do { \ P->num = t; \ if (P->flags & PSI_PARSER_DEBUG) { \ - fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%zu:%zu)\n", \ + fprintf(stderr, "PSI> TOKEN: %d %.*s (EOF=%d %s:%u:%u)\n", \ P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \ P->psi.file.fn, P->line, P->col); \ } \ diff --git a/src/parser_proc.y b/src/parser_proc.y index d55f7e7..80a0519 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -5,6 +5,7 @@ #include "parser.h" +void psi_error(int, const char *, int, const char *, ...); } %name PSI_ParserProc @@ -15,10 +16,11 @@ %extra_argument {PSI_Parser *P} /* TOKEN is defined inside syntax_error */ %syntax_error { + ++P->errors; if (TOKEN && TOKEN->type != PSI_T_EOF) { - PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected token '%s'", TOKEN->text); + psi_error(PSI_WARNING, TOKEN->file, *TOKEN->line, "PSI syntax error: Unexpected token '%s'", TOKEN->text); } else { - PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected end of input"); + psi_error(PSI_WARNING, P->psi.file.fn, P->line, "PSI syntax error: Unexpected end of input"); } } @@ -36,7 +38,7 @@ block ::= EOF. block ::= LIB(T) QUOTED_STRING(libname) EOS. { if (P->psi.file.ln) { - PSI_ParserSyntaxError(P, P->psi.file.ln, T->line, "Extra 'lib %s' statement has no effect", libname->text); + P->error(T, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text); } else { P->psi.file.ln = strndup(libname->text + 1, libname->size - 2); } @@ -68,7 +70,7 @@ block ::= decl_struct(strct). { decl_struct(strct) ::= STRUCT NAME(N) struct_size(size_) LBRACE struct_args(args) RBRACE. { strct = init_decl_struct(N->text, args); strct->size = size_; - free(N); + strct->token = N; } %type struct_size {size_t} @@ -98,34 +100,31 @@ constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) %destructor decl_typedef {free_decl_typedef($$);} decl_typedef(def) ::= TYPEDEF decl_type(type) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, type); - free(ALIAS); + def->token = ALIAS; } /* support opaque types */ decl_typedef(def) ::= TYPEDEF VOID(V) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(V->type, V->text)); + def->token = ALIAS; def->type->token = V; - //free(V); - free(ALIAS); } decl_typedef(def) ::= TYPEDEF STRUCT(S) NAME(N) NAME(ALIAS) EOS. { def = init_decl_typedef(ALIAS->text, init_decl_type(S->type, N->text)); + def->token = ALIAS; def->type->token = N; - free(ALIAS); 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->token = ALIAS; + def->token = ALIAS; + def->type->token = PSI_TokenCopy(s->token); def->type->strct = s; - //free(ALIAS); } %type decl {decl*} %destructor decl {free_decl($$);} decl(decl) ::= decl_abi(abi) decl_func(func) LPAREN decl_args(args) RPAREN EOS. { decl = init_decl(abi, func, args); - } %type decl_func {decl_arg*} @@ -148,18 +147,18 @@ decl_func(func) ::= VOID(T) NAME(N). { %destructor decl_abi {free_decl_abi($$);} decl_abi(abi) ::= NAME(T). { abi = init_decl_abi(T->text); - free(T); + abi->token = T; } %type decl_var {decl_var*} %destructor decl_var {free_decl_var($$);} decl_var(var) ::= indirection(p) NAME(T). { var = init_decl_var(T->text, p, 0); - free(T); + var->token = T; } decl_var(var) ::= indirection(p) NAME(T) LBRACKET NUMBER(D) RBRACKET. { var = init_decl_var(T->text, p+1, atol(D->text)); - free(T); + var->token = T; free(D); } @@ -184,8 +183,8 @@ decl_arg(arg_) ::= VOID(T) pointers(p) NAME(N). { init_decl_var(N->text, p, 0) ); arg_->type->token = T; - //free(T); - free(N); + arg_->var->token = N; + arg_->token = N; } decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { arg_ = init_decl_arg( @@ -193,8 +192,8 @@ decl_arg(arg_) ::= CONST VOID(T) pointers(p) NAME(N). { init_decl_var(N->text, p, 0) ); arg_->type->token = T; - //free(T); - free(N); + arg_->var->token = N; + arg_->token = N; } %type decl_args {decl_args*} @@ -243,7 +242,6 @@ struct_layout(layout) ::= COLON COLON LPAREN NUMBER(POS) COMMA NUMBER(SIZ) RPARE decl_type(type_) ::= decl_type_token(T). { type_ = init_decl_type(T->type, T->text); type_->token = T; - //free(T); } /* unsigned, urgh */ decl_type(type_) ::= UNSIGNED NAME(T). { @@ -254,20 +252,17 @@ decl_type(type_) ::= UNSIGNED NAME(T). { memcpy(type_->name, "unsigned", sizeof("unsigned")-1); type_->name[sizeof("unsigned")] = ' '; type_->name[T->size + sizeof("unsigned")] = 0; - //free(T); } /* we have to support plain int here because we have it in our lexer rules */ decl_type(type_) ::= INT(T). { type_ = init_decl_type(PSI_T_NAME, T->text); type_->token = T; - //free(T); } /* structs ! */ decl_type(type_) ::= STRUCT(S) NAME(T). { type_ = init_decl_type(S->type, T->text); type_->token = T; free(S); - //free(T); } %type const_decl_type {decl_type*} @@ -289,7 +284,7 @@ impl(impl) ::= impl_func(func) LBRACE impl_stmts(stmts) RBRACE. { %destructor impl_func {free_impl_func($$);} impl_func(func) ::= FUNCTION reference(r) NSNAME(NAME) impl_args(args) COLON impl_type(type). { func = init_impl_func(NAME->text, args, type, r); - free(NAME); + func->token = NAME; } %token_class impl_def_val_token NULL NUMBER TRUE FALSE QUOTED_STRING. @@ -304,7 +299,7 @@ impl_def_val(def) ::= impl_def_val_token(T). { %destructor impl_var {free_impl_var($$);} impl_var(var) ::= reference(r) DOLLAR NAME(T). { var = init_impl_var(T->text, r); - free(T); + var->token = T; } %type impl_arg {impl_arg*} @@ -375,10 +370,11 @@ impl_stmt(stmt) ::= free_stmt(free). { %destructor num_exp {free_num_exp($$);} num_exp(exp) ::= num_exp_token(tok). { exp = init_num_exp(tok->type, tok->text); - free(tok); + exp->token = tok; } num_exp(exp) ::= decl_var(var). { exp = init_num_exp(PSI_T_NAME, var); + exp->token = PSI_TokenCopy(var->token); } num_exp(exp) ::= num_exp(exp_) num_exp_op_token(operator_) num_exp(operand_). { exp_->operator = operator_->type; @@ -469,13 +465,14 @@ set_vals(vals) ::= set_vals(vals_) COMMA set_value(val). { %destructor set_func {free_set_func($$);} set_func(func) ::= set_func_token(T). { func = init_set_func(T->type, T->text); - free(T); + func->token = T; } %type return_stmt {return_stmt*} %destructor return_stmt {free_return_stmt($$);} -return_stmt(ret) ::= RETURN set_value(val) EOS. { +return_stmt(ret) ::= RETURN(T) set_value(val) EOS. { ret = init_return_stmt(val); + ret->token = T; } %type free_stmt {free_stmt*} @@ -497,7 +494,7 @@ free_calls(calls) ::= free_calls(calls_) COMMA free_call(call). { %destructor free_call {free_free_call($$);} free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. { call = init_free_call(F->text, vars); - free(F); + call->token = F; } %token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY OBJECT. -- 2.30.2