diff --git a/src/language.yacc b/src/language.yacc
index 794fc9a19494894b43f2af28def38ab6f206fa29..c7ea22e84dfc53307d369daf1221cece68a5b876 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -2,7 +2,7 @@
 || 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: language.yacc,v 1.424 2008/05/18 13:42:09 grubba Exp $
+|| $Id: language.yacc,v 1.425 2008/05/24 15:14:12 grubba Exp $
 */
 
 %pure_parser
@@ -155,6 +155,7 @@
 
 /* #define LAMBDA_DEBUG	1 */
 
+static void yyerror_reserved(const char *keyword);
 static struct pike_string *get_new_name();
 int add_local_name(struct pike_string *, struct pike_type *, node *);
 int low_add_local_name(struct compiler_frame *,
@@ -4390,48 +4391,9 @@ bad_expr_ident:
 
 %%
 
-void low_yyerror(struct pike_string *str)
-{
-  struct compilation *c = MAYBE_THIS_COMPILATION;
-  extern int cumulative_parse_error;
-
-  if (!c) return;
-
-  STACK_LEVEL_START(0);
-
-#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
-
-  CHECK_COMPILER();
-
-  if (Pike_compiler->num_parse_error > 20) return;
-  Pike_compiler->num_parse_error++;
-  cumulative_parse_error++;
-
-  push_int(REPORT_ERROR);
-  ref_push_string(c->lex.current_file);
-  push_int(c->lex.current_line);
-  push_constant_text("parse");
-  ref_push_string(str);
-  safe_apply_current(PC_REPORT_FUN_NUM, 5);
-  pop_stack();
-  STACK_LEVEL_DONE(0);
-}
-
-PMOD_EXPORT void yyerror(const char *str)
-{
-  push_text(str);
-  low_yyerror(Pike_sp[-1].u.string);
-  pop_stack();
-}
-
 static void yyerror_reserved(const char *keyword)
 {
-  char fmt[100];
-  SNPRINTF(fmt, sizeof(fmt), "%s is a reserved word.", keyword);
-  yyerror(fmt);
+  my_yyerror("%s is a reserved word.", keyword);
 }
 
 static struct pike_string *get_new_name()
diff --git a/src/las.c b/src/las.c
index 6bfcddadb6c41bf3d34b94ac393000951ed51cdb..bfedd118c401a131bbfbe4c5bec20f48d3a77428 100644
--- a/src/las.c
+++ b/src/las.c
@@ -2,7 +2,7 @@
 || 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: las.c,v 1.412 2008/05/18 15:37:28 grubba Exp $
+|| $Id: las.c,v 1.413 2008/05/24 15:14:12 grubba Exp $
 */
 
 #include "global.h"
@@ -373,11 +373,11 @@ static int check_node_type(node *n, struct pike_type *t, const char *msg)
 {
   if (pike_types_le(n->type, t)) return 1;
   if (!match_types(n->type, t)) {
-    yytype_error(msg, t, n->type, 0);
+    yytype_report(REPORT_ERROR, NULL, 0, t, NULL, 0, n->type, 0, msg);
     return 0;
   }
   if (THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES) {
-    yytype_error(msg, t, n->type, YYTE_IS_WARNING);
+    yytype_report(REPORT_WARNING, NULL, 0, t, NULL, 0, n->type, 0, msg);
   }
   if (runtime_options & RUNTIME_CHECK_TYPES) {
     node *p = n->parent;
@@ -1323,28 +1323,28 @@ node *debug_mksoftcastnode(struct pike_type *type, node *n)
     if (n->type) {
 #ifdef NEW_ARG_CHECK
       if (!(result_type = soft_cast(type, n->type, 0))) {
-	struct pike_string *t1 = describe_type(type);
-	struct pike_string *t2 = describe_type(n->type);
-	my_yyerror("Soft cast of %S to %S isn't a valid cast.",
-		   t2, t1);
-	free_string(t2);
-	free_string(t1);
+	ref_push_type_value(n->type);
+	ref_push_type_value(type);
+	yytype_report(REPORT_ERROR,
+		      NULL, 0, NULL,
+		      NULL, 0, NULL,
+		      2, "Soft cast of %O to %O isn't a valid cast.");
       } else if (result_type == n->type) {
-	struct pike_string *t1 = describe_type(type);
-	struct pike_string *t2 = describe_type(n->type);
-	yywarning("Soft cast of %S to %S is a noop.",
-		   t2, t1);
-	free_string(t2);
-	free_string(t1);
+	ref_push_type_value(n->type);
+	ref_push_type_value(type);
+	yytype_report(REPORT_WARNING,
+		      NULL, 0, NULL,
+		      NULL, 0, NULL,
+		      2, "Soft cast of %O to %O is a noop.");
       }
 #else /* !NEW_ARG_CHECK */
       if (!check_soft_cast(type, n->type)) {
-	struct pike_string *t1 = describe_type(type);
-	struct pike_string *t2 = describe_type(n->type);
-	yywarning("Soft cast to %S isn't a restriction of %S.",
-		  t1, t2);
-	free_string(t2);
-	free_string(t1);
+	ref_push_type_value(type);
+	ref_push_type_value(n->type);
+	yytype_report(REPORT_WARNING,
+		      NULL, 0, NULL,
+		      NULL, 0, NULL,
+		      2, "Soft cast to %S isn't a restriction of %S.");
       }
       /* FIXME: check_soft_cast() is weaker than pike_types_le()
        * The resulting type should probably be the and between the old
@@ -1658,12 +1658,21 @@ node *index_node(node *n, char *node_name, struct pike_string *id)
 	  if(Pike_compiler->new_program->flags & PROGRAM_PASS_1_DONE)
 	  {
 	    if (!exception) {
+	      struct compilation *c = THIS_COMPILATION;
 	      if (node_name) {
 		my_yyerror("Index %S not present in module \"%s\".",
 			   id, node_name);
 	      } else {
 		my_yyerror("Index %S not present in module.", id);
 	      }
+	      push_int(REPORT_ERROR);
+	      ref_push_string(c->lex.current_file);
+	      push_int(c->lex.current_line);
+	      push_constant_text("compiler");
+	      push_constant_text("Indexed module was: %O.");
+	      resolv_constant(n);
+	      safe_apply_current(PC_REPORT_FUN_NUM, 6);
+	      pop_stack();
 	    }
 	  }else if (!(Pike_compiler->flags & COMPILATION_FORCE_RESOLVE)) {
 	    /* Hope it's there in pass 2 */
@@ -3054,38 +3063,6 @@ static void low_build_function_type(node *n)
   }
 }
 
-void yytype_error(const char *msg, struct pike_type *expected_t,
-		  struct pike_type *got_t, unsigned int flags)
-{
-  if (msg)
-  {
-    if (flags & YYTE_IS_WARNING)
-      yywarning("%s", msg);
-    else
-      yyerror(msg);
-  }
-
-  if (expected_t && got_t) {
-    yyexplain_nonmatching_types(expected_t, got_t, flags);
-  } else if (expected_t) {
-    struct pike_string *s = describe_type(expected_t);
-    if (flags & YYTE_IS_WARNING) {
-      yywarning("Expected: %S", s);
-    } else {
-      my_yyerror("Expected: %S", s);
-    }
-    free_string(s);
-  } else if (got_t) {
-    struct pike_string *s = describe_type(got_t);
-    if (flags & YYTE_IS_WARNING) {
-      yywarning("Got     : %S", s);
-    } else {
-      my_yyerror("Got     : %S", s);
-    }
-    free_string(s);
-  }
-}
-
 static struct pike_string *get_name_of_function(node *n)
 {
   struct pike_string *name = NULL;
@@ -3253,33 +3230,28 @@ void fix_type_field(node *n)
       struct pike_type *soft_type = NULL;
       if (CDR(n) && (CDR(n)->token == F_CONSTANT) &&
 	  (CDR(n)->u.sval.type == T_TYPE)) {
-	struct pike_string *t1;
-	struct pike_string *t2;
 	soft_type = CDR(n)->u.sval.u.type;
 	if ((n->type = soft_cast(soft_type, CAR(n)->type, 0))) {
 	  /* Success. */
 	  break;
 	}
-	t1 = describe_type(soft_type);
-	t2 = describe_type(CAR(n)->type);
-	my_yyerror("Soft cast of %S to %S isn't a valid cast.",
-		   t2, t1);
-	free_string(t2);
-	free_string(t1);
+	ref_push_type_value(CAR(n)->type);
+	ref_push_type_value(soft_type);
+	yytype_report(REPORT_ERROR, NULL, 0, NULL, NULL, 0, NULL, 2,
+		      "Soft cast of %O to %O isn't a valid cast.");
       } else {
-	yytype_error("Soft cast with non-type.",
-		     type_type_string,
-		     CDR(n)->type, 0);
+	yytype_report(REPORT_ERROR, NULL, 0, type_type_string,
+		      NULL, 0, CDR(n)->type, 0,
+		      "Soft cast with non-type.");
       }
       /* Failure: Fall through to the old code. */
 #else /* !NEW_ARG_CHECK */
       if (!check_soft_cast(old_type, CAR(n)->type)) {
-	struct pike_string *t1 = describe_type(old_type);
-	struct pike_string *t2 = describe_type(CAR(n)->type);
-	yywarning("Soft cast to %S isn't a restriction of %S.",
-		  t1, t2);
-	free_string(t2);
-	free_string(t1);
+	ref_push_type_value(old_type);
+	ref_push_type_value(CAR(n)->type);
+	yytype_report(REPORT_ERROR, NULL, 0, NULL, NULL, 0, NULL, 2,
+		      "Soft cast to %S isn't a restriction of %S.",
+		      t1, t2);
       }
       /* FIXME: check_soft_cast() is weaker than pike_types_le()
        * The resulting type should probably be the AND between the old
@@ -3362,8 +3334,9 @@ void fix_type_field(node *n)
 		match_types(array_type_string, CDR(n)->type)) ||
 	       match_types(array_type_string, CADR(n)->type))) &&
 	    !match_types(CDR(n)->type,CAR(n)->type)) {
-	  yytype_error("Bad type in assignment.",
-		       CDR(n)->type, CAR(n)->type, 0);
+	  yytype_report(REPORT_ERROR, NULL, 0, CDR(n)->type,
+			NULL, 0, CAR(n)->type,
+			0, "Bad type in assignment.");
 	} else {
 	  if (c->lex.pragmas & ID_STRICT_TYPES) {
 	    struct pike_string *t1 = describe_type(CAR(n)->type);
@@ -3441,8 +3414,9 @@ void fix_type_field(node *n)
       type_b=CDR(n)->type;
       if(!check_indexing(type_a, type_b, n))
 	if(!Pike_compiler->catch_level)
-	  yyerror("Indexing on illegal type.");
-      n->type=index_type(type_a, type_b,n);
+	  yytype_report(REPORT_ERROR, NULL, 0, NULL, NULL, 0, type_b,
+			0, "Indexing on illegal type.");
+      n->type = index_type(type_a, type_b, n);
     } else {
       copy_pike_type(n->type, mixed_type_string);
     }
@@ -3468,8 +3442,9 @@ void fix_type_field(node *n)
       struct pike_type *array_type;
       MAKE_CONSTANT_TYPE(array_type, tArr(tZero));
       if (!pike_types_le(array_type, CAR(n)->type)) {
-	yytype_error("Bad argument to splice operator.",
-		     array_type, CAR(n)->type, 0);
+	yytype_report(REPORT_ERROR, NULL, 0, array_type,
+		      NULL, 0, CAR(n)->type,
+		      0, "Bad argument to splice operator.");
       }
       free_type(array_type);
       /* FIXME: The type field of the splice operator is not yet utilized.
@@ -3491,7 +3466,10 @@ void fix_type_field(node *n)
       type_a=CAR(n)->type;
       if(!match_types(type_a, array_type_string))
 	if(!Pike_compiler->catch_level)
-	  yyerror("[*] on non-array.");
+	  yytype_report(REPORT_ERROR,
+			NULL, 0, array_type_string,
+			NULL, 0, type_a,
+			0, "[*] on non-array.");
       n->type=index_type(type_a, int_type_string, n);
     }
     break;
@@ -3512,8 +3490,9 @@ void fix_type_field(node *n)
 
       if (!match_types(CAR(n)->type, function_type_string) &&
 	  !match_types(CAR(n)->type, array_type_string)) {
-	yytype_error("Calling non function value.",
-		     function_type_string, CAR(n)->type, 0);
+	yytype_report(REPORT_ERROR, NULL, 0, function_type_string,
+		      NULL, 0, CAR(n)->type,
+		      0, "Calling non function value.");
 	copy_pike_type(n->type, mixed_type_string);
 
 	/* print_tree(n); */
@@ -3556,14 +3535,19 @@ void fix_type_field(node *n)
       copy_pike_type(n->type, mixed_type_string);
 
       if ((s = get_first_arg_type(dmalloc_touch(struct pike_type *, f), 0))) {
-	my_yyerror("Too few arguments to %S (got %d).", name, args);
-	yytype_error(NULL, s, NULL, 0);
+	yytype_report(REPORT_ERROR, NULL, 0, s,
+		      NULL, 0, NULL,
+		      0, "Too few arguments to %S (got %d).",
+		      name, args);
 	free_type(s);
-	yytype_error("Function type:", CAR(n)->type, NULL, 0);
-	yytype_error("Remaining type:", f, NULL, 0);
+	yytype_report(REPORT_ERROR, NULL, 0, NULL,
+		      NULL, 0, CAR(n)->type,
+		      0, "Function type:");
       } else {
-	my_yyerror("Attempt to call a non function value %S.", name);
-	yytype_error(NULL, function_type_string, f, 0);
+	yytype_report(REPORT_ERROR, NULL, 0, function_type_string,
+		      NULL, 0, f,
+		      0, "Attempt to call a non function value %S.",
+		      name);
       }
       free_type(f);
       break;
@@ -3720,8 +3704,7 @@ void fix_type_field(node *n)
 	  my_yyerror("Too few arguments to %s.", alternate_name);
 	}
       } else if (name) {
-	my_yyerror("Bad argument %d to %S.",
-		   max_correct_args+1, name);
+	my_yyerror("Bad argument %d to %S.", max_correct_args+1, name);
       } else {
 	my_yyerror("Bad argument %d to %s.",
 		   max_correct_args+1, alternate_name);
@@ -3846,9 +3829,10 @@ void fix_type_field(node *n)
 	free_type(call_type);
 	break;
       }
-      my_yyerror("Bad arguments to %S.", op_string);
-      yytype_error(NULL, op_node->type ? op_node->type : mixed_type_string,
-		   call_type, 0);
+      yytype_report(REPORT_ERROR, NULL, 0,
+		    op_node->type ? op_node->type : mixed_type_string,
+		    NULL, 0, call_type,
+		    0, "Bad arguments to %S.", op_string);
       free_node(op_node);
       free_type(call_type);
     }
@@ -3899,8 +3883,10 @@ void fix_type_field(node *n)
       if (!match_types(CAR(n)->type, CDR(n)->type)) {
 	if (!match_types(CAR(n)->type, int_type_string) ||
 	    !match_types(CDR(n)->type, int_type_string)) {
-	  yytype_error("Type mismatch in case range.",
-		       CAR(n)->type, CDR(n)->type, 0);
+	  yytype_report(REPORT_ERROR,
+			NULL, 0, CAR(n)->type,
+			NULL, 0, CDR(n)->type,
+			0, "Type mismatch in case range.");
 	}
       } else if ((c->lex.pragmas & ID_STRICT_TYPES) &&
 		 (CAR(n)->type != CDR(n)->type)) {
@@ -3909,14 +3895,18 @@ void fix_type_field(node *n)
 	  /* Note that zero should be handled as int(0..0) here. */
 	  if (!(CAR(n)->type == zero_type_string) ||
 	      !(pike_types_le(CDR(n)->type, int_type_string))) {
-	    yytype_error("Type mismatch in case range.",
-			 CAR(n)->type, CDR(n)->type, YYTE_IS_WARNING);
+	    yytype_report(REPORT_ERROR,
+			  NULL, 0, CAR(n)->type,
+			  NULL, 0, CDR(n)->type,
+			  0, "Type mismatch in case range.");
 	  }
 	} else if (!pike_types_le(CAR(n)->type, CDR(n)->type)) {
 	  if (!(CDR(n)->type == zero_type_string) ||
 	      !(pike_types_le(CAR(n)->type, int_type_string))) {
-	    yytype_error("Type mismatch in case range.",
-			 CDR(n)->type, CAR(n)->type, YYTE_IS_WARNING);
+	    yytype_report(REPORT_WARNING,
+			  NULL, 0, CAR(n)->type,
+			  NULL, 0, CDR(n)->type,
+			  0, "Type mismatch in case range.");
 	  }
 	}
       }
@@ -4010,16 +4000,22 @@ void fix_type_field(node *n)
 	    index_type = check_call(foreach_call_type, index_fun_type, 0);
 	    if (!index_type) {
 	      /* Should not happen. */
-	      yyerror("Bad iterator type for index in foreach().");
+	      yytype_report(REPORT_ERROR,
+			    NULL, 0, NULL,
+			    NULL, 0, NULL,
+			    0, "Bad iterator type for index in foreach().");
 	    } else {
 	      if (!pike_types_le(index_type, CADAR(n)->type)) {
+		int level = REPORT_NOTICE;
 		if (!match_types(CADAR(n)->type, index_type)) {
-		  yytype_error("Type mismatch for index in foreach().",
-			       index_type, CADAR(n)->type, 0);
+		  level = REPORT_ERROR;
 		} else if (c->lex.pragmas & ID_STRICT_TYPES) {
-		  yytype_error("Type mismatch for index in foreach().",
-			       index_type, CADAR(n)->type, YYTE_IS_WARNING);
+		  level = REPORT_WARNING;
 		}
+		yytype_report(level,
+			      NULL, 0, index_type,
+			      NULL, 0, CADAR(n)->type,
+			      0, "Type mismatch for index in foreach().");
 	      }
 	      free_type(index_type);
 	    }
@@ -4040,16 +4036,22 @@ void fix_type_field(node *n)
 	    value_type = check_call(foreach_call_type, value_fun_type, 0);
 	    if (!value_type) {
 	      /* Should not happen. */
-	      yyerror("Bad iterator type for value in foreach().");
+	      yytype_report(REPORT_ERROR,
+			    NULL, 0, NULL,
+			    NULL, 0, NULL,
+			    0, "Bad iterator type for value in foreach().");
 	    } else {
 	      if (!pike_types_le(value_type, CDDAR(n)->type)) {
+		int level = REPORT_NOTICE;
 		if (!match_types(CDDAR(n)->type, value_type)) {
-		  yytype_error("Type mismatch for value in foreach().",
-			       value_type, CDDAR(n)->type, 0);
+		  level = REPORT_ERROR;
 		} else if (c->lex.pragmas & ID_STRICT_TYPES) {
-		  yytype_error("Type mismatch for value in foreach().",
-			       value_type, CDDAR(n)->type, YYTE_IS_WARNING);
+		  level = REPORT_WARNING;
 		}
+		yytype_report(level,
+			      NULL, 0, value_type,
+			      NULL, 0, CDDAR(n)->type,
+			      0, "Type mismatch for value in foreach().");
 	      }
 	      free_type(value_type);
 	    }
@@ -4062,14 +4064,18 @@ void fix_type_field(node *n)
 	  MAKE_CONSTANT_TYPE(array_zero, tArr(tZero));
 	  
 	  if (!pike_types_le(array_zero, CAAR(n)->type)) {
-	    yyerror("Bad argument 1 to foreach().");
+	    yytype_report(REPORT_ERROR,
+			  NULL, 0, array_zero,
+			  NULL, 0, CAAR(n)->type,
+			  0, "Bad argument 1 to foreach().");
 	  } else {
 	    if ((c->lex.pragmas & ID_STRICT_TYPES) &&
 		!pike_types_le(CAAR(n)->type, array_type_string)) {
-	      struct pike_string *t = describe_type(CAAR(n)->type);
-	      yywarning("Argument 1 to foreach() is not always an array.");
-	      yywarning("Got: %S", t);
-	      free_string(t);
+	      yytype_report(REPORT_WARNING,
+			    NULL, 0, CAAR(n)->type,
+			    NULL, 0, array_type_string,
+			    0,
+			    "Argument 1 to foreach() is not always an array.");
 	    }
 	    
 	    if (!CDAR(n)) {
@@ -4125,12 +4131,19 @@ void fix_type_field(node *n)
 	if (!(n->type = new_get_return_type(sscanf_type, 0))) {
 	  struct pike_type *expected;
 	  if ((expected = get_first_arg_type(sscanf_type, 0))) {
-	    my_yyerror("Too few arguments to %S (got %d).", sscanf_name, argno);
-	    yytype_error(NULL, expected, NULL, 0);
+	    yytype_report(REPORT_ERROR,
+			  NULL, 0, expected,
+			  NULL, 0, NULL,
+			  0, "Too few arguments to %S (got %d).",
+			  sscanf_name, argno);
 	    free_type(expected);
 	  } else {
-	    my_yyerror("Attempt to call a non function value %S.", sscanf_name);
-	    yytype_error(NULL, function_type_string, sscanf_type, 0);
+	    /* Most likely not reached. */
+	    yytype_report(REPORT_ERROR,
+			  NULL, 0, function_type_string,
+			  NULL, 0, sscanf_type,
+			  0, "Attempt to call a non function value %S.",
+			  sscanf_name);
 	  }
 	}
 	free_type(sscanf_type);
diff --git a/src/las.h b/src/las.h
index ff680c2928a1a2a6dc6cfe77c35b25641a1b9da5..6de405f168fd407919950c848574fb345b1abcf5 100644
--- a/src/las.h
+++ b/src/las.h
@@ -2,7 +2,7 @@
 || 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: las.h,v 1.78 2008/02/05 23:20:32 mast Exp $
+|| $Id: las.h,v 1.79 2008/05/24 15:14:12 grubba Exp $
 */
 
 #ifndef LAS_H
@@ -22,11 +22,6 @@ typedef void (*c_fun)(INT32);
 
 struct compiler_frame;		/* Avoid gcc warning. */
 
-void yytype_error(const char *msg, struct pike_type *expected_t,
-		  struct pike_type *got_t, unsigned int flags);
-void low_yyerror(struct pike_string *str);
-PMOD_EXPORT void yyerror(const char *s);
-static void yyerror_reserved(const char *keyword);
 int islocal(struct pike_string *str);
 int low_add_local_name(struct compiler_frame *frame,
                        struct pike_string *str,
diff --git a/src/modules/sprintf/sprintf.c b/src/modules/sprintf/sprintf.c
index cc972e884882f6830b9a5a6b750ed9be1a8682e1..95937cf278df96163b6f9e2cca6b6f1f22bcd428 100644
--- a/src/modules/sprintf/sprintf.c
+++ b/src/modules/sprintf/sprintf.c
@@ -2,7 +2,7 @@
 || 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: sprintf.c,v 1.152 2008/05/21 21:59:07 grubba Exp $
+|| $Id: sprintf.c,v 1.153 2008/05/24 15:14:13 grubba Exp $
 */
 
 /* TODO: use ONERROR to cleanup fsp */
@@ -311,7 +311,6 @@
 #include "cyclic.h"
 #include "module.h"
 #include "pike_float.h"
-#include "pike_compiler.h"
 #include <ctype.h>
 
 #include "config.h"
@@ -1870,14 +1869,6 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
 
   PCHARP a,begin;
   PCHARP format_end=ADD_PCHARP(format,format_len);
-  struct compilation *c = THIS_COMPILATION;
-  int severity_level = REPORT_ERROR;
-
-  if ((c->major != -1) &&
-      ((c->major < 7) || ((c->major == 7) && (c->minor < 7)))) {
-    /* Compat mode: Pike 7.6 or earlier. */
-    severity_level = REPORT_WARNING;
-  }
 
   check_c_stack(500);
 
@@ -1907,12 +1898,12 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
       default:
 	if(EXTRACT_PCHARP(a) < 256 && isprint(EXTRACT_PCHARP(a)))
 	{
-	  yyreport(severity_level, "type_check",
-		   "Error in format string, %c is not a format.",
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Error in format string, %c is not a format.",
 		   EXTRACT_PCHARP(a));
 	}else{
-	  yyreport(severity_level, "type_check",
-		   "Error in format string, U%08x is not a format.",
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Error in format string, U%08x is not a format.",
 		   EXTRACT_PCHARP(a));
 	}
 	num_snurkel = 0;
@@ -1941,8 +1932,8 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
 	{
 	case 0: case 1:
 	  if(tmp < 0) {
-	    yyreport(severity_level, "type_check",
-		     "Illegal width %d.", tmp);
+	    yyreport(REPORT_ERROR, type_check_system_string,
+		     0, "Illegal width %d.", tmp);
 	  }
 	case 2: case 3: case 4: break;
 	}
@@ -1958,16 +1949,16 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
       case '/':
         column |= ROUGH_LINEBREAK;
         if( column & LINEBREAK ) {
-	  yyreport(severity_level, "type_check",
-		   "Can not use both the modifiers / and =.");
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Can not use both the modifiers / and =.");
 	}
         continue;
 
       case '=':
         column |= LINEBREAK;
         if( column & ROUGH_LINEBREAK ) {
-	  yyreport(severity_level, "type_check",
-		   "Can not use both the modifiers / and =.");
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Can not use both the modifiers / and =.");
 	}
         continue;
 
@@ -1984,8 +1975,8 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
 	for(INC_PCHARP(a,1);INDEX_PCHARP(a,tmp)!='\'';tmp++)
 	{
 	  if(COMPARE_PCHARP(a,>=,format_end)) {
-	    yyreport(severity_level, "type_check",
-		     "Unfinished pad string in format string.");
+	    yyreport(REPORT_ERROR, type_check_system_string,
+		     0, "Unfinished pad string in format string.");
 	  }
 	}
 	INC_PCHARP(a,tmp);
@@ -2002,8 +1993,8 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
 	/* FIXME: !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
 	return 0;	/* FAILURE! */
 	if(!lastarg) {
-	  yyreport(severity_level, "type_check",
-		   "No last argument.");
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "No last argument.");
 	}
 	arg=lastarg;
 	continue;
@@ -2019,13 +2010,13 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
 	} else
 	  tmp=STRTOL_PCHARP(a,&a,10);
 	if(EXTRACT_PCHARP(a)!=']')  {
-	  yyreport(severity_level, "type_check",
-		   "Expected ] in format string, not %c.",
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Expected ] in format string, not %c.",
 		   EXTRACT_PCHARP(a));
 	}
 	if(tmp >= num_arg) {
-	  yyreport(severity_level, "type_check",
-		   "Not enough arguments to [%d].", tmp);
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Not enough arguments to [%d].", tmp);
 	}
 	/* arg = argp+tmp; */
 	continue;
@@ -2039,8 +2030,8 @@ static int push_sprintf_argument_types(PCHARP format, ptrdiff_t format_len,
 	{
 	  if (!INDEX_PCHARP(a,e) &&
 	      !COMPARE_PCHARP(ADD_PCHARP(a,e),<,format_end)) {
-	    yyreport(severity_level, "type_check",
-		     "Missing %} in format string.");
+	    yyreport(REPORT_ERROR, type_check_system_string,
+		     0, "Missing %%} in format string.");
 	    break;
 	  } else if(INDEX_PCHARP(a,e)=='%') {
 	    switch(INDEX_PCHARP(a,e+1))
@@ -2232,14 +2223,6 @@ void f___handle_sprintf_format(INT32 args)
   struct pike_string *fmt;
   int found = 0;
   int fmt_count;
-  struct compilation *c = THIS_COMPILATION;
-  int severity_level = REPORT_ERROR;
-
-  if ((c->major != -1) &&
-      ((c->major < 7) || ((c->major == 7) && (c->minor < 7)))) {
-    /* Compat mode: Pike 7.6 or earlier. */
-    severity_level = REPORT_WARNING;
-  }
 
 #if 0
   fprintf(stderr, "__handle_sprintf_format()\n");
@@ -2307,11 +2290,6 @@ void f___handle_sprintf_format(INT32 args)
 	  res = pop_unfinished_type();
 	  pop_n_elems(args);
 	  push_type_value(res);
-	  if (severity_level <= REPORT_WARNING) {
-	    /* Disable further checks in compat mode. */
-	    pop_stack();
-	    push_undefined();
-	  }
 	  return;
 	} else {
 	  /* Join the argument types into the array. */
@@ -2355,11 +2333,6 @@ void f___handle_sprintf_format(INT32 args)
     res = pop_unfinished_type();
     pop_n_elems(args);
     push_type_value(res);
-    if (severity_level <= REPORT_WARNING) {
-      /* Disable further checks in compat mode. */
-      pop_stack();
-      push_undefined();
-    }
   } else {
     /* No marker found. */
 #if 0
diff --git a/src/pike_compiler.h b/src/pike_compiler.h
index ec7c901443705d36b13839eab64e635a223a975f..3f63d9a5e31dfba1a9c6ce7c6a5da64c20fa8680 100644
--- a/src/pike_compiler.h
+++ b/src/pike_compiler.h
@@ -2,7 +2,7 @@
 || 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: pike_compiler.h,v 1.13 2008/05/18 15:36:23 grubba Exp $
+|| $Id: pike_compiler.h,v 1.14 2008/05/24 15:14:12 grubba Exp $
 */
 
 #ifndef PIKE_COMPILER_H
@@ -56,12 +56,6 @@ struct compilation
 #define COMPILER_BUSY	1	/* The compiler is busy compiling. */
 #define COMPILER_DONE	2	/* The is finished compiling. */
 
-/* Report levels */
-#define REPORT_NOTICE	0	/* FYI. */
-#define REPORT_WARNING	1	/* Compiler warning. */
-#define REPORT_ERROR	2	/* Compilation error. */
-#define REPORT_FATAL	3	/* Unrecoverable error. */
-
 /* CompilerEnvironment function numbers. */
 #define CE_REPORT_FUN_NUM				0
 #define CE_COMPILE_FUN_NUM				1
diff --git a/src/pike_types.c b/src/pike_types.c
index f3dfb3740fd8b0677963dff4733ae3f43f0ec496..0e53035447c34cf745df45ba4316bc2f681ba023 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -2,7 +2,7 @@
 || 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: pike_types.c,v 1.336 2008/05/18 15:44:51 grubba Exp $
+|| $Id: pike_types.c,v 1.337 2008/05/24 15:14:12 grubba Exp $
 */
 
 #include "global.h"
@@ -4529,7 +4529,7 @@ static int low_get_return_type(struct pike_type *a, struct pike_type *b)
 #if 0
     if ((c->lex.pragmas & ID_STRICT_TYPES) &&
 	!low_pike_types_le(a, b, 0, 0)) {
-      yywarning("Type mismatch");
+      yyreport_type(REPORT_WARNING, NULL, 0, b, NULL, 0, a, 0, "Type mismatch");
     }
 #endif /* 0 */
     switch(a->type)
@@ -4925,22 +4925,18 @@ static struct pike_type *debug_low_range_type(struct pike_type *t,
     /* Check that the index types are compatible with int. */
     {
       if (index1_type && !low_match_types(int_type_string, index1_type, 0)) {
-	struct pike_string *s = describe_type(t);
-	yywarning("Bad argument 1 to range operator on %s.",
-		  s->str);
-	free_string(s);
-	yyexplain_nonmatching_types(int_type_string, index1_type,
-				    YYTE_IS_WARNING);
+	ref_push_type_value(t);
+	yytype_report(REPORT_WARNING, NULL, 0, int_type_string,
+		      NULL, 0, index1_type,
+		      1, "Bad argument 1 to range operator on %O.");
 	/* Bad index1 type. */
 	return 0;
       }
       if (index2_type && !low_match_types(int_type_string, index2_type, 0)) {
-	struct pike_string *s = describe_type(t);
-	yywarning("Bad argument 2 to range operator on %s.",
-		  s->str);
-	free_string(s);
-	yyexplain_nonmatching_types(int_type_string, index2_type,
-				    YYTE_IS_WARNING);
+	ref_push_type_value(t);
+	yytype_report(REPORT_WARNING, NULL, 0, int_type_string,
+		      NULL, 0, index2_type,
+		      1, "Bad argument 2 to range operator on %O.");
 	/* Bad index2 type. */
 	return 0;
       }
@@ -4979,7 +4975,8 @@ struct pike_type *range_type(struct pike_type *type,
   clear_markers();
   t = low_range_type(type, index1_type, index2_type);
   if(!t) {
-    yyerror("Invalid range operation.");
+    yytype_report(REPORT_ERROR, NULL, 0, NULL, NULL, 0, NULL,
+		  0, "Invalid range operation.");
     copy_pike_type(t, type);
   }
   return t;
@@ -5318,24 +5315,21 @@ struct pike_type *check_call(struct pike_type *args,
   {
     if (strict) {
       if (!strict_check_call(type, args)) {
-	struct pike_string *type_t = describe_type(type);
 	struct pike_type *func_zero_type;
 
 	MAKE_CONSTANT_TYPE(func_zero_type, tFuncV(tNone,tZero,tMix));
 
 	if (!low_pike_types_le(type, func_zero_type, 0, 0)) {
-	  yywarning("Calling non-function value.");
-	  yywarning("Type called: %s", type_t->str);
+	  yytype_report(REPORT_WARNING, NULL, 0, function_type_string,
+			NULL, 0, type,
+			0, "Calling non-function value.");
 	} else {
-	  struct pike_string *arg_t = describe_type(args);
-	  yywarning("Arguments not strictly compatible.");
-	  yywarning("Expected: %s", type_t->str);
-	  yywarning("Got     : %s", arg_t->str);
-	  free_string(arg_t);
+	  yytype_report(REPORT_WARNING, NULL, 0, type,
+			NULL, 0, args,
+			0, "Arguments not strictly compatible.");
 	}
 
 	free_type(func_zero_type);
-	free_string(type_t);
       }
     }
     return pop_unfinished_type();
@@ -6799,14 +6793,12 @@ struct pike_type *new_check_call(struct pike_string *fun_name,
 	!(flags & CALL_ARG_LVALUE)){
       if (!(tmp = low_new_check_call(fun_type, args->type,
 				     flags|CALL_STRICT, sval))) {
-	yywarning("Type mismatch in argument %d to %S.",
-		  *argno, fun_name);
-	if ((tmp = get_first_arg_type(fun_type, 0))) {
-	  yytype_error(NULL, tmp, args->type, YYTE_IS_WARNING);
-	  free_type(tmp);
-	} else {
-	  yytype_error(NULL, NULL, args->type, YYTE_IS_WARNING);
-	}
+	tmp = get_first_arg_type(fun_type, 0);
+	yytype_report(REPORT_WARNING, NULL, 0, tmp,
+		      NULL, 0, args->type,
+		      0, "Type mismatch in argument %d to %S.",
+		      *argno, fun_name);
+	if (tmp) free_type(tmp);
       } else {
 	free_type(tmp);
       }
@@ -6823,9 +6815,8 @@ struct pike_type *new_check_call(struct pike_string *fun_name,
       fprintf(stderr, " Bad argument.\n");
     }
 #endif /* PIKE_DEBUG */
-    my_yyerror("Bad argument %d to %S.",
-	       *argno, fun_name);
-    yytype_error(NULL, tmp, args->type, 0);
+    yytype_report(REPORT_ERROR, NULL, 0, tmp, NULL, 0, args->type,
+		  0, "Bad argument %d to %S.", *argno, fun_name);
 
     /* Try advancing with the suggested type, so that we can check
      * the rest of the arguments.
@@ -6855,9 +6846,10 @@ struct pike_type *new_check_call(struct pike_string *fun_name,
       fprintf(stderr, " Too many arguments.\n");
     }
 #endif /* PIKE_DEBUG */
-    my_yyerror("Too many arguments to %S (expected %d arguments).",
-	       fun_name, *argno - 1);
-    yytype_error(NULL, NULL, args->type, 0);
+    yytype_report(REPORT_ERROR, NULL, 0, NULL,
+		  NULL, 0, args->type,
+		  0, "Too many arguments to %S (expected %d arguments).",
+		  fun_name, *argno - 1);
   }
   free_type(fun_type);
   return NULL;
@@ -7248,9 +7240,13 @@ int type_may_overload(struct pike_type *type, int lfun)
 }
 
 
-void yyexplain_nonmatching_types(struct pike_type *type_a,
-				 struct pike_type *type_b,
-				 int flags)
+void yyexplain_nonmatching_types(int severity_level,
+				 struct pike_string *a_file,
+				 INT32 a_line,
+				 struct pike_type *type_a,
+				 struct pike_string *b_file,
+				 INT32 b_line,
+				 struct pike_type *type_b)
 {
   DECLARE_CYCLIC();
 
@@ -7267,18 +7263,13 @@ void yyexplain_nonmatching_types(struct pike_type *type_a,
 #endif /* 0 */
   {
     struct pike_string *s1, *s2;
-    s1 = describe_type(type_a);
-    s2 = describe_type(type_b);
-    if(flags & YYTE_IS_WARNING)
-    {
-      yywarning("Expected: %S", s1);
-      yywarning("Got     : %S", s2);
-    }else{
-      my_yyerror("Expected: %S", s1);
-      my_yyerror("Got     : %S", s2);
-    }
-    free_string(s1);
-    free_string(s2);
+
+    ref_push_type_value(type_a);
+    yytype_report(severity_level, NULL, 0, NULL, a_file, a_line, NULL,
+		  1, "Expected: %O");
+    ref_push_type_value(type_b);
+    yytype_report(severity_level, NULL, 0, NULL, b_file, b_line, NULL,
+		  1, "Got     : %O");
   }
 
   /* Protect against circularities. */
@@ -7290,9 +7281,9 @@ void yyexplain_nonmatching_types(struct pike_type *type_a,
 
   if(implements_a && implements_b) {
     if (implements_mode) {
-      yyexplain_not_implements(implements_a, implements_b, flags);
+      yyexplain_not_implements(severity_level, implements_a, implements_b);
     } else {
-      yyexplain_not_compatible(implements_a, implements_b, flags);
+      yyexplain_not_compatible(severity_level, implements_a, implements_b);
     }
   }
   END_CYCLIC();
diff --git a/src/pike_types.h b/src/pike_types.h
index 7c011edeea1fae19efe14065e3ca3d1e3cdeb9de..ab612e5ffc19580862f4e25f0e9022431d71825b 100644
--- a/src/pike_types.h
+++ b/src/pike_types.h
@@ -2,7 +2,7 @@
 || 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: pike_types.h,v 1.117 2008/05/17 22:48:33 grubba Exp $
+|| $Id: pike_types.h,v 1.118 2008/05/24 15:14:12 grubba Exp $
 */
 
 #ifndef PIKE_TYPES_H
@@ -284,9 +284,13 @@ void gc_mark_type_as_referenced(struct pike_type *t);
 void gc_check_type (struct pike_type *t);
 void gc_check_all_types (void);
 int type_may_overload(struct pike_type *type, int lfun);
-void yyexplain_nonmatching_types(struct pike_type *type_a,
-				 struct pike_type *type_b,
-				 int flags);
+void yyexplain_nonmatching_types(int severity_level,
+				 struct pike_string *a_file,
+				 INT32 a_line,
+				 struct pike_type *type_a,
+				 struct pike_string *b_file,
+				 INT32 b_line,
+				 struct pike_type *type_b);
 struct pike_type *debug_make_pike_type(const char *t);
 struct pike_string *type_to_string(struct pike_type *t);
 int pike_type_allow_premature_toss(struct pike_type *type);
diff --git a/src/program.c b/src/program.c
index d322f4ba5ad93bf97be5c69d604a91b6cb41c8e6..ecaa3b3015911ea2f2b9c36b48e8b21ad8abf68b 100644
--- a/src/program.c
+++ b/src/program.c
@@ -2,7 +2,7 @@
 || 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"
@@ -107,6 +107,10 @@ 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",
@@ -2076,11 +2080,12 @@ int override_identifier (struct reference *new_ref, struct pike_string *name)
 	  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,
-						    new_ref)->type,
-					YYTE_IS_WARNING);
+	    yytype_report(REPORT_WARNING,
+			  NULL, 0, sub_id->type,
+			  NULL, 0, ID_FROM_PTR(Pike_compiler->new_program,
+					       new_ref)->type,
+			  0, "Type mismatch when overloading function %S.",
+			  name);
 	  }
 	} else {
 	  struct identifier *new_id;
@@ -2095,9 +2100,10 @@ int override_identifier (struct reference *new_ref, struct pike_string *name)
 		(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);
 	  }
 	}
       }
@@ -2197,9 +2203,10 @@ void fixate_program(void)
 		(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;
@@ -2211,9 +2218,10 @@ void fixate_program(void)
 		(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;
@@ -4889,7 +4897,7 @@ int define_variable(struct pike_string *name,
 #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);
 
@@ -4938,21 +4946,16 @@ int define_variable(struct pike_string *name,
  	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,
-			 ID_FROM_INT(Pike_compiler->new_program, n)->type,
-			 type, 0);
-	    return n;
-	  } else {
-	    yywarning("Redefining inherited variable %S "
-		      "with different type.", name);
-	    yytype_error(NULL,
-			 ID_FROM_INT(Pike_compiler->new_program, n)->type,
-			 type, YYTE_IS_WARNING);
+	    level = REPORT_ERROR;
 	  }
+	  yytype_report(level, NULL, 0,
+			ID_FROM_INT(Pike_compiler->new_program, n)->type,
+			NULL, 0, type, 0,
+			"Illegal to redefine inherited variable %S "
+			"with different type.", name);
 	}
 	
 
@@ -4968,11 +4971,11 @@ int define_variable(struct pike_string *name,
 	     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,
-		       ID_FROM_INT(Pike_compiler->new_program, n)->type,
-		       type, 0);
+	  yytype_report(REPORT_ERROR, NULL, 0,
+			ID_FROM_INT(Pike_compiler->new_program, n)->type,
+			NULL, 0, type, 0,
+			"Illegal to redefine inherited variable %S "
+			"with different type.", name);
 	  return n;
 	}
 
@@ -5468,15 +5471,15 @@ INT32 define_function(struct pike_string *name,
     }
 #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) == '`') &&
@@ -5513,13 +5516,15 @@ INT32 define_function(struct pike_string *name,
       /* 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) && 
@@ -5621,8 +5626,10 @@ INT32 define_function(struct pike_string *name,
 	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);
 	  }
 	}
       }
@@ -6869,25 +6876,181 @@ PMOD_EXPORT struct pike_string *low_get_function_line (struct object *o,
   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;
-  init_string_builder(&s, 0);
-  string_builder_vsprintf(&s, fmt, args);
-  tmp = finish_string_builder(&s);
-  low_yyerror(tmp);
-  free_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, 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)
@@ -6923,7 +7086,8 @@ void handle_compile_exception (const char *yyerror_fmt, ...)
   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);
   }
 
@@ -6934,8 +7098,8 @@ void handle_compile_exception (const char *yyerror_fmt, ...)
   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");
     }
   }
 
@@ -7257,6 +7421,7 @@ static void f_compilation_env_report(INT32 args)
   INT_TYPE linenumber;
   struct pike_string *subsystem;
   struct pike_string *message;
+
   if (args > 5) {
     f_sprintf(args - 4);
     args = 5;
@@ -7947,7 +8112,7 @@ static void f_compilation_report(INT32 args)
   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);
 
@@ -9378,6 +9543,9 @@ void init_program(void)
   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++) {
@@ -10141,56 +10309,6 @@ int find_child(struct program *parent, struct program *child)
 }
 #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 */
@@ -10373,7 +10491,8 @@ PMOD_EXPORT int is_compatible(struct program *a, struct program *b)
 }
 
 /* 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");
@@ -10420,30 +10539,13 @@ void yyexplain_not_compatible(struct program *a, struct program *b, int flags)
     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);
@@ -10453,10 +10555,15 @@ void yyexplain_not_compatible(struct program *a, struct program *b, int flags)
 }
 
 /* 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)) {
@@ -10465,6 +10572,9 @@ void yyexplain_not_implements(struct program *a, struct program *b, int flags)
   }
   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;
@@ -10477,25 +10587,31 @@ void yyexplain_not_implements(struct program *a, struct program *b, int flags)
     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.",
-		  bid->name);
-	yytype_error(NULL, ID_FROM_INT(a,i)->type, bid->type, YYTE_IS_WARNING);
+	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);
       }
       continue;
     }
   }
+  free_string(b_file);
+  free_string(a_file);
   END_CYCLIC();
 }
 
diff --git a/src/program.h b/src/program.h
index 66c8e79784861b7bfcbf105973682251fc19dfea..bc956412b1025349c23a77253456760bcb7316ad 100644
--- a/src/program.h
+++ b/src/program.h
@@ -2,7 +2,7 @@
 || 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.h,v 1.247 2008/05/21 21:55:49 grubba Exp $
+|| $Id: program.h,v 1.248 2008/05/24 15:14:12 grubba Exp $
 */
 
 #ifndef PROGRAM_H
@@ -53,6 +53,10 @@ PMOD_EXPORT extern struct program_state * Pike_compiler;
 
 extern struct pike_string *this_program_string;
 
+/* Common compiler subsystems */
+extern struct pike_string *parser_system_string;
+extern struct pike_string *type_check_system_string;
+
 #define LFUN___INIT 0
 #define LFUN_CREATE 1
 #define LFUN_DESTROY 2
@@ -682,6 +686,12 @@ extern struct object *placeholder_object;
 #define SEE_STATIC 1
 #define SEE_PRIVATE 2
 
+/* Report levels */
+#define REPORT_NOTICE	0	/* FYI. */
+#define REPORT_WARNING	1	/* Compiler warning. */
+#define REPORT_ERROR	2	/* Compilation error. */
+#define REPORT_FATAL	3	/* Unrecoverable error. */
+
 
 #define COMPILER_IN_CATCH 1
 
@@ -879,8 +889,27 @@ PMOD_EXPORT struct pike_string *get_line(PIKE_OPCODE_T *pc,
 					 struct program *prog, INT32 *linep);
 PMOD_EXPORT struct pike_string *low_get_function_line (struct object *o,
 						       int fun, INT32 *linep);
-PMOD_EXPORT void va_yyerror(const char *fmt, va_list args);
+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);
+PMOD_EXPORT void low_yyreport(int severity_level,
+			      struct pike_string *file, INT32 line,
+			      struct pike_string *system,
+			      INT32 args, const char *fmt, ...);
+PMOD_EXPORT void yyreport(int severity_level, struct pike_string *system,
+			  INT32 args, const char *fmt, ...);
+PMOD_EXPORT void yywarning(char *fmt, ...);
 PMOD_EXPORT void my_yyerror(const char *fmt,...);
+PMOD_EXPORT void yyerror(const char *s);
+void yytype_report(int severity_level,
+		   struct pike_string *expect_file, INT32 expect_line, 
+		   struct pike_type *expected_t,
+		   struct pike_string *got_file, INT32 got_line,
+		   struct pike_type *got_t,
+		   INT32 args, const char *fmt, ...);
+void yytype_error(const char *msg, struct pike_type *expected_t,
+		  struct pike_type *got_t, unsigned int flags);
 struct pike_string *format_exception_for_error_msg (struct svalue *thrown);
 void handle_compile_exception (const char *yyerror_fmt, ...);
 struct supporter_marker;
@@ -934,15 +963,13 @@ PMOD_EXPORT struct program *program_from_function(const struct svalue *f);
 PMOD_EXPORT struct program *program_from_svalue(const struct svalue *s);
 struct find_child_cache_s;
 int find_child(struct program *parent, struct program *child);
-void va_yyreport(int severity_level, const char *system,
-		 const char *fmt, va_list args);
-void yyreport(int severity_level, const char *system, const char *fmt, ...);
-void yywarning(char *fmt, ...);
 struct implements_cache_s;
 PMOD_EXPORT int implements(struct program *a, struct program *b);
 PMOD_EXPORT int is_compatible(struct program *a, struct program *b);
-void yyexplain_not_compatible(struct program *a, struct program *b, int flags);
-void yyexplain_not_implements(struct program *a, struct program *b, int flags);
+void yyexplain_not_compatible(int severity_level,
+			      struct program *a, struct program *b);
+void yyexplain_not_implements(int severity_level,
+			      struct program *a, struct program *b);
 PMOD_EXPORT void *parent_storage(int depth);
 PMOD_EXPORT void change_compiler_compatibility(int major, int minor);
 void make_program_executable(struct program *p);
diff --git a/src/sscanf.c b/src/sscanf.c
index b35d1c673543adaedf48832b06a312fbad7cac5b..6acb7d0cda4ee3c938f0af7e53b83767113f1aad 100644
--- a/src/sscanf.c
+++ b/src/sscanf.c
@@ -2,7 +2,7 @@
 || 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: sscanf.c,v 1.183 2008/05/21 21:59:07 grubba Exp $
+|| $Id: sscanf.c,v 1.184 2008/05/24 15:14:12 grubba Exp $
 */
 
 #include "global.h"
@@ -17,7 +17,6 @@
 #include "bignum.h"
 #include "pike_float.h"
 #include "pike_types.h"
-#include "pike_compiler.h"
 #include "sscanf.h"
 
 #define sp Pike_sp
@@ -1642,15 +1641,6 @@ void f_sscanf_76(INT32 args)
 static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 				       int cnt, int flags)
 {
-  struct compilation *c = THIS_COMPILATION;
-  int severity_level = REPORT_ERROR;
-
-  if ((c->major != -1) &&
-      ((c->major < 7) || ((c->major == 7) && (c->minor < 7)))) {
-    /* Compat mode: Pike 7.6 or earlier. */
-    severity_level = REPORT_WARNING;
-  }
-
   for(; cnt < format_len; cnt++)
   {
     int no_assign=0;
@@ -1677,8 +1667,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
       case '5': case '6': case '7': case '8': case '9':
 	cnt++;
 	if(cnt>=format_len) {
-	  yyreport(severity_level, "type_check",
-		   "Error in sscanf format string.");
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Error in sscanf format string.");
 	  break;
 	}
 	continue;
@@ -1691,8 +1681,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 	  {
 	    if(e>=format_len)
 	    {
-	      yyreport(severity_level, "type_check",
-		       "Missing %%} in format string.");
+	      yyreport(REPORT_ERROR, type_check_system_string,
+		       0, "Missing %%} in format string.");
 	      break;
 	    }
 	    if(INDEX_PCHARP(format, e)=='%')
@@ -1741,8 +1731,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 	    int ch;
 	    cnt++;
 	    if (cnt >= format_len) {
-	      yyreport(severity_level, "type_check",
-		       "Error in sscanf format string.");
+	      yyreport(REPORT_ERROR, type_check_system_string,
+		       0, "Error in sscanf format string.");
 	      break;
 	    }
 	    if((INDEX_PCHARP(format, cnt)=='^') &&
@@ -1753,8 +1743,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 	    {
 	      cnt++;
 	      if(cnt >= format_len) {
-		yyreport(severity_level, "type_check",
-			 "Error in sscanf format string.");
+		yyreport(REPORT_ERROR, type_check_system_string,
+			 0, "Error in sscanf format string.");
 		break;
 	      }
 	    }
@@ -1763,8 +1753,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 	    {
 	      cnt++;
 	      if(cnt >= format_len) {
-		yyreport(severity_level, "type_check",
-			 "Error in sscanf format string.");
+		yyreport(REPORT_ERROR, type_check_system_string,
+			 0, "Error in sscanf format string.");
 		break;
 	      }
 	      ch = INDEX_PCHARP(format, cnt);
@@ -1776,8 +1766,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 	      {
 		cnt++;
 		if(cnt >= format_len) {
-		  yyreport(severity_level, "type_check",
-			   "Error in sscanf format string.");
+		  yyreport(REPORT_ERROR, type_check_system_string,
+			   0, "Error in sscanf format string.");
 		  break;
 		}
 
@@ -1788,8 +1778,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 	      }
 	      cnt++;
 	      if(cnt>=format_len) {
-		yyreport(severity_level, "type_check",
-			 "Error in sscanf format string.");
+		yyreport(REPORT_ERROR, type_check_system_string,
+			 0, "Error in sscanf format string.");
 		break;
 	      }
 	      ch = INDEX_PCHARP(format, cnt);
@@ -1816,8 +1806,8 @@ static void push_sscanf_argument_types(PCHARP format, ptrdiff_t format_len,
 	  break;
 
 	default:
-	  yyreport(severity_level, "type_check",
-		   "Unknown sscanf token %%%c(0x%02x) at offset %d.",
+	  yyreport(REPORT_ERROR, type_check_system_string,
+		   0, "Unknown sscanf token %%%c(0x%02x) at offset %d.",
 		   INDEX_PCHARP(format, cnt), INDEX_PCHARP(format, cnt),
 		   cnt-1);
 	  break;
@@ -1838,14 +1828,6 @@ void f___handle_sscanf_format(INT32 args)
   int flags = 0;
   int found = 0;
   int fmt_count;
-  struct compilation *c = THIS_COMPILATION;
-  int severity_level = REPORT_ERROR;
-
-  if ((c->major != -1) &&
-      ((c->major < 7) || ((c->major == 7) && (c->minor < 7)))) {
-    /* Compat mode: Pike 7.6 or earlier. */
-    severity_level = REPORT_WARNING;
-  }
 
 #if 0
   fprintf(stderr, "__handle_sprintf_format()\n");
@@ -1925,11 +1907,6 @@ void f___handle_sscanf_format(INT32 args)
 	res = pop_unfinished_type();
 	pop_n_elems(args);
 	push_type_value(res);
-	if (severity_level <= REPORT_WARNING) {
-	  /* Disable further checks in compat mode. */
-	  pop_stack();
-	  push_undefined();
-	}
 	return;
       } else {
 	if (!(fmt_count = pop_stack_mark())) {
@@ -1969,11 +1946,6 @@ void f___handle_sscanf_format(INT32 args)
     res = pop_unfinished_type();
     pop_n_elems(args);
     push_type_value(res);
-    if (severity_level <= REPORT_WARNING) {
-      /* Disable further checks in compat mode. */
-      pop_stack();
-      push_undefined();
-    }
     return;
   } else if (tmp) {
     /* Check if it's in the return type. */
@@ -2023,11 +1995,6 @@ void f___handle_sscanf_format(INT32 args)
       res = pop_unfinished_type();
       pop_n_elems(args);
       push_type_value(res);
-      if (severity_level <= REPORT_WARNING) {
-	/* Disable further checks in compat mode. */
-	pop_stack();
-	push_undefined();
-      }
       return;
     }
   }