changeset 10066:2cd940306a06

make unwind_protect frames local
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 06 Jan 2010 13:18:41 +0100
parents 64a06079cae4
children 6f79338c269b
files src/ChangeLog src/DLD-FUNCTIONS/cellfun.cc src/DLD-FUNCTIONS/daspk.cc src/DLD-FUNCTIONS/dasrt.cc src/DLD-FUNCTIONS/dassl.cc src/DLD-FUNCTIONS/eigs.cc src/DLD-FUNCTIONS/lsode.cc src/DLD-FUNCTIONS/quad.cc src/DLD-FUNCTIONS/rand.cc src/DLD-FUNCTIONS/typecast.cc src/DLD-FUNCTIONS/urlwrite.cc src/debug.cc src/dynamic-ld.cc src/error.cc src/graphics.cc src/help.cc src/input.cc src/load-path.cc src/ls-mat4.cc src/ls-mat5.cc src/mex.cc src/oct-hist.cc src/octave.cc src/ov-builtin.cc src/ov-class.cc src/ov-fcn-handle.cc src/ov-list.cc src/ov-mex-fcn.cc src/ov-struct.cc src/ov-usr-fcn.cc src/pager.cc src/pr-output.cc src/pt-arg-list.cc src/pt-eval.cc src/pt-eval.h src/toplev.cc src/unwind-prot.cc src/unwind-prot.h src/utils.cc src/variables.cc
diffstat 40 files changed, 543 insertions(+), 687 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ChangeLog	Wed Jan 06 13:18:41 2010 +0100
@@ -1,3 +1,70 @@
+2010-01-06  Jaroslav Hajek  <highegg@gmail.com>
+
+	* 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  <highegg@gmail.com>
 
 	* Cell.cc (Cell::cellstr_value): New method.
--- a/src/DLD-FUNCTIONS/cellfun.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/cellfun.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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");
--- a/src/DLD-FUNCTIONS/daspk.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/daspk.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/DLD-FUNCTIONS/dasrt.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/dasrt.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/DLD-FUNCTIONS/dassl.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/dassl.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/DLD-FUNCTIONS/eigs.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/eigs.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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
--- a/src/DLD-FUNCTIONS/lsode.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/lsode.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/DLD-FUNCTIONS/quad.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/quad.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/DLD-FUNCTIONS/rand.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/rand.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
--- a/src/DLD-FUNCTIONS/typecast.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/typecast.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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<const void *> (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 ());
--- a/src/DLD-FUNCTIONS/urlwrite.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/DLD-FUNCTIONS/urlwrite.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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)
--- a/src/debug.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/debug.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/dynamic-ld.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/dynamic-ld.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/error.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/error.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;  
 }
 
--- a/src/graphics.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/graphics.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
--- a/src/help.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/help.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 
--- a/src/input.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/input.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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 ();
--- a/src/load-path.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/load-path.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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
--- a/src/ls-mat4.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ls-mat4.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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<double> (*s++ & 0x00FF);
        	}
       os.write (reinterpret_cast<char *> (buf), nrow*ncol*sizeof(double));
-      
-      unwind_protect::run_frame (uwp_frame);
     }
   else if (tc.is_range ())
     {
--- a/src/ls-mat5.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ls-mat5.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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
 	  {
--- a/src/mex.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/mex.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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<void *> (&context));
+  frame.add (mex::cleanup, static_cast<void *> (&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;
--- a/src/oct-hist.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/oct-hist.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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
--- a/src/octave.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/octave.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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.
--- a/src/ov-builtin.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ov-builtin.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
--- a/src/ov-class.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ov-class.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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 << "  <class " << class_name () << ">";
   newline (os);
-
-  unwind_protect::run_frame (uwp_frame);
 }
 
 bool
--- a/src/ov-fcn-handle.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ov-fcn-handle.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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
     {
--- a/src/ov-list.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ov-list.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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
--- a/src/ov-mex-fcn.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ov-mex-fcn.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
--- a/src/ov-struct.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ov-struct.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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 << "<structure>";
       newline (os);
     }
-
-  unwind_protect::run_frame (uwp_frame);
 }
 
 bool
--- a/src/ov-usr-fcn.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/ov-usr-fcn.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
--- a/src/pager.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/pager.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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);
     }
 }
 
--- a/src/pr-output.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/pr-output.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
--- a/src/pt-arg-list.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/pt-arg-list.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/pt-eval.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/pt-eval.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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
--- a/src/pt-eval.h	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/pt-eval.h	Wed Jan 06 13:18:41 2010 +0100
@@ -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&);
--- a/src/toplev.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/toplev.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
 }
 
--- a/src/unwind-prot.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/unwind-prot.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -33,42 +33,10 @@
 #include "unwind-prot.h"
 #include "utils.h"
 
-std::stack<unwind_protect::elem *> unwind_protect::elt_list;
-
-std::stack<std::pair <std::string, unwind_protect::frame_id_t> > 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<std::string, frame_id_t> 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<std::string, frame_id_t> 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");
 }
 
 /*
--- a/src/unwind-prot.h	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/unwind-prot.h	Wed Jan 06 13:18:41 2010 +0100
@@ -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 <cstddef>
 
 #include <string>
-#include <stack>
 #include <memory>
 
+// 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<elem> 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<void *> (fcn, ptr));
+      add (new fcn_arg_elem<void *> (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 <class T>
-  static void add_fcn (void (*action) (T), T val)
+  void add_fcn (void (*action) (T), T val)
     {
-      elt_list.push (new fcn_arg_elem<T> (action, val));
+      add (new fcn_arg_elem<T> (action, val));
     }
 
   // Call to T::method (void).
   template <class T>
-  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<T> (obj, method));
+      add (new method_elem<T> (obj, method));
     }
 
   // Call to delete (T*).
 
   template <class T>
-  static void add_delete (T *obj)
+  void add_delete (T *obj)
     {
-      elt_list.push (new delete_ptr_elem<T> (obj));
+      add (new delete_ptr_elem<T> (obj));
     }
 
   // Protect any variable.
   template <class T>
-  static void protect_var (T& var)
+  void protect_var (T& var)
     {
-      elt_list.push (new restore_var_elem<T> (var, var));
+      add (new restore_var_elem<T> (var, var));
     }
 
   // Protect any variable, value given.
   template <class T>
-  static void protect_var (T& var, const T& val)
+  void protect_var (T& var, const T& val)
+    {
+      add (new restore_var_elem<T> (var, val));
+    }
+
+  operator bool (void) const 
+    { 
+      return head != 0; 
+    }
+
+  void run_top (void) 
+    { 
+      if (head)
+        {
+          // No leak on exception!
+          std::auto_ptr<elem> 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<T> (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<elem *> elt_list;
-
-  static std::stack<std::pair <std::string, frame_id_t> > 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
 
--- a/src/utils.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/utils.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;
--- a/src/variables.cc	Tue Jan 05 13:16:16 2010 +0100
+++ b/src/variables.cc	Wed Jan 06 13:18:41 2010 +0100
@@ -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;