diff --git a/src/cpp.c b/src/cpp.c
index ef2d53e8d9798d1fd9cba8fb5c73fb00fbd9fbe8..d1aa838365f9dc6f507f0cbcc62b35a792d596d6 100644
--- a/src/cpp.c
+++ b/src/cpp.c
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: cpp.c,v 1.92 2001/08/15 22:18:41 mast Exp $
+ * $Id: cpp.c,v 1.93 2001/08/16 04:38:49 mast Exp $
  */
 #include "global.h"
 #include "stralloc.h"
@@ -29,6 +29,9 @@
 
 #include <ctype.h>
 
+#undef ATTRIBUTE
+#define ATTRIBUTE(X)
+
 #define CPP_NO_OUTPUT 1
 #define CPP_EXPECT_ELSE 2
 #define CPP_EXPECT_ENDIF 4
@@ -118,8 +121,8 @@ void cpp_error(struct cpp *this,char *err)
     ref_push_string(this->current_file);
     push_int(this->current_line);
     push_text(err);
-    safe_apply_handler("compile_error", this->handler,
-		       this->compat_handler, 3);
+    low_safe_apply_handler("compile_error", this->handler,
+			   this->compat_handler, 3);
     pop_stack();
   }else{
     (void)fprintf(stderr, "%s:%ld: %s\n",
@@ -130,6 +133,54 @@ void cpp_error(struct cpp *this,char *err)
   }
 }
 
+void cpp_error_sprintf(struct cpp *this, char *fmt, ...)  ATTRIBUTE((format(printf,2,3)))
+{
+  va_list args;
+  char buf[8192];
+
+  va_start(args,fmt);
+#ifdef HAVE_VSNPRINTF
+  vsnprintf(buf, 8190, fmt, args);
+#else /* !HAVE_VSNPRINTF */
+  VSPRINTF(buf, fmt, args);
+#endif /* HAVE_VSNPRINTF */
+  va_end(args);
+
+  if((size_t)strlen(buf) >= (size_t)sizeof(buf))
+    fatal("Buffer overflow in cpp_error.\n");
+
+  cpp_error(this, buf);
+}
+
+void cpp_describe_exception(struct cpp *this, struct svalue *thrown)
+{
+  /* FIXME: Doesn't handle wide string error messages. */
+  struct pike_string *s = 0;
+
+  if ((thrown->type == T_ARRAY) && thrown->u.array->size &&
+      (thrown->u.array->item[0].type == T_STRING)) {
+    /* Old-style backtrace */
+    s = thrown->u.array->item[0].u.string;
+  } else if (thrown->type == T_OBJECT) {
+    struct generic_error_struct *ge;
+    if ((ge = (struct generic_error_struct *)
+	 get_storage(thrown->u.object, generic_error_program))) {
+      s = ge->desc;
+    }
+  }
+
+  if (s && !s->size_shift) {
+    extern void f_string_trim_all_whites(INT32 args);
+    ref_push_string(s);
+    f_string_trim_all_whites(1);
+    push_constant_text("\n");
+    push_constant_text(" ");
+    f_replace(3);
+    cpp_error(this, sp[-1].u.string->str);
+    pop_stack();
+  }
+}
+
 void cpp_change_compat(struct cpp *this, int major, int minor)
 {
   if(this->compat_major == major &&
@@ -1095,10 +1146,34 @@ static void check_constant(struct cpp *this,
 	push_int(0);
       }
 
-      safe_apply_handler("resolv", this->handler, this->compat_handler, 3);
-      
-      res=(throw_value.type!=T_STRING) &&
-	(!(IS_ZERO(sp-1) && sp[-1].subtype == NUMBER_UNDEFINED));
+      if (safe_apply_handler("resolv", this->handler,
+			     this->compat_handler, 3, 0))
+	res = !(IS_ZERO(sp-1) && sp[-1].subtype == NUMBER_UNDEFINED);
+      else {
+	if (throw_value.type == T_STRING && !throw_value.u.string->size_shift) {
+	  cpp_error(this, throw_value.u.string->str);
+	  free_svalue(&throw_value);
+	  throw_value.type = T_INT;
+	  res = 0;
+	}
+	else {
+	  struct svalue thrown = throw_value;
+	  throw_value.type = T_INT;
+
+	  if (!s->size_shift)
+	    cpp_error_sprintf(this, "Error resolving '%s'.", s->str);
+	  else
+	    cpp_error(this, "Error resolving identifier.");
+
+	  push_svalue(&thrown);
+	  low_safe_apply_handler("compile_exception", this->handler,
+				 this->compat_handler, 1);
+	  if (IS_ZERO(sp-1)) cpp_describe_exception(this, &thrown);
+	  pop_stack();
+	  free_svalue(&thrown);
+	  res = 0;
+	}
+      }
     }else{
       res=0;
     }
@@ -1113,11 +1188,24 @@ static void check_constant(struct cpp *this,
       push_int(0);
     }
 
-    safe_apply_handler("handle_import", this->handler,
-		       this->compat_handler, 3);
+    if (safe_apply_handler("handle_import", this->handler,
+			   this->compat_handler, 3,
+			   BIT_MAPPING|BIT_OBJECT|BIT_PROGRAM))
+      res = !(IS_ZERO(sp-1) && sp[-1].subtype == NUMBER_UNDEFINED);
+    else {
+      struct svalue thrown = throw_value;
+      throw_value.type = T_INT;
+
+      cpp_error(this, "Error importing '.'.");
 
-    res=(throw_value.type!=T_STRING) &&
-      (!(IS_ZERO(sp-1) && sp[-1].subtype == NUMBER_UNDEFINED));
+      push_svalue(&thrown);
+      low_safe_apply_handler("compile_exception", this->handler,
+			     this->compat_handler, 1);
+      if (IS_ZERO(sp-1)) cpp_describe_exception(this, &thrown);
+      pop_stack();
+      free_svalue(&thrown);
+      res = 0;
+    }
   }
 
   while(1)
@@ -1224,6 +1312,8 @@ static int do_safe_index_call(struct pike_string *s)
   if(!s) return 0;
   
   if (SETJMP(recovery)) {
+    /* FIXME: Maybe call compile_exception here, but then we probably
+     * want to provide some extra flag to it. */
     res = 0;
     free_svalue(&throw_value);
     throw_value.type = T_INT;
diff --git a/src/interpret.c b/src/interpret.c
index dcc8dc4e4472be3704145206af48e2905a21f293..ce1c5f85b6f90dd222c9ee00e0fb6c08d540e579 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.242 2001/08/15 20:55:51 mast Exp $");
+RCSID("$Id: interpret.c,v 1.243 2001/08/16 04:38:50 mast Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -1816,9 +1816,10 @@ PMOD_EXPORT void safe_apply_low2(struct object *o,int fun,int args, int handle_e
     Pike_sp->type = T_INT;
     Pike_sp++;
   }else{
-    ptrdiff_t expected_stack = Pike_sp - Pike_interpreter.evaluator_stack + 1;
+    /* ptrdiff_t expected_stack = Pike_sp - Pike_interpreter.evaluator_stack + 1; */
     Pike_sp+=args;
     apply_low(o,fun,args);
+    /* apply_low already does this, afaics. /mast
     if(Pike_sp - Pike_interpreter.evaluator_stack > expected_stack)
       pop_n_elems(Pike_sp - Pike_interpreter.evaluator_stack - expected_stack);
     if(Pike_sp - Pike_interpreter.evaluator_stack < expected_stack)
@@ -1828,6 +1829,7 @@ PMOD_EXPORT void safe_apply_low2(struct object *o,int fun,int args, int handle_e
       Pike_sp->type = T_INT;
       Pike_sp++;
     }
+    */
   }
   UNSETJMP(recovery);
 }
@@ -1845,39 +1847,93 @@ PMOD_EXPORT void safe_apply(struct object *o, char *fun ,INT32 args)
   safe_apply_low2(o, find_identifier(fun, o->prog), args, 1);
 }
 
-PMOD_EXPORT void safe_apply_handler(const char *fun,
-				    struct object *handler,
-				    struct object *compat,
-				    INT32 args)
+PMOD_EXPORT void low_safe_apply_handler(const char *fun,
+					struct object *handler,
+					struct object *compat,
+					INT32 args)
 {
   int i;
 #if 0
-  fprintf(stderr, "safe_apply_handler(\"%s\", 0x%08p, 0x%08p, %d)\n",
+  fprintf(stderr, "low_safe_apply_handler(\"%s\", 0x%08p, 0x%08p, %d)\n",
 	  fun, handler, compat, args);
 #endif /* 0 */
-
-  free_svalue(&throw_value);
-  throw_value.type = T_INT;
-
   if (handler && handler->prog &&
       (i = find_identifier(fun, handler->prog)) != -1) {
-    safe_apply_low2(handler, i, args, 0);
+    safe_apply_low2(handler, i, args, 1);
   } else if (compat && compat->prog &&
 	     (i = find_identifier(fun, compat->prog)) != -1) {
-    safe_apply_low2(compat, i, args, 0);
+    safe_apply_low2(compat, i, args, 1);
   } else {
     struct object *master_obj = master();
     if ((i = find_identifier(fun, master_obj->prog)) != -1)
-      safe_apply_low2(master_obj, i, args, 0);
+      safe_apply_low2(master_obj, i, args, 1);
     else {
       pop_n_elems(args);
       push_undefined();
     }
   }
-  if (throw_value.type != T_STRING && throw_value.type != T_INT) {
-    free_svalue(&throw_value);
-    throw_value.type = T_INT;
+}
+
+PMOD_EXPORT int safe_apply_handler(const char *fun,
+				   struct object *handler,
+				   struct object *compat,
+				   INT32 args,
+				   TYPE_FIELD rettypes)
+{
+  JMP_BUF recovery;
+  int i, ret;
+#if 0
+  fprintf(stderr, "safe_apply_handler(\"%s\", 0x%08p, 0x%08p, %d)\n",
+	  fun, handler, compat, args);
+#endif /* 0 */
+
+  Pike_sp-=args;
+  free_svalue(& throw_value);
+  throw_value.type=T_INT;
+
+  if (SETJMP(recovery))
+    ret = 0;
+  else {
+    Pike_sp += args;
+
+    if (handler && handler->prog &&
+	(i = find_identifier(fun, handler->prog)) != -1) {
+      apply_low(handler, i, args);
+    } else if (compat && compat->prog &&
+	       (i = find_identifier(fun, compat->prog)) != -1) {
+      apply_low(compat, i, args);
+    } else {
+      struct object *master_obj = master();
+      if ((i = find_identifier(fun, master_obj->prog)) != -1)
+	apply_low(master_obj, i, args);
+      else {
+	pop_n_elems(args);
+	push_undefined();
+	goto dont_check_ret_type;
+      }
+    }
+
+    if (rettypes &&
+	!(((1 << Pike_sp[-1].type) & rettypes) ||
+	  ((rettypes & BIT_ZERO) &&
+	   Pike_sp[-1].type == T_INT &&
+	   Pike_sp[-1].u.integer == 0))) {
+      push_constant_text("Invalid return value from %s: %O\n");
+      push_text(fun);
+      push_svalue(Pike_sp - 3);
+      f_sprintf(3);
+      if (!Pike_sp[-1].u.string->size_shift)
+	Pike_error("%s", Pike_sp[-1].u.string->str);
+      else
+	Pike_error("Invalid return value from %s\n", fun);
+    }
+
+  dont_check_ret_type:
+    ret = 1;
   }
+
+  UNSETJMP(recovery);
+  return ret;
 }
 
 PMOD_EXPORT void apply_lfun(struct object *o, int fun, int args)
diff --git a/src/interpret.h b/src/interpret.h
index a6e02b9c03bb98ce3e72c45764f54547fb0b002f..eabd7597fb0ecddf1efa3b2c3239e4d99a4341d8 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: interpret.h,v 1.97 2001/08/15 09:26:32 hubbe Exp $
+ * $Id: interpret.h,v 1.98 2001/08/16 04:38:50 mast Exp $
  */
 #ifndef INTERPRET_H
 #define INTERPRET_H
@@ -362,10 +362,15 @@ PMOD_EXPORT int apply_low_safe_and_stupid(struct object *o, INT32 offset);
 PMOD_EXPORT void safe_apply_low(struct object *o,int fun,int args);
 PMOD_EXPORT void safe_apply_low2(struct object *o,int fun,int args, int handle_errors);
 PMOD_EXPORT void safe_apply(struct object *o, char *fun ,INT32 args);
-PMOD_EXPORT void safe_apply_handler(const char *fun,
-				    struct object *handler,
-				    struct object *compat,
-				    INT32 args);
+PMOD_EXPORT void low_safe_apply_handler(const char *fun,
+					struct object *handler,
+					struct object *compat,
+					INT32 args);
+PMOD_EXPORT int safe_apply_handler(const char *fun,
+				   struct object *handler,
+				   struct object *compat,
+				   INT32 args,
+				   TYPE_FIELD rettypes);
 PMOD_EXPORT void apply_lfun(struct object *o, int fun, int args);
 PMOD_EXPORT void apply_shared(struct object *o,
 		  struct pike_string *fun,
diff --git a/src/language.yacc b/src/language.yacc
index a2444def91e6b03f9732597b579ee185f0360c39..c6a73560f005cffc69672c79b9404107929193a6 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -112,7 +112,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.259 2001/08/16 00:36:47 mast Exp $");
+RCSID("$Id: language.yacc,v 1.260 2001/08/16 04:38:51 mast Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -150,6 +150,7 @@ int low_add_local_name(struct compiler_frame *,
 		       struct pike_string *, struct pike_type *, node *);
 static node *lexical_islocal(struct pike_string *);
 static void safe_inc_enum(void);
+static int call_handle_import(struct pike_string *s);
 
 static int inherit_depth;
 static struct program_state *inherit_state = NULL;
@@ -374,24 +375,15 @@ optional_rename_inherit: ':' TOK_IDENTIFIER { $$=$2; }
 low_program_ref: string_constant
   {
     ref_push_string($1->u.sval.u.string);
-    ref_push_string($1->u.sval.u.string);
-    ref_push_string(lex.current_file);
-    
-    if (error_handler && error_handler->prog) {
-      ref_push_object(error_handler);
-      SAFE_APPLY_MASTER("handle_inherit", 3);
-    } else {
-      SAFE_APPLY_MASTER("handle_inherit", 2);
+    if (call_handle_inherit($1->u.sval.u.string)) {
+      $$=mksvaluenode(Pike_sp-1);
+      pop_stack();
     }
-
-    if(Pike_sp[-1].type != T_PROGRAM)
-      my_yyerror("Couldn't cast string \"%s\" to program",
-		 $1->u.sval.u.string->str);
-    free_node($1);
-    $$=mksvaluenode(Pike_sp-1);
+    else
+      $$=mknewintnode(0);
     if($$->name) free_string($$->name);
-    add_ref( $$->name=Pike_sp[-2].u.string );
-    pop_stack();
+    add_ref( $$->name=Pike_sp[-1].u.string );
+    free_node($1);
   }
   | idents
   {
@@ -460,17 +452,11 @@ import: TOK_IMPORT idents ';'
   }
   | TOK_IMPORT string ';'
   {
-    ref_push_string($2->u.sval.u.string);
-    free_node($2);
-    ref_push_string(lex.current_file);
-    if (error_handler && error_handler->prog) {
-      ref_push_object(error_handler);
-      SAFE_APPLY_MASTER("handle_import", 3);
-    } else {
-      SAFE_APPLY_MASTER("handle_import", 2);
+    if (call_handle_import($2->u.sval.u.string)) {
+      use_module(Pike_sp-1);
+      pop_stack();
     }
-    use_module(Pike_sp-1);
-    pop_stack();
+    free_node($2);
   }
   | TOK_IMPORT error ';' { yyerrok; }
   | TOK_IMPORT error TOK_LEX_EOF
@@ -3185,19 +3171,17 @@ idents: low_idents
   }
   | '.' TOK_IDENTIFIER
   {
-    node *tmp;
-    push_text(".");
-    ref_push_string(lex.current_file);
-    if (error_handler && error_handler->prog) {
-      ref_push_object(error_handler);
-      SAFE_APPLY_MASTER("handle_import", 3);
-    } else {
-      SAFE_APPLY_MASTER("handle_import", 2);
+    struct pike_string *dot;
+    MAKE_CONSTANT_SHARED_STRING(dot, ".");
+    if (call_handle_import(dot)) {
+      node *tmp=mkconstantsvaluenode(Pike_sp-1);
+      pop_stack();
+      $$=index_node(tmp, ".", $2->u.sval.u.string);
+      free_node(tmp);
     }
-    tmp=mkconstantsvaluenode(Pike_sp-1);
-    pop_stack();
-    $$=index_node(tmp, ".", $2->u.sval.u.string);
-    free_node(tmp);
+    else
+      $$=mknewintnode(0);
+    free_string(dot);
     if(Pike_compiler->last_identifier) free_string(Pike_compiler->last_identifier);
     copy_shared_string(Pike_compiler->last_identifier, $2->u.sval.u.string);
     free_node($2);
@@ -3713,7 +3697,7 @@ void yyerror(char *str)
     }
     push_int(lex.current_line);
     push_text(str);
-    safe_apply_handler("compile_error", error_handler, compat_handler, 3);
+    low_safe_apply_handler("compile_error", error_handler, compat_handler, 3);
     pop_stack();
   }else{
     if (lex.current_file) {
@@ -3880,7 +3864,7 @@ static void safe_inc_enum(void)
     while(Pike_sp > save_sp) pop_stack();
 
     push_svalue(&s);
-    safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
     if (IS_ZERO(sp-1)) yy_describe_exception(&s);
     pop_stack();
     free_svalue(&s);
@@ -3896,6 +3880,44 @@ static void safe_inc_enum(void)
 #endif /* PIKE_DEBUG */
 }
 
+
+static int call_handle_import(struct pike_string *s)
+{
+  int args;
+
+  ref_push_string(s);
+  ref_push_string(lex.current_file);
+  if (error_handler && error_handler->prog) {
+    ref_push_object(error_handler);
+    args = 3;
+  }
+  else args = 2;
+
+  if (safe_apply_handler("handle_import", error_handler, compat_handler,
+			 args, BIT_MAPPING|BIT_OBJECT|BIT_PROGRAM|BIT_ZERO))
+    if (Pike_sp[-1].type != T_INT)
+      return 1;
+    else {
+      pop_stack();
+      if (!s->size_shift)
+	my_yyerror("Couldn't find module to import: %s",s->str);
+      else
+	yyerror("Couldn't find module to import");
+    }
+  else {
+    struct svalue thrown = throw_value;
+    throw_value.type = T_INT;
+    my_yyerror("Error finding module to import");
+    push_svalue(&thrown);
+    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+    if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
+    pop_stack();
+    free_svalue(&thrown);
+  }
+
+  return 0;
+}
+
 void cleanup_compiler(void)
 {
 }
diff --git a/src/las.c b/src/las.c
index 3369e3537bc4efc9ba685ed31b7bdc4a5418b326..35dd7f06f110f7443561a287a7d5409d49533127 100644
--- a/src/las.c
+++ b/src/las.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: las.c,v 1.264 2001/08/16 00:36:47 mast Exp $");
+RCSID("$Id: las.c,v 1.265 2001/08/16 04:38:51 mast Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -1690,8 +1690,8 @@ node *index_node(node *n, char *node_name, struct pike_string *id)
 
   if(SETJMP(tmp))
   {
-    struct svalue s;
-    assign_svalue_no_free(&s, &throw_value);
+    struct svalue thrown = throw_value;
+    throw_value.type = T_INT;
 
     if (node_name) {
       my_yyerror("Couldn't index module '%s'.", node_name);
@@ -1699,11 +1699,11 @@ node *index_node(node *n, char *node_name, struct pike_string *id)
       yyerror("Couldn't index module.");
     }
 
-    push_svalue(&s);
-    safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
-    if (IS_ZERO(sp-1)) yy_describe_exception(&s);
+    push_svalue(&thrown);
+    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+    if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
     pop_stack();
-    free_svalue(&s);
+    free_svalue(&thrown);
   }else{
     resolv_constant(n);
     switch(Pike_sp[-1].type)
@@ -1786,7 +1786,7 @@ node *index_node(node *n, char *node_name, struct pike_string *id)
 
 	  if (thrown.type != PIKE_T_UNKNOWN) {
 	    push_svalue(&thrown);
-	    safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+	    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
 	    if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
 	    pop_stack();
 	    free_svalue(&thrown);
@@ -5000,35 +5000,19 @@ ptrdiff_t eval_low(node *n)
       /* Generate error message */
       if(!Pike_compiler->catch_level)
       {
-        if(throw_value.type == T_ARRAY && throw_value.u.array->size)
-        {
-	  union anything *a;
-	  a=low_array_get_item_ptr(throw_value.u.array, 0, T_STRING);
-	  if(a)
-	  {
-	    yyerror(a->string->str);
-	  }else{
-	    yyerror("Nonstandard error format.");
-	  }
-	}
-	else if(throw_value.type == T_OBJECT)
-	{
-	  ref_push_object(throw_value.u.object);
-	  push_int(0);
-	  f_index(2);
-	  if(Pike_sp[-1].type != T_STRING)
-	    yyerror("Nonstandard error format.");
-	  else
-	    yyerror(Pike_sp[-1].u.string->str);
-	  pop_stack();
-	}
-	else
-	{
-	  yyerror("Nonstandard error format.");
-	}
+	struct svalue thrown = throw_value;
+	throw_value.type = T_INT;
+	yyerror("Error evaluating constant.\n");
+	push_svalue(&thrown);
+	low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+	if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
+	pop_stack();
+	free_svalue(&thrown);
+      }
+      else {
+	free_svalue(&throw_value);
+	throw_value.type = T_INT;
       }
-      free_svalue(&throw_value);
-      throw_value.type = T_INT;
     }else{
       if(foo.yes)
 	pop_n_elems(Pike_sp-save_sp);
diff --git a/src/preprocessor.h b/src/preprocessor.h
index 521abd522e552177c8d406438db3b2b258e94587..a9b93b4b3d17b607f8b8139be1cc9b2cfa549267 100644
--- a/src/preprocessor.h
+++ b/src/preprocessor.h
@@ -1,5 +1,5 @@
 /*
- * $Id: preprocessor.h,v 1.44 2001/08/16 00:36:47 mast Exp $
+ * $Id: preprocessor.h,v 1.45 2001/08/16 04:38:52 mast Exp $
  *
  * Preprocessor template.
  * Based on cpp.c 1.45
@@ -750,16 +750,16 @@ static ptrdiff_t calc(struct cpp *this, WCHAR *data, ptrdiff_t len,
 
   if (SETJMP(recovery))
   {
-    struct svalue s;
-    assign_svalue_no_free(&s, &throw_value);
+    struct svalue thrown = throw_value;
+    throw_value.type = T_INT;
 
-    yyerror("Error calculating expression.");
+    cpp_error(this, "Error evaluating expression.");
 
-    push_svalue(&s);
-    safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
-    if (IS_ZERO(sp-1)) yy_describe_exception(&s);
+    push_svalue(&thrown);
+    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+    if (IS_ZERO(sp-1)) cpp_describe_exception(this, &thrown);
     pop_stack();
-    free_svalue(&s);
+    free_svalue(&thrown);
 
     pos=tmp;
     FIND_EOL();
@@ -918,11 +918,14 @@ static ptrdiff_t lower_cpp(struct cpp *this,
 		    arguments[arg].len=0;
 		    continue;
 		  }else{
-		    char buffer[1024];
-		    sprintf(buffer,
-			    "Too few arguments to macro %.950s, expected %d.",
-			    d->link.s->str, d->args);
-		    cpp_error(this, buffer);
+		    if (!d->link.s->size_shift)
+		      cpp_error_sprintf(this,
+					"Too few arguments to macro %s, expected %d.",
+					d->link.s->str, d->args);
+		    else
+		      cpp_error_sprintf(this,
+					"Too few arguments to macro, expected %d.",
+					d->args);
 		    break;
 		  }
 		}
@@ -978,11 +981,12 @@ static ptrdiff_t lower_cpp(struct cpp *this,
 	    }
 	    SKIPWHITE();
 	    if(!GOBBLE(')')) {
-	      char buffer[1024];
-	      sprintf(buffer, "Missing ) in the macro %.950s.", 
-		      d->link.s->str);
 	      this->current_line = start_line;
-	      cpp_error(this, buffer);
+	      if (!d->link.s->size_shift)
+		cpp_error_sprintf(this, "Missing ) in the macro %s.",
+				  d->link.s->str);
+	      else
+		cpp_error(this, "Missing ) in macro.");
 	    }
 	  }
 	  
diff --git a/src/program.c b/src/program.c
index 8a5c29bfbfcad3d12d52667d6146b58707ef51e6..91fdafae6b65440b2d297889f8468b6a29cca533 100644
--- a/src/program.c
+++ b/src/program.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: program.c,v 1.365 2001/08/15 23:00:12 mast Exp $");
+RCSID("$Id: program.c,v 1.366 2001/08/16 04:38:52 mast Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -760,8 +760,8 @@ static struct node_s *index_modules(struct pike_string *ident,
 
     if(SETJMP(tmp))
     {
-      struct svalue s;
-      assign_svalue_no_free(&s, &throw_value);
+      struct svalue thrown = throw_value;
+      throw_value.type = T_INT;
 
       if (!ident->size_shift) {
 	my_yyerror("Couldn't index module '%s'.", ident->str);
@@ -769,11 +769,11 @@ static struct node_s *index_modules(struct pike_string *ident,
 	yyerror("Couldn't index module.");
       }
 
-      push_svalue(&s);
-      safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
-      if (IS_ZERO(sp-1)) yy_describe_exception(&s);
+      push_svalue(&thrown);
+      low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+      if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
       pop_stack();
-      free_svalue(&s);
+      free_svalue(&thrown);
     } else {
       int e = num_used_modules;
       struct svalue *m = modules - num_used_modules;
@@ -890,15 +890,7 @@ struct node_s *find_module_identifier(struct pike_string *ident,
 	push_int(0);
       }
 
-      safe_apply_handler("resolv", error_handler, compat_handler, 3);
-
-      if(throw_value.type == T_STRING)
-      {
-	if(Pike_compiler->compiler_pass==2)
-	  my_yyerror("%s",throw_value.u.string->str);
-      }
-      else
-      {
+      if (safe_apply_handler("resolv", error_handler, compat_handler, 3, 0)) {
 	if(!resolve_cache)
 	  resolve_cache=dmalloc_touch(struct mapping *, allocate_mapping(10));
 	mapping_string_insert(resolve_cache,ident,Pike_sp-1);
@@ -907,8 +899,31 @@ struct node_s *find_module_identifier(struct pike_string *ident,
 	{
 	  ret=mkconstantsvaluenode(Pike_sp-1);
 	}
+	pop_stack();
       }
-      pop_stack();
+      else
+	if(Pike_compiler->compiler_pass==2) {
+	  if (throw_value.type == T_STRING && !throw_value.u.string->size_shift) {
+	    yyerror(throw_value.u.string->str);
+	    free_svalue(&throw_value);
+	    throw_value.type = T_INT;
+	  }
+	  else {
+	    struct svalue thrown = throw_value;
+	    throw_value.type = T_INT;
+
+	    if (!ident->size_shift)
+	      my_yyerror("Error resolving '%s'.", ident->str);
+	    else
+	      yyerror("Error resolving identifier.");
+
+	    push_svalue(&thrown);
+	    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+	    if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
+	    pop_stack();
+	    free_svalue(&thrown);
+	  }
+	}
     }
     END_CYCLIC();
     if(ret) return ret;
@@ -2765,23 +2780,50 @@ void compiler_do_inherit(node *n,
   }
 }
 
-
-void simple_do_inherit(struct pike_string *s,
-		       INT32 flags,
-		       struct pike_string *name)
+int call_handle_inherit(struct pike_string *s)
 {
+  int args;
+
   reference_shared_string(s);
   push_string(s);
   ref_push_string(lex.current_file);
-  safe_apply_handler("handle_inherit", error_handler, compat_handler, 2);
+  if (error_handler && error_handler->prog) {
+    ref_push_object(error_handler);
+    args = 3;
+  }
+  else args = 2;
 
-  if(Pike_sp[-1].type != T_PROGRAM)
-  {
-    my_yyerror("Couldn't find file to inherit %s",s->str);
+  if (safe_apply_handler("handle_inherit", error_handler, compat_handler,
+			 args, BIT_PROGRAM|BIT_FUNCTION|BIT_ZERO))
+    if (Pike_sp[-1].type != T_INT)
+      return 1;
+    else {
+      pop_stack();
+      if (!s->size_shift)
+	my_yyerror("Couldn't find program: %s",s->str);
+      else
+	yyerror("Couldn't find program");
+    }
+  else {
+    struct svalue thrown = throw_value;
+    throw_value.type = T_INT;
+    my_yyerror("Error finding program");
+    push_svalue(&thrown);
+    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+    if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
     pop_stack();
-    return;
+    free_svalue(&thrown);
   }
 
+  return 0;
+}
+
+void simple_do_inherit(struct pike_string *s,
+		       INT32 flags,
+		       struct pike_string *name)
+{
+  if (!call_handle_inherit(s)) return;
+
   if(name)
   {
     free_string(s);
@@ -3761,16 +3803,16 @@ int store_constant(struct svalue *foo,
 
   if(SETJMP(tmp2))
   {
-    struct svalue zero, s;
-    assign_svalue_no_free(&s, &throw_value);
+    struct svalue zero, thrown = throw_value;
+    throw_value.type = T_INT;
 
     yyerror("Couldn't store constant.");
 
-    push_svalue(&s);
-    safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
-    if (IS_ZERO(sp-1)) yy_describe_exception(&s);
+    push_svalue(&thrown);
+    low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
+    if (IS_ZERO(sp-1)) yy_describe_exception(&thrown);
     pop_stack();
-    free_svalue(&s);
+    free_svalue(&thrown);
 
     zero.type = T_INT;
     zero.subtype = NUMBER_NUMBER;
@@ -5314,7 +5356,7 @@ void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2)))
     push_int(lex.current_line);
     push_text(buf);
 
-    safe_apply_handler("compile_warning", error_handler, compat_handler, 3);
+    low_safe_apply_handler("compile_warning", error_handler, compat_handler, 3);
     pop_stack();
   }
 }
diff --git a/src/program.h b/src/program.h
index 3b0b66783702b3c1297b3667e61685db5922c7c1..37526d880f1ae1c9bd9e88fd546f65a4d8395ad5 100644
--- a/src/program.h
+++ b/src/program.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: program.h,v 1.142 2001/08/15 20:58:44 mast Exp $
+ * $Id: program.h,v 1.143 2001/08/16 04:38:53 mast Exp $
  */
 #ifndef PROGRAM_H
 #define PROGRAM_H
@@ -414,6 +414,7 @@ PMOD_EXPORT void do_inherit(struct svalue *s,
 void compiler_do_inherit(node *n,
 			 INT32 flags,
 			 struct pike_string *name);
+int call_handle_inherit(struct pike_string *s);
 void simple_do_inherit(struct pike_string *s,
 		       INT32 flags,
 		       struct pike_string *name);
@@ -600,6 +601,9 @@ void make_program_executable(struct program *p);
 #define add_function pike_add_function
 #endif
 
+#define ADD_INHERIT(PROGRAM, FLAGS) \
+  low_inherit((PROGRAM), 0, 0, 0, (FLAGS), 0)
+
 #define START_NEW_PROGRAM_ID(ID) do { \
     start_new_program();  \
     Pike_compiler->new_program->id=PIKE_CONCAT3(PROG_,ID,_ID); \