# HG changeset patch # User John W. Eaton # Date 1559317778 0 # Node ID 6b0c61a5a0f0c4406d32d64e5951db63c1396475 # Parent 25d0c4b5a3aab869106d9687dab82e80d80f1441 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. diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libgui/src/m-editor/file-editor-tab.cc --- 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 diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/cellfun.cc --- 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 (count + static_cast (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) diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/error.cc --- 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. } diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/error.h --- 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 diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/graphics.cc --- 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 (); } diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/input.cc --- 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 { diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/interpreter-private.cc --- 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); diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/interpreter-private.h --- 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); diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/interpreter.cc --- 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)); diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/interpreter.h --- 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; diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/utils.cc --- 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 { diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/corefcn/variables.cc --- 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)); } } diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/octave-value/cdef-object.cc --- 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 ()); diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/octave-value/ov-oncleanup.cc --- 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 ()); diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/parse-tree/bp-table.cc --- 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 W = U.index (static_cast (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 W = U.index (static_cast (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 W = U.index (static_cast (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 *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 " 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& 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 ()) { diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/parse-tree/bp-table.h --- 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 m_caught_that_stop; std::set 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& id_list); + bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname, const intmap& line, const std::string& condition, intmap& retval); diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/parse-tree/oct-parse.yy --- 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 diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/parse-tree/pt-eval.cc --- 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); } diff -r 25d0c4b5a3aa -r 6b0c61a5a0f0 libinterp/parse-tree/pt.cc --- 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 #include +#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;