# HG changeset patch # User Jaroslav Hajek # Date 1262780321 -3600 # Node ID 2cd940306a0695817e78f105a0848c1e2cb4c725 # Parent 64a06079cae44481dff6f3503eae51c06e7c921a make unwind_protect frames local diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,70 @@ +2010-01-06 Jaroslav Hajek + + * unwind_protect.h, unwind_protect.cc (unwind_protect): Rewrite. + Remove obsolete macros. Use a simple linked list. + + * debug.cc (Fdbwhere): Update to new unwind_protect style. + * dynamic-ld.cc (octave_dynamic_loader::do_load_oct, + octave_dynamic_loader::do_load_mex): Ditto. + * error.cc (Flasterror, Flasterr, error_2, warning_1): Ditto. + * graphics.cc (base_graphics_object::remove_all_listeners, + axes::update_axis_limits, gh_manager::do_execute_callback, + Fdrawnow): Ditto. + * help.cc (raw_help_from_file): Ditto. + * input.cc (do_keyboard, Fkeyboard, get_debug_input): Ditto. + * load-path.cc (load_path::do_set, execute_pkg_add_or_del, + * ls-mat4.cc (save_mat_binary_data): Ditto. + * ls-mat5.cc (read_mat5_binary_element): Ditto. + * mex.cc (call_mex, mexGetVariable): Ditto. + * oct-hist.cc (do_edit_history, do_run_history): Ditto. + * octave.cc (execute_startup_files, execute_eval_option_code, + execute_command_line_file): Ditto. + * ov-builtin.cc (octave_builtin::do_multi_index_op): Ditto. + * ov-class.cc (octave_class::subsasgn, octave_class::print_raw): + Ditto. + * ov-fcn-handle.cc (octave_fcn_handle::load_ascii, + octave_fcn_handle::load_binary, octave_fcn_handle::load_hdf5): Ditto. + * ov-list.cc (octave_list::print_raw): Ditto. + * ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Ditto. + * ov-struct.cc (octave_struct::print_raw): Ditto. + * ov-usr-fcn.cc (octave_user_script::do_multi_index_op, + octave_user_function::do_multi_index_op): Ditto. + * pager.cc (flush_octave_stdout): Ditto. + * pr-output.cc (Frats): Ditto. + * pt-arg-list.cc (tree_argument_list::convert_to_const_vector): Ditto. + + * pt-eval.cc (tree_evaluator::visit_simple_for_command, + tree_evaluator::visit_complex_for_command, + tree_evaluator::visit_while_command, + tree_evaluator::visit_do_until_command): Update to new unwind_protect + style. + (do_catch_code): Remove. + (tree_evaluator::visit_try_catch_command): Simplify. Don't register + catch code for unwind_protect. + (tree_evaluator::do_unwind_protect_cleanup_code): Make a + tree_evaluator method. Update to new unwind_protect style. + (tree_evaluator::visit_unwind_protect_command): Use explicit try/catch + handling rather than inserting unsafe code into unwind_protect. + + * pt-eval.h (tree_evaluator::do_unwind_protect_cleanup_code): New decl. + * toplev.cc (main_loop): Update to new unwind_protect style. + (run_command_and_return_output): Ditto. + * utils.cc (Fisindex): Ditto. + * variables.cc (generate_struct_completions, safe_symbol_lookup, + do_who): Ditto. + + * DLD-FUNCTIONS/cellfun.cc (Fcellfun): Ditto. + * DLD-FUNCTIONS/daspk.cc (Fdaspk): Ditto. + * DLD-FUNCTIONS/dasrt.cc (Fdasrt): Ditto. + * DLD-FUNCTIONS/dassl.cc (Fdassl): Ditto. + * DLD-FUNCTIONS/eigs.cc (Feigs): Ditto. + * DLD-FUNCTIONS/lsode.cc (Flsode): Ditto. + * DLD-FUNCTIONS/quad.cc (Fquad): Ditto. + * DLD-FUNCTIONS/rand.cc (Frandn, Frande, Frandg, Frandp): Ditto. + * DLD-FUNCTIONS/typecast.cc (get_data_and_bytesize, Ftypecast): Ditto. + * DLD-FUNCTIONS/urlwrite.cc (Furlwrite, mput_directory, + getallfiles, F__ftp_mget__): Ditto. + 2010-01-05 Jaroslav Hajek * Cell.cc (Cell::cellstr_value): New method. diff --git a/src/DLD-FUNCTIONS/cellfun.cc b/src/DLD-FUNCTIONS/cellfun.cc --- a/src/DLD-FUNCTIONS/cellfun.cc +++ b/src/DLD-FUNCTIONS/cellfun.cc @@ -477,8 +477,8 @@ if (func.is_function_handle () || func.is_inline_function () || func.is_function ()) { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); - unwind_protect::protect_var (buffer_error_messages); + unwind_protect frame; + frame.protect_var (buffer_error_messages); bool uniform_output = true; octave_value error_handler; @@ -540,14 +540,14 @@ dim_vector fdims (1, 1); if (error_state) - goto cellfun_err; + return octave_value_list (); for (int j = 0; j < nargin; j++) { if (! args(j+1).is_cell ()) { error ("cellfun: arguments must be cells"); - goto cellfun_err; + return octave_value_list (); } inputs[j] = args(j+1).cell_value (); @@ -567,7 +567,7 @@ if (mask[i] && inputs[i].dims () != fdims) { error ("cellfun: Dimensions mismatch."); - goto cellfun_err; + return octave_value_list (); } } break; @@ -605,18 +605,18 @@ buffer_error_messages++; if (error_state) - goto cellfun_err; + return octave_value_list (); } if (error_state) - goto cellfun_err; + return octave_value_list (); if (tmp.length () < nargout1) { if (tmp.length () < nargout) { error ("cellfun: too many output arguments"); - goto cellfun_err; + return octave_value_list (); } else nargout1 = 0; @@ -697,18 +697,18 @@ buffer_error_messages++; if (error_state) - goto cellfun_err; + return octave_value_list (); } if (error_state) - goto cellfun_err; + return octave_value_list (); if (tmp.length () < nargout1) { if (tmp.length () < nargout) { error ("cellfun: too many output arguments"); - goto cellfun_err; + return octave_value_list (); } else nargout1 = 0; @@ -723,12 +723,6 @@ for (int j = 0; j < nargout1; j++) retval(j) = results[j]; } - -cellfun_err: - if (error_state) - retval = octave_value_list(); - - unwind_protect::run_frame (uwp_frame); } else error ("cellfun: first argument must be a string or function handle"); diff --git a/src/DLD-FUNCTIONS/daspk.cc b/src/DLD-FUNCTIONS/daspk.cc --- a/src/DLD-FUNCTIONS/daspk.cc +++ b/src/DLD-FUNCTIONS/daspk.cc @@ -153,12 +153,7 @@ } #define DASPK_ABORT() \ - do \ - { \ - unwind_protect::run_frame (uwp_frame); \ - return retval; \ - } \ - while (0) + return retval #define DASPK_ABORT1(msg) \ do \ @@ -280,9 +275,9 @@ warned_fcn_imaginary = false; warned_jac_imaginary = false; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth > 1) @@ -480,8 +475,6 @@ else print_usage (); - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/DLD-FUNCTIONS/dasrt.cc b/src/DLD-FUNCTIONS/dasrt.cc --- a/src/DLD-FUNCTIONS/dasrt.cc +++ b/src/DLD-FUNCTIONS/dasrt.cc @@ -188,12 +188,7 @@ } #define DASRT_ABORT \ - do \ - { \ - unwind_protect::run_frame (uwp_frame); \ - return retval; \ - } \ - while (0) + return retval #define DASRT_ABORT1(msg) \ do \ @@ -353,9 +348,9 @@ warned_jac_imaginary = false; warned_cf_imaginary = false; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth > 1) @@ -368,7 +363,6 @@ if (nargin < 4 || nargin > 6) { print_usage (); - unwind_protect::run_frame (uwp_frame); return retval; } @@ -587,8 +581,6 @@ } } - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/DLD-FUNCTIONS/dassl.cc b/src/DLD-FUNCTIONS/dassl.cc --- a/src/DLD-FUNCTIONS/dassl.cc +++ b/src/DLD-FUNCTIONS/dassl.cc @@ -153,12 +153,7 @@ } #define DASSL_ABORT() \ - do \ - { \ - unwind_protect::run_frame (uwp_frame); \ - return retval; \ - } \ - while (0) + return retval #define DASSL_ABORT1(msg) \ do \ @@ -281,9 +276,9 @@ warned_fcn_imaginary = false; warned_jac_imaginary = false; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth > 1) @@ -482,8 +477,6 @@ else print_usage (); - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/DLD-FUNCTIONS/eigs.cc b/src/DLD-FUNCTIONS/eigs.cc --- a/src/DLD-FUNCTIONS/eigs.cc +++ b/src/DLD-FUNCTIONS/eigs.cc @@ -340,9 +340,9 @@ warned_imaginary = false; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth > 1) @@ -350,7 +350,6 @@ error ("eigs: invalid recursive call"); if (fcn_name.length()) clear_function (fcn_name); - unwind_protect::run_frame (uwp_frame); return retval; } @@ -736,8 +735,6 @@ if (! fcn_name.empty ()) clear_function (fcn_name); - - unwind_protect::run_frame (uwp_frame); #else error ("eigs: not available in this version of Octave"); #endif diff --git a/src/DLD-FUNCTIONS/lsode.cc b/src/DLD-FUNCTIONS/lsode.cc --- a/src/DLD-FUNCTIONS/lsode.cc +++ b/src/DLD-FUNCTIONS/lsode.cc @@ -139,12 +139,7 @@ } #define LSODE_ABORT() \ - do \ - { \ - unwind_protect::run_frame (uwp_frame); \ - return retval; \ - } \ - while (0) + return retval #define LSODE_ABORT1(msg) \ do \ @@ -280,9 +275,9 @@ warned_fcn_imaginary = false; warned_jac_imaginary = false; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth > 1) @@ -473,8 +468,6 @@ else print_usage (); - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/DLD-FUNCTIONS/quad.cc b/src/DLD-FUNCTIONS/quad.cc --- a/src/DLD-FUNCTIONS/quad.cc +++ b/src/DLD-FUNCTIONS/quad.cc @@ -153,7 +153,6 @@ { \ if (fcn_name.length()) \ clear_function (fcn_name); \ - unwind_protect::run_frame (uwp_frame); \ return retval; \ } \ while (0) @@ -221,9 +220,9 @@ warned_imaginary = false; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth > 1) @@ -471,8 +470,6 @@ else print_usage (); - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/DLD-FUNCTIONS/rand.cc b/src/DLD-FUNCTIONS/rand.cc --- a/src/DLD-FUNCTIONS/rand.cc +++ b/src/DLD-FUNCTIONS/rand.cc @@ -464,7 +464,7 @@ static std::string current_distribution = octave_rand::distribution (); static void -reset_rand_generator (void *) +reset_rand_generator (void) { octave_rand::distribution (current_distribution); } @@ -492,15 +492,15 @@ int nargin = args.length (); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; // This relies on the fact that elements are popped from the unwind // stack in the reverse of the order they are pushed // (i.e. current_distribution will be reset before calling // reset_rand_generator()). - unwind_protect::add (reset_rand_generator, 0); - unwind_protect::protect_var (current_distribution); + frame.add_fcn (reset_rand_generator); + frame.protect_var (current_distribution); current_distribution = "normal"; @@ -508,8 +508,6 @@ retval = do_rand (args, nargin, "randn"); - unwind_protect::run_frame (uwp_frame); - return retval; } @@ -565,15 +563,15 @@ int nargin = args.length (); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; // This relies on the fact that elements are popped from the unwind // stack in the reverse of the order they are pushed // (i.e. current_distribution will be reset before calling // reset_rand_generator()). - unwind_protect::add (reset_rand_generator, 0); - unwind_protect::protect_var (current_distribution); + frame.add_fcn (reset_rand_generator); + frame.protect_var (current_distribution); current_distribution = "exponential"; @@ -581,8 +579,6 @@ retval = do_rand (args, nargin, "rande"); - unwind_protect::run_frame (uwp_frame); - return retval; } @@ -697,23 +693,21 @@ error ("randg: insufficient arguments"); else { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; // This relies on the fact that elements are popped from the unwind // stack in the reverse of the order they are pushed // (i.e. current_distribution will be reset before calling // reset_rand_generator()). - unwind_protect::add (reset_rand_generator, 0); - unwind_protect::protect_var (current_distribution); + frame.add_fcn (reset_rand_generator); + frame.protect_var (current_distribution); current_distribution = "gamma"; octave_rand::distribution (current_distribution); retval = do_rand (args, nargin, "randg", true); - - unwind_protect::run_frame (uwp_frame); } return retval; @@ -911,23 +905,21 @@ error ("randp: insufficient arguments"); else { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; // This relies on the fact that elements are popped from the unwind // stack in the reverse of the order they are pushed // (i.e. current_distribution will be reset before calling // reset_rand_generator()). - unwind_protect::add (reset_rand_generator, 0); - unwind_protect::protect_var (current_distribution); + frame.add_fcn (reset_rand_generator); + frame.protect_var (current_distribution); current_distribution = "poisson"; octave_rand::distribution (current_distribution); retval = do_rand (args, nargin, "randp", true); - - unwind_protect::run_frame (uwp_frame); } return retval; diff --git a/src/DLD-FUNCTIONS/typecast.cc b/src/DLD-FUNCTIONS/typecast.cc --- a/src/DLD-FUNCTIONS/typecast.cc +++ b/src/DLD-FUNCTIONS/typecast.cc @@ -49,11 +49,12 @@ get_data_and_bytesize (const ArrayType& array, const void *& data, octave_idx_type& byte_size, - dim_vector& old_dims) + dim_vector& old_dims, + unwind_protect& frame) { // The array given may be a temporary, constructed from a scalar or sparse // array. This will ensure the data will be deallocated after we exit. - unwind_protect::add_delete (new ArrayType (array)); + frame.add_delete (new ArrayType (array)); data = reinterpret_cast (array.data ()); byte_size = array.byte_size (); @@ -137,6 +138,7 @@ if (args.length () == 2) { + unwind_protect frame; const void *data = 0; octave_idx_type byte_size = 0; dim_vector old_dims; @@ -144,43 +146,43 @@ octave_value array = args(0); if (array.is_bool_type ()) - get_data_and_bytesize (array.bool_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.bool_array_value (), data, byte_size, old_dims, frame); else if (array.is_string ()) - get_data_and_bytesize (array.char_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.char_array_value (), data, byte_size, old_dims, frame); else if (array.is_integer_type ()) { if (array.is_int8_type ()) - get_data_and_bytesize (array.int8_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.int8_array_value (), data, byte_size, old_dims, frame); else if (array.is_int16_type ()) - get_data_and_bytesize (array.int16_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.int16_array_value (), data, byte_size, old_dims, frame); else if (array.is_int32_type ()) - get_data_and_bytesize (array.int32_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.int32_array_value (), data, byte_size, old_dims, frame); else if (array.is_int64_type ()) - get_data_and_bytesize (array.int64_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.int64_array_value (), data, byte_size, old_dims, frame); else if (array.is_uint8_type ()) - get_data_and_bytesize (array.uint8_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.uint8_array_value (), data, byte_size, old_dims, frame); else if (array.is_uint16_type ()) - get_data_and_bytesize (array.uint16_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.uint16_array_value (), data, byte_size, old_dims, frame); else if (array.is_uint32_type ()) - get_data_and_bytesize (array.uint32_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.uint32_array_value (), data, byte_size, old_dims, frame); else if (array.is_uint64_type ()) - get_data_and_bytesize (array.uint64_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.uint64_array_value (), data, byte_size, old_dims, frame); else assert (0); } else if (array.is_complex_type ()) { if (array.is_single_type ()) - get_data_and_bytesize (array.float_complex_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.float_complex_array_value (), data, byte_size, old_dims, frame); else - get_data_and_bytesize (array.complex_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.complex_array_value (), data, byte_size, old_dims, frame); } else if (array.is_real_type ()) { if (array.is_single_type ()) - get_data_and_bytesize (array.float_array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.float_array_value (), data, byte_size, old_dims, frame); else - get_data_and_bytesize (array.array_value (), data, byte_size, old_dims); + get_data_and_bytesize (array.array_value (), data, byte_size, old_dims, frame); } else error ("typecast: invalid input class: %s", array.class_name ().c_str ()); diff --git a/src/DLD-FUNCTIONS/urlwrite.cc b/src/DLD-FUNCTIONS/urlwrite.cc --- a/src/DLD-FUNCTIONS/urlwrite.cc +++ b/src/DLD-FUNCTIONS/urlwrite.cc @@ -804,9 +804,9 @@ return retval; } - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect_safe frame; - unwind_protect::add_fcn (cleanup_urlwrite, filename); + frame.add_fcn (cleanup_urlwrite, filename); bool res; curl_handle curl = curl_handle (url, method, param, ofile, res); @@ -814,9 +814,9 @@ ofile.close (); if (!error_state) - unwind_protect::discard_frame (uwp_frame); + frame.discard (); else - unwind_protect::run_frame (uwp_frame); + frame.run (); if (nargout > 0) { @@ -1426,10 +1426,9 @@ if (! error_state) { - unwind_protect::frame_id_t uwp_frame = - unwind_protect::begin_frame (); + unwind_protect_safe frame; - unwind_protect::add_fcn (reset_path, curl); + frame.add_fcn (reset_path, curl); std::string realdir = base.length() == 0 ? dir : base + file_ops::dir_sep_str () + dir; @@ -1491,8 +1490,6 @@ else error ("__ftp_mput__: can not read the directory ""%s""", realdir.c_str()); - - unwind_protect::run_frame (uwp_frame); } return retval; @@ -1602,12 +1599,11 @@ if (! error_state) { - unwind_protect::frame_id_t uwp_frame = - unwind_protect::begin_frame (); + unwind_protect_safe frame; - unwind_protect::add_fcn (reset_path, curl); + frame.add_fcn (reset_path, curl); - string_vector sv = curl.list (); + string_vector sv = curl.list (); for (octave_idx_type i = 0; i < sv.length (); i++) { @@ -1632,26 +1628,23 @@ break; } - unwind_protect::frame_id_t uwp_frame2 = - unwind_protect::begin_frame (); + unwind_protect_safe frame2; - unwind_protect::add_fcn (delete_file, realfile); + frame2.add_fcn (delete_file, realfile); curl.get (sv(i), ofile); ofile.close (); if (!error_state) - unwind_protect::discard_frame (uwp_frame2); + frame2.discard (); else - unwind_protect::run_frame (uwp_frame2); + frame2.run (); } if (error_state) break; } - - unwind_protect::run_frame (uwp_frame); } } } @@ -1713,19 +1706,18 @@ break; } - unwind_protect::frame_id_t uwp_frame = - unwind_protect::begin_frame (); + unwind_protect_safe frame; - unwind_protect::add_fcn (delete_file, target + sv(i)); + frame.add_fcn (delete_file, target + sv(i)); curl.get (sv(i), ofile); ofile.close (); if (!error_state) - unwind_protect::discard_frame (uwp_frame); + frame.discard (); else - unwind_protect::run_frame (uwp_frame); + frame.run (); } if (error_state) diff --git a/src/debug.cc b/src/debug.cc --- a/src/debug.cc +++ b/src/debug.cc @@ -661,10 +661,10 @@ octave_stdout << name << ":"; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::add_fcn (octave_call_stack::restore_frame, - octave_call_stack::current_frame ()); + frame.add_fcn (octave_call_stack::restore_frame, + octave_call_stack::current_frame ()); // Skip the frame assigned to the dbwhere function. octave_call_stack::goto_frame_relative (0); @@ -692,8 +692,6 @@ } else octave_stdout << " (unknown line)\n"; - - unwind_protect::run_frame (uwp_frame); } else error ("dbwhere: must be inside of a user function to use dbwhere\n"); @@ -860,7 +858,7 @@ { octave_value_list retval; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; octave_idx_type curr_frame = -1; @@ -924,8 +922,6 @@ } } - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/dynamic-ld.cc b/src/dynamic-ld.cc --- a/src/dynamic-ld.cc +++ b/src/dynamic-ld.cc @@ -334,9 +334,9 @@ { octave_function *retval = 0; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (octave_dynamic_loader::doing_load); + frame.protect_var (octave_dynamic_loader::doing_load); doing_load = true; @@ -384,8 +384,6 @@ file_name.c_str ()); } - unwind_protect::run_frame (uwp_frame); - return retval; } @@ -396,9 +394,9 @@ { octave_function *retval = 0; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (octave_dynamic_loader::doing_load); + frame.protect_var (octave_dynamic_loader::doing_load); doing_load = true; @@ -455,8 +453,6 @@ file_name.c_str ()); } - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/error.cc b/src/error.cc --- a/src/error.cc +++ b/src/error.cc @@ -486,7 +486,8 @@ && Vdebug_on_error && init_state == 0 && octave_call_stack::caller_user_code ()) { - unwind_protect::protect_var (Vdebug_on_error); + unwind_protect frame; + frame.protect_var (Vdebug_on_error); Vdebug_on_error = false; error_state = 0; @@ -494,8 +495,6 @@ pr_where ("error"); do_keyboard (octave_value_list ()); - - unwind_protect::run (); } } @@ -677,12 +676,11 @@ && Vdebug_on_warning && octave_call_stack::caller_user_code ()) { - unwind_protect::protect_var (Vdebug_on_warning); + unwind_protect frame; + frame.protect_var (Vdebug_on_warning); Vdebug_on_warning = false; do_keyboard (octave_value_list ()); - - unwind_protect::run (); } } } @@ -1524,9 +1522,9 @@ octave_value retval; int nargin = args.length(); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (error_state); + frame.protect_var (error_state); error_state = 0; if (nargin < 2) @@ -1631,8 +1629,6 @@ else print_usage (); - unwind_protect::run_frame (uwp_frame); - return retval; } @@ -1646,9 +1642,9 @@ { octave_value_list retval; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (error_state); + frame.protect_var (error_state); error_state = 0; int argc = args.length () + 1; @@ -1680,8 +1676,6 @@ else print_usage (); - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/graphics.cc b/src/graphics.cc --- a/src/graphics.cc +++ b/src/graphics.cc @@ -2290,10 +2290,10 @@ // ask whether it is OK to delete the listener for the given // property. How can we know in advance that it will be OK? - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); - - unwind_protect::protect_var (discard_error_messages); - unwind_protect::protect_var (error_state); + unwind_protect frame; + + frame.protect_var (discard_error_messages); + frame.protect_var (error_state); discard_error_messages = true; @@ -2301,8 +2301,6 @@ if (! error_state && p.ok ()) p.delete_listener (); - - unwind_protect::run_frame (uwp_frame); } } @@ -3859,7 +3857,9 @@ } - unwind_protect::protect_var (updating_axis_limits); + unwind_protect frame; + frame.protect_var (updating_axis_limits); + updating_axis_limits = true; switch (update_type) @@ -3897,8 +3897,6 @@ } xproperties.update_transform (); - - unwind_protect::run (); } inline @@ -4501,8 +4499,8 @@ else args(1) = Matrix (); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); - unwind_protect::add_fcn (gh_manager::restore_gcbo); + unwind_protect_safe frame; + frame.add_fcn (gh_manager::restore_gcbo); if (true) { @@ -4551,8 +4549,6 @@ feval (fcn, args); END_INTERRUPT_WITH_EXCEPTIONS; - - unwind_protect::run_frame (uwp_frame); } void @@ -5381,10 +5377,10 @@ gh_manager::lock (); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); - unwind_protect::protect_var (Vdrawnow_requested, false); - - unwind_protect::protect_var (drawnow_executing); + unwind_protect frame; + frame.protect_var (Vdrawnow_requested, false); + + frame.protect_var (drawnow_executing); if (++drawnow_executing <= 1) { @@ -5519,8 +5515,6 @@ print_usage (); } - unwind_protect::run_frame (uwp_frame); - gh_manager::unlock (); return retval; diff --git a/src/help.cc b/src/help.cc --- a/src/help.cc +++ b/src/help.cc @@ -666,13 +666,12 @@ bool retval = false; // FIXME -- this is a bit of a kluge... - unwind_protect::protect_var (reading_script_file); + unwind_protect frame; + frame.protect_var (reading_script_file); reading_script_file = true; h = get_help_from_file (nm, symbol_found, file); - unwind_protect::run (); - if (h.length () > 0) retval = true; diff --git a/src/input.cc b/src/input.cc --- a/src/input.cc +++ b/src/input.cc @@ -686,9 +686,9 @@ if (! msg.empty ()) std::cerr << msg << std::endl; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (VPS1); + frame.protect_var (VPS1); VPS1 = prompt; if (stdin_is_tty) @@ -701,32 +701,33 @@ || input_from_startup_file || input_from_command_line_file)) { - unwind_protect::protect_var (forced_interactive); + frame.protect_var (forced_interactive); forced_interactive = true; - unwind_protect::protect_var (reading_fcn_file); + frame.protect_var (reading_fcn_file); reading_fcn_file = false; - unwind_protect::protect_var (reading_classdef_file); + frame.protect_var (reading_classdef_file); reading_classdef_file = false; - unwind_protect::protect_var (reading_script_file); + frame.protect_var (reading_script_file); reading_script_file = false; - unwind_protect::protect_var (input_from_startup_file); + frame.protect_var (input_from_startup_file); input_from_startup_file = false; - unwind_protect::protect_var (input_from_command_line_file); + frame.protect_var (input_from_command_line_file); input_from_command_line_file = false; - unwind_protect::protect_var (get_input_from_eval_string); + frame.protect_var (get_input_from_eval_string); get_input_from_eval_string = false; YY_BUFFER_STATE old_buf = current_buffer (); YY_BUFFER_STATE new_buf = create_buffer (get_input_from_stdin ()); - unwind_protect::add_fcn (switch_to_buffer, old_buf); - unwind_protect::add_fcn (delete_buffer, new_buf); + // FIXME: are these safe? + frame.add_fcn (switch_to_buffer, old_buf); + frame.add_fcn (delete_buffer, new_buf); switch_to_buffer (new_buf); } @@ -738,12 +739,12 @@ reset_parser (); // Save current value of global_command. - unwind_protect::protect_var (global_command); + frame.protect_var (global_command); // Do this with an unwind-protect cleanup function so that the // forced variables will be unmarked in the event of an interrupt. symbol_table::scope_id scope = symbol_table::top_scope (); - unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope); + frame.add_fcn (symbol_table::unmark_forced_variables, scope); // This is the same as yyparse in parse.y. int retval = octave_parse (); @@ -767,18 +768,14 @@ } // Unmark forced variables. - unwind_protect::run (); - // Restore previous value of global_command. - unwind_protect::run (); + frame.run_top (2); OCTAVE_QUIT; } } else warning ("invalid attempt to debug script read from stdin"); - - unwind_protect::run_frame (uwp_frame); } // If the user simply hits return, this will produce an empty matrix. @@ -960,20 +957,20 @@ assert (nargin == 0 || nargin == 1); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; // FIXME -- we shouldn't need both the // command_history object and the // Vsaving_history variable... command_history::ignore_entries (false); - unwind_protect::add_fcn (command_history::ignore_entries, ! Vsaving_history); + frame.add_fcn (command_history::ignore_entries, ! Vsaving_history); - unwind_protect::protect_var (Vsaving_history); - unwind_protect::protect_var (Vdebugging); + frame.protect_var (Vsaving_history); + frame.protect_var (Vdebugging); - unwind_protect::add_fcn (octave_call_stack::restore_frame, - octave_call_stack::current_frame ()); + frame.add_fcn (octave_call_stack::restore_frame, + octave_call_stack::current_frame ()); // FIXME -- probably we just want to print one line, not the // entire statement, which might span many lines... @@ -991,8 +988,6 @@ if (! error_state) get_debug_input (prompt); - unwind_protect::run_frame (uwp_frame); - return retval; } @@ -1019,15 +1014,14 @@ if (nargin == 0 || nargin == 1) { - unwind_protect::add_fcn (octave_call_stack::restore_frame, - octave_call_stack::current_frame ()); + unwind_protect frame; + frame.add_fcn (octave_call_stack::restore_frame, + octave_call_stack::current_frame ()); // Skip the frame assigned to the keyboard function. octave_call_stack::goto_frame_relative (0); do_keyboard (args); - - unwind_protect::run (); } else print_usage (); diff --git a/src/load-path.cc b/src/load-path.cc --- a/src/load-path.cc +++ b/src/load-path.cc @@ -562,7 +562,8 @@ // Temporarily disable add hook. - unwind_protect::protect_var (add_hook); + unwind_protect frame; + frame.protect_var (add_hook); add_hook = 0; @@ -574,8 +575,7 @@ do_append (*i, warn); // Restore add hook and execute for all newly added directories. - - unwind_protect::run (); + frame.run_top (); for (dir_info_list_iterator i = dir_info_list.begin (); i != dir_info_list.end (); @@ -1820,9 +1820,9 @@ if (! octave_interpreter_ready) return; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); - - unwind_protect::protect_var (input_from_startup_file); + unwind_protect frame; + + frame.protect_var (input_from_startup_file); input_from_startup_file = true; @@ -1832,8 +1832,6 @@ if (fs.exists ()) source_file (file, "base"); - - unwind_protect::run_frame (uwp_frame); } void diff --git a/src/ls-mat4.cc b/src/ls-mat4.cc --- a/src/ls-mat4.cc +++ b/src/ls-mat4.cc @@ -492,7 +492,7 @@ if (tc.is_string ()) { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; charMatrix chm = tc.char_matrix_value (); @@ -510,8 +510,6 @@ buf[j*nrow+i] = static_cast (*s++ & 0x00FF); } os.write (reinterpret_cast (buf), nrow*ncol*sizeof(double)); - - unwind_protect::run_frame (uwp_frame); } else if (tc.is_range ()) { diff --git a/src/ls-mat5.cc b/src/ls-mat5.cc --- a/src/ls-mat5.cc +++ b/src/ls-mat5.cc @@ -869,18 +869,18 @@ tc2 = m2.contents("MCOS")(0).cell_value()(1 + off).cell_value()(1); m2 = tc2.map_value(); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect_safe frame; // Set up temporary scope to use for evaluating the text // that defines the anonymous function. symbol_table::scope_id local_scope = symbol_table::alloc_scope (); - unwind_protect::add_fcn (symbol_table::erase_scope, local_scope); + frame.add_fcn (symbol_table::erase_scope, local_scope); symbol_table::set_scope (local_scope); octave_call_stack::push (local_scope, 0); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); if (m2.nfields() > 0) { @@ -919,7 +919,7 @@ goto skip_ahead; } - unwind_protect::run_frame (uwp_frame); + frame.run (); } else { diff --git a/src/mex.cc b/src/mex.cc --- a/src/mex.cc +++ b/src/mex.cc @@ -3038,14 +3038,14 @@ for (int i = 0; i < nout; i++) argout[i] = 0; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect_safe frame; // Save old mex pointer. - unwind_protect::protect_var (mex_context); + frame.protect_var (mex_context); mex context (curr_mex_fcn); - unwind_protect::add (mex::cleanup, static_cast (&context)); + frame.add (mex::cleanup, static_cast (&context)); for (int i = 0; i < nargin; i++) argin[i] = context.make_value (args(i)); @@ -3090,7 +3090,7 @@ } // Clean up mex resources. - unwind_protect::run_frame (uwp_frame); + frame.run (); return retval; } @@ -3270,7 +3270,7 @@ { // FIXME -- should this be in variables.cc? - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; bool caller = ! strcmp (space, "caller"); bool base = ! strcmp (space, "base"); @@ -3283,14 +3283,12 @@ octave_call_stack::goto_base_frame (); if (! error_state) - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); val = symbol_table::varval (name); } else mexErrMsgTxt ("mexGetVariable: symbol table does not exist"); - - unwind_protect::run_frame (uwp_frame); } if (val.is_defined ()) @@ -3330,7 +3328,7 @@ { // FIXME -- should this be in variables.cc? - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; bool caller = ! strcmp (space, "caller"); bool base = ! strcmp (space, "base"); @@ -3343,14 +3341,12 @@ octave_call_stack::goto_base_frame (); if (! error_state) - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); symbol_table::varref (name) = mxArray::as_octave_value (ptr); } else mexErrMsgTxt ("mexPutVariable: symbol table does not exist"); - - unwind_protect::run_frame (uwp_frame); } return 0; diff --git a/src/oct-hist.cc b/src/oct-hist.cc --- a/src/oct-hist.cc +++ b/src/oct-hist.cc @@ -424,6 +424,11 @@ return name; } +static void unlink_cleanup (const char *file) +{ + unlink (file); +} + static void do_edit_history (int argc, const string_vector& argv) { @@ -480,22 +485,16 @@ // Turn on command echo, so the output from this will make better // sense. - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (Vecho_executing_commands); - unwind_protect::protect_var (input_from_tmp_history_file); + frame.add_fcn (unlink_cleanup, name.c_str ()); + frame.protect_var (Vecho_executing_commands); + frame.protect_var (input_from_tmp_history_file); Vecho_executing_commands = ECHO_CMD_LINE; input_from_tmp_history_file = true; source_file (name); - - unwind_protect::run_frame (uwp_frame); - - // Delete the temporary file. Should probably be done with an - // unwind_protect. - - unlink (name.c_str ()); } static void @@ -509,23 +508,16 @@ // Turn on command echo so the output from this will make better // sense. - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (Vecho_executing_commands); - unwind_protect::protect_var (input_from_tmp_history_file); + frame.add_fcn (unlink_cleanup, name.c_str ()); + frame.protect_var (Vecho_executing_commands); + frame.protect_var (input_from_tmp_history_file); Vecho_executing_commands = ECHO_CMD_LINE; input_from_tmp_history_file = true; source_file (name); - - unwind_protect::run_frame (uwp_frame); - - // Delete the temporary file. - - // FIXME -- should probably be done using an unwind_protect. - - unlink (name.c_str ()); } void diff --git a/src/octave.cc b/src/octave.cc --- a/src/octave.cc +++ b/src/octave.cc @@ -291,9 +291,9 @@ static void execute_startup_files (void) { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (input_from_startup_file); + frame.protect_var (input_from_startup_file); input_from_startup_file = true; @@ -367,28 +367,26 @@ source_file (local_rc, context, verbose, require_file); } } - - unwind_protect::run_frame (uwp_frame); } static int execute_eval_option_code (const std::string& code) { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; octave_save_signal_mask (); can_interrupt = true; octave_signal_hook = octave_signal_handler; - octave_interrupt_hook = unwind_protect::run_all; - octave_bad_alloc_hook = unwind_protect::run_all; + octave_interrupt_hook = 0; + octave_bad_alloc_hook = 0; octave_catch_interrupts (); octave_initialized = true; - unwind_protect::protect_var (interactive); + frame.protect_var (interactive); interactive = false; @@ -411,37 +409,35 @@ << std::endl; } - unwind_protect::run_frame (uwp_frame); - return parse_status; } static void execute_command_line_file (const std::string& fname) { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; octave_save_signal_mask (); can_interrupt = true; octave_signal_hook = octave_signal_handler; - octave_interrupt_hook = unwind_protect::run_all; - octave_bad_alloc_hook = unwind_protect::run_all; + octave_interrupt_hook = 0; + octave_bad_alloc_hook = 0; octave_catch_interrupts (); octave_initialized = true; - unwind_protect::protect_var (interactive); - unwind_protect::protect_var (reading_script_file); - unwind_protect::protect_var (input_from_command_line_file); + frame.protect_var (interactive); + frame.protect_var (reading_script_file); + frame.protect_var (input_from_command_line_file); - unwind_protect::protect_var (curr_fcn_file_name); - unwind_protect::protect_var (curr_fcn_file_full_name); + frame.protect_var (curr_fcn_file_name); + frame.protect_var (curr_fcn_file_full_name); - unwind_protect::protect_var (octave_program_invocation_name); - unwind_protect::protect_var (octave_program_name); + frame.protect_var (octave_program_invocation_name); + frame.protect_var (octave_program_name); interactive = false; reading_script_file = true; @@ -479,8 +475,6 @@ std::cerr << "error: memory exhausted or requested size too large for range of Octave's index type -- execution of " << fname << " failed" << std::endl; } - - unwind_protect::run_frame (uwp_frame); } // Usage message with extra help. diff --git a/src/ov-builtin.cc b/src/ov-builtin.cc --- a/src/ov-builtin.cc +++ b/src/ov-builtin.cc @@ -96,11 +96,11 @@ ::error ("invalid use of colon in function argument list"); else { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; octave_call_stack::push (this); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); try { @@ -113,8 +113,6 @@ { gripe_library_execution_error (); } - - unwind_protect::run_frame (uwp_frame); } return retval; diff --git a/src/ov-class.cc b/src/ov-class.cc --- a/src/ov-class.cc +++ b/src/ov-class.cc @@ -578,12 +578,11 @@ if (obsolete_copies == 0 && meth.is_user_function () && meth.user_function_value ()->subsasgn_optimization_ok ()) { - unwind_protect::protect_var (obsolete_copies); + unwind_protect frame; + frame.protect_var (obsolete_copies); obsolete_copies = 2; tmp = feval (meth.function_value (), args); - - unwind_protect::run (); } else tmp = feval (meth.function_value (), args); @@ -983,15 +982,13 @@ void octave_class::print_raw (std::ostream& os, bool) const { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (Vstruct_levels_to_print); + frame.protect_var (Vstruct_levels_to_print); indent (os); os << " "; newline (os); - - unwind_protect::run_frame (uwp_frame); } bool diff --git a/src/ov-fcn-handle.cc b/src/ov-fcn-handle.cc --- a/src/ov-fcn-handle.cc +++ b/src/ov-fcn-handle.cc @@ -379,18 +379,18 @@ pos = is.tellg (); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect_safe frame; // Set up temporary scope to use for evaluating the text that // defines the anonymous function. symbol_table::scope_id local_scope = symbol_table::alloc_scope (); - unwind_protect::add_fcn (symbol_table::erase_scope, local_scope); + frame.add_fcn (symbol_table::erase_scope, local_scope); symbol_table::set_scope (local_scope); octave_call_stack::push (local_scope, 0); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); octave_idx_type len = 0; @@ -450,8 +450,6 @@ } else success = false; - - unwind_protect::run_frame (uwp_frame); } else success = set_fcn (octaveroot, fpath); @@ -560,18 +558,18 @@ OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1); is.get (ctmp2, tmp+1, 0); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect_safe frame; // Set up temporary scope to use for evaluating the text that // defines the anonymous function. symbol_table::scope_id local_scope = symbol_table::alloc_scope (); - unwind_protect::add_fcn (symbol_table::erase_scope, local_scope); + frame.add_fcn (symbol_table::erase_scope, local_scope); symbol_table::set_scope (local_scope); octave_call_stack::push (local_scope, 0); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); if (len > 0) { @@ -620,8 +618,6 @@ else success = false; } - - unwind_protect::run_frame (uwp_frame); } else { @@ -1057,18 +1053,18 @@ H5Eset_auto (err_func, err_func_data); #endif - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect_safe frame; // Set up temporary scope to use for evaluating the text that // defines the anonymous function. symbol_table::scope_id local_scope = symbol_table::alloc_scope (); - unwind_protect::add_fcn (symbol_table::erase_scope, local_scope); + frame.add_fcn (symbol_table::erase_scope, local_scope); symbol_table::set_scope (local_scope); octave_call_stack::push (local_scope, 0); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); if (len > 0 && success) { @@ -1132,7 +1128,7 @@ success = false; } - unwind_protect::run_frame (uwp_frame); + frame.run (); } else { diff --git a/src/ov-list.cc b/src/ov-list.cc --- a/src/ov-list.cc +++ b/src/ov-list.cc @@ -293,7 +293,7 @@ void octave_list::print_raw (std::ostream& os, bool) const { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; octave_idx_type n = data.length (); @@ -325,8 +325,6 @@ os << "()"; newline (os); - - unwind_protect::run_frame (uwp_frame); } bool diff --git a/src/ov-mex-fcn.cc b/src/ov-mex-fcn.cc --- a/src/ov-mex-fcn.cc +++ b/src/ov-mex-fcn.cc @@ -139,11 +139,11 @@ ::error ("invalid use of colon in function argument list"); else { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; octave_call_stack::push (this); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); try { @@ -153,8 +153,6 @@ { gripe_library_execution_error (); } - - unwind_protect::run_frame (uwp_frame); } return retval; diff --git a/src/ov-struct.cc b/src/ov-struct.cc --- a/src/ov-struct.cc +++ b/src/ov-struct.cc @@ -580,9 +580,9 @@ void octave_struct::print_raw (std::ostream& os, bool) const { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (Vstruct_levels_to_print); + frame.protect_var (Vstruct_levels_to_print); if (Vstruct_levels_to_print >= 0) { @@ -647,8 +647,6 @@ os << ""; newline (os); } - - unwind_protect::run_frame (uwp_frame); } bool diff --git a/src/ov-usr-fcn.cc b/src/ov-usr-fcn.cc --- a/src/ov-usr-fcn.cc +++ b/src/ov-usr-fcn.cc @@ -114,7 +114,7 @@ { octave_value_list retval; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; if (! error_state) { @@ -122,16 +122,16 @@ { if (cmd_list) { - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth < Vmax_recursion_depth) { octave_call_stack::push (this); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); - unwind_protect::protect_var (tree_evaluator::in_fcn_or_script_body); + frame.protect_var (tree_evaluator::in_fcn_or_script_body); tree_evaluator::in_fcn_or_script_body = true; cmd_list->accept (*current_evaluator); @@ -153,8 +153,6 @@ error ("invalid call to script %s", file_name.c_str ()); } - unwind_protect::run_frame (uwp_frame); - return retval; } @@ -334,15 +332,14 @@ int nargin = args.length (); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (call_depth); + frame.protect_var (call_depth); call_depth++; if (call_depth >= Vmax_recursion_depth) { ::error ("max_recursion_limit exceeded"); - unwind_protect::run_frame (uwp_frame); return retval; } @@ -350,13 +347,13 @@ // eval_undefined_error(). octave_call_stack::push (this, local_scope, call_depth); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); if (call_depth > 0) { symbol_table::push_context (); - unwind_protect::add_fcn (symbol_table::pop_context); + frame.add_fcn (symbol_table::pop_context); } string_vector arg_names = args.name_tags (); @@ -365,7 +362,7 @@ { param_list->define_from_arg_vector (args); if (error_state) - goto abort; + return retval; } // Force parameter list to be undefined when this function exits. @@ -373,16 +370,14 @@ // variables that are also named function parameters. if (param_list) - unwind_protect::add_method (param_list, - &tree_parameter_list::undefine); + frame.add_method (param_list, &tree_parameter_list::undefine); // Force return list to be undefined when this function exits. // Doing so decrements the reference counts on the values of local // variables that are also named values returned by this function. if (ret_list) - unwind_protect::add_method (ret_list, - &tree_parameter_list::undefine); + frame.add_method (ret_list, &tree_parameter_list::undefine); if (call_depth == 0) { @@ -396,89 +391,80 @@ // declared global will be unmarked as global before they are // undefined by the clear_param_list cleanup function. - unwind_protect::add_fcn (symbol_table::clear_variables); + frame.add_fcn (symbol_table::clear_variables); } - // The following code is in a separate scope to avoid warnings from - // G++ about `goto abort' crossing the initialization of some - // variables. + bind_automatic_vars (arg_names, nargin, nargout, all_va_args (args)); - { - bind_automatic_vars (arg_names, nargin, nargout, all_va_args (args)); + bool echo_commands = (Vecho_executing_commands & ECHO_FUNCTIONS); - bool echo_commands = (Vecho_executing_commands & ECHO_FUNCTIONS); + if (echo_commands) + print_code_function_header (); - if (echo_commands) - print_code_function_header (); - - // Evaluate the commands that make up the function. + // Evaluate the commands that make up the function. - unwind_protect::protect_var (tree_evaluator::in_fcn_or_script_body); - tree_evaluator::in_fcn_or_script_body = true; + frame.protect_var (tree_evaluator::in_fcn_or_script_body); + tree_evaluator::in_fcn_or_script_body = true; - bool special_expr = (is_inline_function () - || cmd_list->is_anon_function_body ()); + bool special_expr = (is_inline_function () + || cmd_list->is_anon_function_body ()); - if (special_expr) - { - assert (cmd_list->length () == 1); + if (special_expr) + { + assert (cmd_list->length () == 1); - tree_statement *stmt = 0; + tree_statement *stmt = 0; - if ((stmt = cmd_list->front ()) - && stmt->is_expression ()) - { - tree_expression *expr = stmt->expression (); + if ((stmt = cmd_list->front ()) + && stmt->is_expression ()) + { + tree_expression *expr = stmt->expression (); - retval = expr->rvalue (nargout); - } - } - else - cmd_list->accept (*current_evaluator); + retval = expr->rvalue (nargout); + } + } + else + cmd_list->accept (*current_evaluator); - if (echo_commands) - print_code_function_trailer (); + if (echo_commands) + print_code_function_trailer (); - if (tree_return_command::returning) - tree_return_command::returning = 0; + if (tree_return_command::returning) + tree_return_command::returning = 0; - if (tree_break_command::breaking) - tree_break_command::breaking--; + if (tree_break_command::breaking) + tree_break_command::breaking--; - if (error_state) - { - octave_call_stack::backtrace_error_message (); - goto abort; - } - - // Copy return values out. + if (error_state) + { + octave_call_stack::backtrace_error_message (); + return retval; + } + + // Copy return values out. - if (ret_list && ! special_expr) - { - ret_list->initialize_undefined_elements (my_name, nargout, Matrix ()); - - Cell varargout; + if (ret_list && ! special_expr) + { + ret_list->initialize_undefined_elements (my_name, nargout, Matrix ()); - if (ret_list->takes_varargs ()) - { - octave_value varargout_varval = symbol_table::varval ("varargout"); + Cell varargout; - if (varargout_varval.is_defined ()) - { - varargout = varargout_varval.cell_value (); + if (ret_list->takes_varargs ()) + { + octave_value varargout_varval = symbol_table::varval ("varargout"); - if (error_state) - error ("expecting varargout to be a cell array object"); - } - } + if (varargout_varval.is_defined ()) + { + varargout = varargout_varval.cell_value (); - if (! error_state) - retval = ret_list->convert_to_const_vector (nargout, varargout); - } - } + if (error_state) + error ("expecting varargout to be a cell array object"); + } + } - abort: - unwind_protect::run_frame (uwp_frame); + if (! error_state) + retval = ret_list->convert_to_const_vector (nargout, varargout); + } return retval; } diff --git a/src/pager.cc b/src/pager.cc --- a/src/pager.cc +++ b/src/pager.cc @@ -364,10 +364,10 @@ { if (! flushing_output_to_pager) { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (really_flush_to_pager); - unwind_protect::protect_var (flushing_output_to_pager); + frame.protect_var (really_flush_to_pager); + frame.protect_var (flushing_output_to_pager); really_flush_to_pager = true; flushing_output_to_pager = true; @@ -375,8 +375,6 @@ octave_stdout.flush (); clear_external_pager (); - - unwind_protect::run_frame (uwp_frame); } } diff --git a/src/pr-output.cc b/src/pr-output.cc --- a/src/pr-output.cc +++ b/src/pr-output.cc @@ -3205,9 +3205,9 @@ print_usage (); else { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); - - unwind_protect::protect_var (rat_string_len); + unwind_protect frame; + + frame.protect_var (rat_string_len); rat_string_len = 9; @@ -3220,7 +3220,7 @@ if (arg.is_numeric_type ()) { - unwind_protect::protect_var (rat_format); + frame.protect_var (rat_format); rat_format = true; @@ -3254,8 +3254,6 @@ else error ("rats: expecting numeric input"); } - - unwind_protect::run_frame (uwp_frame); } return retval; diff --git a/src/pt-arg-list.cc b/src/pt-arg-list.cc --- a/src/pt-arg-list.cc +++ b/src/pt-arg-list.cc @@ -163,11 +163,11 @@ && ! (object->is_function () || object->is_function_handle ())); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; if (stash_object) { - unwind_protect::protect_var (indexed_object); + frame.protect_var (indexed_object); indexed_object = object; } @@ -181,8 +181,8 @@ { if (stash_object) { - unwind_protect::protect_var (index_position); - unwind_protect::protect_var (num_indices); + frame.protect_var (index_position); + frame.protect_var (num_indices); index_position = k; num_indices = len; @@ -215,8 +215,6 @@ } } - unwind_protect::run_frame (uwp_frame); - return args; } diff --git a/src/pt-eval.cc b/src/pt-eval.cc --- a/src/pt-eval.cc +++ b/src/pt-eval.cc @@ -279,9 +279,9 @@ if (debug_mode) do_breakpoint (cmd.is_breakpoint ()); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (in_loop_command); + frame.protect_var (in_loop_command); in_loop_command = true; @@ -290,7 +290,7 @@ octave_value rhs = expr->rvalue1 (); if (error_state || rhs.is_undefined ()) - goto cleanup; + return; { tree_expression *lhs = cmd.left_hand_side (); @@ -298,7 +298,7 @@ octave_lvalue ult = lhs->lvalue (); if (error_state) - goto cleanup; + return; tree_statement_list *loop_body = cmd.body (); @@ -387,9 +387,6 @@ cmd.line (), cmd.column ()); } } - - cleanup: - unwind_protect::run_frame (uwp_frame); } void @@ -401,9 +398,9 @@ if (debug_mode) do_breakpoint (cmd.is_breakpoint ()); - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (in_loop_command); + frame.protect_var (in_loop_command); in_loop_command = true; @@ -412,7 +409,7 @@ octave_value rhs = expr->rvalue1 (); if (error_state || rhs.is_undefined ()) - goto cleanup; + return; if (rhs.is_map ()) { @@ -462,9 +459,6 @@ } else error ("in statement `for [X, Y] = VAL', VAL must be a structure"); - - cleanup: - unwind_protect::run_frame (uwp_frame); } void @@ -819,49 +813,14 @@ cmd.line (), cmd.column ()); } -static void -do_catch_code (tree_statement_list *list) -{ - // Is it safe to call OCTAVE_QUIT here? We are already running - // something on the unwind_protect stack, but the element for this - // action would have already been popped from the top of the stack, - // so we should not be attempting to run it again. - - OCTAVE_QUIT; - - // If we are interrupting immediately, or if an interrupt is in - // progress (octave_interrupt_state < 0), then we don't want to run - // the catch code (it should only run on errors, not interrupts). - - // If octave_interrupt_state is positive, an interrupt is pending. - // The only way that could happen would be for the interrupt to - // come in after the OCTAVE_QUIT above and before the if statement - // below -- it's possible, but unlikely. In any case, we should - // probably let the catch code throw the exception because we don't - // want to skip that and potentially run some other code. For - // example, an error may have originally brought us here for some - // cleanup operation and we shouldn't skip that. - - if (octave_interrupt_immediately || octave_interrupt_state < 0) - return; - - // Set up for letting the user print any messages from errors that - // occurred in the body of the try_catch statement. - - buffer_error_messages--; - - if (list) - list->accept (*current_evaluator); -} - void tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (buffer_error_messages); - unwind_protect::protect_var (Vdebug_on_error); - unwind_protect::protect_var (Vdebug_on_warning); + 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; @@ -869,37 +828,40 @@ tree_statement_list *catch_code = cmd.cleanup (); - unwind_protect::add_fcn (do_catch_code, catch_code); + // The catch code is *not* added to unwind_protect stack; it doesn't need + // to be run on interrupts. tree_statement_list *try_code = cmd.body (); if (try_code) - try_code->accept (*this); + { + try_code->accept (*this); + // FIXME: should std::bad_alloc be handled here? + } - if (catch_code && error_state) - { - error_state = 0; - unwind_protect::run_frame (uwp_frame); - } - else + if (error_state) { error_state = 0; - // Unwind stack elements must be cleared or run in the reverse - // order in which they were added to the stack. + if (catch_code) + { + // Set up for letting the user print any messages from errors that + // occurred in the body of the try_catch statement. - // For clearing the do_catch_code cleanup function. - unwind_protect::discard (); + buffer_error_messages--; - // Run the rest of the frame. - unwind_protect::run_frame (uwp_frame); + if (catch_code) + catch_code->accept (*this); + } } } -static void -do_unwind_protect_cleanup_code (tree_statement_list *list) +void +tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list) { - unwind_protect::protect_var (octave_interrupt_state); + unwind_protect frame; + + frame.protect_var (octave_interrupt_state); octave_interrupt_state = 0; // We want to run the cleanup code without error_state being set, @@ -907,7 +869,7 @@ // in the first part of the unwind_protect are not completely // ignored. - unwind_protect::protect_var (error_state); + frame.protect_var (error_state); error_state = 0; // Similarly, if we have seen a return or break statement, allow all @@ -915,14 +877,14 @@ // We don't have to worry about continue statements because they can // only occur in loops. - unwind_protect::protect_var (tree_return_command::returning); + frame.protect_var (tree_return_command::returning); tree_return_command::returning = 0; - unwind_protect::protect_var (tree_break_command::breaking); + frame.protect_var (tree_break_command::breaking); tree_break_command::breaking = 0; if (list) - list->accept (*current_evaluator); + list->accept (*this); // The unwind_protects are popped off the stack in the reverse of // the order they are pushed on. @@ -953,13 +915,11 @@ if (tree_break_command::breaking || tree_return_command::returning) { - unwind_protect::discard (); - unwind_protect::discard (); + frame.discard_top (2); } else { - unwind_protect::run (); - unwind_protect::run (); + frame.run_top (2); } // We don't want to ignore errors that occur in the cleanup code, so @@ -967,11 +927,11 @@ // Otherwise, set it back to what it was before. if (error_state) - unwind_protect::discard (); + frame.discard_top (); else - unwind_protect::run (); + frame.run_top (); - unwind_protect::run (); + frame.run (); } void @@ -979,14 +939,27 @@ { tree_statement_list *cleanup_code = cmd.cleanup (); - unwind_protect::add_fcn (do_unwind_protect_cleanup_code, cleanup_code); - tree_statement_list *unwind_protect_code = cmd.body (); if (unwind_protect_code) - unwind_protect_code->accept (*this); + { + try + { + unwind_protect_code->accept (*this); + } + catch (...) + { + // Run the cleanup code on exceptions, so that it is run even in case + // of interrupt or out-of-memory. + do_unwind_protect_cleanup_code (cleanup_code); + // FIXME: should error_state be checked here? + // We want to rethrow the exception, even if error_state is set, so + // that interrupts continue. + throw; + } - unwind_protect::run (); + do_unwind_protect_cleanup_code (cleanup_code); + } } void @@ -995,9 +968,9 @@ if (error_state) return; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (in_loop_command); + frame.protect_var (in_loop_command); in_loop_command = true; @@ -1020,7 +993,7 @@ loop_body->accept (*this); if (error_state) - goto cleanup; + return; } if (quit_loop_now ()) @@ -1029,9 +1002,6 @@ else break; } - - cleanup: - unwind_protect::run_frame (uwp_frame); } void @@ -1040,9 +1010,9 @@ if (error_state) return; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (in_loop_command); + frame.protect_var (in_loop_command); in_loop_command = true; @@ -1060,7 +1030,7 @@ loop_body->accept (*this); if (error_state) - goto cleanup; + return; } if (quit_loop_now ()) @@ -1072,9 +1042,6 @@ if (expr->is_logically_true ("do-until")) break; } - - cleanup: - unwind_protect::run_frame (uwp_frame); } void diff --git a/src/pt-eval.h b/src/pt-eval.h --- a/src/pt-eval.h +++ b/src/pt-eval.h @@ -126,6 +126,8 @@ void visit_try_catch_command (tree_try_catch_command&); + void do_unwind_protect_cleanup_code (tree_statement_list *list); + void visit_unwind_protect_command (tree_unwind_protect_command&); void visit_while_command (tree_while_command&); diff --git a/src/toplev.cc b/src/toplev.cc --- a/src/toplev.cc +++ b/src/toplev.cc @@ -540,8 +540,8 @@ can_interrupt = true; octave_signal_hook = octave_signal_handler; - octave_interrupt_hook = unwind_protect::run_all; - octave_bad_alloc_hook = unwind_protect::run_all; + octave_interrupt_hook = 0; + octave_bad_alloc_hook = 0; octave_catch_interrupts (); @@ -554,7 +554,7 @@ { try { - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; reset_error_handler (); @@ -564,7 +564,7 @@ // the forced variables will be unmarked in the event of an // interrupt. symbol_table::scope_id scope = symbol_table::top_scope (); - unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope); + frame.add_fcn (symbol_table::unmark_forced_variables, scope); // This is the same as yyparse in parse.y. retval = octave_parse (); @@ -616,8 +616,6 @@ else if (parser_end_of_input) break; } - - unwind_protect::run_frame (uwp_frame); } catch (octave_interrupt_exception) { @@ -797,7 +795,8 @@ if (cmd) { - unwind_protect::add (cleanup_iprocstream, cmd); + unwind_protect frame; + frame.add (cleanup_iprocstream, cmd); if (*cmd) { @@ -835,8 +834,6 @@ retval(0) = cmd_status; retval(1) = output_buf.str (); } - - unwind_protect::run (); } else error ("unable to start subprocess for `%s'", cmd_str.c_str ()); @@ -890,7 +887,7 @@ { octave_value_list retval; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; int nargin = args.length (); @@ -993,8 +990,6 @@ else print_usage (); - unwind_protect::run_frame (uwp_frame); - return retval; } diff --git a/src/unwind-prot.cc b/src/unwind-prot.cc --- a/src/unwind-prot.cc +++ b/src/unwind-prot.cc @@ -33,42 +33,10 @@ #include "unwind-prot.h" #include "utils.h" -std::stack unwind_protect::elt_list; - -std::stack > unwind_protect::tag_list; - -void -unwind_protect::begin_frame (const std::string& tag) -{ - tag_list.push (std::make_pair (tag, begin_frame ())); -} - -void -unwind_protect::run_frame (const std::string& tag) +void unwind_protect_safe::gripe_exception (void) { - while (! tag_list.empty ()) - { - std::pair top = tag_list.top (); - tag_list.pop (); - - run_frame (top.second); - if (top.first == tag) - break; - } -} - -void -unwind_protect::discard_frame (const std::string& tag) -{ - while (! tag_list.empty ()) - { - std::pair top = tag_list.top (); - tag_list.pop (); - - run_frame (top.second); - if (top.first == tag) - break; - } + // FIXME: can this throw an exception? + error ("internal: unhandled exception in unwind_protect handler"); } /* diff --git a/src/unwind-prot.h b/src/unwind-prot.h --- a/src/unwind-prot.h +++ b/src/unwind-prot.h @@ -2,7 +2,7 @@ Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2004, 2005, 2006, 2007, 2008 John W. Eaton -Copyright (C) 2009 VZLU Prague +Copyright (C) 2009, 2010 VZLU Prague This file is part of Octave. @@ -28,9 +28,9 @@ #include #include -#include #include +// This class allows registering cleanup actions. class OCTINTERP_API unwind_protect @@ -38,11 +38,16 @@ public: // A generic unwind_protect element. Knows how to run itself and discard itself. + // Also, contains a pointer to the next element. class elem { + elem *next; + public: virtual void run (void) { } virtual ~elem (void) { } + + friend class unwind_protect; }; // An element that merely runs a void (*)(void) function. @@ -122,152 +127,149 @@ T *e_ptr; }; - typedef size_t frame_id_t; - - // Generic. Users may subclass elem to provide their own cleanup. - static void add (elem *el) - { - elt_list.push (el); - } - - static bool empty (void) - { return elt_list.empty (); } + unwind_protect (void) : head () { } - static void run (void) - { - // Use auto_ptr, so that even if the following run () call throws an - // exception, we still clean up the element. - std::auto_ptr elt (elt_list.top ()); - elt_list.pop (); - - elt->run (); - } - - static void discard (void) - { - // No need to use ato_ptr here. - elem *elt = elt_list.top (); - elt_list.pop (); - - delete elt; - } - - static frame_id_t begin_frame () + void add (elem *new_elem) { - return elt_list.size (); - } - - static void run_frame (frame_id_t frame_id) - { - while (elt_list.size () > frame_id) - run (); - } - - static void discard_frame (frame_id_t frame_id) - { - while (elt_list.size () > frame_id) - discard (); - } - - // String tags are deprecated. Use the above trio. - - static void begin_frame (const std::string& tag) GCC_ATTR_DEPRECATED; - - static void run_frame (const std::string& tag) GCC_ATTR_DEPRECATED; - - static void discard_frame (const std::string& tag) GCC_ATTR_DEPRECATED; - - static void run_all (void) - { - run_frame (0); - while (! tag_list.empty ()) - tag_list.pop (); - } - - static void discard_all (void) - { - discard_frame (0); - while (! tag_list.empty ()) - tag_list.pop (); + new_elem->next = head; + head = new_elem; } // For backward compatibility. - static void add (void (*fcn) (void *), void *ptr = 0) + void add (void (*fcn) (void *), void *ptr = 0) { - elt_list.push (new fcn_arg_elem (fcn, ptr)); + add (new fcn_arg_elem (fcn, ptr)); } // Call to void func (void). - static void add_fcn (void (*fcn) (void)) + void add_fcn (void (*fcn) (void)) { - elt_list.push (new fcn_elem (fcn)); + add (new fcn_elem (fcn)); } // Call to void func (T). template - static void add_fcn (void (*action) (T), T val) + void add_fcn (void (*action) (T), T val) { - elt_list.push (new fcn_arg_elem (action, val)); + add (new fcn_arg_elem (action, val)); } // Call to T::method (void). template - static void add_method (T *obj, void (T::*method) (void)) + void add_method (T *obj, void (T::*method) (void)) { - elt_list.push (new method_elem (obj, method)); + add (new method_elem (obj, method)); } // Call to delete (T*). template - static void add_delete (T *obj) + void add_delete (T *obj) { - elt_list.push (new delete_ptr_elem (obj)); + add (new delete_ptr_elem (obj)); } // Protect any variable. template - static void protect_var (T& var) + void protect_var (T& var) { - elt_list.push (new restore_var_elem (var, var)); + add (new restore_var_elem (var, var)); } // Protect any variable, value given. template - static void protect_var (T& var, const T& val) + void protect_var (T& var, const T& val) + { + add (new restore_var_elem (var, val)); + } + + operator bool (void) const + { + return head != 0; + } + + void run_top (void) + { + if (head) + { + // No leak on exception! + std::auto_ptr ptr (head); + head = ptr->next; + ptr->run (); + } + } + + void run_top (int num) + { + while (num-- > 0) + run_top (); + } + + void discard_top (void) { - elt_list.push (new restore_var_elem (var, val)); + if (head) + { + elem *ptr = head; + head = ptr->next; + delete ptr; + } + } + + void discard_top (int num) + { + while (num-- > 0) + discard_top (); + } + + void run (void) + { + while (head) + run_top (); + } + + void discard (void) + { + while (head) + discard_top (); + } + + // Destructor should not raise an exception, so all actions registered should + // be exception-safe (but setting error_state is allowed). If you're not sure, + // see unwind_protect_safe. + ~unwind_protect (void) + { + run (); } private: - static std::stack elt_list; - - static std::stack > tag_list; + elem *head; }; -// Backward compatibility macros. Avoid them; use protect_var directly. - -#define unwind_protect_bool(b) \ - unwind_protect::protect_var (b) +// Like unwind_protect, but this one will guard against the possibility of seeing +// an exception (or interrupt) in the cleanup actions. Not that we can do much about +// it, but at least we won't crash. -#define unwind_protect_int(i) \ - unwind_protect::protect_var (i) - -#define unwind_protect_size_t(i) \ - unwind_protect::protect_var (i) +class unwind_protect_safe : public unwind_protect +{ + static void gripe_exception (void); -#define unwind_protect_str(s) \ - unwind_protect::protect_var (s) - -#define unwind_protect_ptr(p) \ - unwind_protect::protect_var (p) - -#define unwind_protect_fptr(p) \ - unwind_protect::protect_var (p) - -#define unwind_protect_const_ptr(p) \ - unwind_protect::protect_var (p) +public: + ~unwind_protect_safe (void) + { + while (*this) + { + try + { + run_top (); + } + catch (...) // Yes, the black hole. Remember we're in a dtor. + { + gripe_exception (); + } + } + } +}; #endif diff --git a/src/utils.cc b/src/utils.cc --- a/src/utils.cc +++ b/src/utils.cc @@ -1368,9 +1368,9 @@ if (! error_state) { - unwind_protect::frame_id_t uwp = unwind_protect::begin_frame (); - unwind_protect::protect_var (error_state); - unwind_protect::protect_var (discard_error_messages); + unwind_protect frame; + frame.protect_var (error_state); + frame.protect_var (discard_error_messages); discard_error_messages = true; try @@ -1390,8 +1390,6 @@ { retval = false; } - - unwind_protect::run_frame (uwp); } return retval; diff --git a/src/variables.cc b/src/variables.cc --- a/src/variables.cc +++ b/src/variables.cc @@ -267,20 +267,20 @@ { int parse_status; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (error_state); - unwind_protect::protect_var (warning_state); + frame.protect_var (error_state); + frame.protect_var (warning_state); - unwind_protect::protect_var (discard_error_messages); - unwind_protect::protect_var (discard_warning_messages); + frame.protect_var (discard_error_messages); + frame.protect_var (discard_warning_messages); discard_error_messages = true; discard_warning_messages = true; octave_value tmp = eval_string (prefix, true, parse_status); - unwind_protect::run_frame (uwp_frame); + frame.run (); if (tmp.is_defined () && tmp.is_map ()) names = tmp.map_keys (); @@ -309,16 +309,16 @@ { int parse_status; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (discard_error_messages); - unwind_protect::protect_var (error_state); + frame.protect_var (discard_error_messages); + frame.protect_var (error_state); discard_error_messages = true; octave_value tmp = eval_string (text, true, parse_status); - unwind_protect::run_frame (uwp_frame); + frame.run (); retval = (tmp.is_defined () && tmp.is_map ()); } @@ -383,11 +383,11 @@ { octave_value retval; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; - unwind_protect::protect_var (buffer_error_messages); - unwind_protect::protect_var (Vdebug_on_error); - unwind_protect::protect_var (Vdebug_on_warning); + 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; @@ -397,8 +397,6 @@ error_state = 0; - unwind_protect::run_frame (uwp_frame); - return retval; } @@ -1425,19 +1423,19 @@ { std::string nm = argv [i + 1]; - unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame (); + unwind_protect frame; // Set up temporary scope. symbol_table::scope_id tmp_scope = symbol_table::alloc_scope (); - unwind_protect::add_fcn (symbol_table::erase_scope, tmp_scope); + frame.add_fcn (symbol_table::erase_scope, tmp_scope); symbol_table::set_scope (tmp_scope); octave_call_stack::push (tmp_scope, 0); - unwind_protect::add_fcn (octave_call_stack::pop); + frame.add_fcn (octave_call_stack::pop); - unwind_protect::add_fcn (symbol_table::clear_variables); + frame.add_fcn (symbol_table::clear_variables); feval ("load", octave_value (nm), 0); @@ -1448,8 +1446,6 @@ retval = do_who (i, argv, return_list, verbose, newmsg); } - - unwind_protect::run_frame (uwp_frame); } return retval;