diff liboctave/util/quit.h @ 27471:fd32c1a9b1bd

revamp error handling In "error" and similar functions that ultimately call it, simply throw an exception that contains information about the error (message, id, stack info) instead of printing an error message immediately and then throwing an exception. The new approach is more flexible and sllows for some simplification of the error message routines as they no longer need feedback from the interpreter to know when to display or buffer messages. It is now the responsibility of any code that catches an execution exception to determine whether and when to display error messages. * quit.h, quit.cc (class frame_info): New class. (execution_exception::m_err_type, execution_exception::m_id, execution_exception::m_message, execution_exception::m_stack_info): New data members. (class execution_exception): Store error type, message, id, and stack info. Provide methods setting and accessing data as needed and for generating stack trace message from stack info. (execution_exception::m_stack_trace): Delete data member. execution_exception::set_stack_trace): Delete method. (execution_exception::set_err_type, execution_exception::err_type, execution_exception::stack_trace, execution_exception::set_identifier, execution_exception::identifier, execution_exception::message, execution_exception::set_stack_info, execution_exception::display): New methods. * call-stack.cc, call-stack.h (call_stack::backtrace_info): New functions. * oct-parse.yy (maybe_print_last_error_message): Delete function and all uses. * pt-eval.h, pt-eval.cc (tree_evaluator::backtrace_info, tree_evaluator::backtrace_message): New functions. (tree_evaluator::backtrace): Now const. (tree_evaluator::visit_unwind_protect_command, tree_evaluator::do_unwind_protect_cleanup_code, tree_evaluator::visit_try_catch_command, tree_evaluator::evalin, tree_evaluator::eval, tree_evaluator::repl, debugger::repl): Save current exception info. * interpreter.h, interpreter.cc (interpreter::handle_exception): New function. Use it in place of direct calls to error_system::save_exception, error_system::display_exception (or execution_exception::display) and interpreter::recover_from_exception, so that we have uniform behavior when responding to an execution exception. * error.h, error.cc (error_system::m_buffer_error_messages, error_system::m_discard_error_messages, error_system::m_in_try_catch): Delete data members and associated functions. Remove all uses. Because the error system no longer displays messages immediately, it does not need to track whether to discard or buffer error messages or know whether error and warning functions are invoked inside of try-catch blocks. Everywhere that catches execution_exceptions must now handle saving the exception state (for lasterror) and displaying the error message and traceback as needed. (): Delete functions and all uses. (error_stack_frame): Delete struct definition. (verror, vpr_where, pr_where_internal, pr_where, maybe_enter_debugger, make_execution_exception, vmessage_with_id, message_with_id, error_system::maybe_enter_debugger, reset_error_handler, error_system::reset): Delete functions and all uses. (error_system::try_option): Delete enum and all uses. (vusage, error_1, error_system::vwarning, error_system::rethrow_error, error_system::interpreter_try): Simplify. (format_message, make_stack_map, error_system::throw_error, error_system::save_exception, error_system::display_exception): New functions. (Ferror): Update for error_system changes.
author John W. Eaton <jwe@octave.org>
date Fri, 04 Oct 2019 01:15:13 -0400
parents d4fdaeaab7f3
children 63b417917f5e
line wrap: on
line diff
--- a/liboctave/util/quit.h	Fri Oct 04 00:30:34 2019 -0400
+++ b/liboctave/util/quit.h	Fri Oct 04 01:15:13 2019 -0400
@@ -28,6 +28,8 @@
 /* The signal header is just needed for the sig_atomic_t type.  */
 #if defined (__cplusplus)
 #  include <csignal>
+#  include <iosfwd>
+#  include <list>
 #  include <string>
 extern "C" {
 #else
@@ -38,12 +40,65 @@
 
 namespace octave
 {
+  class frame_info
+  {
+  public:
+
+    frame_info (void) = default;
+
+    frame_info (const std::string& file_name, const std::string& fcn_name,
+                int line, int column)
+      : m_file_name (file_name), m_fcn_name (fcn_name), m_line (line),
+        m_column (column)
+    { }
+
+    frame_info (const frame_info&) = default;
+
+    frame_info& operator = (const frame_info&) = default;
+
+    ~frame_info (void) = default;
+
+    std::string file_name (void) const { return m_file_name; }
+
+    std::string fcn_name (void) const { return m_fcn_name; }
+
+    int line (void) const { return m_line; }
+
+    int column (void) const { return m_column; }
+
+  private:
+
+    std::string m_file_name;
+
+    std::string m_fcn_name;
+
+    int m_line;
+
+    int m_column;
+  };
+
+  inline bool operator == (const frame_info& a, const frame_info& b)
+  {
+    return (a.file_name () == b.file_name ()
+            && a.fcn_name () == b.fcn_name ()
+            && a.line () == b.line ()
+            && a.column () == b.column ());
+  }
+
   class
   execution_exception
   {
   public:
 
-    execution_exception (void) = default;
+    typedef std::list<frame_info> stack_info_type;
+
+    execution_exception (const std::string& err_type = "error",
+                         const std::string& id = "",
+                         const std::string& message = "unspecified error",
+                         const stack_info_type& stack_info = stack_info_type ())
+      : m_err_type (err_type), m_id (id), m_message (message),
+        m_stack_info (stack_info)
+    { }
 
     execution_exception (const execution_exception&) = default;
 
@@ -51,24 +106,50 @@
 
     ~execution_exception (void) = default;
 
-    virtual void set_stack_trace (const std::string& st)
+    void set_err_type (const std::string& et)
     {
-      m_stack_trace = st;
+      m_err_type = et;
+    }
+
+    std::string err_type (void) const { return m_err_type; }
+
+    virtual std::string stack_trace (void) const;
+
+    void set_identifier (const std::string& id)
+    {
+      m_id = id;
     }
 
-    virtual void set_stack_trace (void)
+    virtual std::string identifier (void) const { return m_id; }
+
+    void set_message (const std::string& msg)
     {
-      m_stack_trace = "";
+      m_message = msg;
     }
 
-    virtual std::string info (void) const
+    virtual std::string message (void) const { return m_message; }
+
+    virtual stack_info_type stack_info (void) const
     {
-      return m_stack_trace;
+      return m_stack_info;
     }
 
+    void set_stack_info (const stack_info_type& stack_info)
+    {
+      m_stack_info = stack_info;
+    }
+
+    virtual void display (std::ostream& os) const;
+
   private:
 
-    std::string m_stack_trace;
+    std::string m_err_type;
+
+    std::string m_id;
+
+    std::string m_message;
+
+    stack_info_type m_stack_info;
   };
 
   class