# HG changeset patch # User John W. Eaton
# Date 1419228760 18000 # Mon Dec 22 01:12:40 2014 -0500 # Node ID 2a67edb90cef57595edc7383e6812b19084cbd71 # Parent 8b785ca93de7b63ab17cebb8d94e010641b14b24 exception error diffs diff --git a/libinterp/corefcn/cellfun.cc b/libinterp/corefcn/cellfun.cc --- a/libinterp/corefcn/cellfun.cc +++ b/libinterp/corefcn/cellfun.cc @@ -70,17 +70,22 @@ octave_value& error_handler) { octave_value_list tmp; + + bool execution_error = false; + try { tmp = func.do_multi_index_op (nargout, inputlist); } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { if (error_handler.is_defined ()) - error_state = 1; + execution_error = true; + else + octave_throw_execution_exception (); } - if (error_state) + if (execution_error) { if (error_handler.is_defined ()) { @@ -96,14 +101,7 @@ buffer_error_messages--; - error_state = 0; - tmp = error_handler.do_multi_index_op (nargout, errlist); - - buffer_error_messages++; - - if (error_state) - tmp.clear (); } else tmp.clear (); diff --git a/libinterp/corefcn/error.cc b/libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc +++ b/libinterp/corefcn/error.cc @@ -92,22 +92,11 @@ // // Valid values: // -// -2: an error has occurred, but don't print any messages. -// -1: an error has occurred, we are printing a traceback // 0: no error // 1: an error has occurred // int error_state = 0; -// Current warning state. -// -// Valid values: -// -// 0: no warning -// 1: a warning has occurred -// -int warning_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. @@ -122,8 +111,6 @@ void reset_error_handler (void) { - error_state = 0; - warning_state = 0; buffer_error_messages = 0; discard_error_messages = false; } @@ -145,6 +132,26 @@ return octave_call_stack::empty_backtrace (); } +static void +debug_or_throw_exception (void) +{ + if ((interactive || forced_interactive) + && Vdebug_on_error && octave_call_stack::caller_user_code ()) + { + unwind_protect frame; + frame.protect_var (Vdebug_on_error); + Vdebug_on_error = false; + + tree_evaluator::debug_mode = true; + + tree_evaluator::current_frame = octave_call_stack::current_frame (); + + do_keyboard (octave_value_list ()); + } + else + octave_throw_execution_exception (); +} + // Warning messages are never buffered. static void @@ -170,13 +177,8 @@ std::string msg_string = output_buf.str (); - if (! warning_state) - { - // This is the first warning in a possible series. - - Vlast_warning_id = id; - Vlast_warning_message = msg_string; - } + Vlast_warning_id = id; + Vlast_warning_message = msg_string; if (! Vquiet_warning) { @@ -207,7 +209,7 @@ std::string base_msg = output_buf.str (); - bool to_beep_or_not_to_beep_p = Vbeep_on_error && ! error_state; + bool to_beep_or_not_to_beep_p = Vbeep_on_error; std::string msg_string; @@ -241,7 +243,7 @@ msg_string += base_msg + "\n"; - if (! error_state && save_last_error) + if (save_last_error) { // This is the first error in a possible series. @@ -331,51 +333,6 @@ } } -// Note that we don't actually print any message if the error string -// is just "" or "\n". This allows error ("") and error ("\n") to -// just set the error state. - -static void -error_1 (std::ostream& os, const char *name, const char *id, - const char *fmt, va_list args, bool with_cfn = false) -{ - if (error_state != -2) - { - if (fmt) - { - if (*fmt) - { - size_t len = strlen (fmt); - - if (len > 0) - { - if (fmt[len - 1] == '\n') - { - if (len > 1) - { - char *tmp_fmt = strsave (fmt); - tmp_fmt[len - 1] = '\0'; - verror (true, os, name, id, tmp_fmt, args, with_cfn); - delete [] tmp_fmt; - } - - error_state = -2; - } - else - { - verror (true, os, name, id, fmt, args, with_cfn); - - if (! error_state) - error_state = 1; - } - } - } - } - else - panic ("error_1: invalid format"); - } -} - void vmessage (const char *name, const char *fmt, va_list args) { @@ -411,7 +368,8 @@ usage_1 (const char *id, const char *fmt, va_list args) { verror (true, std::cerr, "usage", id, fmt, args); - error_state = -1; + + debug_or_throw_exception (); } void @@ -445,38 +403,52 @@ } static void -error_2 (const char *id, const char *fmt, va_list args, bool with_cfn = false) +error_1 (std::ostream& os, const char *name, const char *id, + const char *fmt, va_list args, bool with_cfn = false) { - int init_state = error_state; + // Note that we don't actually print any message if the error string + // is just "" or "\n". This allows error ("") and error ("\n") to + // just set the error state. - error_1 (std::cerr, "error", id, fmt, args, with_cfn); + if (fmt) + { + if (*fmt) + { + size_t len = strlen (fmt); - if (error_state != -2 && ! symbol_table::at_top_level () - && ! discard_error_messages) - pr_where ("error"); + if (len > 0) + { + if (fmt[len - 1] == '\n') + { + if (len > 1) + { + char *tmp_fmt = strsave (fmt); + tmp_fmt[len - 1] = '\0'; + verror (true, os, name, id, tmp_fmt, args, with_cfn); + delete [] tmp_fmt; + } + } + else + { + verror (true, os, name, id, fmt, args, with_cfn); - if ((interactive || forced_interactive) - && Vdebug_on_error && init_state == 0 - && octave_call_stack::caller_user_code ()) - { - unwind_protect frame; - frame.protect_var (Vdebug_on_error); - Vdebug_on_error = false; + if (! symbol_table::at_top_level () + && ! discard_error_messages) + pr_where ("error"); + } + } + } + } + else + panic ("error_1: invalid format"); - error_state = 0; - - tree_evaluator::debug_mode = true; - - tree_evaluator::current_frame = octave_call_stack::current_frame (); - - do_keyboard (octave_value_list ()); - } + debug_or_throw_exception (); } void verror (const char *fmt, va_list args) { - error_2 ("", fmt, args); + error_1 (std::cerr, "error", "", fmt, args); } void @@ -491,7 +463,7 @@ void verror_with_cfn (const char *fmt, va_list args) { - error_2 ("", fmt, args, true); + error_1 (std::cerr, "error", "", fmt, args, true); } void @@ -506,7 +478,7 @@ void verror_with_id (const char *id, const char *fmt, va_list args) { - error_2 (id, fmt, args); + error_1 (std::cerr, "error", id, fmt, args); } void @@ -521,7 +493,7 @@ void verror_with_id_cfn (const char *id, const char *fmt, va_list args) { - error_2 (id, fmt, args, true); + error_1 (std::cerr, "error", id, fmt, args, true); } void @@ -635,7 +607,7 @@ { // Handle this warning as an error. - error_2 (id, fmt, args); + error_1 (std::cerr, "error", id, fmt, args); } else if (warn_opt == 1) { @@ -643,12 +615,9 @@ if (! symbol_table::at_top_level () && Vbacktrace_on_warning - && ! warning_state && ! discard_warning_messages) pr_where ("warning"); - warning_state = 1; - if ((interactive || forced_interactive) && Vdebug_on_warning && octave_call_stack::caller_user_code ()) @@ -850,120 +819,117 @@ { const octave_scalar_map err = args(0).scalar_map_value (); - if (! error_state) + if (err.contains ("message") && err.contains ("identifier")) { - if (err.contains ("message") && err.contains ("identifier")) + std::string msg = err.contents ("message").string_value (); + std::string id = err.contents ("identifier").string_value (); + int len = msg.length (); + + std::string file; + std::string nm; + int l = -1; + int c = -1; + + octave_map err_stack = initialize_last_error_stack (); + + if (err.contains ("stack")) { - std::string msg = err.contents ("message").string_value (); - std::string id = err.contents ("identifier").string_value (); - int len = msg.length (); + err_stack = err.contents ("stack").map_value (); - std::string file; - std::string nm; - int l = -1; - int c = -1; + if (err_stack.numel () > 0) + { + if (err_stack.contains ("file")) + file = err_stack.contents ("file")(0).string_value (); - octave_map err_stack = initialize_last_error_stack (); + if (err_stack.contains ("name")) + nm = err_stack.contents ("name")(0).string_value (); - if (err.contains ("stack")) + if (err_stack.contains ("line")) + l = err_stack.contents ("line")(0).nint_value (); + + if (err_stack.contains ("column")) + c = err_stack.contents ("column")(0).nint_value (); + } + } + + // Ugh. + char *tmp_msg = strsave (msg.c_str ()); + if (tmp_msg[len-1] == '\n') + { + if (len > 1) { - err_stack = err.contents ("stack").map_value (); + tmp_msg[len - 1] = '\0'; + rethrow_error (id.c_str (), "%s\n", tmp_msg); + } + } + else + rethrow_error (id.c_str (), "%s", tmp_msg); + delete [] tmp_msg; - if (err_stack.numel () > 0) + // FIXME: is this the right thing to do for Vlast_error_stack? + // Should it be saved and restored with unwind_protect? + + Vlast_error_stack = err_stack; + + if (err.contains ("stack")) + { + if (file.empty ()) + { + if (nm.empty ()) { - if (err_stack.contains ("file")) - file = err_stack.contents ("file")(0).string_value (); - - if (err_stack.contains ("name")) - nm = err_stack.contents ("name")(0).string_value (); - - if (err_stack.contains ("line")) - l = err_stack.contents ("line")(0).nint_value (); - - if (err_stack.contains ("column")) - c = err_stack.contents ("column")(0).nint_value (); - } - } - - // Ugh. - char *tmp_msg = strsave (msg.c_str ()); - if (tmp_msg[len-1] == '\n') - { - if (len > 1) - { - tmp_msg[len - 1] = '\0'; - rethrow_error (id.c_str (), "%s\n", tmp_msg); - } - } - else - rethrow_error (id.c_str (), "%s", tmp_msg); - delete [] tmp_msg; - - // FIXME: is this the right thing to do for Vlast_error_stack? - // Should it be saved and restored with unwind_protect? - - Vlast_error_stack = err_stack; - - if (err.contains ("stack")) - { - if (file.empty ()) - { - if (nm.empty ()) + if (l > 0) { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: near line %d, column %d", - l, c); - else - pr_where_1 ("error: near line %d", l); - } - } - else - { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: called from '%s' near line %d, column %d", - nm.c_str (), l, c); - else - pr_where_1 ("error: called from '%d' near line %d", - nm.c_str (), l); - } + if (c > 0) + pr_where_1 ("error: near line %d, column %d", + l, c); + else + pr_where_1 ("error: near line %d", l); } } else { - if (nm.empty ()) + if (l > 0) { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: in file %s near line %d, column %d", - file.c_str (), l, c); - else - pr_where_1 ("error: in file %s near line %d", - file.c_str (), l); - } + if (c > 0) + pr_where_1 ("error: called from '%s' near line %d, column %d", + nm.c_str (), l, c); + else + pr_where_1 ("error: called from '%d' near line %d", + nm.c_str (), l); } - else + } + } + else + { + if (nm.empty ()) + { + if (l > 0) { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: called from '%s' in file %s near line %d, column %d", - nm.c_str (), file.c_str (), l, c); - else - pr_where_1 ("error: called from '%d' in file %s near line %d", - nm.c_str (), file.c_str (), l); - } + if (c > 0) + pr_where_1 ("error: in file %s near line %d, column %d", + file.c_str (), l, c); + else + pr_where_1 ("error: in file %s near line %d", + file.c_str (), l); + } + } + else + { + if (l > 0) + { + if (c > 0) + pr_where_1 ("error: called from '%s' in file %s near line %d, column %d", + nm.c_str (), file.c_str (), l, c); + else + pr_where_1 ("error: called from '%d' in file %s near line %d", + nm.c_str (), file.c_str (), l); } } } } - else - error ("rethrow: ERR structure must contain the fields 'message and 'identifier'"); } + else + error ("rethrow: ERR structure must contain the fields 'message and 'identifier'"); } return retval; } @@ -988,31 +954,28 @@ { std::string arg1 = args(0).string_value (); - if (! error_state) + // For compatibility with Matlab, an identifier must contain + // ':', but not at the beginning or the end, and it must not + // contain '%' (even if it is not a valid conversion + // operator) or whitespace. + + if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos + && arg1.find (':') != std::string::npos + && arg1[0] != ':' + && arg1[arg1.length ()-1] != ':') { - // For compatibility with Matlab, an identifier must contain - // ':', but not at the beginning or the end, and it must not - // contain '%' (even if it is not a valid conversion - // operator) or whitespace. + if (nargin > 1) + { + id = arg1; - if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos - && arg1.find (':') != std::string::npos - && arg1[0] != ':' - && arg1[arg1.length ()-1] != ':') - { - if (nargin > 1) - { - id = arg1; + nargs.resize (nargin-1); - nargs.resize (nargin-1); - - for (int i = 1; i < nargin; i++) - nargs(i-1) = args(i); - } - else - nargs(0) = "call to " + caller - + " with message identifier requires message"; + for (int i = 1; i < nargin; i++) + nargs(i-1) = args(i); } + else + nargs(0) = "call to " + caller + + " with message identifier requires message"; } } @@ -1154,12 +1117,7 @@ // handle_message, error_with_id, etc. } else - { - have_fmt = maybe_extract_message_id ("error", args, nargs, id); - - if (error_state) - return retval; - } + have_fmt = maybe_extract_message_id ("error", args, nargs, id); handle_message (error_with_id, id.c_str (), "unspecified error", nargs, have_fmt); @@ -1183,6 +1141,8 @@ octave_idx_type nel = ident.numel (); + assert (nel != 0); + bool found = false; std::string val; @@ -1210,13 +1170,14 @@ } } - if (found) - { - retval.assign ("identifier", id); - retval.assign ("state", val); - } - else - error ("warning: unable to find default warning state!"); + // The warning state "all" is always supposed to remain in the list, + // so we should always find a state, either explicitly or by using the + // state for "all". + + assert (found); + + retval.assign ("identifier", id); + retval.assign ("state", val); return retval; } @@ -1294,70 +1255,200 @@ { string_vector argv = args.make_argv ("warning"); - if (! error_state) + std::string arg1 = argv(1); + std::string arg2 = "all"; + + if (argc >= 3) + arg2 = argv(2); + + if (arg1 == "on" || arg1 == "off" || arg1 == "error") { - std::string arg1 = argv(1); - std::string arg2 = "all"; + octave_map old_warning_options = warning_options; - if (argc >= 3) - arg2 = argv(2); + if (argc == 4 && argv(3) == "local" + && ! symbol_table::at_top_level ()) + { + symbol_table::scope_id scope + = octave_call_stack::current_scope (); - if (arg1 == "on" || arg1 == "off" || arg1 == "error") + symbol_table::context_id context + = octave_call_stack::current_context (); + + octave_scalar_map val = warning_query (arg2); + + octave_value curr_state = val.contents ("state"); + + // FIXME: this might be better with a dictionary object. + + octave_value curr_warning_states + = symbol_table::varval (".saved_warning_states.", + scope, context); + + octave_map m; + + if (curr_warning_states.is_defined ()) + m = curr_warning_states.map_value (); + else + { + string_vector fields (2); + + fields(0) = "identifier"; + fields(1) = "state"; + + m = octave_map (dim_vector (0, 1), fields); + } + + Cell ids = m.contents ("identifier"); + Cell states = m.contents ("state"); + + octave_idx_type nel = states.numel (); + bool found = false; + octave_idx_type i; + for (i = 0; i < nel; i++) + { + std::string id = ids(i).string_value (); + + if (id == arg2) + { + states(i) = curr_state; + found = true; + break; + } + } + + if (! found) + { + m.resize (dim_vector (nel+1, 1)); + + ids.resize (dim_vector (nel+1, 1)); + states.resize (dim_vector (nel+1, 1)); + + ids(nel) = arg2; + states(nel) = curr_state; + } + + m.contents ("identifier") = ids; + m.contents ("state") = states; + + symbol_table::assign + (".saved_warning_states.", m, scope, context); + + // Now ignore the "local" argument and continue to + // handle the current setting. + argc--; + } + + if (arg2 == "all") { - octave_map old_warning_options = warning_options; + octave_map tmp; - if (argc == 4 && argv(3) == "local" - && ! symbol_table::at_top_level ()) + Cell id (1, 1); + Cell st (1, 1); + + id(0) = arg2; + st(0) = arg1; + + // Since internal Octave functions are not + // compatible, turning all warnings into errors + // should leave the state of + // Octave:matlab-incompatible alone. + + if (arg1 == "error" + && warning_options.contains ("identifier")) { - symbol_table::scope_id scope - = octave_call_stack::current_scope (); + octave_idx_type n = 1; - symbol_table::context_id context - = octave_call_stack::current_context (); + Cell tid = warning_options.contents ("identifier"); + Cell tst = warning_options.contents ("state"); - octave_scalar_map val = warning_query (arg2); + for (octave_idx_type i = 0; i < tid.numel (); i++) + { + octave_value vid = tid(i); - octave_value curr_state = val.contents ("state"); + if (vid.is_string ()) + { + std::string key = vid.string_value (); - // FIXME: this might be better with a dictionary object. + if (key == "Octave:matlab-incompatible" + || key == "Octave:single-quote-string") + { + id.resize (dim_vector (1, n+1)); + st.resize (dim_vector (1, n+1)); - octave_value curr_warning_states - = symbol_table::varval (".saved_warning_states.", - scope, context); + id(n) = tid(i); + st(n) = tst(i); - octave_map m; + n++; + } + } + } + } - if (curr_warning_states.is_defined ()) - m = curr_warning_states.map_value (); - else + tmp.assign ("identifier", id); + tmp.assign ("state", st); + + warning_options = tmp; + + done = true; + } + else if (arg2 == "backtrace") + { + if (arg1 != "error") + { + Vbacktrace_on_warning = (arg1 == "on"); + done = true; + } + } + else if (arg2 == "debug") + { + if (arg1 != "error") + { + Vdebug_on_warning = (arg1 == "on"); + done = true; + } + } + else if (arg2 == "verbose") + { + if (arg1 != "error") + { + Vverbose_warning = (arg1 == "on"); + done = true; + } + } + else if (arg2 == "quiet") + { + if (arg1 != "error") + { + Vquiet_warning = (arg1 == "on"); + done = true; + } + } + else + { + if (arg2 == "last") + arg2 = Vlast_warning_id; + + if (arg2 == "all") + initialize_warning_options (arg1); + else + { + Cell ident = warning_options.contents ("identifier"); + Cell state = warning_options.contents ("state"); + + octave_idx_type nel = ident.numel (); + + bool found = false; + + for (octave_idx_type i = 0; i < nel; i++) { - string_vector fields (2); + if (ident(i).string_value () == arg2) + { + // FIXME: if state for "all" is same as arg1, + // we can simply remove the item + // from the list. - fields(0) = "identifier"; - fields(1) = "state"; - - m = octave_map (dim_vector (0, 1), fields); - } - - if (error_state) - panic_impossible (); - - Cell ids = m.contents ("identifier"); - Cell states = m.contents ("state"); - - octave_idx_type nel = states.numel (); - bool found = false; - octave_idx_type i; - for (i = 0; i < nel; i++) - { - std::string id = ids(i).string_value (); - - if (error_state) - panic_impossible (); - - if (id == arg2) - { - states(i) = curr_state; + state(i) = arg1; + warning_options.assign ("state", state); found = true; break; } @@ -1365,191 +1456,52 @@ if (! found) { - m.resize (dim_vector (nel+1, 1)); + // FIXME: if state for "all" is same as arg1, + // we don't need to do anything. - ids.resize (dim_vector (nel+1, 1)); - states.resize (dim_vector (nel+1, 1)); + ident.resize (dim_vector (1, nel+1)); + state.resize (dim_vector (1, nel+1)); - ids(nel) = arg2; - states(nel) = curr_state; - } + ident(nel) = arg2; + state(nel) = arg1; - m.contents ("identifier") = ids; - m.contents ("state") = states; + warning_options.clear (); - symbol_table::assign - (".saved_warning_states.", m, scope, context); - - // Now ignore the "local" argument and continue to - // handle the current setting. - argc--; - } - - if (arg2 == "all") - { - octave_map tmp; - - Cell id (1, 1); - Cell st (1, 1); - - id(0) = arg2; - st(0) = arg1; - - // Since internal Octave functions are not - // compatible, turning all warnings into errors - // should leave the state of - // Octave:matlab-incompatible alone. - - if (arg1 == "error" - && warning_options.contains ("identifier")) - { - octave_idx_type n = 1; - - Cell tid = warning_options.contents ("identifier"); - Cell tst = warning_options.contents ("state"); - - for (octave_idx_type i = 0; i < tid.numel (); i++) - { - octave_value vid = tid(i); - - if (vid.is_string ()) - { - std::string key = vid.string_value (); - - if (key == "Octave:matlab-incompatible" - || key == "Octave:single-quote-string") - { - id.resize (dim_vector (1, n+1)); - st.resize (dim_vector (1, n+1)); - - id(n) = tid(i); - st(n) = tst(i); - - n++; - } - } - } - } - - tmp.assign ("identifier", id); - tmp.assign ("state", st); - - warning_options = tmp; - - done = true; - } - else if (arg2 == "backtrace") - { - if (arg1 != "error") - { - Vbacktrace_on_warning = (arg1 == "on"); - done = true; + warning_options.assign ("identifier", ident); + warning_options.assign ("state", state); } } - else if (arg2 == "debug") - { - if (arg1 != "error") - { - Vdebug_on_warning = (arg1 == "on"); - done = true; - } - } - else if (arg2 == "verbose") - { - if (arg1 != "error") - { - Vverbose_warning = (arg1 == "on"); - done = true; - } - } - else if (arg2 == "quiet") - { - if (arg1 != "error") - { - Vquiet_warning = (arg1 == "on"); - done = true; - } - } - else - { - if (arg2 == "last") - arg2 = Vlast_warning_id; - - if (arg2 == "all") - initialize_warning_options (arg1); - else - { - Cell ident = warning_options.contents ("identifier"); - Cell state = warning_options.contents ("state"); - - octave_idx_type nel = ident.numel (); - - bool found = false; - - for (octave_idx_type i = 0; i < nel; i++) - { - if (ident(i).string_value () == arg2) - { - // FIXME: if state for "all" is same as arg1, - // we can simply remove the item - // from the list. - - state(i) = arg1; - warning_options.assign ("state", state); - found = true; - break; - } - } - - if (! found) - { - // FIXME: if state for "all" is same as arg1, - // we don't need to do anything. - - ident.resize (dim_vector (1, nel+1)); - state.resize (dim_vector (1, nel+1)); - - ident(nel) = arg2; - state(nel) = arg1; - - warning_options.clear (); - - warning_options.assign ("identifier", ident); - warning_options.assign ("state", state); - } - } - - done = true; - } - - if (done && nargout > 0) - retval = old_warning_options; - } - else if (arg1 == "query") - { - if (arg2 == "all") - retval = 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"); - else if (arg2 == "debug") - tmp.assign ("state", Vdebug_on_warning ? "on" : "off"); - else if (arg2 == "verbose") - tmp.assign ("state", Vverbose_warning ? "on" : "off"); - else - tmp.assign ("state", Vquiet_warning ? "on" : "off"); - - retval = tmp; - } - else - retval = warning_query (arg2); done = true; } + + if (done && nargout > 0) + retval = old_warning_options; + } + else if (arg1 == "query") + { + if (arg2 == "all") + retval = 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"); + else if (arg2 == "debug") + tmp.assign ("state", Vdebug_on_warning ? "on" : "off"); + else if (arg2 == "verbose") + tmp.assign ("state", Vverbose_warning ? "on" : "off"); + else + tmp.assign ("state", Vquiet_warning ? "on" : "off"); + + retval = tmp; + } + else + retval = warning_query (arg2); + + done = true; } } else if (argc == 1) @@ -1569,7 +1521,69 @@ octave_map m = arg.map_value (); if (m.contains ("identifier") && m.contains ("state")) - warning_options = m; + { + // Ensure that we preserve the old state for "all". + + Cell ident = m.contents ("identifier"); + Cell state = m.contents ("state"); + + octave_idx_type nel = ident.numel (); + + bool found = false; + + for (octave_idx_type i = 0; i < nel; i++) + { + if (ident(i).string_value () == "all") + { + found = true; + break; + } + } + + if (! found) + { + ident.resize (dim_vector (1, nel+1)); + state.resize (dim_vector (1, nel+1)); + + for (octave_idx_type i = nel; i > 0; i--) + { + ident(i) = ident(i-1); + state(i) = state(i-1); + } + + Cell tid = warning_options.contents ("identifier"); + Cell tst = warning_options.contents ("state"); + + nel = tid.numel (); + + found = false; + + for (octave_idx_type i = 0; i < nel; i++) + { + if (tid(i).string_value () == "all") + { + ident(0) = "all"; + state(0) = tst(i).string_value (); + found = true; + break; + } + } + + // The warning state "all" is always supposed to + // remain in the list, so we should always find a + // state, either explicitly or by using the state for + // "all". + + assert (found); + + m.clear (); + + m.assign ("identifier", ident); + m.assign ("state", state); + } + + warning_options = m; + } else error ("warning: expecting structure with fields 'identifier' and 'state'"); @@ -1580,7 +1594,7 @@ } } - if (! (error_state || done)) + if (! done) { octave_value_list nargs = args; @@ -1588,9 +1602,6 @@ bool have_fmt = maybe_extract_message_id ("warning", args, nargs, id); - if (error_state) - return retval; - std::string prev_msg = Vlast_warning_message; std::string curr_msg = handle_message (warning_with_id, id.c_str (), @@ -1696,11 +1707,6 @@ octave_value retval; int nargin = args.length (); - unwind_protect frame; - - frame.protect_var (error_state); - error_state = 0; - if (nargin < 2) { octave_scalar_map err; @@ -1735,47 +1741,47 @@ int new_error_line = -1; int new_error_column = -1; - if (! error_state && new_err.contains ("message")) + if (new_err.contains ("message")) { const std::string tmp = new_err.getfield ("message").string_value (); new_error_message = tmp; } - if (! error_state && new_err.contains ("identifier")) + if (new_err.contains ("identifier")) { const std::string tmp = new_err.getfield ("identifier").string_value (); new_error_id = tmp; } - if (! error_state && new_err.contains ("stack")) + if (new_err.contains ("stack")) { new_err_stack = new_err.getfield ("stack").scalar_map_value (); - if (! error_state && new_err_stack.contains ("file")) + if (new_err_stack.contains ("file")) { const std::string tmp = new_err_stack.getfield ("file").string_value (); new_error_file = tmp; } - if (! error_state && new_err_stack.contains ("name")) + if (new_err_stack.contains ("name")) { const std::string tmp = new_err_stack.getfield ("name").string_value (); new_error_name = tmp; } - if (! error_state && new_err_stack.contains ("line")) + if (new_err_stack.contains ("line")) { const int tmp = new_err_stack.getfield ("line").nint_value (); new_error_line = tmp; } - if (! error_state && new_err_stack.contains ("column")) + if (new_err_stack.contains ("column")) { const int tmp = new_err_stack.getfield ("column").nint_value (); @@ -1783,35 +1789,31 @@ } } - if (! error_state) + Vlast_error_message = new_error_message; + Vlast_error_id = new_error_id; + + if (new_err.contains ("stack")) { - Vlast_error_message = new_error_message; - Vlast_error_id = new_error_id; + 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; + } + else + { + // No stack field. Fill it in with backtrace info. + octave_idx_type curr_frame = -1; - 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; - } - else - { - // No stack field. Fill it in with backtrace info. - octave_idx_type curr_frame = -1; - - Vlast_error_stack - = octave_call_stack::backtrace (0, curr_frame); - } + Vlast_error_stack + = octave_call_stack::backtrace (0, curr_frame); } } else error ("lasterror: argument must be a structure or a string"); } - if (! error_state) - retval = err; + retval = err; } else print_usage (); @@ -1833,36 +1835,26 @@ { octave_value_list retval; - unwind_protect frame; - - frame.protect_var (error_state); - error_state = 0; - int argc = args.length () + 1; if (argc < 4) { string_vector argv = args.make_argv ("lasterr"); - if (! error_state) + std::string prev_error_id = Vlast_error_id; + std::string prev_error_message = Vlast_error_message; + + if (argc > 2) + Vlast_error_id = argv(2); + + if (argc > 1) + Vlast_error_message = argv(1); + + if (argc == 1 || nargout > 0) { - std::string prev_error_id = Vlast_error_id; - std::string prev_error_message = Vlast_error_message; - - if (argc > 2) - Vlast_error_id = argv(2); - - if (argc > 1) - Vlast_error_message = argv(1); - - if (argc == 1 || nargout > 0) - { - retval(1) = prev_error_id; - retval(0) = prev_error_message; - } + retval(1) = prev_error_id; + retval(0) = prev_error_message; } - else - error ("lasterr: all arguments must be strings"); } else print_usage (); @@ -1890,26 +1882,20 @@ { string_vector argv = args.make_argv ("lastwarn"); - if (! error_state) + std::string prev_warning_id = Vlast_warning_id; + std::string prev_warning_message = Vlast_warning_message; + + if (argc > 2) + Vlast_warning_id = argv(2); + + if (argc > 1) + Vlast_warning_message = argv(1); + + if (argc == 1 || nargout > 0) { - std::string prev_warning_id = Vlast_warning_id; - std::string prev_warning_message = Vlast_warning_message; - - if (argc > 2) - Vlast_warning_id = argv(2); - - if (argc > 1) - Vlast_warning_message = argv(1); - - if (argc == 1 || nargout > 0) - { - warning_state = 0; - retval(1) = prev_warning_id; - retval(0) = prev_warning_message; - } + retval(1) = prev_warning_id; + retval(0) = prev_warning_message; } - else - error ("lastwarn: all arguments must be strings"); } else print_usage (); @@ -2036,7 +2022,6 @@ void interpreter_try (unwind_protect& frame) { - frame.protect_var (error_state); frame.protect_var (buffer_error_messages); frame.protect_var (Vdebug_on_error); frame.protect_var (Vdebug_on_warning); diff --git a/libinterp/corefcn/gripes.cc b/libinterp/corefcn/gripes.cc --- a/libinterp/corefcn/gripes.cc +++ b/libinterp/corefcn/gripes.cc @@ -205,15 +205,6 @@ } void -gripe_library_execution_error (void) -{ - octave_exception_state = octave_no_exception; - - if (! error_state) - error ("caught execution error in library function"); -} - -void gripe_invalid_inquiry_subscript (void) { error ("invalid dimension inquiry of a non-existent value"); diff --git a/libinterp/corefcn/gripes.h b/libinterp/corefcn/gripes.h --- a/libinterp/corefcn/gripes.h +++ b/libinterp/corefcn/gripes.h @@ -114,9 +114,6 @@ gripe_logical_conversion (void); extern OCTINTERP_API void -gripe_library_execution_error (void); - -extern OCTINTERP_API void gripe_invalid_inquiry_subscript (void); extern OCTINTERP_API void diff --git a/libinterp/corefcn/jit-typeinfo.cc b/libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc +++ b/libinterp/corefcn/jit-typeinfo.cc @@ -215,41 +215,20 @@ extern "C" void octave_jit_gripe_nan_to_logical_conversion (void) { - try - { - gripe_nan_to_logical_conversion (); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - } + gripe_nan_to_logical_conversion (); } extern "C" void octave_jit_ginvalid_index (void) { - try - { - gripe_invalid_index (); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - } + gripe_invalid_index (); } extern "C" void octave_jit_gindex_range (int nd, int dim, octave_idx_type iext, octave_idx_type ext) { - try - { - gripe_index_out_of_range (nd, dim, iext, ext); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - } + gripe_index_out_of_range (nd, dim, iext, ext); } extern "C" jit_matrix @@ -281,19 +260,12 @@ octave_idx_type idx_count) { // FIXME: Replace this with a more optimal version - try - { - Array