changeset 27164:6b0c61a5a0f0

move global error configuration and status variables inside a class * error.h, error.cc (error_system): New class. (Vbacktrace_on_warning, Vbeep_on_error, Vdebug_on_caught, Vdebug_on_error, Vdebug_on_warning, Vlast_error_id, Vlast_error_message, Vlast_error_stack, Vlast_warning_id, Vlast_warning_message, Vquiet_warning, Vverbose_warning, buffer_error_messages, discard_error_messages, discard_warning_messages, in_try_catch, warning_options): Move global and file-scope static variables inside error_system class. Change all uses. * interpreter.h, interpreter.cc (m_error_system): New member variable. (get_error_system): New function. * interpreter-private.h, interpreter-private.cc (__get_error_system__): New function.
author John W. Eaton <jwe@octave.org>
date Fri, 31 May 2019 15:49:38 +0000
parents 25d0c4b5a3aa
children 7883e6e71b0a
files libgui/src/m-editor/file-editor-tab.cc libinterp/corefcn/cellfun.cc libinterp/corefcn/error.cc libinterp/corefcn/error.h libinterp/corefcn/graphics.cc libinterp/corefcn/input.cc libinterp/corefcn/interpreter-private.cc libinterp/corefcn/interpreter-private.h libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/utils.cc libinterp/corefcn/variables.cc libinterp/octave-value/cdef-object.cc libinterp/octave-value/ov-oncleanup.cc libinterp/parse-tree/bp-table.cc libinterp/parse-tree/bp-table.h libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt.cc
diffstat 19 files changed, 1022 insertions(+), 439 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/m-editor/file-editor-tab.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libgui/src/m-editor/file-editor-tab.cc	Fri May 31 15:49:38 2019 +0000
@@ -394,15 +394,23 @@
                                    &ok);
         if (ok)     // If cancel, don't change breakpoint condition.
           {
+            interpreter& interp
+              = __get_interpreter__ ("handle_context_menu_break_condition");
+
+            error_system& es = interp.get_error_system ();
+
             try
               {
                 // Suppress error messages on the console.
                 unwind_protect frame;
-                frame.protect_var (buffer_error_messages);
-                buffer_error_messages++;
-
-                bp_table& bptab
-                  = __get_bp_table__ ("handle_context_menu_break_condition");
+
+                int bem = es.buffer_error_messages ();
+                frame.add_method (es, &error_system::set_buffer_error_messages, bem);
+
+                es.buffer_error_messages (bem + 1);
+
+                tree_evaluator& tw = interp.get_evaluator ();
+                bp_table& bptab = tw.get_bp_table ();
 
                 bptab.condition_valid (new_condition.toStdString ());
                 valid = true;
@@ -416,7 +424,7 @@
               }
 
             // In case we repeat, set new prompt.
-            prompt = "ERROR: " + last_error_message () + "\n\ndbstop if";
+            prompt = "ERROR: " + es.last_error_message () + "\n\ndbstop if";
             cond = new_condition;
           }
         else
--- a/libinterp/corefcn/cellfun.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/cellfun.cc	Fri May 31 15:49:38 2019 +0000
@@ -66,7 +66,8 @@
 #include "ov-fcn-handle.h"
 
 static octave_value_list
-get_output_list (octave_idx_type count, octave_idx_type nargout,
+get_output_list (octave::error_system& es,
+                 octave_idx_type count, octave_idx_type nargout,
                  const octave_value_list& inputlist,
                  octave_value& func,
                  octave_value& error_handler)
@@ -96,8 +97,8 @@
       if (error_handler.is_defined ())
         {
           octave_scalar_map msg;
-          msg.assign ("identifier", last_error_id ());
-          msg.assign ("message", last_error_message ());
+          msg.assign ("identifier", es.last_error_id ());
+          msg.assign ("message", es.last_error_message ());
           msg.assign ("index",
                       static_cast<double> (count
                                            + static_cast<octave_idx_type> (1)));
@@ -105,7 +106,7 @@
           octave_value_list errlist = inputlist;
           errlist.prepend (msg);
 
-          buffer_error_messages--;
+          es.buffer_error_messages (es.buffer_error_messages () - 1);
 
           tmp = octave::feval (error_handler, errlist, nargout);
         }
@@ -541,11 +542,15 @@
         }
     }
 
+  octave::error_system& es = interp.get_error_system ();
+
   octave::unwind_protect frame;
-  frame.protect_var (buffer_error_messages);
+
+  int bem = es.buffer_error_messages ();
+  frame.add_method (es, &octave::error_system::set_buffer_error_messages, bem);
 
   if (error_handler.is_defined ())
-    buffer_error_messages++;
+    es.buffer_error_messages (bem + 1);
 
   // Apply functions.
 
@@ -566,7 +571,7 @@
             }
 
           const octave_value_list tmp
-            = get_output_list (count, nargout, inputlist, func,
+            = get_output_list (es, count, nargout, inputlist, func,
                                error_handler);
 
           if (nargout > 0 && tmp.length () < nargout)
@@ -647,7 +652,7 @@
             }
 
           const octave_value_list tmp
-            = get_output_list (count, nargout, inputlist, func,
+            = get_output_list (es, count, nargout, inputlist, func,
                                error_handler);
 
           if (nargout > 0 && tmp.length () < nargout)
@@ -1230,11 +1235,16 @@
             }
         }
 
+      octave::error_system& es = interp.get_error_system ();
+
       octave::unwind_protect frame;
-      frame.protect_var (buffer_error_messages);
+
+      int bem = es.buffer_error_messages ();
+      frame.add_method (es, &octave::error_system::set_buffer_error_messages,
+                        bem);
 
       if (error_handler.is_defined ())
-        buffer_error_messages++;
+        es.buffer_error_messages (bem + 1);
 
       // Apply functions.
 
@@ -1257,7 +1267,7 @@
                 }
 
               const octave_value_list tmp
-                = get_output_list (count, nargout, inputlist, func,
+                = get_output_list (es, count, nargout, inputlist, func,
                                    error_handler);
 
               if (nargout > 0 && tmp.length () < nargout)
@@ -1349,7 +1359,7 @@
                 }
 
               const octave_value_list tmp
-                = get_output_list (count, nargout, inputlist, func,
+                = get_output_list (es, count, nargout, inputlist, func,
                                    error_handler);
 
               if (nargout > 0 && tmp.length () < nargout)
--- a/libinterp/corefcn/error.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/error.cc	Fri May 31 15:49:38 2019 +0000
@@ -52,101 +52,169 @@
 #include "utils.h"
 #include "variables.h"
 
-// TRUE means that Octave will try to beep obnoxiously before printing
-// error messages.
-static bool Vbeep_on_error = false;
-
-// TRUE means that Octave will try to enter the debugger when an error
-// is encountered.  This will also inhibit printing of the normal
-// traceback message (you will only see the top-level error message).
-bool Vdebug_on_error = false;
-
-// TRUE means that Octave will try to enter the debugger when an error
-// is encountered within the 'try' section of a 'try' / 'catch' block.
-bool Vdebug_on_caught = false;
-
-// TRUE means that Octave will try to enter the debugger when a warning
-// is encountered.
-bool Vdebug_on_warning = false;
-
-// TRUE means that Octave will try to display a stack trace when a
-// warning is encountered.
-static bool Vbacktrace_on_warning = true;
-
-// TRUE means that Octave will print a verbose warning.  Currently unused.
-static bool Vverbose_warning;
-
-// TRUE means that Octave will print no warnings, but lastwarn will be updated
-static bool Vquiet_warning = false;
-
-// A structure containing (most of) the current state of warnings.
-static octave_map warning_options;
-
-// The text of the last error message.
-static std::string Vlast_error_message;
-
-// The text of the last warning message.
-static std::string Vlast_warning_message;
-
-// The last warning message id.
-static std::string Vlast_warning_id;
-
-// The last error message id.
-static std::string Vlast_error_id;
-
-// The last file in which an error occurred
-static octave_map Vlast_error_stack;
-
-// Current error state.
-//
-// Valid values:
-//
-//    0: no error
-//    1: an error has occurred
-//
+// This variable is obsolete and always has the value 0.
 int error_state = 0;
 
-// Tell the error handler whether to print messages, or just store
-// them for later.  Used for handling errors in eval() and
-// the 'unwind_protect' statement.
-int buffer_error_messages = 0;
-
-// The number of layers of try / catch blocks we're in.  Used to print
-// "caught error" instead of error when "dbstop if caught error" is on.
-int in_try_catch = 0;
-
-// TRUE means error messages are turned off.
-bool discard_error_messages = false;
-
-// TRUE means warning messages are turned off.
-bool discard_warning_messages = false;
-
 void
 reset_error_handler (void)
 {
-  buffer_error_messages = 0;
-  in_try_catch = 0;
-  discard_error_messages = false;
+  octave::error_system& es
+    = octave::__get_error_system__ ("reset_error_handler");
+
+  es.reset ();
 }
 
-static void
-initialize_warning_options (const std::string& state)
+namespace octave
 {
-  octave_scalar_map initw;
-
-  initw.setfield ("identifier", "all");
-  initw.setfield ("state", state);
-
-  warning_options = initw;
-}
-
-static octave_map
-initialize_last_error_stack (void)
-{
-  octave::call_stack& cs
-    = octave::__get_call_stack__ ("initialize_last_error_stack");
-
-  return cs.empty_backtrace ();
+  static octave_scalar_map
+  init_warning_options (const std::string& state)
+  {
+    octave_scalar_map initw;
+
+    initw.setfield ("identifier", "all");
+    initw.setfield ("state", state);
+
+    return initw;
+  }
+
+  static octave_map
+  init_error_stack (interpreter& interp)
+  {
+    octave::call_stack& cs = interp.get_call_stack ();
+
+    return cs.empty_backtrace ();
+  }
+
+  error_system::error_system (interpreter& interp)
+    : m_interpreter (interp),
+      m_debug_on_error (false),
+      m_debug_on_caught (false),
+      m_debug_on_warning (false),
+      m_buffer_error_messages (0),
+      m_in_try_catch (0),
+      m_discard_error_messages (false),
+      m_discard_warning_messages (false),
+      m_beep_on_error (false),
+      m_backtrace_on_warning (true),
+      m_verbose_warning (false),
+      m_quiet_warning (false),
+      m_warning_options (init_warning_options ("on")),
+      m_last_error_message (),
+      m_last_warning_message (),
+      m_last_warning_id (),
+      m_last_error_id (),
+      m_last_error_stack (init_error_stack (interp))
+  { }
+
+  octave_value
+  error_system::debug_on_error (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_debug_on_error, args, nargout,
+                                  "debug_on_error");
+  }
+
+  octave_value
+  error_system::debug_on_caught (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_debug_on_caught, args, nargout,
+                                  "debug_on_caught");
+  }
+
+  octave_value
+  error_system::debug_on_warning (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_debug_on_warning, args, nargout,
+                                  "debug_on_warning");
+  }
+
+  octave_value
+  error_system::buffer_error_messages (const octave_value_list& args,
+                                        int nargout)
+  {
+    return set_internal_variable (m_buffer_error_messages, args, nargout,
+                                  "buffer_error_messages");
+  }
+
+  octave_value
+  error_system::in_try_catch (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_in_try_catch, args, nargout,
+                                  "in_try_catch");
+  }
+
+  octave_value
+  error_system::discard_error_messages (const octave_value_list& args,
+                                        int nargout)
+  {
+    return set_internal_variable (m_discard_error_messages, args, nargout,
+                                  "discard_error_messages");
+  }
+
+  octave_value
+  error_system::discard_warning_messages (const octave_value_list& args,
+                                          int nargout)
+  {
+    return set_internal_variable (m_discard_warning_messages, args, nargout,
+                                  "discard_warning_messages");
+  }
+
+  octave_value
+  error_system::beep_on_error (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_beep_on_error, args, nargout,
+                                  "beep_on_error");
+  }
+
+  octave_value
+  error_system::backtrace_on_warning (const octave_value_list& args,
+                                      int nargout)
+  {
+    return set_internal_variable (m_backtrace_on_warning, args, nargout,
+                                  "backtrace_on_warning");
+  }
+
+  octave_value
+  error_system::verbose_warning (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_verbose_warning, args, nargout,
+                                  "verbose_warning");
+  }
+
+  octave_value
+  error_system::quiet_warning (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_quiet_warning, args, nargout,
+                                  "quiet_warning");
+  }
+
+  octave_value
+  error_system::last_error_message (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_last_error_message, args, nargout,
+                                  "last_error_message");
+  }
+
+  octave_value
+  error_system::last_warning_message (const octave_value_list& args,
+                                      int nargout)
+  {
+    return set_internal_variable (m_last_warning_message, args, nargout,
+                                  "last_warning_message");
+  }
+
+  octave_value
+  error_system::last_warning_id (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_last_warning_id, args, nargout,
+                                  "last_warning_id");
+  }
+
+  octave_value
+  error_system::last_error_id (const octave_value_list& args, int nargout)
+  {
+    return set_internal_variable (m_last_error_id, args, nargout,
+                                  "last_error_id");
+  }
 }
 
 static void
@@ -154,10 +222,14 @@
         const char *name, const char *id, const char *fmt, va_list args,
         bool with_cfn = false)
 {
-  if (discard_error_messages && ! Vdebug_on_caught)
+  octave::interpreter& interp = octave::__get_interpreter__ ("verror");
+
+  octave::error_system& es = interp.get_error_system ();
+
+  if (es.discard_error_messages () && ! es.debug_on_caught ())
     return;
 
-  if (! buffer_error_messages || Vdebug_on_caught)
+  if (! es.buffer_error_messages () || es.debug_on_caught ())
     octave::flush_stdout ();
 
   // FIXME: we really want to capture the message before it has all the
@@ -170,7 +242,7 @@
 
   std::string base_msg = output_buf.str ();
 
-  bool to_beep_or_not_to_beep_p = Vbeep_on_error;
+  bool to_beep_or_not_to_beep_p = es.beep_on_error ();
 
   std::string msg_string;
 
@@ -179,13 +251,13 @@
 
   if (name)
     {
-      if (in_try_catch && ! strcmp (name, "error"))
+      if (es.in_try_catch () && ! strcmp (name, "error"))
         msg_string += "caught error: ";
       else
         msg_string += std::string (name) + ": ";
     }
 
-  octave::call_stack& cs = octave::__get_call_stack__ ("verror");
+  octave::call_stack& cs = interp.get_call_stack ();
 
   // If with_fcn is specified, we'll attempt to prefix the message with the name
   // of the current executing function.  But we'll do so only if:
@@ -215,18 +287,18 @@
     {
       // This is the first error in a possible series.
 
-      Vlast_error_id = id;
-      Vlast_error_message = base_msg;
+      es.last_error_id (id);
+      es.last_error_message (base_msg);
 
       octave_user_code *fcn = cs.current_user_code ();
 
       if (fcn)
-        Vlast_error_stack = cs.backtrace ();
+        es.last_error_stack (cs.backtrace ());
       else
-        Vlast_error_stack = initialize_last_error_stack ();
+        es.last_error_stack (octave::init_error_stack (interp));
     }
 
-  if (! buffer_error_messages || Vdebug_on_caught)
+  if (! es.buffer_error_messages () || es.debug_on_caught ())
     {
       octave_diary << msg_string;
       os << msg_string;
@@ -350,21 +422,27 @@
 maybe_enter_debugger (octave::execution_exception& e,
                       bool show_stack_trace = false)
 {
-  octave::call_stack& cs = octave::__get_call_stack__ ("maybe_enter_debugger");
-  octave::bp_table& bptab = octave::__get_bp_table__ ("maybe_enter_debugger");
+  octave::interpreter& interp
+    = octave::__get_interpreter__ ("maybe_enter_debugger");
+
+  octave::call_stack& cs = interp.get_call_stack ();
+  octave::tree_evaluator& tw = interp.get_evaluator ();
+  octave::bp_table& bptab = tw.get_bp_table ();
+  octave::error_system& es = interp.get_error_system ();
 
   if ((octave::application::interactive ()
        || octave::application::forced_interactive ())
-      && ((Vdebug_on_error && bptab.debug_on_err (last_error_id ()))
-          || (Vdebug_on_caught && bptab.debug_on_caught (last_error_id ())))
+      && ((es.debug_on_error ()
+           && bptab.debug_on_err (es.last_error_id ()))
+          || (es.debug_on_caught ()
+              && bptab.debug_on_caught (es.last_error_id ())))
       && cs.current_user_code ())
     {
       octave::unwind_protect frame;
-      frame.protect_var (Vdebug_on_error);
-      Vdebug_on_error = false;
-
-      octave::tree_evaluator& tw
-        = octave::__get_evaluator__ ("maybe_enter_debugger");
+
+      frame.add_method (es, &octave::error_system::set_debug_on_error,
+                        es.debug_on_error ());
+      es.debug_on_error (false);
 
       if (show_stack_trace)
         {
@@ -387,7 +465,11 @@
 static void
 vwarning (const char *name, const char *id, const char *fmt, va_list args)
 {
-  if (discard_warning_messages)
+  octave::interpreter& interp = octave::__get_interpreter__ ("vwarning");
+
+  octave::error_system& es = interp.get_error_system ();
+
+  if (es.discard_warning_messages ())
     return;
 
   octave::flush_stdout ();
@@ -408,10 +490,10 @@
 
   msg_string += base_msg + '\n';
 
-  Vlast_warning_id = id;
-  Vlast_warning_message = base_msg;
-
-  if (! Vquiet_warning)
+  es.last_warning_id (id);
+  es.last_warning_message (base_msg);
+
+  if (! es.quiet_warning ())
     {
       octave_diary << msg_string;
 
@@ -518,12 +600,15 @@
                 {
                   verror (true, os, name, id, fmt, args, with_cfn);
 
-                  octave::call_stack& cs
-                    = octave::__get_call_stack__ ("error_1");
+                  octave::interpreter& interp
+                    = octave::__get_interpreter__ ("error_1");
+
+                  octave::call_stack& cs = interp.get_call_stack ();
+                  octave::error_system& es = interp.get_error_system ();
 
                   bool in_user_code = cs.current_user_code () != nullptr;
 
-                  if (in_user_code && ! discard_error_messages)
+                  if (in_user_code && ! es.discard_error_messages ())
                     show_stack_trace = true;
                 }
             }
@@ -652,12 +737,17 @@
   int all_state = -1;
   int id_state = -1;
 
-  octave_idx_type nel = warning_options.numel ();
+  octave::error_system& es
+    = octave::__get_error_system__ ("warning_enabled");
+
+  octave_map opts = es.warning_options ();
+
+  octave_idx_type nel = opts.numel ();
 
   if (nel > 0)
     {
-      Cell identifier = warning_options.contents ("identifier");
-      Cell state = warning_options.contents ("state");
+      Cell identifier = opts.contents ("identifier");
+      Cell state = opts.contents ("state");
 
       bool all_found = false;
       bool id_found = false;
@@ -741,28 +831,30 @@
       else
         vwarning ("warning", id, fmt, args);
 
-      octave::call_stack& cs = octave::__get_call_stack__ ("warning_1");
+      octave::interpreter& interp = octave::__get_interpreter__ ("warning_1");
+
+      octave::call_stack& cs = interp.get_call_stack ();
+      octave::error_system& es = interp.get_error_system ();
 
       bool in_user_code = cs.current_user_code () != nullptr;
 
       if (! fmt_suppresses_backtrace && in_user_code
-          && Vbacktrace_on_warning
-          && ! discard_warning_messages)
+          && es.backtrace_on_warning ()
+          && ! es.discard_warning_messages ())
         pr_where (std::cerr, "warning");
 
-      octave::bp_table& bptab
-        = octave::__get_bp_table__ ("warning_1");
+      octave::tree_evaluator& tw = interp.get_evaluator ();
+      octave::bp_table& bptab = tw.get_bp_table ();
 
       if ((octave::application::interactive ()
            || octave::application::forced_interactive ())
-          && Vdebug_on_warning && in_user_code && bptab.debug_on_warn (id))
+          && es.debug_on_warning () && in_user_code && bptab.debug_on_warn (id))
         {
           octave::unwind_protect frame;
-          frame.protect_var (Vdebug_on_warning);
-          Vdebug_on_warning = false;
-
-          octave::tree_evaluator& tw
-            = octave::__get_evaluator__ ("warning_1");
+
+          frame.add_method (es, &octave::error_system::set_debug_on_warning,
+                            es.debug_on_warning ());
+          es.debug_on_warning (false);
 
           tw.enter_debugger ();
         }
@@ -890,9 +982,11 @@
             && stack.contains ("line")))
     error ("rethrow: STACK struct must contain the fields 'file', 'name', and 'line'");
 
-  Vlast_error_id = id;
-  Vlast_error_message = msg;
-  Vlast_error_stack = stack;
+  octave::error_system& es = octave::__get_error_system__ ("rethrow_error");
+
+  es.last_error_id (id);
+  es.last_error_message (msg);
+  es.last_error_stack (stack);
 
   size_t len = msg.length ();
 
@@ -922,11 +1016,18 @@
 panic (const char *fmt, ...)
 {
   va_list args;
+
   va_start (args, fmt);
-  buffer_error_messages = 0;
-  discard_error_messages = false;
+
+  octave::error_system& es = octave::__get_error_system__ ("panic");
+
+  es.buffer_error_messages (0);
+  es.discard_error_messages (false);
+
   verror (false, std::cerr, "panic", "", fmt, args);
+
   va_end (args);
+
   abort ();
 }
 
@@ -1007,8 +1108,8 @@
   return retval;
 }
 
-DEFUN (rethrow, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (rethrow, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} rethrow (@var{err})
 Reissue a previous error as defined by @var{err}.
 
@@ -1030,7 +1131,7 @@
   std::string msg = err.contents ("message").string_value ();
   std::string id = err.contents ("identifier").string_value ();
 
-  octave_map err_stack = initialize_last_error_stack ();
+  octave_map err_stack = octave::init_error_stack (interp);
 
   if (err.contains ("stack"))
     err_stack = err.contents ("stack").xmap_value ("ERR.STACK must be a struct");
@@ -1238,11 +1339,15 @@
 
   std::string id = id_arg;
 
+  octave::error_system& es = octave::__get_error_system__ ("warning_query");
+
   if (id == "last")
-    id = Vlast_warning_id;
-
-  Cell ident = warning_options.contents ("identifier");
-  Cell state = warning_options.contents ("state");
+    id = es.last_warning_id ();
+
+  octave_map opts = es.warning_options ();
+
+  Cell ident = opts.contents ("identifier");
+  Cell state = opts.contents ("state");
 
   octave_idx_type nel = ident.numel ();
 
@@ -1292,8 +1397,13 @@
 {
   std::string retval = "on";
 
-  Cell ident = warning_options.contents ("identifier");
-  Cell state = warning_options.contents ("state");
+  octave::error_system& es
+    = octave::__get_error_system__ ("default_warning_state");
+
+  octave_map opts = es.warning_options ();
+
+  Cell ident = opts.contents ("identifier");
+  Cell state = opts.contents ("state");
 
   octave_idx_type nel = ident.numel ();
 
@@ -1312,8 +1422,13 @@
 static void
 display_warning_options (std::ostream& os)
 {
-  Cell ident = warning_options.contents ("identifier");
-  Cell state = warning_options.contents ("state");
+  octave::error_system& es
+    = octave::__get_error_system__ ("display_warning_options");
+
+  octave_map opts = es.warning_options ();
+
+  Cell ident = opts.contents ("identifier");
+  Cell state = opts.contents ("state");
 
   octave_idx_type nel = ident.numel ();
 
@@ -1352,8 +1467,13 @@
   if (state != "on" && state != "off" && state != "error")
     error ("invalid warning state: %s", state.c_str ());
 
-  Cell tid = warning_options.contents ("identifier");
-  Cell tst = warning_options.contents ("state");
+  octave::error_system& es
+    = octave::__get_error_system__ ("set_warning_option");
+
+  octave_map opts = es.warning_options ();
+
+  Cell tid = opts.contents ("identifier");
+  Cell tst = opts.contents ("state");
 
   octave_idx_type nel = tid.numel ();
 
@@ -1379,10 +1499,12 @@
           else
             tst(i) = state;
 
-          warning_options.clear ();
-
-          warning_options.assign ("identifier", tid);
-          warning_options.assign ("state", tst);
+          opts.clear ();
+
+          opts.assign ("identifier", tid);
+          opts.assign ("state", tst);
+
+          es.warning_options (opts);
 
           return;
         }
@@ -1396,10 +1518,12 @@
   tid(nel) = ident;
   tst(nel) = state;
 
-  warning_options.clear ();
-
-  warning_options.assign ("identifier", tid);
-  warning_options.assign ("state", tst);
+  opts.clear ();
+
+  opts.assign ("identifier", tid);
+  opts.assign ("state", tst);
+
+  es.warning_options (opts);
 }
 
 DEFMETHOD (warning, interp, args, nargout,
@@ -1529,6 +1653,8 @@
   int nargin = args.length ();
   bool done = false;
 
+  octave::error_system& es = interp.get_error_system ();
+
   if (nargin > 0 && args.all_strings_p ())
     {
       string_vector argv = args.make_argv ("warning");
@@ -1544,7 +1670,7 @@
           // Prepare output structure
           octave_map old_warning_options;
           if (arg2 == "all")
-            old_warning_options = warning_options;
+            old_warning_options = es.warning_options ();
           else
             old_warning_options = octave_map (warning_query (arg2));
 
@@ -1644,7 +1770,7 @@
               tmp.assign ("identifier", id);
               tmp.assign ("state", st);
 
-              warning_options = tmp;
+              es.warning_options (tmp);
 
               done = true;
             }
@@ -1652,7 +1778,7 @@
             {
               if (arg1 != "error")
                 {
-                  Vbacktrace_on_warning = (arg1 == "on");
+                  es.backtrace_on_warning (arg1 == "on");
                   done = true;
                 }
             }
@@ -1660,7 +1786,7 @@
             {
               if (arg1 != "error")
                 {
-                  Vdebug_on_warning = (arg1 == "on");
+                  es.debug_on_warning (arg1 == "on");
                   done = true;
                 }
             }
@@ -1668,7 +1794,7 @@
             {
               if (arg1 != "error")
                 {
-                  Vverbose_warning = (arg1 == "on");
+                  es.verbose_warning (arg1 == "on");
                   done = true;
                 }
             }
@@ -1676,14 +1802,14 @@
             {
               if (arg1 != "error")
                 {
-                  Vquiet_warning = (arg1 == "on");
+                  es.quiet_warning (arg1 == "on");
                   done = true;
                 }
             }
           else
             {
               if (arg2 == "last")
-                arg2 = Vlast_warning_id;
+                arg2 = es.last_warning_id ();
 
               set_warning_option (arg1, arg2);
 
@@ -1696,20 +1822,20 @@
       else if (arg1 == "query")
         {
           if (arg2 == "all")
-            retval = warning_options;
+            retval = es.warning_options ();
           else if (arg2 == "backtrace" || arg2 == "debug"
                    || arg2 == "verbose" || arg2 == "quiet")
             {
               octave_scalar_map tmp;
               tmp.assign ("identifier", arg2);
               if (arg2 == "backtrace")
-                tmp.assign ("state", Vbacktrace_on_warning ? "on" : "off");
+                tmp.assign ("state", es.backtrace_on_warning () ? "on" : "off");
               else if (arg2 == "debug")
-                tmp.assign ("state", Vdebug_on_warning ? "on" : "off");
+                tmp.assign ("state", es.debug_on_warning () ? "on" : "off");
               else if (arg2 == "verbose")
-                tmp.assign ("state", Vverbose_warning ? "on" : "off");
+                tmp.assign ("state", es.verbose_warning () ? "on" : "off");
               else
-                tmp.assign ("state", Vquiet_warning ? "on" : "off");
+                tmp.assign ("state", es.quiet_warning () ? "on" : "off");
 
               retval = tmp;
             }
@@ -1722,7 +1848,7 @@
   else if (nargin == 0)
     {
       if (nargout > 0)
-        retval = warning_options;
+        retval = es.warning_options ();
       else
         display_warning_options (octave_stdout);
 
@@ -1783,7 +1909,7 @@
 
       bool have_fmt = maybe_extract_message_id ("warning", args, nargs, id);
 
-      std::string prev_msg = Vlast_warning_message;
+      std::string prev_msg = es.last_warning_message ();
 
       std::string curr_msg = handle_message (warning_with_id, id.c_str (),
                                              "unspecified warning", nargs,
@@ -1847,7 +1973,10 @@
 void
 initialize_default_warning_state (void)
 {
-  initialize_warning_options ("on");
+  octave::error_system& es
+    = octave::__get_error_system__ ("initialize_default_warning_state");
+
+  es.warning_options (octave::init_warning_options ("on"));
 
   // Most people will want to have the following disabled.
 
@@ -1918,24 +2047,28 @@
   if (nargin > 1)
     print_usage ();
 
+  octave::error_system& es = interp.get_error_system ();
+
   octave_scalar_map err;
 
-  err.assign ("message", Vlast_error_message);
-  err.assign ("identifier", Vlast_error_id);
-
-  err.assign ("stack", octave_value (Vlast_error_stack));
+  err.assign ("message", es.last_error_message ());
+  err.assign ("identifier", es.last_error_id ());
+
+  err.assign ("stack", octave_value (es.last_error_stack ()));
 
   if (nargin == 1)
     {
+      octave::call_stack& cs = interp.get_call_stack ();
+
       if (args(0).is_string ())
         {
           if (args(0).string_value () != "reset")
             error ("lasterror: unrecognized string argument");
 
-          Vlast_error_message = "";
-          Vlast_error_id = "";
-
-          Vlast_error_stack = initialize_last_error_stack ();
+          es.last_error_message ("");
+          es.last_error_id ("");
+
+          es.last_error_stack (cs.empty_backtrace ());
         }
       else if (args(0).isstruct ())
         {
@@ -2002,25 +2135,22 @@
                 }
             }
 
-          Vlast_error_message = new_error_message;
-          Vlast_error_id = new_error_id;
+          es.last_error_message (new_error_message);
+          es.last_error_id (new_error_id);
 
           if (initialize_stack)
-            Vlast_error_stack = initialize_last_error_stack ();
+            es.last_error_stack (cs.empty_backtrace ());
           else if (new_err.contains ("stack"))
             {
               new_err_stack.setfield ("file", new_error_file);
               new_err_stack.setfield ("name", new_error_name);
               new_err_stack.setfield ("line", new_error_line);
               new_err_stack.setfield ("column", new_error_column);
-              Vlast_error_stack = new_err_stack;
+
+              es.last_error_stack (new_err_stack);
             }
           else
-            {
-              octave::call_stack& cs = interp.get_call_stack ();
-
-              Vlast_error_stack = cs.backtrace ();
-            }
+            es.last_error_stack (cs.backtrace ());
         }
       else
         error ("lasterror: argument must be a structure or a string");
@@ -2042,8 +2172,8 @@
 %! assert (y, x);
 */
 
-DEFUN (lasterr, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (lasterr, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {[@var{msg}, @var{msgid}] =} lasterr ()
 @deftypefnx {} {} lasterr (@var{msg})
 @deftypefnx {} {} lasterr (@var{msg}, @var{msgid})
@@ -2063,20 +2193,22 @@
   if (nargin > 2)
     print_usage ();
 
+  octave::error_system& es = interp.get_error_system ();
+
   string_vector argv = args.make_argv ("lasterr");
 
-  std::string prev_error_id = Vlast_error_id;
-  std::string prev_error_message = Vlast_error_message;
+  std::string prev_error_id = es.last_error_id ();
+  std::string prev_error_message = es.last_error_message ();
 
   if (nargin == 2)
     {
-      Vlast_error_id = argv[2];
-      Vlast_error_message = argv[1];
+      es.last_error_id (argv[2]);
+      es.last_error_message (argv[1]);
     }
   else if (nargin == 1)
     {
-      Vlast_error_id = "";
-      Vlast_error_message = argv[1];
+      es.last_error_id ("");
+      es.last_error_message (argv[1]);
     }
 
   if (nargin == 0 || nargout > 0)
@@ -2085,8 +2217,8 @@
     return ovl ();
 }
 
-DEFUN (lastwarn, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (lastwarn, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {[@var{msg}, @var{msgid}] =} lastwarn ()
 @deftypefnx {} {} lastwarn (@var{msg})
 @deftypefnx {} {} lastwarn (@var{msg}, @var{msgid})
@@ -2106,20 +2238,22 @@
   if (nargin > 2)
     print_usage ();
 
+  octave::error_system& es = interp.get_error_system ();
+
   string_vector argv = args.make_argv ("lastwarn");
 
-  std::string prev_warning_id = Vlast_warning_id;
-  std::string prev_warning_message = Vlast_warning_message;
+  std::string prev_warning_id = es.last_warning_id ();
+  std::string prev_warning_message = es.last_warning_message ();
 
   if (nargin == 2)
     {
-      Vlast_warning_id = argv[2];
-      Vlast_warning_message = argv[1];
+      es.last_warning_id (argv[2]);
+      es.last_warning_message (argv[1]);
     }
   else if (nargin == 1)
     {
-      Vlast_warning_id = "";
-      Vlast_warning_message = argv[1];
+      es.last_warning_id ("");
+      es.last_warning_message (argv[1]);
     }
 
   if (nargin == 0 || nargout > 0)
@@ -2128,8 +2262,8 @@
     return ovl ();
 }
 
-DEFUN (beep_on_error, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (beep_on_error, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} beep_on_error ()
 @deftypefnx {} {@var{old_val} =} beep_on_error (@var{new_val})
 @deftypefnx {} {} beep_on_error (@var{new_val}, "local")
@@ -2141,11 +2275,13 @@
 The original variable value is restored when exiting the function.
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (beep_on_error);
+  octave::error_system& es = interp.get_error_system ();
+
+  return es.beep_on_error (args, nargout);
 }
 
-DEFUN (debug_on_error, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (debug_on_error, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} debug_on_error ()
 @deftypefnx {} {@var{old_val} =} debug_on_error (@var{new_val})
 @deftypefnx {} {} debug_on_error (@var{new_val}, "local")
@@ -2161,11 +2297,13 @@
 @seealso{debug_on_warning, debug_on_interrupt}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (debug_on_error);
+  octave::error_system& es = interp.get_error_system ();
+
+  return es.debug_on_error (args, nargout);
 }
 
-DEFUN (debug_on_warning, args, nargout,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (debug_on_warning, interp, args, nargout,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{val} =} debug_on_warning ()
 @deftypefnx {} {@var{old_val} =} debug_on_warning (@var{new_val})
 @deftypefnx {} {} debug_on_warning (@var{new_val}, "local")
@@ -2178,48 +2316,73 @@
 @seealso{debug_on_error, debug_on_interrupt}
 @end deftypefn */)
 {
-  return SET_INTERNAL_VARIABLE (debug_on_warning);
+  octave::error_system& es = interp.get_error_system ();
+
+  return es.debug_on_warning (args, nargout);
 }
 
 std::string
 last_error_message (void)
 {
-  return Vlast_error_message;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_error_message");
+
+  return es.last_error_message ();
 }
 
 std::string
 last_error_id (void)
 {
-  return Vlast_error_id;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_error_id");
+
+  return es.last_error_id ();
 }
 
 octave_map
 last_error_stack (void)
 {
-  return Vlast_error_stack;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_error_stack");
+
+  return es.last_error_stack ();
 }
 
 std::string
 last_warning_message (void)
 {
-  return Vlast_warning_message;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_warning_message");
+
+  return es.last_warning_message ();
 }
 
 std::string
 last_warning_id (void)
 {
-  return Vlast_warning_id;
+  octave::error_system& es
+    = octave::__get_error_system__ ("last_warning_id");
+
+  return es.last_warning_id ();
 }
 
 void
 interpreter_try (octave::unwind_protect& frame)
 {
-  frame.protect_var (buffer_error_messages);
-  frame.protect_var (Vdebug_on_error);
-  frame.protect_var (Vdebug_on_warning);
-
-  buffer_error_messages++;
-  Vdebug_on_error = false;
-  Vdebug_on_warning = false;
-  // leave Vdebug_on_caught as it was, so errors in try/catch are still caught
+  octave::error_system& es
+    = octave::__get_error_system__ ("interpreter_try");
+
+  int bem = es.buffer_error_messages ();
+  frame.add_method (es, &octave::error_system::set_buffer_error_messages, bem);
+  frame.add_method (es, &octave::error_system::set_debug_on_error,
+                    es.debug_on_error ());
+  frame.add_method (es, &octave::error_system::set_debug_on_warning,
+                    es.debug_on_warning ());
+
+  es.buffer_error_messages (bem + 1);
+  es.debug_on_error (false);
+  es.debug_on_warning (false);
+
+  // Leave debug_on_caught as it was, so errors in try/catch are still
+  // caught.
 }
--- a/libinterp/corefcn/error.h	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/error.h	Fri May 31 15:49:38 2019 +0000
@@ -31,7 +31,8 @@
 
 #include "unwind-prot.h"
 
-class octave_map;
+#include "oct-map.h"
+
 class octave_value_list;
 namespace octave
 {
@@ -41,6 +42,7 @@
 #define panic_impossible()                                              \
   panic ("impossible state reached in file '%s' at line %d", __FILE__, __LINE__)
 
+OCTAVE_DEPRECATED (6, "use 'error_system::reset' instead")
 extern OCTINTERP_API void reset_error_handler (void);
 
 extern OCTINTERP_API int warning_enabled (const std::string& id);
@@ -146,57 +148,325 @@
 extern OCTINTERP_API void disable_warning (const std::string& id);
 extern OCTINTERP_API void initialize_default_warning_state (void);
 
-//! TRUE means that Octave will try to enter the debugger when an error
-//! is encountered.  This will also inhibit printing of the normal
-//! traceback message (you will only see the top-level error message).
-
-extern OCTINTERP_API bool Vdebug_on_error;
-
-//! TRUE means that Octave will try to enter the debugger when an error
-//! is encountered within the 'try' section of a 'try' / 'catch' block.
-
-extern OCTINTERP_API bool Vdebug_on_caught;
-
-//! TRUE means that Octave will try to enter the debugger when a warning
-//! is encountered.
-
-extern OCTINTERP_API bool Vdebug_on_warning;
-
-//! Current error state.
-
 OCTAVE_DEPRECATED (6, "this variable is obsolete and always has the value 0")
 extern OCTINTERP_API int error_state;
 
-//! Tell the error handler whether to print messages, or just store
-//! them for later.  Used for handling errors in eval() and
-//! the 'unwind_protect' statement.
-
-extern OCTINTERP_API int buffer_error_messages;
-
-//! The number of layers of try / catch blocks we're in.  Used to print
-//! "caught error" instead of "error" when "dbstop if caught error" is on.
-
-extern OCTINTERP_API int in_try_catch;
-
-//! TRUE means error messages are turned off.
-
-extern OCTINTERP_API bool discard_error_messages;
-
-//! TRUE means warning messages are turned off.
-
-extern OCTINTERP_API bool discard_warning_messages;
-
-//! Helper functions to pass last error and warning messages and ids.
-//! @{
-
-extern OCTINTERP_API std::string last_error_message (void);
-extern OCTINTERP_API std::string last_error_id (void);
-extern OCTINTERP_API octave_map last_error_stack (void);
-extern OCTINTERP_API std::string last_warning_message (void);
-extern OCTINTERP_API std::string last_warning_id (void);
-
-//! @}
-
 extern OCTINTERP_API void interpreter_try (octave::unwind_protect&);
 
+namespace octave
+{
+  class error_system
+  {
+  public:
+
+    error_system (interpreter& interp);
+
+    error_system (const error_system&) = delete;
+
+    error_system& operator = (const error_system&) = delete;
+
+    ~error_system (void) = default;
+
+    void reset (void)
+    {
+      m_buffer_error_messages = 0;
+      m_in_try_catch = 0;
+      m_discard_error_messages = false;
+    }
+
+    octave_value debug_on_error (const octave_value_list& args, int nargout);
+
+    void set_debug_on_error (bool flag) { m_debug_on_error = flag; }
+
+    bool debug_on_error (void) const { return m_debug_on_error; }
+
+    bool debug_on_error (bool flag)
+    {
+      bool val = m_debug_on_error;
+      m_debug_on_error = flag;
+      return val;
+    }
+
+    octave_value debug_on_caught (const octave_value_list& args, int nargout);
+
+    void set_debug_on_caught (bool flag) { m_debug_on_caught = flag; }
+
+    bool debug_on_caught (void) const { return m_debug_on_caught; }
+
+    bool debug_on_caught (bool flag)
+    {
+      bool val = m_debug_on_caught;
+      m_debug_on_caught = flag;
+      return val;
+    }
+
+    octave_value debug_on_warning (const octave_value_list& args, int nargout);
+
+    void set_debug_on_warning (bool flag) { m_debug_on_warning = flag; }
+
+    bool debug_on_warning (void) const { return m_debug_on_warning; }
+
+    bool debug_on_warning (bool flag)
+    {
+      bool val = m_debug_on_warning;
+      m_debug_on_warning = flag;
+      return val;
+    }
+
+    octave_value buffer_error_messages (const octave_value_list& args, int nargout);
+
+    void set_buffer_error_messages (int val) { m_buffer_error_messages = val; }
+
+    int buffer_error_messages (void) const { return m_buffer_error_messages; }
+
+    int buffer_error_messages (int new_val)
+    {
+      int val = m_buffer_error_messages;
+      m_buffer_error_messages = new_val;
+      return val;
+    }
+
+    octave_value in_try_catch (const octave_value_list& args, int nargout);
+
+    void set_in_try_catch (int val) { m_in_try_catch = val; }
+
+    int in_try_catch (void) const { return m_in_try_catch; }
+
+    int in_try_catch (int new_val)
+    {
+      int val = m_in_try_catch;
+      m_in_try_catch = new_val;
+      return val;
+    }
+
+    octave_value discard_error_messages (const octave_value_list& args, int nargout);
+
+    void set_discard_error_messages (bool flag) { m_discard_error_messages = flag; }
+
+    bool discard_error_messages (void) const { return m_discard_error_messages; }
+
+    bool discard_error_messages (bool flag)
+    {
+      bool val = m_discard_error_messages;
+      m_discard_error_messages = flag;
+      return val;
+    }
+
+    octave_value discard_warning_messages (const octave_value_list& args, int nargout);
+
+    void set_discard_warning_messages (bool flag) { m_discard_warning_messages = flag; }
+
+    bool discard_warning_messages (void) const { return m_discard_warning_messages; }
+
+    bool discard_warning_messages (bool flag)
+    {
+      bool val = m_discard_warning_messages;
+      m_discard_warning_messages = flag;
+      return val;
+    }
+
+    octave_value beep_on_error (const octave_value_list& args, int nargout);
+
+    void set_beep_on_error (bool flag) { m_beep_on_error = flag; }
+
+    bool beep_on_error (void) const { return m_beep_on_error; }
+
+    bool beep_on_error (bool flag)
+    {
+      bool val = m_beep_on_error;
+      m_beep_on_error = flag;
+      return val;
+    }
+
+    octave_value backtrace_on_warning (const octave_value_list& args, int nargout);
+
+    void set_backtrace_on_warning (bool flag) { m_backtrace_on_warning = flag; }
+
+    bool backtrace_on_warning (void) const { return m_backtrace_on_warning; }
+
+    bool backtrace_on_warning (bool flag)
+    {
+      bool val = m_backtrace_on_warning;
+      m_backtrace_on_warning = flag;
+      return val;
+    }
+
+    octave_value verbose_warning (const octave_value_list& args, int nargout);
+
+    void set_verbose_warning (bool flag) { m_verbose_warning = flag; }
+
+    bool verbose_warning (void) const { return m_verbose_warning; }
+
+    bool verbose_warning (bool flag)
+    {
+      bool val = m_verbose_warning;
+      m_verbose_warning = flag;
+      return val;
+    }
+
+    octave_value quiet_warning (const octave_value_list& args, int nargout);
+
+    void set_quiet_warning (bool flag) { m_quiet_warning = flag; }
+
+    bool quiet_warning (void) const { return m_quiet_warning; }
+
+    bool quiet_warning (bool flag)
+    {
+      bool val = m_quiet_warning;
+      m_quiet_warning = flag;
+      return val;
+    }
+
+    octave_map warning_options (void) const { return m_warning_options; }
+
+    void set_warning_options (const octave_map& val) { m_warning_options = val; }
+
+    octave_map warning_options (const octave_map& new_val)
+    {
+      octave_map val = m_warning_options;
+      m_warning_options = new_val;
+      return val;
+    }
+
+    octave_value last_error_message (const octave_value_list& args, int nargout);
+
+    void set_last_error_message (const std::string& val) { m_last_error_message = val; }
+
+    std::string last_error_message (void) const { return m_last_error_message; }
+
+    std::string last_error_message (const std::string& s)
+    {
+      std::string val = m_last_error_message;
+      m_last_error_message = s;
+      return val;
+    }
+
+    octave_value last_warning_message (const octave_value_list& args, int nargout);
+
+    void set_last_warning_message (const std::string& val) { m_last_warning_message = val; }
+
+    std::string last_warning_message (void) const { return m_last_warning_message; }
+
+    std::string last_warning_message (const std::string& s)
+    {
+      std::string val = m_last_warning_message;
+      m_last_warning_message = s;
+      return val;
+    }
+
+    octave_value last_warning_id (const octave_value_list& args, int nargout);
+
+    void set_last_warning_id (const std::string& val) { m_last_warning_id = val; }
+
+    std::string last_warning_id (void) const { return m_last_warning_id; }
+
+    std::string last_warning_id (const std::string& s)
+    {
+      std::string val = m_last_warning_id;
+      m_last_warning_id = s;
+      return val;
+    }
+
+    octave_value last_error_id (const octave_value_list& args, int nargout);
+
+    void set_last_error_id (const std::string& val) { m_last_error_id = val; }
+
+    std::string last_error_id (void) const { return m_last_error_id; }
+
+    std::string last_error_id (const std::string& s)
+    {
+      std::string val = m_last_error_id;
+      m_last_error_id = s;
+      return val;
+    }
+
+    void set_last_error_stack (const octave_map& val)
+    {
+      m_last_error_stack = val;
+    }
+
+    octave_map last_error_stack (void) const { return m_last_error_stack; }
+
+    octave_map last_error_stack (const octave_map& new_val)
+    {
+      octave_map val = m_last_error_stack;
+      m_last_error_stack = new_val;
+      return val;
+    }
+
+  private:
+
+    interpreter& m_interpreter;
+
+    //! TRUE means that Octave will try to enter the debugger when an error
+    //! is encountered.  This will also inhibit printing of the normal
+    //! traceback message (you will only see the top-level error message).
+
+    bool m_debug_on_error;
+
+    //! TRUE means that Octave will try to enter the debugger when an error
+    //! is encountered within the 'try' section of a 'try' / 'catch' block.
+
+    bool m_debug_on_caught;
+
+    //! TRUE means that Octave will try to enter the debugger when a warning
+    //! is encountered.
+
+    bool m_debug_on_warning;
+
+    //! Tell the error handler whether to print messages, or just store
+    //! them for later.  Used for handling errors in eval() and
+    //! the 'unwind_protect' statement.
+
+    int m_buffer_error_messages;
+
+    //! The number of layers of try / catch blocks we're in.  Used to print
+    //! "caught error" instead of "error" when "dbstop if caught error" is on.
+
+    int m_in_try_catch;
+
+    //! TRUE means error messages are turned off.
+
+    bool m_discard_error_messages;
+
+    //! TRUE means warning messages are turned off.
+
+    bool m_discard_warning_messages;
+
+    //! TRUE means that Octave will try to beep obnoxiously before
+    //! printing error messages.
+    bool m_beep_on_error;
+
+    //! TRUE means that Octave will try to display a stack trace when a
+    //! warning is encountered.
+    bool m_backtrace_on_warning;
+
+    //! TRUE means that Octave will print a verbose warning.  Currently
+    //! unused.
+    bool m_verbose_warning;
+
+    //! TRUE means that Octave will print no warnings, but lastwarn will
+    //! be updated
+    bool m_quiet_warning;
+
+    //! A structure containing (most of) the current state of warnings.
+    octave_map m_warning_options;
+
+    //! The text of the last error message.
+    std::string m_last_error_message;
+
+    //! The text of the last warning message.
+    std::string m_last_warning_message;
+
+    //! The last warning message id.
+    std::string m_last_warning_id;
+
+    //! The last error message id.
+    std::string m_last_error_id;
+
+    //! The last file in which an error occurred.
+    octave_map m_last_error_stack;
+  };
+}
+
 #endif
--- a/libinterp/corefcn/graphics.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/graphics.cc	Fri May 31 15:49:38 2019 +0000
@@ -3570,13 +3570,22 @@
 
       octave::unwind_protect frame;
 
-      frame.protect_var (discard_error_messages);
-      frame.protect_var (Vdebug_on_error);
-      frame.protect_var (Vdebug_on_warning);
-
-      discard_error_messages = true;
-      Vdebug_on_error = false;
-      Vdebug_on_warning = false;
+      octave::error_system& es
+        = octave::__get_error_system__ ("base_graphics_object::remove_all_listeners");
+
+      // Almost the same as interpreter_try but discard instead of
+      // buffer error messages.
+
+      frame.add_method (es, &octave::error_system::set_discard_error_messages,
+                        es.discard_error_messages ());
+      frame.add_method (es, &octave::error_system::set_debug_on_error,
+                        es.debug_on_error ());
+      frame.add_method (es, &octave::error_system::set_debug_on_warning,
+                        es.debug_on_warning ());
+
+      es.discard_error_messages (true);
+      es.debug_on_error (false);
+      es.debug_on_warning (false);
 
       try
         {
@@ -11720,6 +11729,11 @@
       // Copy CB because "function_value" method is non-const.
       octave_value cb = cb_arg;
 
+      octave::interpreter& interp
+        = octave::__get_interpreter__ ("gh_manager::do_execute_callback");
+
+      octave::error_system& es = interp.get_error_system ();
+
       if (cb.is_function ())
         fcn = cb.function_value ();
       else if (cb.is_function_handle ())
@@ -11731,16 +11745,16 @@
 
           try
             {
-              octave::interpreter& interp
-                = octave::__get_interpreter__ ("gh_manager::do_execute_callback");
-
               interp.eval_string (s, false, status, 0);
             }
           catch (octave::execution_exception&)
             {
               std::cerr << "execution error in graphics callback function"
                         << std::endl;
-              Flasterr (ovl ("execution error in graphics callback function"));
+
+              es.last_error_id ("");
+              es.last_error_message ("execution error in graphics callback function");
+
               octave::interpreter::recover_from_exception ();
             }
         }
@@ -11775,7 +11789,10 @@
           {
             std::cerr << "execution error in graphics callback function"
                       << std::endl;
-            Flasterr (ovl ("execution error in graphics callback function"));
+
+            es.last_error_id ("");
+            es.last_error_message ("execution error in graphics callback function");
+
             octave::interpreter::recover_from_exception ();
           }
 
--- a/libinterp/corefcn/input.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/input.cc	Fri May 31 15:49:38 2019 +0000
@@ -187,13 +187,17 @@
           {
             int parse_status;
 
+            error_system& es = interp.get_error_system ();
+
             unwind_protect frame;
 
-            frame.protect_var (discard_error_messages);
-            frame.protect_var (discard_warning_messages);
+            frame.add_method (es, &error_system::set_discard_error_messages,
+                              es.discard_error_messages ());
+            frame.add_method (es, &error_system::set_discard_warning_messages,
+                              es.discard_warning_messages ());
 
-            discard_error_messages = true;
-            discard_warning_messages = true;
+            es.discard_error_messages (true);
+            es.discard_warning_messages (true);
 
             try
               {
--- a/libinterp/corefcn/interpreter-private.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/interpreter-private.cc	Fri May 31 15:49:38 2019 +0000
@@ -67,6 +67,13 @@
     return interp.get_dynamic_loader ();
   }
 
+  error_system& __get_error_system__ (const std::string& who)
+  {
+    interpreter& interp = __get_interpreter__ (who);
+
+    return interp.get_error_system ();
+  }
+
   help_system& __get_help_system__ (const std::string& who)
   {
     interpreter& interp = __get_interpreter__ (who);
--- a/libinterp/corefcn/interpreter-private.h	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/interpreter-private.h	Fri May 31 15:49:38 2019 +0000
@@ -37,6 +37,7 @@
   class cdef_manager;
   class child_list;
   class dynamic_loader;
+  class error_system;
   class gtk_manager;
   class help_system;
   class history_system;
@@ -52,6 +53,8 @@
 
   extern dynamic_loader& __get_dynamic_loader__ (const std::string& who);
 
+  extern error_system& __get_error_system__ (const std::string& who);
+
   extern help_system& __get_help_system__ (const std::string& who);
 
   extern history_system& __get_history_system__ (const std::string& who);
--- a/libinterp/corefcn/interpreter.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/interpreter.cc	Fri May 31 15:49:38 2019 +0000
@@ -362,6 +362,7 @@
     : m_app_context (app_context),
       m_environment (),
       m_settings (),
+      m_error_system (*this),
       m_help_system (*this),
       m_input_system (*this),
       m_output_system (*this),
@@ -996,19 +997,23 @@
     {                                                                   \
       try                                                               \
         {                                                               \
-          unwind_protect frame;                                 \
+          unwind_protect frame;                                         \
                                                                         \
-          frame.protect_var (Vdebug_on_error);                          \
-          frame.protect_var (Vdebug_on_warning);                        \
+          frame.add_method (m_error_system,                             \
+                            &error_system::set_debug_on_error,          \
+                            m_error_system.debug_on_error ());          \
+          frame.add_method (m_error_system,                             \
+                            &error_system::set_debug_on_warning,        \
+                            m_error_system.debug_on_warning ());        \
                                                                         \
-          Vdebug_on_error = false;                                      \
-          Vdebug_on_warning = false;                                    \
+          m_error_system.debug_on_error (false);                        \
+          m_error_system.debug_on_warning (false);                      \
                                                                         \
           F ARGS;                                                       \
         }                                                               \
-      OCTAVE_IGNORE_EXCEPTION (const exit_exception&)           \
-      OCTAVE_IGNORE_EXCEPTION (const interrupt_exception&)      \
-      OCTAVE_IGNORE_EXCEPTION (const execution_exception&)      \
+      OCTAVE_IGNORE_EXCEPTION (const exit_exception&)                   \
+      OCTAVE_IGNORE_EXCEPTION (const interrupt_exception&)              \
+      OCTAVE_IGNORE_EXCEPTION (const execution_exception&)              \
       OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&)                   \
     }                                                                   \
   while (0)
@@ -1029,7 +1034,7 @@
 
         atexit_functions.pop_front ();
 
-        OCTAVE_SAFE_CALL (reset_error_handler, ());
+        OCTAVE_SAFE_CALL (m_error_system.reset, ());
 
         OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));
 
@@ -1685,7 +1690,7 @@
 
     m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%");
 
-    Fbeep_on_error (octave_value (true));
+    m_error_system.beep_on_error (true);
     Fconfirm_recursive_rmdir (octave_value (false));
 
     Fdisable_diagonal_matrix (octave_value (true));
--- a/libinterp/corefcn/interpreter.h	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/interpreter.h	Fri May 31 15:49:38 2019 +0000
@@ -35,6 +35,7 @@
 #include "cdef-manager.h"
 #include "dynamic-ld.h"
 #include "environment.h"
+#include "error.h"
 #include "gtk-manager.h"
 #include "help.h"
 #include "input.h"
@@ -160,6 +161,11 @@
       return m_settings;
     }
 
+    error_system& get_error_system (void)
+    {
+      return m_error_system;
+    }
+
     help_system& get_help_system (void)
     {
       return m_help_system;
@@ -414,6 +420,8 @@
 
     settings m_settings;
 
+    error_system m_error_system;
+
     help_system m_help_system;
 
     input_system m_input_system;
--- a/libinterp/corefcn/utils.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/utils.cc	Fri May 31 15:49:38 2019 +0000
@@ -1344,8 +1344,8 @@
   }
 }
 
-DEFUN (isindex, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (isindex, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} isindex (@var{ind})
 @deftypefnx {} {} isindex (@var{ind}, @var{n})
 Return true if @var{ind} is a valid index.
@@ -1373,10 +1373,13 @@
 
   octave_value retval;
 
+  octave::error_system& es = interp.get_error_system ();
+
   octave::unwind_protect frame;
 
-  frame.protect_var (discard_error_messages);
-  discard_error_messages = true;
+  frame.add_method (es, &octave::error_system::set_discard_error_messages,
+                    es.discard_error_messages ());
+  es.discard_error_messages (true);
 
   try
     {
--- a/libinterp/corefcn/variables.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/corefcn/variables.cc	Fri May 31 15:49:38 2019 +0000
@@ -1396,27 +1396,31 @@
 void
 maybe_missing_function_hook (const std::string& name)
 {
+  octave::interpreter& interp
+    = octave::__get_interpreter__ ("maybe_missing_function_hook");
+
+  octave::error_system& es = interp.get_error_system ();
+
   // Don't do this if we're handling errors.
-  if (buffer_error_messages == 0 && ! Vmissing_function_hook.empty ())
-    {
-      octave::symbol_table& symtab
-        = octave::__get_symbol_table__ ("maybe_missing_function_hook");
+  if (es.buffer_error_messages () || Vmissing_function_hook.empty ())
+    return;
 
-      octave_value val = symtab.find_function (Vmissing_function_hook);
+  octave::symbol_table& symtab = interp.get_symbol_table ();
+
+  octave_value val = symtab.find_function (Vmissing_function_hook);
 
-      if (val.is_defined ())
-        {
-          // Ensure auto-restoration.
-          octave::unwind_protect frame;
-          frame.protect_var (Vmissing_function_hook);
+  if (val.is_defined ())
+    {
+      // Ensure auto-restoration.
+      octave::unwind_protect frame;
+      frame.protect_var (Vmissing_function_hook);
 
-          // Clear the variable prior to calling the function.
-          const std::string func_name = Vmissing_function_hook;
-          Vmissing_function_hook.clear ();
+      // Clear the variable prior to calling the function.
+      const std::string func_name = Vmissing_function_hook;
+      Vmissing_function_hook.clear ();
 
-          // Call.
-          octave::feval (func_name, octave_value (name));
-        }
+      // Call.
+      octave::feval (func_name, octave_value (name));
     }
 }
 
--- a/libinterp/octave-value/cdef-object.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/octave-value/cdef-object.cc	Fri May 31 15:49:38 2019 +0000
@@ -29,6 +29,7 @@
 #include "cdef-property.h"
 #include "cdef-utils.h"
 #include "interpreter.h"
+#include "interpreter-private.h"
 #include "ov-classdef.h"
 
 // Define to 1 to enable debugging statements.
@@ -79,7 +80,11 @@
           }
         catch (const execution_exception&)
           {
-            std::string msg = last_error_message ();
+            octave::error_system& es
+              = octave::__get_error_system__ ("cdef_object::release");
+
+            std::string msg = es.last_error_message ();
+
             warning ("error caught while executing handle class delete method:\n%s\n",
                      msg.c_str ());
 
--- a/libinterp/octave-value/ov-oncleanup.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/octave-value/ov-oncleanup.cc	Fri May 31 15:49:38 2019 +0000
@@ -26,6 +26,7 @@
 
 #include "defun.h"
 #include "interpreter.h"
+#include "interpreter-private.h"
 #include "ov-oncleanup.h"
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
@@ -175,7 +176,11 @@
     }
   catch (const octave::execution_exception&)
     {
-      std::string msg = last_error_message ();
+      octave::error_system& es
+        = octave::__get_error_system__ ("octave_oncleanup::call_object_destructor");
+
+      std::string msg = es.last_error_message ();
+
       warning ("onCleanup: error caught while executing cleanup function:\n%s\n",
                msg.c_str ());
 
--- a/libinterp/parse-tree/bp-table.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/parse-tree/bp-table.cc	Fri May 31 15:49:38 2019 +0000
@@ -57,13 +57,16 @@
 
   void bp_table::dbclear_all_signals (void)
   {
-    Vdebug_on_error = false;
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
+    es.debug_on_error (false);
     bp_table::m_errors_that_stop.clear ();
 
-    Vdebug_on_caught = false;
+    es.debug_on_caught (false);
     bp_table::m_caught_that_stop.clear ();
 
-    Vdebug_on_warning = false;
+    es.debug_on_warning (false);
     bp_table::m_warnings_that_stop.clear ();
 
     Vdebug_on_interrupt = false;
@@ -74,6 +77,9 @@
 
   void bp_table::dbstop_process_map_args (const octave_map& mv)
   {
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
     // process errs
     // why so many levels of indirection needed?
     bool fail = false;
@@ -84,7 +90,7 @@
       {
         Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
         if (W.isempty () || W(0).isempty ())
-          Vdebug_on_error = 1;    // like "dbstop if error" with no identifier
+          es.debug_on_error (true);    // like "dbstop if error" with no identifier
         else if (! W(0).iscell ())
           fail = true;
         else
@@ -93,7 +99,7 @@
             for (int i = 0; i < V.numel (); i++)
               {
                 m_errors_that_stop.insert (V(i).string_value ());
-                Vdebug_on_error = 1;
+                es.debug_on_error (true);
               }
           }
       }
@@ -111,7 +117,7 @@
       {
         Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
         if (W.isempty () || W(0).isempty ())
-          Vdebug_on_caught = 1;    // like "dbstop if caught error" with no ID
+          es.debug_on_caught (true);    // like "dbstop if caught error" with no ID
         else if (! W(0).iscell ())
           fail = true;
         else
@@ -120,7 +126,7 @@
             for (int i = 0; i < V.numel (); i++)
               {
                 m_caught_that_stop.insert (V(i).string_value ());
-                Vdebug_on_caught = 1;
+                es.debug_on_caught (true);
               }
           }
       }
@@ -138,7 +144,7 @@
       {
         Array<octave_value> W = U.index (static_cast<octave_idx_type> (0));
         if (W.isempty () || W(0).isempty ())
-          Vdebug_on_warning = 1;    // like "dbstop if warning" with no identifier
+          es.debug_on_warning (true);    // like "dbstop if warning" with no identifier
         else if (! W(0).iscell ())
           fail = true;
         else
@@ -147,7 +153,7 @@
             for (int i = 0; i < V.numel (); i++)
               {
                 m_warnings_that_stop.insert (V(i).string_value ());
-                Vdebug_on_warning = 1;
+                es.debug_on_warning (true);
               }
           }
       }
@@ -157,7 +163,7 @@
 
     // process interrupt
     if (mv.isfield ("intr"))
-      Vdebug_on_interrupt = 1;
+      Vdebug_on_interrupt = true;
   }
 
   // Insert a breakpoint in function fcn at line within file fname,
@@ -415,28 +421,23 @@
             else    // stop on event (error, warning, interrupt, NaN/inf)
               {
                 std::string condition = args(pos).string_value ();
-                int on_off = ! strcmp(who, "dbstop");
+                bool on_off = ! strcmp (who, "dbstop");
 
-                // list of error/warning IDs to update
-                std::set<std::string> *id_list = nullptr;
-                bool *stop_flag = nullptr;         // Vdebug_on_... flag
+                // FIXME: the following seems a bit messy in the way it
+                // duplicates checks on CONDITION.
 
                 if (condition == "error")
-                  {
-                    id_list = &m_errors_that_stop;
-                    stop_flag = &Vdebug_on_error;
-                  }
+                  process_id_list (who, condition, args, nargin, pos, on_off,
+                                   m_errors_that_stop);
                 else if (condition == "warning")
-                  {
-                    id_list = &m_warnings_that_stop;
-                    stop_flag = &Vdebug_on_warning;
-                  }
+                  process_id_list (who, condition, args, nargin, pos, on_off,
+                                   m_warnings_that_stop);
                 else if (condition == "caught" && nargin > pos+1
                          && args(pos+1).string_value () == "error")
                   {
-                    id_list = &m_caught_that_stop;
-                    stop_flag = &Vdebug_on_caught;
                     pos++;
+                    process_id_list (who, condition, args, nargin, pos, on_off,
+                                     m_caught_that_stop);
                   }
                 else if (condition == "interrupt")
                   {
@@ -456,38 +457,6 @@
                   error ("%s: invalid condition %s",
                          who, condition.c_str ());
 
-                // process ID list for "dbstop if error <error_ID>" etc
-                if (id_list)
-                  {
-                    pos++;
-                    if (pos < nargin)       // only affect a single error ID
-                      {
-                        if (! args(pos).is_string () || nargin > pos+1)
-                          error ("%s: ID must be a single string", who);
-                        else if (on_off == 1)
-                          {
-                            id_list->insert (args(pos).string_value ());
-                            *stop_flag = true;
-                          }
-                        else
-                          {
-                            id_list->erase (args(pos).string_value ());
-                            if (id_list->empty ())
-                              *stop_flag = false;
-                          }
-                      }
-                    else   // unqualified.  Turn all on or off
-                      {
-                        id_list->clear ();
-                        *stop_flag = on_off;
-                        if (stop_flag == &Vdebug_on_error)
-                          {
-                            // Matlab stops on both.
-                            Vdebug_on_interrupt = on_off;
-                          }
-                      }
-                  }
-
                 pos = nargin;
               }
             break;
@@ -514,6 +483,59 @@
     %! assert (s.errs, {"Octave:undefined-function"});
   */
 
+  void bp_table::set_stop_flag (const char *who, const std::string& condition,
+                                bool on_off)
+  {
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
+    if (condition == "error")
+      es.debug_on_error (on_off);
+    else if (condition == "warning")
+      es.debug_on_warning (on_off);
+    else if (condition == "caught")
+      es.debug_on_caught (on_off);
+    else
+      error ("%s: internal error in set_stop_flag", who);
+  }
+
+  void bp_table::process_id_list (const char *who,
+                                  const std::string& condition,
+                                  const octave_value_list& args,
+                                  int nargin, int& pos, bool on_off,
+                                  std::set<std::string>& id_list)
+  {
+    pos++;
+
+    if (nargin > pos)       // only affect a single error ID
+      {
+        if (! args(pos).is_string () || nargin > pos+1)
+          error ("%s: ID must be a single string", who);
+        else if (on_off)
+          {
+            id_list.insert (args(pos).string_value ());
+            set_stop_flag (who, condition, true);
+          }
+        else
+          {
+            id_list.erase (args(pos).string_value ());
+            if (id_list.empty ())
+              set_stop_flag (who, condition, false);
+          }
+      }
+    else   // unqualified.  Turn all on or off
+      {
+        id_list.clear ();
+        set_stop_flag (who, condition, on_off);
+
+        if (condition == "error")
+          {
+            // Matlab stops on both.
+            Vdebug_on_interrupt = on_off;
+          }
+      }
+  }
+
   // Return the sub/nested/main function of MAIN_FCN that contains
   // line number LINENO of the source file.
   // If END_LINE != 0, *END_LINE is set to last line of the returned function.
@@ -861,8 +883,11 @@
   {
     octave_map retval;
 
+    interpreter& interp = m_evaluator.get_interpreter ();
+    error_system& es = interp.get_error_system ();
+
     // print dbstop if error information
-    if (Vdebug_on_error)
+    if (es.debug_on_error ())
       {
         if (m_errors_that_stop.empty ())
           {
@@ -889,7 +914,7 @@
       }
 
     // print dbstop if caught error information
-    if (Vdebug_on_caught)
+    if (es.debug_on_caught ())
       {
         if (m_caught_that_stop.empty ())
           {
@@ -916,7 +941,7 @@
       }
 
     // print dbstop if warning information
-    if (Vdebug_on_warning)
+    if (es.debug_on_warning ())
       {
         if (m_warnings_that_stop.empty ())
           {
--- a/libinterp/parse-tree/bp-table.h	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/parse-tree/bp-table.h	Fri May 31 15:49:38 2019 +0000
@@ -143,6 +143,14 @@
     std::set<std::string> m_caught_that_stop;
     std::set<std::string> m_warnings_that_stop;
 
+    void set_stop_flag (const char *who, const std::string& condition,
+                        bool on_off);
+
+    void process_id_list (const char *who, const std::string& condition,
+                          const octave_value_list& args,
+                          int nargin, int& pos, bool on_off,
+                          std::set<std::string>& id_list);
+
     bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname,
                            const intmap& line, const std::string& condition,
                            intmap& retval);
--- a/libinterp/parse-tree/oct-parse.yy	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/parse-tree/oct-parse.yy	Fri May 31 15:49:38 2019 +0000
@@ -2500,13 +2500,18 @@
   {
     tree_expression *retval = nullptr;
 
+    interpreter& interp = __get_interpreter__ ("finish_colon_expression");
+    error_system& es = interp.get_error_system ();
+
     unwind_protect frame;
 
-    frame.protect_var (discard_error_messages);
-    frame.protect_var (discard_warning_messages);
-
-    discard_error_messages = true;
-    discard_warning_messages = true;
+    frame.add_method (es, &error_system::set_discard_error_messages,
+                      es.discard_error_messages ());
+    frame.add_method (es, &error_system::set_discard_warning_messages,
+                      es.discard_warning_messages ());
+
+    es.discard_error_messages (true);
+    es.discard_warning_messages (true);
 
     if (! base || ! limit)
       {
@@ -2528,8 +2533,7 @@
       {
         try
           {
-            tree_evaluator& tw
-              = __get_evaluator__ ("finish_colon_expression");
+            tree_evaluator& tw = interp.get_evaluator ();
 
             octave_value tmp = tw.evaluate (e);
 
@@ -4163,20 +4167,24 @@
   {
     tree_expression *retval = array_list;
 
+    interpreter& interp = __get_interpreter__ ("finish_array_list");
+    error_system& es = interp.get_error_system ();
+
     unwind_protect frame;
 
-    frame.protect_var (discard_error_messages);
-    frame.protect_var (discard_warning_messages);
-
-    discard_error_messages = true;
-    discard_warning_messages = true;
+    frame.add_method (es, &error_system::set_discard_error_messages,
+                      es.discard_error_messages ());
+    frame.add_method (es, &error_system::set_discard_warning_messages,
+                      es.discard_warning_messages ());
+
+    es.discard_error_messages (true);
+    es.discard_warning_messages (true);
 
     if (array_list->all_elements_are_constant ())
       {
         try
           {
-            tree_evaluator& tw
-              = __get_evaluator__ ("finish_array_list");
+            tree_evaluator& tw = interp.get_evaluator ();
 
             octave_value tmp = tw.evaluate (array_list);
 
@@ -5144,10 +5152,19 @@
 maybe_print_last_error_message (bool *doit)
 {
   if (doit && *doit)
-    // Print error message again, which was lost because of the stderr buffer
-    // Note: this keeps error_state and last_error_stack intact
-    message_with_id ("error", last_error_id ().c_str (),
-                     "%s", last_error_message ().c_str ());
+    {
+      // Print error message again, which was lost because of the stderr
+      // buffer.  Note: this keeps error_state and last_error_stack
+      // intact.
+
+      octave::error_system& es
+        = octave::__get_error_system__ ("maybe_print_last_error_message");
+
+      std::string id = es.last_error_id ();
+      std::string msg = es.last_error_message ();
+
+      message_with_id ("error", id.c_str (), "%s", msg.c_str ());
+    }
 }
 
 static void
--- a/libinterp/parse-tree/pt-eval.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Fri May 31 15:49:38 2019 +0000
@@ -240,6 +240,8 @@
 
     parser curr_parser (m_interpreter);
 
+    error_system& es = m_interpreter.get_error_system ();
+
     while (m_in_debug_repl)
       {
         if (m_exit_debug_repl || m_abort_debug_repl || tw.dbstep_flag ())
@@ -249,7 +251,7 @@
           {
             Vtrack_line_num = false;
 
-            reset_error_handler ();
+            es.reset ();
 
             curr_parser.reset ();
 
@@ -327,11 +329,13 @@
                         ? new lexer (m_interpreter)
                         : new lexer (stdin, m_interpreter));
 
+    error_system& es = m_interpreter.get_error_system ();
+
     do
       {
         try
           {
-            reset_error_handler ();
+            es.reset ();
 
             repl_parser.reset ();
 
@@ -415,7 +419,9 @@
           }
 
 #if defined (DBSTOP_NANINF)
-        if (Vdebug_on_naninf)
+        error_system& es = m_interpreter.get_error_system ();
+
+        if (es.debug_on_naninf ())
           {
             if (setjump (naninf_jump) != 0)
               debug_or_throw_exception (true);  // true = stack trace
@@ -577,10 +583,14 @@
   {
     octave_value_list retval;
 
+    error_system& es = m_interpreter.get_error_system ();
+
     unwind_protect frame;
 
-    frame.protect_var (buffer_error_messages);
-    buffer_error_messages++;
+    int bem = es.buffer_error_messages ();
+    frame.add_method (es, &error_system::set_buffer_error_messages, bem);
+
+    es.buffer_error_messages (bem + 1);
 
     int parse_status = 0;
 
@@ -604,7 +614,7 @@
         // Set up for letting the user print any messages from
         // errors that occurred in the first part of this eval().
 
-        buffer_error_messages--;
+        es.buffer_error_messages (es.buffer_error_messages () - 1);
 
         tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
 
@@ -665,8 +675,12 @@
     else
       error ("evalin: CONTEXT must be \"caller\" or \"base\"");
 
-    frame.protect_var (buffer_error_messages);
-    buffer_error_messages++;
+    error_system& es = m_interpreter.get_error_system ();
+
+    int bem = es.buffer_error_messages ();
+    frame.add_method (es, &error_system::set_buffer_error_messages, bem);
+
+    es.buffer_error_messages (bem + 1);
 
     int parse_status = 0;
 
@@ -690,7 +704,7 @@
         // Set up for letting the user print any messages from
         // errors that occurred in the first part of this eval().
 
-        buffer_error_messages--;
+        es.buffer_error_messages (es.buffer_error_messages () - 1);
 
         tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
 
@@ -3820,19 +3834,15 @@
         m_echo_file_pos = line + 1;
       }
 
+    error_system& es = m_interpreter.get_error_system ();
+
     bool execution_error = false;
 
     {
       // unwind frame before catch block
       unwind_protect frame;
 
-      frame.protect_var (buffer_error_messages);
-      frame.protect_var (Vdebug_on_error);
-      frame.protect_var (Vdebug_on_warning);
-
-      buffer_error_messages++;
-      Vdebug_on_error = false;
-      Vdebug_on_warning = false;
+      interpreter_try (frame);
 
       // The catch code is *not* added to unwind_protect stack;
       // it doesn't need to be run on interrupts.
@@ -3843,15 +3853,20 @@
         {
           try
             {
-              in_try_catch++;
+              unwind_protect inner_frame;
+
+              int itc = es.in_try_catch ();
+              inner_frame.add_method (es, &error_system::set_in_try_catch,
+                                      es.in_try_catch ());
+
+              es.in_try_catch (itc + 1);
+
               try_code->accept (*this);
-              in_try_catch--;
             }
           catch (const execution_exception&)
             {
               interpreter::recover_from_exception ();
 
-              in_try_catch--;          // must be restored before "catch" block
               execution_error = true;
             }
         }
@@ -3873,9 +3888,9 @@
 
                 octave_scalar_map err;
 
-                err.assign ("message", last_error_message ());
-                err.assign ("identifier", last_error_id ());
-                err.assign ("stack", last_error_stack ());
+                err.assign ("message", es.last_error_message ());
+                err.assign ("identifier", es.last_error_id ());
+                err.assign ("stack", es.last_error_stack ());
 
                 ult.assign (octave_value::op_asn_eq, err);
               }
--- a/libinterp/parse-tree/pt.cc	Fri Jun 07 13:29:41 2019 -0400
+++ b/libinterp/parse-tree/pt.cc	Fri May 31 15:49:38 2019 +0000
@@ -27,6 +27,7 @@
 #include <sstream>
 #include <string>
 
+#include "interpreter.h"
 #include "ov-fcn.h"
 #include "pt.h"
 #include "pt-eval.h"
@@ -89,8 +90,13 @@
           }
         catch (const execution_exception& e)
           {
+            interpreter& interp = tw.get_interpreter ();
+            error_system& es = interp.get_error_system ();
+
+            std::string tmp = es.last_error_message ();
+
             warning ("Error evaluating breakpoint condition:\n    %s",
-                     last_error_message ().c_str ());
+                     tmp.c_str ());
           }
       }
     return retval;