changeset 8011:3100283874d7

improve backtrace error messages
author John W. Eaton <jwe@octave.org>
date Tue, 05 Aug 2008 23:09:32 -0400
parents 0e9b6af36559
children 63dbb85452cc
files src/ChangeLog src/gripes.cc src/gripes.h src/ov-builtin.cc src/ov-mex-fcn.cc src/ov-usr-fcn.cc src/ov-usr-fcn.h src/ov.cc src/pt-assign.cc src/pt-assign.h src/pt-binop.cc src/pt-binop.h src/pt-cbinop.cc src/pt-colon.cc src/pt-colon.h src/pt-decl.cc src/pt-exp.cc src/pt-idx.cc src/pt-idx.h src/pt-loop.cc src/pt-loop.h src/pt-select.cc src/pt-select.h src/pt-stmt.cc src/pt-unop.cc src/pt-unop.h src/toplev.cc src/toplev.h
diffstat 28 files changed, 168 insertions(+), 416 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/ChangeLog	Tue Aug 05 23:09:32 2008 -0400
@@ -1,5 +1,65 @@
 2008-08-05  John W. Eaton  <jwe@octave.org>
 
+	* toplev.cc (octave_call_stack::backtrace_error_message): New
+	function.
+	* toplev.h: Provide decl.
+	(octave_call_stack::do_pop): Call backtrace_error_message if
+	error_state is nonzero.
+
+	* pt-unop.cc (tree_prefix_expression::eval_error, 
+	tree_postfix_expression::eval_error): Delete.  Eliminate all uses.
+	* pt-unop.h: Delete decls.
+
+	* pt-select.cc (tree_switch_case::eval_error,
+	tree_switch_command::eval_error): Delete.  Eliminate all uses.
+	(tree_if_command::eval): Omit "evaluating if command" message.
+	* pt-select.h: Delete decls.
+
+	* pt-loop.cc (tree_while_command::eval_error,
+	tree_complex_for_command::eval_error,
+	tree_simple_for_command::eval_error,
+	tree_do_until_command::eval_error): Delete.  Eliminate all uses.
+	* pt-loop.h: Delete decls.
+
+	* pt-exp.cc (tree_expression::is_logically_true): Omit "evaluating
+	conditional expression" error message.
+
+	* pt-decl.cc (tree_global_command::eval): Omit "evaluating global
+	command" error message.
+	(tree_static_command::eval): Omit "evaluating static command"
+	error message.
+
+	* pt-colon.cc (tree_colon_expression::eval_error): Omit
+	"evaluating colon expression" error message.
+	* pt-colon.h (tree_colon_expression::eval_error): Eliminate
+	default argument value.
+
+	* pt-idx.cc (tree_index_expression::eval_error): Delete.
+	Eliminate all uses.
+	* pt-idx.h: Delete decl.
+
+	* pt-binop.cc (tree_binary_expression::eval_error): Delete.
+	* pt-binop.cc, pt-cbinop.cc: Eliminate all uses of eval_error.
+	* pt-binop.h: Delete decl.
+
+	* pt-assign.cc (tree_simple_assignment::eval_error,
+	tree_multi_assignment::eval_error): Delete.  Eliminate all uses.
+	* pt-assign.h: Delete decls.
+
+	* ov-usr-fcn.cc (octave_user_script::traceback_error,
+	octave_user_function::traceback_error): Delete.  Eliminate all uses.
+	* ov-usr-fcn.h: Delete decls.
+
+	* ov-builtin.cc (octave_builtin::do_multi_index_op): Call
+	gripe_library_exectuion_error on octave_execution_exception.
+	* ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Likewise.
+	* ov.cc (do_binary_op, do_cat_op, do_unary_op,
+	do_non_const_unary_op): Likewise.
+	* pt-stmt.cc (tree_statement::eval): Likewise.
+
+	* gripes.cc (gripe_library_execution_error): New function.
+	* gripes.h: Provide decl.
+
 	* dirfns.cc (Fpathsep): Fix usage of dir_path::path_sep_str.
 	* defaults.cc (set_exec_path, set_image_path): Likewise.
 	* load-path.h (load_path::set_command_line_path): Likewise.
--- a/src/gripes.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/gripes.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -212,6 +212,15 @@
                    srctype, desttype);
 }
 
+void
+gripe_library_execution_error (void)
+{
+  octave_exception_state = octave_no_exception;
+
+  if (! error_state)
+    error ("caught execution error in library function");
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
--- a/src/gripes.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/gripes.h	Tue Aug 05 23:09:32 2008 -0400
@@ -116,6 +116,9 @@
 extern OCTINTERP_API void
 gripe_logical_conversion (void);
 
+extern OCTINTERP_API void
+gripe_library_execution_error (void);
+
 #endif
 
 /*
--- a/src/ov-builtin.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/ov-builtin.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -26,6 +26,7 @@
 #endif
 
 #include "error.h"
+#include "gripes.h"
 #include "oct-obj.h"
 #include "ov-builtin.h"
 #include "ov.h"
@@ -107,8 +108,7 @@
 	}
       catch (octave_execution_exception)
 	{
-	  octave_exception_state = octave_no_exception;
-	  error ("caught execution error in library function");
+	  gripe_library_execution_error ();
 	}
 
       unwind_protect::run_frame ("builtin_func_eval");
--- a/src/ov-mex-fcn.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/ov-mex-fcn.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -29,6 +29,7 @@
 #include <defaults.h>
 #include "dynamic-ld.h"
 #include "error.h"
+#include "gripes.h"
 #include "oct-obj.h"
 #include "ov-mex-fcn.h"
 #include "ov.h"
@@ -149,8 +150,7 @@
 	}
       catch (octave_execution_exception)
 	{
-	  octave_exception_state = octave_no_exception;
-	  error ("caught execution error in library function");
+	  gripe_library_execution_error ();
 	}
 
       unwind_protect::run_frame ("mex_func_eval");
--- a/src/ov-usr-fcn.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/ov-usr-fcn.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -110,14 +110,14 @@
 {
   octave_value_list retval;
 
+  unwind_protect::begin_frame ("user_script_eval");
+
   if (! error_state)
     {
       if (args.length () == 0 && nargout == 0)
 	{
 	  if (cmd_list)
 	    {
-	      unwind_protect::begin_frame ("user_script_eval");
-
 	      unwind_protect_int (call_depth);
 	      call_depth++;
 
@@ -134,20 +134,17 @@
 
 		  if (tree_break_command::breaking)
 		    tree_break_command::breaking--;
-
-		  if (error_state)
-		    traceback_error ();
 		}
 	      else
 		::error ("max_recursion_limit exceeded");
-
-	      unwind_protect::run_frame ("user_script_eval");
     	    }
 	}
       else
 	error ("invalid call to script");
     }
 
+  unwind_protect::run_frame ("user_script_eval");
+
   return retval;
 }
 
@@ -157,32 +154,6 @@
   tw.visit_octave_user_script (*this);
 }
 
-// FIXME -- this function is exactly the same as
-// octave_user_function::traceback_error.
-
-void
-octave_user_script::traceback_error (void) const
-{
-  if (error_state >= 0)
-    error_state = -1;
-
-  if (my_name.empty ())
-    {
-      if (file_name.empty ())
-	::error ("called from `?unknown?'");
-      else
-	::error ("called from file `%s'", file_name.c_str ());
-    }
-  else
-    {
-      if (file_name.empty ())
-	::error ("called from `%s'", my_name.c_str ());
-      else 
-	::error ("called from `%s' in file `%s'",
-		 my_name.c_str (), file_name.c_str ());
-    }
-}
-
 // User defined functions.
 
 DEFINE_OCTAVE_ALLOCATOR (octave_user_function);
@@ -473,10 +444,7 @@
       tree_break_command::breaking--;
 
     if (error_state)
-      {
-	traceback_error ();
-	goto abort;
-      }
+      goto abort;
     
     // Copy return values out.
 
@@ -511,29 +479,6 @@
 }
 
 void
-octave_user_function::traceback_error (void) const
-{
-  if (error_state >= 0)
-    error_state = -1;
-
-  if (my_name.empty ())
-    {
-      if (file_name.empty ())
-	::error ("called from `?unknown?'");
-      else
-	::error ("called from file `%s'", file_name.c_str ());
-    }
-  else
-    {
-      if (file_name.empty ())
-	::error ("called from `%s'", my_name.c_str ());
-      else 
-	::error ("called from `%s' in file `%s'",
-		 my_name.c_str (), file_name.c_str ());
-    }
-}
-
-void
 octave_user_function::accept (tree_walker& tw)
 {
   tw.visit_octave_user_function (*this);
--- a/src/ov-usr-fcn.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/ov-usr-fcn.h	Tue Aug 05 23:09:32 2008 -0400
@@ -134,8 +134,6 @@
 
   tree_statement_list *body (void) { return cmd_list; }
 
-  void traceback_error (void) const;
-
   void accept (tree_walker& tw);
 
 private:
@@ -299,8 +297,6 @@
   octave_value_list
   do_multi_index_op (int nargout, const octave_value_list& args);
 
-  void traceback_error (void) const;
-
   tree_parameter_list *parameter_list (void) { return param_list; }
 
   tree_parameter_list *return_list (void) { return ret_list; }
--- a/src/ov.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/ov.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -1546,8 +1546,7 @@
 	    }
 	  catch (octave_execution_exception)
 	    {
-	      octave_exception_state = octave_no_exception;
-	      error ("caught execution error in library function");
+	      gripe_library_execution_error ();
 	    }
 	}	    
       else
@@ -1570,8 +1569,7 @@
 	    }
 	  catch (octave_execution_exception)
 	    {
-	      octave_exception_state = octave_no_exception;
-	      error ("caught execution error in library function");
+	      gripe_library_execution_error ();
 	    }
 	}
       else
@@ -1630,8 +1628,7 @@
 		    }
 		  catch (octave_execution_exception)
 		    {
-		      octave_exception_state = octave_no_exception;
-		      error ("caught execution error in library function");
+		      gripe_library_execution_error ();
 		    }
 		}
 	      else
@@ -1685,8 +1682,7 @@
 			    }
 			  catch (octave_execution_exception)
 			    {
-			      octave_exception_state = octave_no_exception;
-			      error ("caught execution error in library function");
+			      gripe_library_execution_error ();
 			    }
 			}
 		      else
@@ -1749,8 +1745,7 @@
 			}
 		      catch (octave_execution_exception)
 			{
-			  octave_exception_state = octave_no_exception;
-			  error ("caught execution error in library function");
+			  gripe_library_execution_error ();
 			}
 		    }
 		  else
@@ -1826,8 +1821,7 @@
 	    }
 	  catch (octave_execution_exception)
 	    {
-	      octave_exception_state = octave_no_exception;
-	      error ("caught execution error in library function");
+	      gripe_library_execution_error ();
 	    }
 	}	    
       else
@@ -1846,8 +1840,7 @@
 	    }
 	  catch (octave_execution_exception)
 	    {
-	      octave_exception_state = octave_no_exception;
-	      error ("caught execution error in library function");
+	      gripe_library_execution_error ();
 	    }
 	}
       else
@@ -1893,8 +1886,7 @@
 	}
       catch (octave_execution_exception)
 	{
-	  octave_exception_state = octave_no_exception;
-	  error ("caught execution error in library function");
+	  gripe_library_execution_error ();
 	}
     }
   else
@@ -1953,8 +1945,7 @@
 		}
 	      catch (octave_execution_exception)
 		{
-		  octave_exception_state = octave_no_exception;
-		  error ("caught execution error in library function");
+		  gripe_library_execution_error ();
 		}
 	    }
 	  else
@@ -2010,8 +2001,7 @@
 	    }
 	  catch (octave_execution_exception)
 	    {
-	      octave_exception_state = octave_no_exception;
-	      error ("caught execution error in library function");
+	      gripe_library_execution_error ();
 	    }
 	}
       else
@@ -2034,8 +2024,7 @@
 	    }
 	  catch (octave_execution_exception)
 	    {
-	      octave_exception_state = octave_no_exception;
-	      error ("caught execution error in library function");
+	      gripe_library_execution_error ();
 	    }
 	}
       else
@@ -2063,8 +2052,7 @@
 			}
 		      catch (octave_execution_exception)
 			{
-			  octave_exception_state = octave_no_exception;
-			  error ("caught execution error in library function");
+			  gripe_library_execution_error ();
 			}
 		    }
 		  else
@@ -2111,8 +2099,7 @@
 	}
       catch (octave_execution_exception)
 	{
-	  octave_exception_state = octave_no_exception;
-	  error ("caught execution error in library function");
+	  gripe_library_execution_error ();
 	}
     }
   else
@@ -2140,8 +2127,7 @@
 		    }
 		  catch (octave_execution_exception)
 		    {
-		      octave_exception_state = octave_no_exception;
-		      error ("caught execution error in library function");
+		      gripe_library_execution_error ();
 		    }
 
 		  if (old_rep && --old_rep->count == 0)
--- a/src/pt-assign.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-assign.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -208,7 +208,6 @@
 	  if (rhs_val.is_undefined ())
 	    {
 	      error ("value on right hand side of assignment is undefined");
-	      eval_error ();
 	      return retval;
 	    }
 	  else
@@ -222,16 +221,13 @@
 		  else
 		    {
 		      error ("invalid number of elements on RHS of assignment");
-		      eval_error ();
 		      return retval;
 		    }
 		}
 
 	      octave_lvalue ult = lhs->lvalue ();
 
-	      if (error_state)
-		eval_error ();
-	      else
+	      if (! error_state)
 		{
 		  ult.assign (etype, rhs_val);
 
@@ -259,29 +255,14 @@
 						     lhs->name ());
 			}
 		    }
-		  else
-		    eval_error ();
 		}
 	    }
 	}
-      else
-	eval_error ();
     }
 
   return retval;
 }
 
-void
-tree_simple_assignment::eval_error (void)
-{
-  int l = line ();
-  int c = column ();
-
-  if (l != -1 && c != -1)
-    ::error ("evaluating assignment expression near line %d, column %d",
-	     l, c);
-}
-
 std::string
 tree_simple_assignment::oper (void) const
 {
@@ -380,7 +361,6 @@
 	  if (n_out > 0)
 	    {
 	      error ("value on right hand side of assignment is undefined");
-	      eval_error ();
 	      return retval;
 	    }
 	}
@@ -467,10 +447,7 @@
 		}
 
 	      if (error_state)
-		{
-		  eval_error ();
-		  break;
-		}
+		break;
 	      else if (print_result ())
 		{
 		  // We clear any index here so that we can get
@@ -493,23 +470,10 @@
 	    }
 	}
     }
-  else
-    eval_error ();
 
   return retval;
 }
 
-void
-tree_multi_assignment::eval_error (void)
-{
-  int l = line ();
-  int c = column ();
-
-  if (l != -1 && c != -1)
-    ::error ("evaluating assignment expression near line %d, column %d",
-	     l, c);
-}
-
 std::string
 tree_multi_assignment::oper (void) const
 {
--- a/src/pt-assign.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-assign.h	Tue Aug 05 23:09:32 2008 -0400
@@ -65,8 +65,6 @@
 
   bool is_assignment_expression (void) const { return true; }
 
-  void eval_error (void);
-
   std::string oper (void) const;
 
   tree_expression *left_hand_side (void) { return lhs; }
@@ -136,8 +134,6 @@
 
   octave_value_list rvalue (int nargout);
 
-  void eval_error (void);
-
   std::string oper (void) const;
 
   tree_argument_list *left_hand_side (void) { return lhs; }
--- a/src/pt-binop.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-binop.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -62,43 +62,23 @@
     {
       octave_value a = op_lhs->rvalue ();
 
-      if (error_state)
-	eval_error ();
-      else if (a.is_defined () && op_rhs)
+      if (! error_state && a.is_defined () && op_rhs)
 	{
 	  octave_value b = op_rhs->rvalue ();
 
-	  if (error_state)
-	    eval_error ();
-	  else if (b.is_defined ())
+	  if (! error_state && b.is_defined ())
 	    {
 	      retval = ::do_binary_op (etype, a, b);
 
 	      if (error_state)
-		{
-		  retval = octave_value ();
-		  eval_error ();
-		}
+		retval = octave_value ();
 	    }
-	  else
-	    eval_error ();
 	}
-      else
-	eval_error ();
     }
-  else
-    eval_error ();
 
   return retval;
 }
 
-void
-tree_binary_expression::eval_error (void)
-{
-  ::error ("evaluating binary operator `%s' near line %d, column %d",
-	   oper () . c_str (), line (), column ());
-}
-
 std::string
 tree_binary_expression::oper (void) const
 {
@@ -157,15 +137,11 @@
     {
       octave_value a = op_lhs->rvalue ();
 
-      if (error_state)
-	eval_error ();
-      else
+      if (! error_state)
 	{
 	  bool a_true = a.is_true ();
 
-	  if (error_state)
-	    eval_error ();
-	  else
+	  if (! error_state)
 	    {
 	      if (a_true)
 		{
@@ -185,18 +161,9 @@
 		{
 		  octave_value b = op_rhs->rvalue ();
 
-		  if (error_state)
-		    eval_error ();
-		  else
-		    {
-		      result = b.is_true ();
-
-		      if (error_state)
-			eval_error ();
-		    }
+		  if (! error_state)
+		    result = b.is_true ();
 		}
-	      else
-		eval_error ();
 
 	    done:
 
@@ -205,8 +172,6 @@
 	    }
 	}
     }
-  else
-    eval_error ();
 
   return retval;
 }
--- a/src/pt-binop.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-binop.h	Tue Aug 05 23:09:32 2008 -0400
@@ -74,8 +74,6 @@
 
   octave_value_list rvalue (int nargout);
 
-  void eval_error (void);
-
   std::string oper (void) const;
 
   octave_value::binary_op op_type (void) const { return etype; }
--- a/src/pt-cbinop.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-cbinop.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -125,32 +125,19 @@
     {
       octave_value a = op_lhs->rvalue ();
 
-      if (error_state)
-	eval_error ();
-      else if (a.is_defined () && op_rhs)
+      if (! error_state && a.is_defined () && op_rhs)
 	{
 	  octave_value b = op_rhs->rvalue ();
 
-	  if (error_state)
-	    eval_error ();
-	  else if (b.is_defined ())
+	  if (! error_state && b.is_defined ())
 	    {
 	      retval = ::do_binary_op (etype, a, b);
 
 	      if (error_state)
-		{
-		  retval = octave_value ();
-		  eval_error ();
-		}
+		retval = octave_value ();
 	    }
-	  else
-	    eval_error ();
 	}
-      else
-	eval_error ();
     }
-  else
-    eval_error ();
 
   return retval;
 }
--- a/src/pt-colon.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-colon.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -184,11 +184,7 @@
 void
 tree_colon_expression::eval_error (const std::string& s) const
 {
-  if (! s.empty ())
-    ::error ("%s", s.c_str ());
-
-  ::error ("evaluating colon expression near line %d column %d",
-	   line (), column ());
+  ::error ("%s", s.c_str ());
 }
 
 int
--- a/src/pt-colon.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-colon.h	Tue Aug 05 23:09:32 2008 -0400
@@ -81,7 +81,7 @@
 
   octave_value_list rvalue (int nargout);
 
-  void eval_error (const std::string& s = std::string ()) const;
+  void eval_error (const std::string& s) const;
 
   tree_expression *base (void) { return op_base; }
 
--- a/src/pt-decl.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-decl.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -172,10 +172,6 @@
 
   if (init_list)
     init_list->eval (do_init);
-
-  if (error_state)
-    ::error ("evaluating global command near line %d, column %d",
-	     line (), column ());
 }
 
 tree_command *
@@ -225,10 +221,6 @@
 
   if (init_list)
     init_list->eval (do_init);
-
-  if (error_state)
-    ::error ("evaluating static command near line %d, column %d",
-	     line (), column ());
 }
 
 tree_command *
--- a/src/pt-exp.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-exp.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -50,8 +50,6 @@
 	::error ("%s: undefined value used in conditional expression",
 		 warn_for);
     }
-  else
-    ::error ("%s: error evaluating conditional expression", warn_for);
 
   return expr_value;
 }
--- a/src/pt-idx.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-idx.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -242,12 +242,7 @@
 	  break;
 
 	case '.':
-	  {
-	    subs_field(i) = get_struct_index (p_arg_nm, p_dyn_field);
-
-	    if (error_state)
-	      eval_error ();
-	  }
+	  subs_field(i) = get_struct_index (p_arg_nm, p_dyn_field);
 	  break;
 
 	default:
@@ -361,12 +356,7 @@
 	      break;
 
 	    case '.':
-	      {
-		idx.push_back (octave_value (get_struct_index (p_arg_nm, p_dyn_field)));
-
-		if (error_state)
-		  eval_error ();
-	      }
+	      idx.push_back (octave_value (get_struct_index (p_arg_nm, p_dyn_field)));
 	      break;
 
 	    default:
@@ -618,8 +608,6 @@
 
 		    idx.push_back (octave_value (tidx));
 		  }
-		else
-		  eval_error ();
 	      }
 	      break;
 
@@ -667,27 +655,6 @@
 %! assert (x(2).b == 1);
 */
 
-void
-tree_index_expression::eval_error (void) const
-{
-  int l = line ();
-  int c = column ();
-
-  const char *type_str;
-
-  if (type[0] == '.')
-    type_str = "structure reference operator";
-  else if (args.front ())
-    type_str = "index expression";
-  else
-    type_str = "expression";
-
-  if (l != -1 && c != -1)
-    ::error ("evaluating %s near line %d, column %d", type_str, l, c);
-  else
-    ::error ("evaluating %s", type_str);
-}
-
 tree_index_expression *
 tree_index_expression::dup (symbol_table::scope_id scope,
 			    symbol_table::context_id context)
--- a/src/pt-idx.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-idx.h	Tue Aug 05 23:09:32 2008 -0400
@@ -88,8 +88,6 @@
 
   octave_lvalue lvalue (void);
 
-  void eval_error (void) const;
-
   tree_index_expression *dup (symbol_table::scope_id scope,
 			      symbol_table::context_id context);
 
--- a/src/pt-loop.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-loop.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -101,10 +101,7 @@
 	      list->eval ();
 
 	      if (error_state)
-		{
-		  eval_error ();
-		  goto cleanup;
-		}
+		goto cleanup;
 	    }
 
 	  if (quit_loop_now ())
@@ -118,13 +115,6 @@
   unwind_protect::run_frame ("while_command::eval");
 }
 
-void
-tree_while_command::eval_error (void)
-{
-  ::error ("evaluating while command near line %d, column %d",
-	   line (), column ());
-}
-
 tree_command *
 tree_while_command::dup (symbol_table::scope_id scope,
 			 symbol_table::context_id context)
@@ -168,10 +158,7 @@
 	  list->eval ();
 
 	  if (error_state)
-	    {
-	      eval_error ();
-	      goto cleanup;
-	    }
+	    goto cleanup;
 	}
 
       if (quit_loop_now () || expr->is_logically_true ("do-until"))
@@ -182,13 +169,6 @@
   unwind_protect::run_frame ("do_until_command::eval");
 }
 
-void
-tree_do_until_command::eval_error (void)
-{
-  ::error ("evaluating do-until command near line %d, column %d",
-	   line (), column ());
-}
-
 tree_command *
 tree_do_until_command::dup (symbol_table::scope_id scope,
 			    symbol_table::context_id context)
@@ -223,18 +203,8 @@
 {
   ult.assign (octave_value::op_asn_eq, rhs);
 
-  if (! error_state)
-    {
-      if (list)
-	{
-	  list->eval ();
-
-	  if (error_state)
-	    eval_error ();
-	}
-    }
-  else
-    eval_error ();
+  if (! error_state && list)
+    list->eval ();
 
   quit = quit_loop_now ();
 }
@@ -337,19 +307,13 @@
   octave_value rhs = expr->rvalue ();
 
   if (error_state || rhs.is_undefined ())
-    {
-      eval_error ();
-      goto cleanup;
-    }
+    goto cleanup;
 
   {
     octave_lvalue ult = lhs->lvalue ();
 
     if (error_state)
-      {
-	eval_error ();
-	goto cleanup;
-      }
+      goto cleanup;
 
     if (rhs.is_range ())
       {
@@ -489,13 +453,6 @@
   unwind_protect::run_frame ("simple_for_command::eval");
 }
 
-void
-tree_simple_for_command::eval_error (void)
-{
-  ::error ("evaluating for command near line %d, column %d",
-	   line (), column ());
-}
-
 tree_command *
 tree_simple_for_command::dup (symbol_table::scope_id scope,
 			      symbol_table::context_id context)
@@ -534,18 +491,8 @@
   val_ref.assign (octave_value::op_asn_eq, val);
   key_ref.assign (octave_value::op_asn_eq, key);
 
-  if (! error_state)
-    {
-      if (list)
-	{
-	  list->eval ();
-
-	  if (error_state)
-	    eval_error ();
-	}
-    }
-  else
-    eval_error ();
+  if (! error_state && list)
+    list->eval ();
 
   quit = quit_loop_now ();
 }
@@ -565,10 +512,7 @@
   octave_value rhs = expr->rvalue ();
 
   if (error_state || rhs.is_undefined ())
-    {
-      eval_error ();
-      goto cleanup;
-    }
+    goto cleanup;
 
   if (rhs.is_map ())
     {
@@ -611,13 +555,6 @@
   unwind_protect::run_frame ("complex_for_command::eval");
 }
 
-void
-tree_complex_for_command::eval_error (void)
-{
-  ::error ("evaluating for command near line %d, column %d",
-	   line (), column ());
-}
-
 tree_command *
 tree_complex_for_command::dup (symbol_table::scope_id scope,
 			       symbol_table::context_id context)
--- a/src/pt-loop.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-loop.h	Tue Aug 05 23:09:32 2008 -0400
@@ -69,8 +69,6 @@
 
   void eval (void);
 
-  void eval_error (void);
-
   tree_expression *condition (void) { return expr; }
 
   tree_statement_list *body (void) { return list; }
@@ -133,8 +131,6 @@
 
   void eval (void);
 
-  void eval_error (void);
-
   tree_command *dup (symbol_table::scope_id scope,
 		     symbol_table::context_id context);
 
@@ -172,8 +168,6 @@
 
   void eval (void);
 
-  void eval_error (void);
-
   tree_expression *left_hand_side (void) { return lhs; }
 
   tree_expression *control_expr (void) { return expr; }
@@ -237,8 +231,6 @@
 
   void eval (void);
 
-  void eval_error (void);
-
   tree_argument_list *left_hand_side (void) { return lhs; }
 
   tree_expression *control_expr (void) { return expr; }
--- a/src/pt-select.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-select.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -124,10 +124,6 @@
 {
   if (list)
     list->eval ();
-
-  if (error_state)
-    ::error ("evaluating if command near line %d, column %d",
-	     line (), column ());
 }
 
 tree_command *
@@ -195,10 +191,7 @@
 		  bool match = equal (val, cell(i,j));
 
 		  if (error_state)
-		    {
-		      eval_error ();
-		      return false;
-		    }
+		    return false;
 		  else if (match)
 		    return true;
 		}
@@ -209,16 +202,11 @@
 	  bool match = equal (val, label_value);
 
 	  if (error_state)
-	    {
-	      eval_error ();
-	      return false;
-	    }
+	    return false;
 	  else
 	    return match;
 	}
     }
-  else
-    eval_error ();
 
   return false;
 }
@@ -239,12 +227,6 @@
   return retval;
 }
 
-void
-tree_switch_case::eval_error (void)
-{
-  ::error ("evaluating switch case label");
-}
-
 tree_switch_case *
 tree_switch_case::dup (symbol_table::scope_id scope,
 		       symbol_table::context_id context)
@@ -313,29 +295,14 @@
     {
       octave_value val = expr->rvalue ();
 
-      if (! error_state)
-	{
-	  if (list)
-	    list->eval (val);
-
-	  if (error_state)
-	    eval_error ();
-	}
-      else
-	eval_error ();
+      if (! error_state && list)
+	list->eval (val);
     }
   else
     ::error ("missing value in switch command near line %d, column %d",
 	     line (), column ());
 }
 
-void
-tree_switch_command::eval_error (void)
-{
-  ::error ("evaluating switch command near line %d, column %d",
-	   line (), column ());
-}
-
 tree_command *
 tree_switch_command::dup (symbol_table::scope_id scope,
 			  symbol_table::context_id context)
--- a/src/pt-select.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-select.h	Tue Aug 05 23:09:32 2008 -0400
@@ -192,8 +192,6 @@
 
   int eval (const octave_value& val);
 
-  void eval_error (void);
-
   tree_expression *case_label (void) { return label; }
 
   tree_statement_list *commands (void) { return list; }
@@ -277,8 +275,6 @@
 
   void eval (void);
 
-  void eval_error (void);
-
   tree_expression *switch_value (void) { return expr; }
 
   tree_switch_case_list *case_list (void) { return list; }
--- a/src/pt-stmt.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-stmt.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -29,6 +29,7 @@
 
 #include "defun.h"
 #include "error.h"
+#include "gripes.h"
 #include "ov.h"
 #include "oct-lvalue.h"
 #include "input.h"
@@ -129,8 +130,7 @@
 	}
       catch (octave_execution_exception)
 	{
-	  octave_exception_state = octave_no_exception;
-	  error ("caught execution error in library function");
+	  gripe_library_execution_error ();
 	}
     }
 
--- a/src/pt-unop.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-unop.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -83,11 +83,7 @@
 
 		  retval = ref.value ();
 		}
-	      else
-		eval_error ();
 	    }
-	  else
-	    eval_error ();
 	}
       else
 	{
@@ -98,28 +94,14 @@
 	      retval = ::do_unary_op (etype, val);
 
 	      if (error_state)
-		{
-		  retval = octave_value ();
-		  eval_error ();
-		}
+		retval = octave_value ();
 	    }
-	  else
-	    eval_error ();
 	}
     }
-  else
-    eval_error ();
 
   return retval;
 }
 
-void
-tree_prefix_expression::eval_error (void)
-{
-  ::error ("evaluating prefix operator `%s' near line %d, column %d",
-	   oper () . c_str (), line (), column ());
-}
-
 tree_expression *
 tree_prefix_expression::dup (symbol_table::scope_id scope,
 			     symbol_table::context_id context)
@@ -181,11 +163,7 @@
 
 		  ref.do_unary_op (etype);
 		}
-	      else
-		eval_error ();
 	    }
-	  else
-	    eval_error ();
 	}
       else
 	{
@@ -196,28 +174,14 @@
 	      retval = ::do_unary_op (etype, val);
 
 	      if (error_state)
-		{
-		  retval = octave_value ();
-		  eval_error ();
-		}
+		retval = octave_value ();
 	    }
-	  else
-	    eval_error ();
 	}
     }
-  else
-    eval_error ();
 
   return retval;
 }
 
-void
-tree_postfix_expression::eval_error (void)
-{
-  ::error ("evaluating postfix operator `%s' near line %d, column %d",
-	   oper () . c_str (), line (), column ());
-}
-
 tree_expression *
 tree_postfix_expression::dup (symbol_table::scope_id scope,
 			      symbol_table::context_id context)
--- a/src/pt-unop.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/pt-unop.h	Tue Aug 05 23:09:32 2008 -0400
@@ -104,8 +104,6 @@
 
   octave_value_list rvalue (int nargout);
 
-  void eval_error (void);
-
   tree_expression *dup (symbol_table::scope_id scope,
 			symbol_table::context_id context);
 
@@ -143,8 +141,6 @@
 
   octave_value_list rvalue (int nargout);
 
-  void eval_error (void);
-
   tree_expression *dup (symbol_table::scope_id scope,
 			symbol_table::context_id context);
 
--- a/src/toplev.cc	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/toplev.cc	Tue Aug 05 23:09:32 2008 -0400
@@ -473,6 +473,41 @@
 }
 
 void
+octave_call_stack::backtrace_error_message (void) const
+{
+  if (error_state > 0)
+    {
+      error_state = -1;
+
+      error ("called from:");
+    }
+
+  if (! cs.empty ())
+    {
+      const call_stack_elt& elt = cs.back ();
+
+      octave_function *fcn = elt.fcn;
+      tree_statement *stmt = elt.stmt;
+
+      std::string fcn_name = "?unknown?";
+
+      if (fcn)
+	{
+	  fcn_name = fcn->fcn_file_name ();
+
+	  if (fcn_name.empty ())
+	    fcn_name = fcn->name ();
+	}
+
+      int line = stmt ? stmt->line () : -1;
+      int column = stmt ? stmt->column () : -1;
+
+      error ("  %s at line %d, column %d",
+	     fcn_name.c_str (), line, column);
+    }
+}
+
+void
 recover_from_exception (void)
 {
   can_interrupt = true;
--- a/src/toplev.h	Tue Aug 05 12:14:33 2008 -0400
+++ b/src/toplev.h	Tue Aug 05 23:09:32 2008 -0400
@@ -380,6 +380,9 @@
   {
     if (cs.size () > 1)
       {
+	if (error_state)
+	  backtrace_error_message ();
+
 	const call_stack_elt& elt = cs.back ();
 	curr_frame = elt.prev;
 	cs.pop_back ();
@@ -389,6 +392,8 @@
   }
 
   void do_clear (void) { cs.clear (); }
+
+  void backtrace_error_message (void) const;
 };
 
 #endif