silence first validation round
authorMichael Wallner <mike@php.net>
Fri, 29 Jan 2016 13:49:42 +0000 (14:49 +0100)
committerMichael Wallner <mike@php.net>
Fri, 29 Jan 2016 13:49:42 +0000 (14:49 +0100)
php_psi.h
src/context.c
src/context.h
src/context_validate.c
src/module.c
src/parser.h
src/parser.re
src/parser_proc.y

index 44918f057db2b78cfef4af9c1c3bcbfd21891021..3d68d587405990ae41ba4abfeeed96467d0a55c4 100644 (file)
--- a/php_psi.h
+++ b/php_psi.h
@@ -20,7 +20,7 @@ extern zend_module_entry psi_module_entry;
 
 #include "context.h"
 
-void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...);
+void psi_error_wrapper(void *context, 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);
 
index d1c1655792cabac455ddba5faba9ca1b0d209e53..8bd2deef155d1b20da822b217b65e686ed49cde0 100644 (file)
@@ -37,7 +37,7 @@
 #include "php_psi_structs.h"
 
 
-PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error)
+PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error, unsigned flags)
 {
        PSI_Data T;
        struct psi_predef_type *predef_type;
@@ -51,6 +51,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr
        memset(C, 0, sizeof(*C));
 
        C->error = error;
+       C->flags = flags;
        C->ops = ops;
 
        if (ops->init) {
@@ -157,11 +158,10 @@ static int psi_select_dirent(const struct dirent *entry)
 
 void PSI_ContextBuild(PSI_Context *C, const char *paths)
 {
-       int i, n, flags = psi_check_env("PSI_DEBUG") ? PSI_PARSER_DEBUG : 0;
+       int i, n;
        char *sep = NULL, *cpy = strdup(paths), *ptr = cpy;
        struct dirent **entries = NULL;
 
-
        do {
                sep = strchr(ptr, ':');
 
@@ -177,11 +177,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(NULL, PSI_WARNING, "Path to PSI file too long: %s/%s",
+                                       C->error(C, 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(NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s",
+                               if (!PSI_ParserInit(&P, psi, C->error, C->flags)) {
+                                       C->error(C, NULL, PSI_WARNING, "Failed to init PSI parser (%s): %s",
                                                psi, strerror(errno));
                                        continue;
                                }
@@ -211,7 +211,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(NULL, PSI_WARNING, "Failed to register functions!");
+               C->error(C, NULL, PSI_WARNING, "Failed to register functions!");
        }
 
        free(cpy);
index a54e69a5cde08d6f3edefa7d5c40e20cabffdc76..6de73890e8a2dcd6bfa6ec2fedb55f44e67af563 100644 (file)
@@ -5,7 +5,7 @@
 
 #define PSI_ERROR 16
 #define PSI_WARNING 32
-typedef void (*PSI_ContextErrorFunc)(PSI_Token *token, int type, const char *msg, ...);
+typedef void (*PSI_ContextErrorFunc)(void *context, PSI_Token *token, int type, const char *msg, ...);
 
 typedef struct PSI_Context PSI_Context;
 typedef struct PSI_ContextOps PSI_ContextOps;
@@ -26,7 +26,7 @@ struct PSI_Context {
        size_t count;
 };
 
-PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error);
+PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErrorFunc error, unsigned flags);
 void PSI_ContextBuild(PSI_Context *C, const char *path);
 int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P);
 int PSI_ContextValidateData(PSI_Data *C, PSI_Data *D);
index 01dbfb7eca2cfc81f98d163cc6ef7f271d076ea9..12befca821bf12da20baf7319a618622206961de 100644 (file)
@@ -28,13 +28,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(NULL, PSI_WARNING, "Library name too long: '%s'", ptr);
+                       data->error(data, NULL, PSI_WARNING, "Library name too long: '%s'", ptr);
                }
                lib[len] = 0;
                ptr = lib;
        }
        if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
-               data->error(NULL, PSI_WARNING, "Could not open library '%s': %s.",
+               data->error(data, NULL, PSI_WARNING, "Could not open library '%s': %s.",
                                data->psi.file.ln, dlerror());
                return 0;
        }
@@ -148,7 +148,7 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
 }
 static inline int validate_decl_typedef(PSI_Data *data, decl_arg *def) {
        if (!validate_decl_type(data, def->type)) {
-               data->error(def->token, PSI_WARNING,
+               data->error(data, def->token, PSI_WARNING,
                        "Type '%s' cannot be aliased to %s'%s'",
                        def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",
                        def->var->name);
@@ -164,7 +164,7 @@ 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(arg->type->token, PSI_WARNING,
+               data->error(data, arg->type->token, PSI_WARNING,
                        "Cannot use '%s' as type for '%s'",
                        arg->type->name, arg->var->name);
                return 0;
@@ -287,7 +287,7 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
        size_t i, pos, len, size, align;
 
        if (!s->size && !s->args->count) {
-               data->error(s->token, PSI_WARNING,
+               data->error(data, s->token, PSI_WARNING,
                                "Cannot compute size of empty struct %s",
                                s->name);
                return 0;
@@ -309,7 +309,7 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
                        align = align_decl_arg(darg, &pos, &len);
 
                        if (darg->layout->len != len) {
-                               data->error(darg->token, PSI_WARNING,
+                               data->error(data, darg->token, PSI_WARNING,
                                                "Computed size %zu of %s.%s does not match"
                                                " pre-defined size %zu of type '%s'",
                                                darg->layout->len, s->name, darg->var->name, len,
@@ -317,7 +317,7 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
                                return 0;
                        }
                        if (darg->layout->pos != pos) {
-                               data->error(darg->token, PSI_WARNING,
+                               data->error(data, darg->token, PSI_WARNING,
                                                "Computed offset %zu of %s.%s does not match"
                                                " pre-defined offset %zu",
                                                darg->layout->len, s->name, darg->var->name, len);
@@ -360,7 +360,7 @@ static inline int validate_decl_union(PSI_Data *data, decl_union *u) {
        size_t i, pos, len, size, align;
 
        if (!u->size && !u->args->count) {
-               data->error(u->token, PSI_WARNING,
+               data->error(data, u->token, PSI_WARNING,
                                "Cannot compute size of empty union %s",
                                u->name);
                return 0;
@@ -382,13 +382,13 @@ static inline int validate_decl_union(PSI_Data *data, decl_union *u) {
                        align = align_decl_arg(darg, &pos, &len);
 
                        if (darg->layout->pos != 0) {
-                               data->error(darg->token, PSI_WARNING,
+                               data->error(data, darg->token, PSI_WARNING,
                                                "Offset of %s.%s must be 0",
                                                u->name, darg->var->name);
                                return 0;
                        }
                        if (darg->layout->len != len) {
-                               data->error(darg->token, PSI_WARNING,
+                               data->error(data, darg->token, PSI_WARNING,
                                                "Computed size %zu of %s.%s does not match"
                                                " pre-defined size %zu of type '%s'",
                                                darg->layout->len, u->name, darg->var->name, size,
@@ -444,7 +444,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(func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)");
+               data->error(data, func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)");
                return 0;
        }
 
@@ -462,7 +462,7 @@ 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(func->token, PSI_WARNING,
+                       data->error(data, func->token, PSI_WARNING,
                                "Failed to locate symbol '%s': %s",
                                func->var->name, dlerror() ?: "not found");
                }
@@ -472,7 +472,7 @@ 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,
+               data->error(data, decl->abi->token, PSI_WARNING,
                                "Invalid calling convention: '%s'", decl->abi->token->text);
                return 0;
        }
@@ -581,7 +581,7 @@ static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *darg
        case PSI_T_NAME:
                if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
                        if (!locate_num_exp_enum_item(exp, data->enums) && !locate_num_exp_enum_item_ex(exp, enm)) {
-                               data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
+                               data->error(data, exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
                                                exp->u.dvar->name);
                                return 0;
                        }
@@ -589,7 +589,7 @@ static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *darg
                return 1;
        case PSI_T_NSNAME:
                if (!locate_num_exp_constant(exp, data->consts)) {
-                       data->error(exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression",
+                       data->error(data, exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression",
                                        exp->u.numb);
                        return 0;
                }
@@ -606,7 +606,7 @@ static inline int validate_decl_enum(PSI_Data *data, decl_enum *e) {
        size_t j;
 
        if (!e->items || !e->items->count) {
-               data->error(e->token, PSI_WARNING, "Empty enum '%s'", e->name);
+               data->error(data, e->token, PSI_WARNING, "Empty enum '%s'", e->name);
                return 0;
        }
 
@@ -689,14 +689,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(set->func->token, PSI_WARNING, "Invalid cast '%s' in `set` statement", set->func->name);
+               data->error(data, set->func->token, PSI_WARNING, "Invalid cast '%s' in `set` statement", 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(svar->token, PSI_WARNING, "Unknown variable '%s' in `set` statement", svar->name);
+                       data->error(data, svar->token, PSI_WARNING, "Unknown variable '%s' in `set` statement", svar->name);
                        return 0;
                }
        }
@@ -711,7 +711,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(set->func->token, E_WARNING, "Inner `set` statement casts only work with "
+                       data->error(data, 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;
                }
@@ -743,7 +743,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg
 
                if (sub_ref) {
                        if (strcmp(sub_var->name, set_var->name)) {
-                               data->error(sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
+                               data->error(data, 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)) {
@@ -751,7 +751,7 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg
                        }
                }
        } else if (set->count > 1) {
-               data->error(set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once");
+               data->error(data, set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once");
                return 0;
        }
 
@@ -793,12 +793,12 @@ 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(impl->stmts->ret.list[1]->token, PSI_WARNING,
+                       data->error(data, 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(impl->func->token, PSI_WARNING,
+                       data->error(data, impl->func->token, PSI_WARNING,
                                        "Missing `return` statement for implementation %s",
                                        impl->func->name);
                }
@@ -808,7 +808,7 @@ 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(ret->token, PSI_WARNING,
+               data->error(data, ret->token, PSI_WARNING,
                                "Missing declaration '%s' for `return` statment for implementation %s",
                                ret->set->vars->vars[0]->name, impl->func->name);
                return 0;
@@ -840,7 +840,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(let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
+                       data->error(data, let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
                                        " of implementation '%s'", let_var->name, impl->func->name);
                        return 0;
                }
@@ -887,7 +887,7 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
                                }
                        }
                        if (!check) {
-                               data->error(let->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement"
+                               data->error(data, 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;
@@ -911,7 +911,7 @@ static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
                        }
                }
                if (!check) {
-                       data->error(impl->func->token, PSI_WARNING,
+                       data->error(data, 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, "*****",
@@ -940,7 +940,7 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
                        }
                }
                if (!check) {
-                       data->error(set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement"
+                       data->error(data, set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement"
                                        " of implementation '%s'",
                                        set->var->name, impl->func->name);
                        return 0;
@@ -983,7 +983,7 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
                        }
 
                        if (!check) {
-                               data->error(set_var->token, PSI_WARNING, "Unknown value '%s' of `set` statement"
+                               data->error(data, 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;
@@ -1017,7 +1017,7 @@ 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(free_call->token, PSI_WARNING,
+                               data->error(data, free_call->token, PSI_WARNING,
                                                "Missing declaration '%s' in `free` statement"
                                                " of implementation '%s'",
                                                free_call->func, impl->func->name);
@@ -1047,7 +1047,7 @@ static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) {
                                }
 
                                if (!check) {
-                                       data->error(free_var->token, PSI_WARNING,
+                                       data->error(data, free_var->token, PSI_WARNING,
                                                        "Unknown variable '%s' of `free` statement"
                                                        " of implementation '%s'",
                                                        free_var->name, impl->func->name);
@@ -1060,7 +1060,7 @@ 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(impl->func->token, PSI_WARNING,
+               data->error(data, impl->func->token, PSI_WARNING,
                                "Missing body for implementation %s!",
                                impl->func->name);
                return 0;
@@ -1093,7 +1093,7 @@ static inline int validate_impl_args(PSI_Data *data, impl *impl) {
                if (iarg->def) {
                        def = 1;
                } else if (def) {
-                       data->error(impl->func->token, PSI_WARNING,
+                       data->error(data, impl->func->token, PSI_WARNING,
                                        "Non-optional argument %zu '$%s' of implementation '%s'"
                                        " follows optional argument",
                                        i+1, iarg->var->name, impl->func->name);
@@ -1120,38 +1120,11 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
        decl_typedefs *check_defs = P->defs;
        decl_structs *check_structs = P->structs;
        decl_enums *check_enums = P->enums;
+       unsigned silent = C->flags & PSI_PARSER_SILENT;
 
        C->data = realloc(C->data, C->count * sizeof(*C->data));
        D = PSI_DataExchange(&C->data[count], PSI_DATA(P));
-/*
-       if (D->defs) {
-               for (i = 0; i < D->defs->count; ++i) {
-                       if (validate_decl_typedef(PSI_DATA(C), D->defs->list[i])) {
-                               C->defs = add_decl_typedef(C->defs, D->defs->list[i]);
-                       } else {
-                               check_defs = add_decl_typedef(check_defs, D->defs->list[i]);
-                       }
-               }
-       }
-       if (D->structs) {
-               for (i = 0; i < D->structs->count; ++i) {
-                       if (validate_decl_struct(PSI_DATA(C), D->structs->list[i])) {
-                               C->structs = add_decl_struct(C->structs, D->structs->list[i]);
-                       } else {
-                               check_structs = add_decl_struct(check_structs, D->structs->list[i]);
-                       }
-               }
-       }
-       if (D->enums) {
-               for (i = 0; i < D->enums->count; ++i) {
-                       if (validate_decl_enum(PSI_DATA(C), D->enums->list[i])) {
-                               C->enums = add_decl_enum(C->enums, D->enums->list[i]);
-                       } else {
-                               check_enums = add_decl_enum(check_enums, D->enums->list[i]);
-                       }
-               }
-       }
-*/
+
 #define REVALIDATE(what) do { \
                if (check_round && check_ ##what) { \
                        free(check_ ##what->list); \
@@ -1162,13 +1135,16 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
 #define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
 #define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
 
+       if (!silent) {
+               /* no warnings on first round */
+               C->flags |= PSI_PARSER_SILENT;
+       }
        for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
                decl_typedefs *recheck_defs = NULL;
                decl_structs *recheck_structs = NULL;
                decl_enums *recheck_enums = NULL;
 
                check_count = CHECK_TOTAL;
-               fprintf(stderr, "### Validation round %zu with %zu checks\n", check_round, check_count);
 
                for (i = 0; i < CHECK_COUNT(defs); ++i) {
                        if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) {
@@ -1195,6 +1171,10 @@ int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
                REVALIDATE(defs);
                REVALIDATE(structs);
                REVALIDATE(enums);
+
+               if (check_round == 0 && !silent) {
+                       C->flags &= ~PSI_PARSER_SILENT;
+               }
        }
 
 
index f71975b295932bdc053129e3b2fd03b4e955ae41..aff784dbc28235c13f65583f69c58f6962638d25 100644 (file)
@@ -37,12 +37,18 @@ zend_class_entry *psi_object_get_class_entry()
        return psi_class_entry;
 }
 
-void psi_error_wrapper(PSI_Token *t, int type, const char *msg, ...)
+void psi_error_wrapper(void *context, PSI_Token *t, int type, const char *msg, ...)
 {
        va_list argv;
        const char *fn = NULL;
        unsigned ln = 0;
 
+       if (context) {
+               if (PSI_DATA(context)->flags & PSI_PARSER_SILENT) {
+                       return;
+               }
+       }
+
        if (t) {
                fn = t->file;
                ln = t->line;
@@ -151,6 +157,8 @@ static PHP_MINIT_FUNCTION(psi)
 {
        PSI_ContextOps *ops = NULL;
        zend_class_entry ce = {0};
+       unsigned flags = psi_check_env("PSI_DEBUG") ? PSI_PARSER_DEBUG : (
+                       psi_check_env("PSI_SILENT") ? PSI_PARSER_SILENT : 0);
 
        REGISTER_INI_ENTRIES();
 
@@ -177,7 +185,7 @@ static PHP_MINIT_FUNCTION(psi)
                return FAILURE;
        }
 
-       PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper);
+       PSI_ContextInit(&PSI_G(context), ops, psi_error_wrapper, flags);
        PSI_ContextBuild(&PSI_G(context), PSI_G(directory));
 
        if (psi_check_env("PSI_DUMP")) {
index 066e8a355c947321cb6c41c29734ae5808c80073..94860c5248d0e0fd9e6076b4ae90e5e4ce5a2fe5 100644 (file)
@@ -1409,7 +1409,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)(PSI_Token *token, int type, const char *msg, ...);
+typedef void (*psi_error_cb)(void *context, PSI_Token *token, int type, const char *msg, ...);
 
 #define PSI_DATA(D) ((PSI_Data *) (D))
 #define PSI_DATA_MEMBERS \
@@ -1424,7 +1424,9 @@ typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...);
                decl_file file; \
                decl_libs libs; \
        } psi; \
-       psi_error_cb error
+       psi_error_cb error; \
+       unsigned errors; \
+       unsigned flags
 typedef struct PSI_Data {
        PSI_DATA_MEMBERS;
 } PSI_Data;
@@ -1468,7 +1470,7 @@ typedef struct PSI_Parser {
        FILE *fp;
        token_t num;
        void *proc;
-       unsigned flags, errors, line, col;
+       unsigned line, col;
        char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE];
 } PSI_Parser;
 
@@ -1600,6 +1602,7 @@ static inline uint64_t PSI_TokenHash(PSI_Token *t, char *digest_buf) {
 }
 
 #define PSI_PARSER_DEBUG 0x1
+#define PSI_PARSER_SILENT 0x2
 
 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, ...);
index 5b7e80e83c24d81a36892167a51bbd6094704351..e7787fc6cd47d64d32f0592f9f6cb5d0ea185308 100644 (file)
@@ -19,8 +19,10 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb err
        fp = fopen(filename, "r");
 
        if (!fp) {
-               error(NULL, PSI_WARNING, "Could not open '%s' for reading: %s",
-                               filename, strerror(errno));
+               if (!(flags & PSI_PARSER_SILENT)) {
+                       error(NULL, NULL, PSI_WARNING, "Could not open '%s' for reading: %s",
+                                       filename, strerror(errno));
+               }
                return NULL;
        }
 
index 0e966a8fbd8cb864ab8bec7beac8a111fbb5627b..56938cff0d2321ef3bf3d4d3a405b2d6c45b261f 100644 (file)
@@ -41,7 +41,7 @@ block ::= EOS.
 
 block ::= LIB(T) QUOTED_STRING(libname) EOS. {
        if (P->psi.file.ln) {
-               P->error(T, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
+               P->error(P, T, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
        } else {
                P->psi.file.ln = strndup(libname->text + 1, libname->size - 2);
        }