pike.git / src / program.c

version» Context lines:

pike.git/src/program.c:1:   /*   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: program.c,v 1.701 2008/05/22 20:13:19 mast Exp $ + || $Id: program.c,v 1.702 2008/05/24 15:14:12 grubba Exp $   */      #include "global.h"   #include "program.h"   #include "object.h"   #include "dynamic_buffer.h"   #include "pike_types.h"   #include "stralloc.h"   #include "las.h"   #include "lex.h"
pike.git/src/program.c:100:   #define FIND_FUNCTION_HASH_TRESHOLD 9         #define DECLARE   #include "compilation.h"      struct pike_string *this_program_string;   static struct pike_string *this_string, *this_function_string;   static struct pike_string *UNDEFINED_string;    + /* Common compiler subsystems */ + struct pike_string *parser_system_string; + struct pike_string *type_check_system_string; +    const char *const lfun_names[] = {    "__INIT",    "create",    "destroy",    "`+",    "`-",    "`&",    "`|",    "`^",    "`<<",
pike.git/src/program.c:2069:    sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level);       /* Check if the symbol was used before it was inherited. */    if ((c->lex.pragmas & ID_STRICT_TYPES) &&    (sub_ref->id_flags & ID_USED)) {    struct identifier *sub_id = ID_FROM_PTR(inh->prog, sub_ref);    if (IDENTIFIER_IS_FUNCTION(sub_id->identifier_flags)) {    if ((Pike_compiler->compiler_pass == 2) &&    !pike_types_le(ID_FROM_PTR(Pike_compiler->new_program,    new_ref)->type, sub_id->type)) { -  yywarning("Type mismatch when overloading function %S.", name); -  yyexplain_nonmatching_types(sub_id->type, -  ID_FROM_PTR(Pike_compiler->new_program, +  yytype_report(REPORT_WARNING, +  NULL, 0, sub_id->type, +  NULL, 0, ID_FROM_PTR(Pike_compiler->new_program,    new_ref)->type, -  YYTE_IS_WARNING); +  0, "Type mismatch when overloading function %S.", +  name);    }    } else {    struct identifier *new_id;    /* Variable or constant.    *    * Note: Use weaker check for integers (especially for constants).    */    if (!pike_types_le(sub_id->type,    (new_id = ID_FROM_PTR(Pike_compiler->new_program,    new_ref))->type) &&    !((i->run_time_type == PIKE_T_INT) &&    (new_id->run_time_type == PIKE_T_INT) &&    (IDENTIFIER_IS_CONSTANT(sub_id->identifier_flags) ||    match_types(sub_id->type, new_id->type)))) { -  yywarning("Type mismatch when overloading %S.", name); -  yyexplain_nonmatching_types(sub_id->type, new_id->type, -  YYTE_IS_WARNING); +  yytype_report(REPORT_WARNING, +  NULL, 0, sub_id->type, +  NULL, 0, new_id->type, +  0, "Type mismatch when overloading %S.", name);    }    }    }    }    is_used = ref->id_flags & ID_USED;       *ref=*new_ref;    ref->id_flags |= is_used;    id = cur_id;    }
pike.git/src/program.c:2190:    *    * Yes -- It's needed in case of mixin.    */    if(funa_is_prototype && (funb->func.offset != -1) &&    !(funp->id_flags & ID_INLINE))    {    if ((c->lex.pragmas & ID_STRICT_TYPES) &&    (funp->id_flags & ID_USED)) {    /* Verify that the types are compatible. */    if (!pike_types_le(funb->type, fun->type)) { -  yywarning("Type mismatch when overloading %S.", fun->name); -  yyexplain_nonmatching_types(fun->type, funb->type, -  YYTE_IS_WARNING); +  yytype_report(REPORT_WARNING, NULL, 0, fun->type, +  NULL, 0, funb->type, +  0, "Type mismatch when overloading %S.", +  fun->name);    }    }    funp->inherit_offset = funpb->inherit_offset;    funp->identifier_offset = funpb->identifier_offset;    }    if(!funa_is_prototype && funb->func.offset == -1)    {    if ((c->lex.pragmas & ID_STRICT_TYPES) &&    (funpb->id_flags & ID_USED)) {    /* Verify that the types are compatible. */    if (!pike_types_le(fun->type, funb->type)) { -  yywarning("Type mismatch when overloading %S.", fun->name); -  yyexplain_nonmatching_types(funb->type, fun->type, -  YYTE_IS_WARNING); +  yytype_report(REPORT_WARNING, NULL, 0, funb->type, +  NULL, 0, fun->type, +  0, "Type mismatch when overloading %S.", +  fun->name);    }    }    funpb->inherit_offset = funp->inherit_offset;    funpb->identifier_offset = funp->identifier_offset;    }    }    }    if(found_better!=-1)    continue;    }
pike.git/src/program.c:4882: Inside #if defined(PROGRAM_BUILD_DEBUG)
   fprintf (stderr, "%.*sdefining variable (pass=%d): %s ",    c->compilation_depth, "", Pike_compiler->compiler_pass, d->str);    free_string (d);    push_string (name);    print_svalue (stderr, --Pike_sp);    putc ('\n', stderr);    }   #endif       if(type == void_type_string) -  yyerror("Variables can't be of type void"); +  yyerror("Variables can't be of type void.");       n = isidentifier(name);       if(Pike_compiler->new_program->flags & PROGRAM_PASS_1_DONE)    {    if(n==-1)    yyerror("Pass2: Variable disappeared!");    else {    struct identifier *id=ID_FROM_INT(Pike_compiler->new_program,n);    free_type(id->type);
pike.git/src/program.c:4931:    "variable/functions %S", name);       if(!(IDENTIFIERP(n)->id_flags & ID_INLINE) ||    Pike_compiler->compiler_pass!=1)    {    int n2;       if(ID_FROM_INT(Pike_compiler->new_program, n)->type != type &&    !pike_types_le(type,    ID_FROM_INT(Pike_compiler->new_program, n)->type)) { +  int level = REPORT_WARNING;    if (!match_types(ID_FROM_INT(Pike_compiler->new_program, n)->type,    type)) { -  my_yyerror("Illegal to redefine inherited variable %S " -  "with different type.", name); -  yytype_error(NULL, +  level = REPORT_ERROR; +  } +  yytype_report(level, NULL, 0,    ID_FROM_INT(Pike_compiler->new_program, n)->type, -  type, 0); -  return n; -  } else { -  yywarning("Redefining inherited variable %S " +  NULL, 0, type, 0, +  "Illegal to redefine inherited variable %S "    "with different type.", name); -  yytype_error(NULL, -  ID_FROM_INT(Pike_compiler->new_program, n)->type, -  type, YYTE_IS_WARNING); +     } -  } +           if(!IDENTIFIER_IS_VARIABLE(ID_FROM_INT(Pike_compiler->new_program, n)->    identifier_flags))    {    my_yyerror("Illegal to redefine inherited symbol %S "    "as a variable.", name);    return n;    }       if ((ID_FROM_INT(Pike_compiler->new_program, n)->run_time_type !=    PIKE_T_MIXED) &&    (ID_FROM_INT(Pike_compiler->new_program, n)->run_time_type !=    compile_type_to_runtime_type(type))) { -  my_yyerror("Illegal to redefine inherited variable %S " -  "with different type.", name); -  yytype_error(NULL, +  yytype_report(REPORT_ERROR, NULL, 0,    ID_FROM_INT(Pike_compiler->new_program, n)->type, -  type, 0); +  NULL, 0, type, 0, +  "Illegal to redefine inherited variable %S " +  "with different type.", name);    return n;    }       /* Create an alias for the old variable reference, so that we    * can change the compile-time type. */    n2 = define_alias(name, type, flags & ~ID_EXTERN, 0, n);       /* Hide the old variable. */    Pike_compiler->new_program->identifier_references[n].id_flags |=    ID_HIDDEN;
pike.git/src/program.c:5461:   #endif       /* If this is an lfun, match against the predefined type. */    if ((lfun_type = low_mapping_string_lookup(lfun_types, name))) {   #ifdef PIKE_DEBUG    if (lfun_type->type != T_TYPE) {    Pike_fatal("Bad entry in lfun_types for key \"%s\"\n", name->str);    }   #endif /* PIKE_DEBUG */    if (!pike_types_le(type, lfun_type->u.type)) { +  int level = REPORT_NOTICE;    if (!match_types(type, lfun_type->u.type)) { -  my_yyerror("Type mismatch for callback function %S:", name); -  yytype_error(NULL, lfun_type->u.type, type, 0); -  Pike_fatal("Type mismatch!\n"); +  level = REPORT_ERROR;    } else if (c->lex.pragmas & ID_STRICT_TYPES) { -  yywarning("Type mismatch for callback function %S:", name); -  yytype_error(NULL, lfun_type->u.type, type, -  YYTE_IS_WARNING); +  level = REPORT_WARNING;    } -  +  yytype_report(level, NULL, 0, lfun_type->u.type, +  NULL, 0, type, 0, +  "Type mismatch for callback function %S:", name);    }    } else if (((name->len > 3) &&    (index_shared_string(name, 0) == '`') &&    (index_shared_string(name, 1) == '-') &&    (index_shared_string(name, 2) == '>')) ||    ((name->len > 1) &&    (index_shared_string(name, 0) == '`') &&    ((index_shared_string(name, 1) >= 256) ||    isidchar(index_shared_string(name, 1))))) {    /* Getter setter. */
pike.git/src/program.c:5506:    gs_type = lfun_setter_type_string;    is_setter = 1;    symbol = string_slice(name, delta, name->len-(delta+1));    symbol_type = get_argument_type(type, 0);    }       if (symbol) {    /* We got a getter or a setter. */    struct reference *ref;    if (!pike_types_le(type, gs_type)) { +  int level = REPORT_NOTICE;    if (!match_types(type, gs_type)) { -  my_yyerror("Type mismatch for callback function %S:", name); -  yytype_error(NULL, gs_type, type, 0); +  level = REPORT_ERROR;    } else if (c->lex.pragmas & ID_STRICT_TYPES) { -  yywarning("Type mismatch for callback function %S:", name); -  yytype_error(NULL, gs_type, type, YYTE_IS_WARNING); +  level = REPORT_WARNING;    } -  +  yytype_report(level, NULL, 0, gs_type, +  NULL, 0, type, 0, +  "Type mismatch for callback function %S:", name);    }    i = isidentifier(symbol);    if ((i >= 0) &&    !((ref = PTR_FROM_INT(Pike_compiler->new_program, i))->    id_flags & ID_INHERITED)) {    /* Not an inherited symbol. */    struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, i);    if (!IDENTIFIER_IS_VARIABLE(id->identifier_flags)) {    my_yyerror("Illegal to redefine function %S with variable.", symbol);    } else if (id->run_time_type != PIKE_T_GET_SET) {
pike.git/src/program.c:5614:    /* Note: The type from pass 1 may be incompatible with the one from    * pass 2. Only do this in pass 2, and only if the previous    * type isn't from pass 1.    */    if ((Pike_compiler->compiler_pass == 2) &&    (funp->run_time_type == T_FUNCTION)) {    /* match types against earlier prototype or vice versa */    if(!match_types(type, funp->type))    {    if (!(flags & ID_VARIANT)) { -  my_yyerror("Prototype doesn't match for function %S.", name); -  yytype_error(NULL, funp->type, type, 0); +  yytype_report(REPORT_ERROR, NULL, 0, +  funp->type, +  NULL, 0, type, 0, +  "Prototype doesn't match for function %S.", name);    }    }    }       if(func)    funp->func = *func;   #if 0 /* prototypes does not override non-prototypes, ok? */    else    funp->func.offset = -1;   #endif
pike.git/src/program.c:6862:    o = loc.o;    }    if (IDENTIFIER_IS_PIKE_FUNCTION(id->identifier_flags))    return low_get_line (p->program + id->func.offset, p, linep);    return low_get_program_line(o->prog, linep);    }    *linep = 0;    return NULL;   }    - /* FIXME: Consider converting these to using va_yyreport(). */ -  - PMOD_EXPORT void va_yyerror(const char *fmt, va_list args) + /* Main entry point for compiler messages originating from +  * C-code. +  * +  * Sends the message along to PikeCompiler()->report(). +  * +  * NOTE: The format string fmt (and vargs) is only formatted with +  * string_builder_vsprintf() if the number of extra +  * Pike stack arguments (args) is zero. +  */ + PMOD_EXPORT void va_yyreport(int severity_level, +  struct pike_string *file, INT32 line, +  struct pike_string *system, INT32 args, +  const char *fmt, va_list vargs)   { -  +  struct compilation *c = MAYBE_THIS_COMPILATION;    struct string_builder s; -  struct pike_string *tmp; +  struct pike_string *msg; +  +  if (!c) return; /* No compiler context. */ +  +  STACK_LEVEL_START(args); +  + #ifdef PIKE_DEBUG +  if(Pike_interpreter.recoveries && Pike_sp-Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer) +  Pike_fatal("Stack error (underflow)\n"); + #endif +  +  /* Convert type errors to warnings in non-strict compat mode. */ +  if ((system == type_check_system_string) && +  (severity_level == REPORT_ERROR) && +  (c->major != -1) && +  !(c->lex.pragmas & ID_STRICT_TYPES) && +  ((c->major < PIKE_MAJOR_VERSION) || +  ((c->major == PIKE_MAJOR_VERSION) && +  (c->minor < PIKE_MINOR_VERSION)))) { +  severity_level = REPORT_WARNING; +  } +  +  /* If we have parse errors we might get erroneous warnings, +  * so don't print them. +  * This has the additional benefit of making it easier to +  * visually locate the actual error message. +  */ +  if ((severity_level <= REPORT_WARNING) && +  Pike_compiler->num_parse_error) { +  return; +  } +  +  if (severity_level >= REPORT_ERROR) { +  if (Pike_compiler->num_parse_error > 20) return; +  Pike_compiler->num_parse_error++; +  cumulative_parse_error++; +  } +  +  push_int(severity_level); +  ref_push_string(file?file:c->lex.current_file); +  push_int(line?line:c->lex.current_line); +  ref_push_string(system); +  if (args) { +  int i = args; +  push_text(fmt); +  /* Copy the arguments. */ +  while (i--) { +  push_svalue(Pike_sp-(args+5)); +  } +  } else {    init_string_builder(&s, 0); -  string_builder_vsprintf(&s, fmt, args); -  tmp = finish_string_builder(&s); -  low_yyerror(tmp); -  free_string(tmp); +  string_builder_vsprintf(&s, fmt, vargs); +  push_string(finish_string_builder(&s));    }    -  +  safe_apply_current(PC_REPORT_FUN_NUM, args + 5); +  pop_stack(); +  if (args) pop_n_elems(args); +  STACK_LEVEL_DONE(0); + } +  + PMOD_EXPORT void low_yyreport(int severity_level, +  struct pike_string *file, INT32 line, +  struct pike_string *system, +  INT32 args, const char *fmt, ...) + { +  va_list vargs; +  +  va_start(vargs,fmt); +  va_yyreport(severity_level, file, line, system, args, fmt, vargs); +  va_end(vargs); + } +  + PMOD_EXPORT void yyreport(int severity_level, struct pike_string *system, +  INT32 args, const char *fmt, ...) + { +  va_list vargs; +  +  va_start(vargs,fmt); +  va_yyreport(severity_level, NULL, 0, system, args, fmt, vargs); +  va_end(vargs); + } +  + PMOD_EXPORT void yywarning(char *fmt, ...) + { +  va_list vargs; +  +  va_start(vargs,fmt); +  va_yyreport(REPORT_WARNING, NULL, 0, parser_system_string, 0, fmt, vargs); +  va_end(vargs); + } +  + /* FIXME: Consider converting these to using va_yyreport(). */ +    PMOD_EXPORT void my_yyerror(const char *fmt,...)   { -  va_list args; -  va_start(args,fmt); -  va_yyerror (fmt, args); -  va_end(args); +  va_list vargs; +  va_start(vargs,fmt); +  va_yyreport(REPORT_ERROR, NULL, 0, parser_system_string, 0, fmt, vargs); +  va_end(vargs);   }    -  + PMOD_EXPORT void yyerror(const char *str) + { +  my_yyerror("%s", str); + } +  + /* Main entry point for errors from the type-checking subsystems. +  * +  * The message (if any) will be formatted for the same source +  * position as the got_t. +  * +  * The expect_t will be formatted for the same position as the got_t +  * if there's no expected_file/expected_line. +  * +  * The got_t will be formatted for the current lex position if there's +  * no got_file/got_line. +  */ + void yytype_report(int severity_level, +  struct pike_string *expected_file, INT32 expected_line, +  struct pike_type *expected_t, +  struct pike_string *got_file, INT32 got_line, +  struct pike_type *got_t, +  INT32 args, const char *fmt, ...) + { +  if (fmt) +  { +  va_list vargs; +  va_start(vargs, fmt); +  va_yyreport(severity_level, got_file, got_line, type_check_system_string, +  args, fmt, vargs); +  va_end(vargs); +  } +  +  if (expected_t && got_t) { +  yyexplain_nonmatching_types(severity_level, +  expected_file?expected_file:got_file, +  expected_line?expected_line:got_line, +  expected_t, +  got_file, got_line, got_t); +  } else if (expected_t) { +  ref_push_type_value(expected_t); +  low_yyreport(severity_level, +  expected_file?expected_file:got_file, +  expected_line?expected_line:got_line, +  type_check_system_string, +  1, "Expected: %O."); +  } else if (got_t) { +  ref_push_type_value(got_t); +  low_yyreport(severity_level, got_file, got_line, type_check_system_string, +  1, "Got : %O"); +  } + } +  + void yytype_error(const char *msg, struct pike_type *expected_t, +  struct pike_type *got_t, unsigned int flags) + { +  yytype_report((flags & YYTE_IS_WARNING)?REPORT_WARNING:REPORT_ERROR, +  NULL, 0, expected_t, NULL, 0, got_t, 0, "%s", msg); + } +    struct pike_string *format_exception_for_error_msg (struct svalue *thrown)   {    struct pike_string *s = NULL;       push_svalue (thrown);    SAFE_APPLY_MASTER ("describe_error", 1);       if (sp[-1].type == T_STRING) {    f_string_trim_all_whites(1);    push_constant_text("\n");
pike.git/src/program.c:6916:    struct compilation *c = THIS_COMPILATION;       CHECK_COMPILER();       move_svalue (&thrown, &throw_value);    mark_free_svalue (&throw_value);       if (yyerror_fmt) {    va_list args;    va_start (args, yyerror_fmt); -  va_yyerror (yyerror_fmt, args); +  va_yyreport(REPORT_ERROR, NULL, 0, parser_system_string, 0, +  yyerror_fmt, args);    va_end (args);    }       push_svalue(&thrown);    /* safe_apply_current(PC_FILTER_EXCEPTION_FUN_NUM, 1); */    low_safe_apply_handler("compile_exception", c->handler, c->compat_handler, 1);       if (SAFE_IS_ZERO(sp-1)) {    struct pike_string *s = format_exception_for_error_msg (&thrown);    if (s) { -  low_yyerror(s); -  free_string (s); +  push_string(s); +  yyreport(REPORT_ERROR, parser_system_string, 1, "%s");    }    }       pop_stack();    free_svalue(&thrown);   }      extern void yyparse(void);      #ifdef PIKE_DEBUG
pike.git/src/program.c:7250:    *! @seealso    *! @[PikeCompiler()->report()]    */   static void f_compilation_env_report(INT32 args)   {    int level;    struct pike_string *filename;    INT_TYPE linenumber;    struct pike_string *subsystem;    struct pike_string *message; +     if (args > 5) {    f_sprintf(args - 4);    args = 5;    }    get_all_args("report", args, "%d%W%i%W%W",    &level, &filename, &linenumber, &subsystem, &message);       /* Ignore informational level messages */    if (level >= REPORT_WARNING) {    if (get_master()) {
pike.git/src/program.c:7940:    struct compilation *c = THIS_COMPILATION;    int level;    struct pike_string *filename;    INT_TYPE linenumber;    struct pike_string *subsystem;    struct pike_string *message;    struct object *handler = NULL;    int fun = -1;       /* FIXME: get_all_args() ought to have a marker -  * indicating that accept more arguments... +  * indicating that we accept more arguments...    */    get_all_args("report", args, "%d", &level);       if ((c->handler || c->compat_handler) &&    (level >= REPORT_WARNING)) {    /* Ignore informational level messages */    const char *fun_name = "compile_warning";       if (level >= REPORT_ERROR) fun_name = "compile_error";   
pike.git/src/program.c:9371:    struct svalue key;    struct svalue val;    struct svalue id;    init_program_blocks();       MAKE_CONST_STRING(this_function_string,"this_function");    MAKE_CONST_STRING(this_program_string,"this_program");    MAKE_CONST_STRING(this_string,"this");    MAKE_CONST_STRING(UNDEFINED_string,"UNDEFINED");    +  MAKE_CONST_STRING(parser_system_string, "parser"); +  MAKE_CONST_STRING(type_check_system_string, "type_check"); +     lfun_ids = allocate_mapping(NUM_LFUNS);    lfun_types = allocate_mapping(NUM_LFUNS);    for (i=0; i < NELEM(lfun_names); i++) {    lfun_strings[i] = make_shared_string(lfun_names[i]);       id.type = T_INT;    id.subtype = NUMBER_NUMBER;    id.u.integer = i;    key.type = T_STRING;    key.u.string = lfun_strings[i];
pike.git/src/program.c:10134: Inside #if 0
   find_child_cache[h].cid=child->id;    find_child_cache[h].id=i;    return i;    }    }    }    return -1;   }   #endif /* 0 */    - void va_yyreport(int severity_level, const char *system, -  const char *fmt, va_list args) - { -  struct compilation *c = MAYBE_THIS_COMPILATION; -  struct string_builder s; -  struct pike_string *msg; +     -  if (!c) return; /* No compiler context. */ +     -  /* If we have parse errors we might get erroneous warnings, -  * so don't print them. -  * This has the additional benefit of making it easier to -  * visually locate the actual error message. -  */ -  if ((severity_level <= REPORT_WARNING) && -  Pike_compiler->num_parse_error) { -  return; -  } -  -  init_string_builder(&s, 0); -  string_builder_vsprintf(&s, fmt, args); -  msg = finish_string_builder(&s); -  -  push_int(severity_level); -  ref_push_string(c->lex.current_file); -  push_int(c->lex.current_line); -  push_text(system); -  push_string(msg); -  safe_apply_current(PC_REPORT_FUN_NUM, 5); -  pop_stack(); - } -  - void yyreport(int severity_level, const char *system, const char *fmt, ...) - { -  va_list args; -  -  va_start(args,fmt); -  va_yyreport(severity_level, system, fmt, args); -  va_end(args); - } -  - void yywarning(char *fmt, ...) - { -  va_list args; -  -  va_start(args,fmt); -  va_yyreport(REPORT_WARNING, "parse", fmt, args); -  va_end(args); - } -  -  -  +    /* returns 1 if a implements b */   static int low_implements(struct program *a, struct program *b)   {    int e;    struct pike_string *s=findstring("__INIT");    for(e=0;e<b->num_identifier_references;e++)    {    struct identifier *bid;    int i;    if (b->identifier_references[e].id_flags & (ID_STATIC|ID_HIDDEN))
pike.git/src/program.c:10366:    is_compatible_cache[hval].bid=bid;    is_compatible_cache[hval].ret = 1; /* Tentatively compatible. */    is_compatible_cache[hval].ret = low_is_compatible(a,b);    /* NOTE: If low_is compatible() returns 0, the cache may have received    * some false positives. Those should be cleared.    */    return is_compatible_cache[hval].ret;   }      /* Explains why a is not compatible with b */ - void yyexplain_not_compatible(struct program *a, struct program *b, int flags) + void yyexplain_not_compatible(int severity_level, +  struct program *a, struct program *b)   {    int e;    struct pike_string *s=findstring("__INIT");    int res = 1;    INT32 a_line = 0;    INT32 b_line = 0;    struct pike_string *a_file;    struct pike_string *b_file;    DECLARE_CYCLIC();   
pike.git/src/program.c:10413:    if(s == bid->name) continue; /* Skip __INIT */    i = find_shared_string_identifier(bid->name,a);    if (i == -1) {    continue; /* It's ok... */    }       /* Note: Uses weaker check for constant integers. */    if(((bid->run_time_type != PIKE_T_INT) ||    (ID_FROM_INT(a, i)->run_time_type != PIKE_T_INT)) &&    !match_types(ID_FROM_INT(a,i)->type, bid->type)) { -  if (flags & YYTE_IS_WARNING) { -  push_int(REPORT_WARNING); -  push_int(REPORT_WARNING); -  } else { -  push_int(REPORT_ERROR); -  push_int(REPORT_ERROR); -  } -  ref_push_string(a_file); -  push_int(a_line); -  push_constant_text("type_check"); -  push_constant_text("Identifier %s in %O is incompatible"); +     ref_push_string(bid->name);    ref_push_program(a); -  safe_apply_current2(PC_REPORT_FUN_NUM, 7, "report"); -  pop_stack(); -  ref_push_string(b_file); -  push_int(b_line); -  push_constant_text("type_check"); -  push_constant_text("with identifier %s in %O"); -  ref_push_string(bid->name); +     ref_push_program(b); -  safe_apply_current2(PC_REPORT_FUN_NUM, 7, "report"); -  pop_stack(); -  yytype_error(NULL, ID_FROM_INT(a,i)->type, bid->type, flags); +  yytype_report(severity_level, +  a_file, a_line, ID_FROM_INT(a, i)->type, +  b_file, b_line, bid->type, 3, +  "Identifier %s in %O is incompatible with the same in %O.");    }    }    free_string(b_file);    free_string(a_file);    END_CYCLIC();    return;   }      /* Explains why a does not implement b */ - void yyexplain_not_implements(struct program *a, struct program *b, int flags) + void yyexplain_not_implements(int severity_level, +  struct program *a, struct program *b)   {    int e;    struct pike_string *s=findstring("__INIT"); -  +  INT32 a_line = 0; +  INT32 b_line = 0; +  struct pike_string *a_file; +  struct pike_string *b_file;    DECLARE_CYCLIC();       if (BEGIN_CYCLIC(a, b)) {    END_CYCLIC();    return;    }    SET_CYCLIC_RET(1);    -  +  a_file = get_program_line(a, &a_line); +  b_file = get_program_line(b, &b_line); +     for(e=0;e<b->num_identifier_references;e++)    {    struct identifier *bid;    int i;    if (b->identifier_references[e].id_flags & (ID_STATIC|ID_HIDDEN))    continue; /* Skip static & hidden */    bid = ID_FROM_INT(b,e);    if(s == bid->name) continue; /* Skip __INIT */    i = find_shared_string_identifier(bid->name,a);    if (i == -1) {    if (b->identifier_references[e].id_flags & (ID_OPTIONAL))    continue; /* It's ok... */ -  if(flags & YYTE_IS_WARNING) -  yywarning("Missing identifier %S.", bid->name); -  else -  my_yyerror("Missing identifier %S.", bid->name); +  yytype_report(severity_level, +  b_file, b_line, bid->type, +  a_file, a_line, NULL, +  0, "Missing identifier %S.", bid->name);    continue;    }       if (!pike_types_le(bid->type, ID_FROM_INT(a, i)->type)) {    if(!match_types(ID_FROM_INT(a,i)->type, bid->type)) { -  my_yyerror("Type of identifier %S does not match.", bid->name); -  yytype_error(NULL, ID_FROM_INT(a,i)->type, bid->type, 0); +  yytype_report(severity_level, +  b_file, b_line, bid->type, +  a_file, a_line, ID_FROM_INT(a, i)->type, +  0, "Type of identifier %S does not match.", bid->name);    } else { -  yywarning("Type of identifier %S is not strictly compatible.", +  yytype_report(REPORT_WARNING, +  NULL, 0, bid->type, +  NULL, 0, ID_FROM_INT(a, i)->type, +  0, "Type of identifier %S is not strictly compatible.",    bid->name); -  yytype_error(NULL, ID_FROM_INT(a,i)->type, bid->type, YYTE_IS_WARNING); +     }    continue;    }    } -  +  free_string(b_file); +  free_string(a_file);    END_CYCLIC();   }      PMOD_EXPORT void *parent_storage(int depth)   {    struct external_variable_context loc;    struct program *p;          loc.o=Pike_fp->current_object;