changeset 9396:17af7cce7d1b

yet more unwind_protect improvements
author Jaroslav Hajek <highegg@gmail.com>
date Thu, 25 Jun 2009 13:57:38 +0200
parents 1de00ca9c9f2
children 394c7adb488f
files src/ChangeLog src/graphics.cc src/input.cc src/lex.h src/ls-mat5.cc src/mex.cc src/ov-builtin.cc src/ov-fcn-handle.cc src/ov-mex-fcn.cc src/ov-usr-fcn.cc src/parse.y src/pt-eval.cc src/symtab.h src/toplev.cc src/toplev.h src/unwind-prot.h src/variables.cc
diffstat 17 files changed, 244 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/ChangeLog	Thu Jun 25 13:57:38 2009 +0200
@@ -1,3 +1,29 @@
+2009-06-25  Jaroslav Hajek  <highegg@gmail.com>
+
+	* unwind-prot.h (unwind_protect::fcn_elem): New class.
+	(unwind_protect::fcn_arg_elem): New class.
+	(unwind_protect::method_elem): New class.
+	(unwind_protect::add_action_var): Rename to add_fcn.
+	(unwind_protect::add_fcn): New static method.
+	(unwind_protect::add_method): New static method.
+
+	* symtab.h: Split clear_variables into two overloads.
+	* toplev.h (octave_call_stack::restore_frame): New static method.
+
+	* graphics.cc: Update unwind_protect usage.
+	* input.cc: Ditto.
+	* lex.h: Ditto.
+	* ls-mat5.cc: Ditto.
+	* mex.cc: Ditto.
+	* ov-builtin.cc: Ditto.
+	* ov-fcn-handle.cc: Ditto.
+	* ov-mex-fcn.cc: Ditto.
+	* ov-usr-fcn.cc: Ditto.
+	* parse.y: Ditto.
+	* pt-eval.cc: Ditto.
+	* toplev.cc: Ditto.
+	* variables.cc: Ditto.
+
 2009-06-25  Jaroslav Hajek  <highegg@gmail.com>
 
 	* input.cc: Use unwind_protect::add_action_var where appropriate.
--- a/src/graphics.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/graphics.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -4190,7 +4190,7 @@
     args(1) = Matrix ();
 
   unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
-  unwind_protect::add (gh_manager::restore_gcbo);
+  unwind_protect::add_fcn (gh_manager::restore_gcbo);
 
   if (true)
     {
@@ -4989,12 +4989,6 @@
   return octave_value (graphics_backend::available_backends_list ());
 }
 
-static void
-clear_drawnow_request (void *)
-{
-  Vdrawnow_requested = false;
-}
-
 DEFUN (drawnow, args, ,
    "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} drawnow ()\n\
@@ -5016,7 +5010,7 @@
   gh_manager::lock ();
 
   unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
-  unwind_protect::add (clear_drawnow_request);
+  unwind_protect::protect_var (Vdrawnow_requested, false);
 
   unwind_protect::protect_var (drawnow_executing);
 
--- a/src/input.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/input.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -669,7 +669,7 @@
       // 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_action_var (symbol_table::unmark_forced_variables, scope);
+      unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope);
 
       // This is the same as yyparse in parse.y.
       int retval = octave_parse ();
@@ -874,20 +874,6 @@
   return retval;
 }
 
-static void
-restore_command_history (void *)
-{
-  command_history::ignore_entries (! Vsaving_history);
-}
-
-static size_t saved_frame = 0;
-
-static void
-restore_frame (void *)
-{
-  octave_call_stack::goto_frame (saved_frame);
-}
-
 octave_value
 do_keyboard (const octave_value_list& args)
 {
@@ -904,14 +890,13 @@
   // Vsaving_history variable...
   command_history::ignore_entries (false);
 
-  unwind_protect::add (restore_command_history, 0);
+  unwind_protect::add_fcn (command_history::ignore_entries, ! Vsaving_history);
 
   unwind_protect::protect_var (Vsaving_history);
   unwind_protect::protect_var (Vdebugging);
 
-  saved_frame = octave_call_stack::current_frame ();
-  unwind_protect::add (restore_frame);
-  unwind_protect::protect_var (saved_frame);
+  unwind_protect::add_fcn (octave_call_stack::restore_frame, 
+                           octave_call_stack::current_frame ());
 
   Vsaving_history = true;
   Vdebugging = true;
@@ -951,9 +936,8 @@
 
   if (nargin == 0 || nargin == 1)
     {
-      saved_frame = octave_call_stack::current_frame ();
-      unwind_protect::add (restore_frame);
-      unwind_protect::protect_var (saved_frame);
+      unwind_protect::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 (1);
--- a/src/lex.h	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/lex.h	Thu Jun 25 13:57:38 2009 +0200
@@ -43,12 +43,6 @@
 // Delete a buffer.
 extern OCTINTERP_API void delete_buffer (YY_BUFFER_STATE buf);
 
-// Restore a buffer (for unwind-prot).
-extern OCTINTERP_API void restore_input_buffer (void *buf);
-
-// Delete a buffer (for unwind-prot).
-extern OCTINTERP_API void delete_input_buffer (void *buf);
-
 // Is the given string a keyword?
 extern bool is_keyword (const std::string& s);
 
--- a/src/ls-mat5.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/ls-mat5.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -875,12 +875,12 @@
 	    // that defines the anonymous function.
 
 	    symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
-	    unwind_protect::add_action_var (symbol_table::erase_scope, local_scope);
+	    unwind_protect::add_fcn (symbol_table::erase_scope, local_scope);
 
 	    symbol_table::set_scope (local_scope);
 
 	    octave_call_stack::push (local_scope, 0);
-	    unwind_protect::add (octave_call_stack::unwind_pop, 0);
+	    unwind_protect::add_fcn (octave_call_stack::pop);
 
 	    if (m2.nfields() > 0)
 	      {
--- a/src/mex.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/mex.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -3283,7 +3283,7 @@
 	    octave_call_stack::goto_base_frame ();
 
 	  if (! error_state)
-	    unwind_protect::add (octave_call_stack::unwind_pop);
+	    unwind_protect::add_fcn (octave_call_stack::pop);
 
 	  val = symbol_table::varval (name);
 	}
@@ -3343,7 +3343,7 @@
 	    octave_call_stack::goto_base_frame ();
 
 	  if (! error_state)
-	    unwind_protect::add (octave_call_stack::unwind_pop);
+	    unwind_protect::add_fcn (octave_call_stack::pop);
 
 	  symbol_table::varref (name) = mxArray::as_octave_value (ptr);
 	}
--- a/src/ov-builtin.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/ov-builtin.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -100,7 +100,7 @@
 
       octave_call_stack::push (this);
 
-      unwind_protect::add (octave_call_stack::unwind_pop, 0);
+      unwind_protect::add_fcn (octave_call_stack::pop);
 
       try
 	{
--- a/src/ov-fcn-handle.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/ov-fcn-handle.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -319,12 +319,12 @@
       // defines the anonymous function.
 
       symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
-      unwind_protect::add_action_var (symbol_table::erase_scope, local_scope);
+      unwind_protect::add_fcn (symbol_table::erase_scope, local_scope);
 
       symbol_table::set_scope (local_scope);
 
       octave_call_stack::push (local_scope, 0);
-      unwind_protect::add (octave_call_stack::unwind_pop, 0);
+      unwind_protect::add_fcn (octave_call_stack::pop);
 
       octave_idx_type len = 0;
 
@@ -500,12 +500,12 @@
       // defines the anonymous function.
 
       symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
-      unwind_protect::add_action_var (symbol_table::erase_scope, local_scope);	      
+      unwind_protect::add_fcn (symbol_table::erase_scope, local_scope);	      
 
       symbol_table::set_scope (local_scope);
 
       octave_call_stack::push (local_scope, 0);
-      unwind_protect::add (octave_call_stack::unwind_pop, 0);
+      unwind_protect::add_fcn (octave_call_stack::pop);
 
       if (len > 0)
 	{
@@ -945,12 +945,12 @@
       // defines the anonymous function.
 
       symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
-      unwind_protect::add_action_var (symbol_table::erase_scope, local_scope);
+      unwind_protect::add_fcn (symbol_table::erase_scope, local_scope);
 
       symbol_table::set_scope (local_scope);
 
       octave_call_stack::push (local_scope, 0);
-      unwind_protect::add (octave_call_stack::unwind_pop, 0);
+      unwind_protect::add_fcn (octave_call_stack::pop);
 
       if (len > 0 && success)
 	{
--- a/src/ov-mex-fcn.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/ov-mex-fcn.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -143,7 +143,7 @@
 
       octave_call_stack::push (this);
 
-      unwind_protect::add (octave_call_stack::unwind_pop, 0);
+      unwind_protect::add_fcn (octave_call_stack::pop);
 
       try
 	{
--- a/src/ov-usr-fcn.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/ov-usr-fcn.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -126,7 +126,7 @@
 		{
 		  octave_call_stack::push (this);
 
-		  unwind_protect::add (octave_call_stack::unwind_pop, 0);
+                  unwind_protect::add_fcn (octave_call_stack::pop);
 
 		  unwind_protect::protect_var (tree_evaluator::in_fcn_or_script_body);
 		  tree_evaluator::in_fcn_or_script_body = true;
@@ -275,24 +275,6 @@
   return retval;
 }
 
-static void
-clear_param_list (void *lst)
-{
-  tree_parameter_list *tmp = static_cast<tree_parameter_list *> (lst);
-
-  if (tmp)
-    tmp->undefine ();
-}
-
-static void
-restore_args_passed (void *fcn)
-{
-  octave_user_function *tmp = static_cast<octave_user_function *> (fcn);
-
-  if (tmp)
-    tmp->restore_args_passed ();
-}
-
 octave_value_list
 octave_user_function::subsref (const std::string& type,
 			       const std::list<octave_value_list>& idx,
@@ -362,20 +344,20 @@
   // eval_undefined_error().
 
   octave_call_stack::push (this, local_scope, call_depth);
-  unwind_protect::add (octave_call_stack::unwind_pop, 0);
+  unwind_protect::add_fcn (octave_call_stack::pop);
 
   if (call_depth > 0)
     {
       symbol_table::push_context ();
 
-      unwind_protect::add (symbol_table::pop_context);
+      unwind_protect::add_fcn (symbol_table::pop_context);
     }
 
   // Save and restore args passed for recursive calls.
 
   save_args_passed (args);
 
-  unwind_protect::add (::restore_args_passed, this);
+  unwind_protect::add_method (this, &octave_user_function::restore_args_passed);
 
   string_vector arg_names = args.name_tags ();
 
@@ -393,13 +375,17 @@
   // Doing so decrements the reference counts on the values of local
   // variables that are also named function parameters.
 
-  unwind_protect::add (clear_param_list, param_list);
+  if (param_list)
+    unwind_protect::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.
 
-  unwind_protect::add (clear_param_list, ret_list);
+  if (ret_list)
+    unwind_protect::add_method (ret_list, 
+                                &tree_parameter_list::undefine);
 
   if (call_depth == 0)
     {
@@ -413,7 +399,7 @@
       // declared global will be unmarked as global before they are
       // undefined by the clear_param_list cleanup function.
 
-      unwind_protect::add (symbol_table::clear_variables);
+      unwind_protect::add_fcn (symbol_table::clear_variables);
     }
 
   // The following code is in a separate scope to avoid warnings from
--- a/src/parse.y	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/parse.y	Thu Jun 25 13:57:38 2009 +0200
@@ -1547,13 +1547,13 @@
 {
   tree_expression *retval = e;
 
-  unwind_protect::begin_frame ("fold_binary_expression");
-
-  unwind_protect_int (error_state);
-  unwind_protect_int (warning_state);
-
-  unwind_protect_bool (discard_error_messages);
-  unwind_protect_bool (discard_warning_messages);
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
+
+  unwind_protect::protect_var (error_state);
+  unwind_protect::protect_var (warning_state);
+
+  unwind_protect::protect_var (discard_error_messages);
+  unwind_protect::protect_var (discard_warning_messages);
 
   discard_error_messages = true;
   discard_warning_messages = true;
@@ -1590,7 +1590,7 @@
 	}
     }
 
-  unwind_protect::run_frame ("fold_binary_expression");
+  unwind_protect::run_frame (uwp_frame);
 
   return retval;
 }
@@ -1600,13 +1600,13 @@
 {
   tree_expression *retval = e;
 
-  unwind_protect::begin_frame ("fold_unary_expression");
-
-  unwind_protect_int (error_state);
-  unwind_protect_int (warning_state);
-
-  unwind_protect_bool (discard_error_messages);
-  unwind_protect_bool (discard_warning_messages);
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
+
+  unwind_protect::protect_var (error_state);
+  unwind_protect::protect_var (warning_state);
+
+  unwind_protect::protect_var (discard_error_messages);
+  unwind_protect::protect_var (discard_warning_messages);
 
   discard_error_messages = true;
   discard_warning_messages = true;
@@ -1636,7 +1636,7 @@
 	}
     }
 
-  unwind_protect::run_frame ("fold_unary_expression");
+  unwind_protect::run_frame (uwp_frame);
 
   return retval;
 }
@@ -1648,13 +1648,13 @@
 {
   tree_expression *retval = e;
 
-  unwind_protect::begin_frame ("finish_colon_expression");
-
-  unwind_protect_int (error_state);
-  unwind_protect_int (warning_state);
-
-  unwind_protect_bool (discard_error_messages);
-  unwind_protect_bool (discard_warning_messages);
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
+
+  unwind_protect::protect_var (error_state);
+  unwind_protect::protect_var (warning_state);
+
+  unwind_protect::protect_var (discard_error_messages);
+  unwind_protect::protect_var (discard_warning_messages);
 
   discard_error_messages = true;
   discard_warning_messages = true;
@@ -1702,7 +1702,7 @@
 	}
     }
 
-  unwind_protect::run_frame ("finish_colon_expression");
+  unwind_protect::run_frame (uwp_frame);
 
   return retval;
 }
@@ -2859,13 +2859,13 @@
 {
   tree_expression *retval = m;
 
-  unwind_protect::begin_frame ("finish_matrix");
-
-  unwind_protect_int (error_state);
-  unwind_protect_int (warning_state);
-
-  unwind_protect_bool (discard_error_messages);
-  unwind_protect_bool (discard_warning_messages);
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
+
+  unwind_protect::protect_var (error_state);
+  unwind_protect::protect_var (warning_state);
+
+  unwind_protect::protect_var (discard_error_messages);
+  unwind_protect::protect_var (discard_warning_messages);
 
   discard_error_messages = true;
   discard_warning_messages = true;
@@ -2893,7 +2893,7 @@
 	}
     }
 
-  unwind_protect::run_frame ("finish_matrix");
+  unwind_protect::run_frame (uwp_frame);
 
   return retval;
 }
@@ -3139,24 +3139,12 @@
   return status;
 }
 
-static void
-restore_command_history (void *)
-{
-  command_history::ignore_entries (! Vsaving_history);
-}
-
-static void
-restore_input_stream (void *f)
-{
-  command_editor::set_input_stream (static_cast<FILE *> (f));
-}
-
 static octave_function *
 parse_fcn_file (const std::string& ff, const std::string& dispatch_type,
 		bool force_script = false, bool require_file = true,
 		const std::string& warn_for = std::string ())
 {
-  unwind_protect::begin_frame ("parse_fcn_file");
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
 
   octave_function *fcn_ptr = 0;
 
@@ -3166,17 +3154,18 @@
 
   FILE *in_stream = command_editor::get_input_stream ();
 
-  unwind_protect::add (restore_input_stream, in_stream);
-
-  unwind_protect_ptr (ff_instream);
-
-  unwind_protect_int (input_line_number);
-  unwind_protect_int (current_input_column);
-  unwind_protect_int (end_tokens_expected);
-  unwind_protect_bool (reading_fcn_file);
-  unwind_protect_bool (line_editing);
-  unwind_protect_str (parent_function_name);
-  unwind_protect_str (current_class_name);
+  unwind_protect::add_fcn (command_editor::set_input_stream,
+                           in_stream);
+
+  unwind_protect::protect_var (ff_instream);
+
+  unwind_protect::protect_var (input_line_number);
+  unwind_protect::protect_var (current_input_column);
+  unwind_protect::protect_var (end_tokens_expected);
+  unwind_protect::protect_var (reading_fcn_file);
+  unwind_protect::protect_var (line_editing);
+  unwind_protect::protect_var (parent_function_name);
+  unwind_protect::protect_var (current_class_name);
 
   input_line_number = 1;
   current_input_column = 1;
@@ -3187,14 +3176,14 @@
   current_class_name = dispatch_type;
 
   // The next four lines must be in this order.
-  unwind_protect::add (restore_command_history, 0);
+  unwind_protect::add_fcn (command_history::ignore_entries, ! Vsaving_history);
 
   // FIXME -- we shouldn't need both the
   // command_history object and the
   // Vsaving_history variable...
   command_history::ignore_entries ();
 
-  unwind_protect_bool (Vsaving_history);
+  unwind_protect::protect_var (Vsaving_history);
 
   Vsaving_history = false;
 
@@ -3214,8 +3203,8 @@
 
 	  bool parsing_script = false;
 
-	  unwind_protect_bool (get_input_from_eval_string);
-	  unwind_protect_bool (parser_end_of_input);
+	  unwind_protect::protect_var (get_input_from_eval_string);
+	  unwind_protect::protect_var (parser_end_of_input);
 
 	  get_input_from_eval_string = false;
 	  parser_end_of_input = false;
@@ -3224,8 +3213,8 @@
 	    {
 	      file_type = "function";
 
-	      unwind_protect_int (Vecho_executing_commands);
-	      unwind_protect_bool (reading_fcn_file);
+	      unwind_protect::protect_var (Vecho_executing_commands);
+	      unwind_protect::protect_var (reading_fcn_file);
 
 	      Vecho_executing_commands = ECHO_OFF;
 	      reading_fcn_file = true;
@@ -3238,7 +3227,7 @@
 	      // proper value when we unwind from this frame.
 	      reading_fcn_file = old_reading_fcn_file_state;
 
-	      unwind_protect_bool (reading_script_file);
+	      unwind_protect::protect_var (reading_script_file);
 
 	      reading_script_file = true;
 
@@ -3248,12 +3237,12 @@
 	  YY_BUFFER_STATE old_buf = current_buffer ();
 	  YY_BUFFER_STATE new_buf = create_buffer (ffile);
 
-	  unwind_protect::add (restore_input_buffer, old_buf);
-	  unwind_protect::add (delete_input_buffer, new_buf);
+	  unwind_protect::add_fcn (switch_to_buffer, old_buf);
+	  unwind_protect::add_fcn (delete_buffer, new_buf);
 
 	  switch_to_buffer (new_buf);
 
-	  unwind_protect_ptr (curr_fcn_ptr);
+	  unwind_protect::protect_var (curr_fcn_ptr);
 	  curr_fcn_ptr = 0;
 
 	  reset_parser ();
@@ -3262,7 +3251,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_action_var (symbol_table::unmark_forced_variables, scope);
+	  unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope);
 
 	  if (! help_txt.empty ())
 	    help_buf.push (help_txt);
@@ -3286,7 +3275,7 @@
   else if (! warn_for.empty ())
     error ("%s: unable to open file `%s'", warn_for.c_str (), ff.c_str ());    
 
-  unwind_protect::run_frame ("parse_fcn_file");
+  unwind_protect::run_frame (uwp_frame);
 
   return fcn_ptr;
 }
@@ -3386,7 +3375,7 @@
 {
   octave_function *retval = 0;
 
-  unwind_protect::begin_frame ("load_fcn_from_file");
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
 
   std::string nm = file_name;
 
@@ -3394,7 +3383,7 @@
 
   std::string file;
 
-  unwind_protect_bool (fcn_file_from_relative_lookup);
+  unwind_protect::protect_var (fcn_file_from_relative_lookup);
 
   fcn_file_from_relative_lookup = false;
 
@@ -3410,7 +3399,7 @@
 
   if (autoload)
     {
-      unwind_protect_bool (autoloading);
+      unwind_protect::protect_var (autoloading);
       autoloading = true;
     }
 
@@ -3433,8 +3422,8 @@
     {
       // These are needed by yyparse.
 
-      unwind_protect_str (curr_fcn_file_name);
-      unwind_protect_str (curr_fcn_file_full_name);
+      unwind_protect::protect_var (curr_fcn_file_name);
+      unwind_protect::protect_var (curr_fcn_file_full_name);
 
       curr_fcn_file_name = nm;
       curr_fcn_file_full_name = file;
@@ -3454,7 +3443,7 @@
 	}
     }
 
-  unwind_protect::run_frame ("load_fcn_from_file");
+  unwind_protect::run_frame (uwp_frame);
 
   return retval;
 }
@@ -3570,10 +3559,10 @@
 {
   std::string file_full_name = file_ops::tilde_expand (file_name);
 
-  unwind_protect::begin_frame ("source_file");
-
-  unwind_protect_str (curr_fcn_file_name);
-  unwind_protect_str (curr_fcn_file_full_name);
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
+
+  unwind_protect::protect_var (curr_fcn_file_name);
+  unwind_protect::protect_var (curr_fcn_file_full_name);
 
   curr_fcn_file_name = file_name;
   curr_fcn_file_full_name = file_full_name;
@@ -3588,7 +3577,7 @@
 	error ("source: context must be \"caller\" or \"base\"");
 
       if (! error_state)
-	unwind_protect::add (octave_call_stack::unwind_pop);
+	unwind_protect::add_fcn (octave_call_stack::pop);
     }      
 
   if (! error_state)
@@ -3622,7 +3611,7 @@
 	       file_full_name.c_str ());
     }
 
-  unwind_protect::run_frame ("source_file");
+  unwind_protect::run_frame (uwp_frame);
 }
 
 DEFUN (mfilename, args, ,
@@ -3878,15 +3867,15 @@
 {
   octave_value_list retval;
 
-  unwind_protect::begin_frame ("eval_string");
-
-  unwind_protect_int (input_line_number);
-  unwind_protect_int (current_input_column);
-  unwind_protect_bool (get_input_from_eval_string);
-  unwind_protect_bool (input_from_eval_string_pending);
-  unwind_protect_bool (parser_end_of_input);
-  unwind_protect_bool (line_editing);
-  unwind_protect_str (current_eval_string);
+  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
+
+  unwind_protect::protect_var (input_line_number);
+  unwind_protect::protect_var (current_input_column);
+  unwind_protect::protect_var (get_input_from_eval_string);
+  unwind_protect::protect_var (input_from_eval_string_pending);
+  unwind_protect::protect_var (parser_end_of_input);
+  unwind_protect::protect_var (line_editing);
+  unwind_protect::protect_var (current_eval_string);
 
   input_line_number = 1;
   current_input_column = 1;
@@ -3900,8 +3889,8 @@
   YY_BUFFER_STATE old_buf = current_buffer ();
   YY_BUFFER_STATE new_buf = create_buffer (0);
 
-  unwind_protect::add (restore_input_buffer, old_buf);
-  unwind_protect::add (delete_input_buffer, new_buf);
+  unwind_protect::add_fcn (switch_to_buffer, old_buf);
+  unwind_protect::add_fcn (delete_buffer, new_buf);
 
   switch_to_buffer (new_buf);
 
@@ -3909,13 +3898,13 @@
     {
       reset_parser ();
 
-      unwind_protect_ptr (global_command);
+      unwind_protect::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 (symbol_table::unmark_forced_variables, &scope);
+      unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope);
 
       parse_status = yyparse ();
 
@@ -3983,7 +3972,7 @@
     }
   while (parse_status == 0);
 
-  unwind_protect::run_frame ("eval_string");
+  unwind_protect::run_frame (uwp_frame);
 
   return retval;
 }
@@ -4048,11 +4037,11 @@
 
   if (nargin > 0)
     {
-      unwind_protect::begin_frame ("Feval");
+      unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
 
       if (nargin > 1)
 	{
-	  unwind_protect_int (buffer_error_messages);
+	  unwind_protect::protect_var (buffer_error_messages);
 	  buffer_error_messages++;
 	}
 
@@ -4078,7 +4067,7 @@
       else if (nargout > 0)
 	retval = tmp;
 
-      unwind_protect::run_frame ("Feval");
+      unwind_protect::run_frame (uwp_frame);
     }
   else
     print_usage ();
@@ -4186,7 +4175,7 @@
 
       if (! error_state)
         {
-	  unwind_protect::begin_frame ("Fassignin");
+	  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
 
 	  if (context == "caller")
 	    octave_call_stack::goto_caller_frame ();
@@ -4197,7 +4186,7 @@
 
 	  if (! error_state)
 	    {
-	      unwind_protect::add (octave_call_stack::unwind_pop);
+	      unwind_protect::add_fcn (octave_call_stack::pop);
 
 	      std::string nm = args(1).string_value ();
 
@@ -4212,7 +4201,7 @@
 		error ("assignin: expecting variable name as second argument");
 	    }
 
-	  unwind_protect::run_frame ("Fassignin");
+	  unwind_protect::run_frame (uwp_frame);
 	}
       else
         error ("assignin: expecting string as first argument");
@@ -4241,7 +4230,7 @@
 
       if (! error_state)
         {
-	  unwind_protect::begin_frame ("Fevalin");
+	  unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
 
 	  if (context == "caller")
 	    octave_call_stack::goto_caller_frame ();
@@ -4252,11 +4241,11 @@
 
 	  if (! error_state)
 	    {
-	      unwind_protect::add (octave_call_stack::unwind_pop);
+	      unwind_protect::add_fcn (octave_call_stack::pop);
 
 	      if (nargin > 2)
 	        {
-		  unwind_protect_int (buffer_error_messages);
+		  unwind_protect::protect_var (buffer_error_messages);
 		  buffer_error_messages++;
 		}
 
@@ -4283,7 +4272,7 @@
 		}
 	    }
 
-	  unwind_protect::run_frame ("Fevalin");
+	  unwind_protect::run_frame (uwp_frame);
 	}
       else
         error ("evalin: expecting string as first argument");
--- a/src/pt-eval.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/pt-eval.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -820,7 +820,7 @@
 }
 
 static void
-do_catch_code (void *ptr)
+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
@@ -845,8 +845,6 @@
   if (octave_interrupt_immediately || octave_interrupt_state < 0)
     return;
 
-  tree_statement_list *list = static_cast<tree_statement_list *> (ptr);
-
   // Set up for letting the user print any messages from errors that
   // occurred in the body of the try_catch statement.
 
@@ -871,7 +869,7 @@
 
   tree_statement_list *catch_code = cmd.cleanup ();
 
-  unwind_protect::add (do_catch_code, catch_code);
+  unwind_protect::add_fcn (do_catch_code, catch_code);
 
   tree_statement_list *try_code = cmd.body ();
 
@@ -899,10 +897,8 @@
 }
 
 static void
-do_unwind_protect_cleanup_code (void *ptr)
+do_unwind_protect_cleanup_code (tree_statement_list *list)
 {
-  tree_statement_list *list = static_cast<tree_statement_list *> (ptr);
-
   unwind_protect::protect_var (octave_interrupt_state);
   octave_interrupt_state = 0;
 
@@ -981,7 +977,7 @@
 {
   tree_statement_list *cleanup_code = cmd.cleanup ();
 
-  unwind_protect::add (do_unwind_protect_cleanup_code, cleanup_code);
+  unwind_protect::add_fcn (do_unwind_protect_cleanup_code, cleanup_code);
 
   tree_statement_list *unwind_protect_code = cmd.body ();
 
--- a/src/symtab.h	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/symtab.h	Thu Jun 25 13:57:38 2009 +0200
@@ -1311,7 +1311,7 @@
     clear_functions ();
   }
 
-  static void clear_variables (scope_id scope = xcurrent_scope)
+  static void clear_variables (scope_id scope)
   {
     symbol_table *inst = get_instance (scope);
 
@@ -1319,6 +1319,12 @@
       inst->do_clear_variables ();
   }
 
+  // This is split for unwind_protect.
+  static void clear_variables (void)
+  {
+    clear_variables (xcurrent_scope);
+  }
+
   static void clear_objects (scope_id scope = xcurrent_scope)
   {
     symbol_table *inst = get_instance (scope);
@@ -1335,22 +1341,6 @@
       inst->do_unmark_forced_variables ();
   }
 
-  // For unwind_protect.
-  static void unmark_forced_variables (void *arg)
-  {
-    // Unmark any symbols that may have been tagged as local variables
-    // while parsing (for example, by force_local_variable in lex.l).
-
-    symbol_table::scope_id *p = static_cast <symbol_table::scope_id *> (arg);
-
-  if (p)
-    unmark_forced_variables (*p);
-}
-
-
-  // For unwind_protect.
-  static void clear_variables (void *) { clear_variables (); }
-
   static void clear_functions (void)
   {
     for (fcn_table_iterator p = fcn_table.begin (); p != fcn_table.end (); p++)
--- a/src/toplev.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/toplev.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -560,7 +560,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_action_var (symbol_table::unmark_forced_variables, scope);
+	  unwind_protect::add_fcn (symbol_table::unmark_forced_variables, scope);
 
 	  // This is the same as yyparse in parse.y.
 	  retval = octave_parse ();
--- a/src/toplev.h	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/toplev.h	Thu Jun 25 13:57:38 2009 +0200
@@ -247,6 +247,11 @@
     return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
   }
 
+  static void restore_frame (size_t n)
+  {
+    goto_frame (n);
+  }
+
   static bool goto_frame_relative (int n, bool verbose = false)
   {
     return instance_ok ()
@@ -277,10 +282,6 @@
       instance->do_pop ();
   }
   
-  // A function for popping the top of the call stack that is suitable
-  // for use as an unwind_protect handler.
-  static void unwind_pop (void *) { pop (); }
-
   static void clear (void)
   {
     if (instance_ok ())
--- a/src/unwind-prot.h	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/unwind-prot.h	Thu Jun 25 13:57:38 2009 +0200
@@ -45,19 +45,51 @@
     virtual ~elem (void) { }
   };
 
-  // An element that merely runs a void (*)(void *) function.
+  // An element that merely runs a void (*)(void) function.
   
   class fcn_elem : public elem
   {
   public:
-    fcn_elem (void (*fptr) (void *), void *ptr)
-      : e_fptr (fptr), e_ptr (ptr) { }
+    fcn_elem (void (*fptr) (void))
+      : e_fptr (fptr) { }
 
-    void run (void) { e_fptr (e_ptr); }
+    void run (void) { e_fptr (); }
 
   private:
-    void (*e_fptr) (void *);
-    void *e_ptr;
+    void (*e_fptr) (void);
+  };
+
+  // An element that stores a variable of type T along with a void (*) (T)
+  // function pointer, and calls the function with the parameter.
+
+  template <class T>
+  class fcn_arg_elem : public elem
+  {
+  public:
+    fcn_arg_elem (void (*fcn) (T), T arg)
+      : e_fcn (fcn), e_arg (arg) { }
+
+    void run (void) { e_fcn (e_arg); }
+
+  private:
+    void (*e_fcn) (T);
+    T e_arg;
+  };
+
+  // An element for calling a member function.
+
+  template <class T>
+  class method_elem : public elem
+  {
+  public:
+    method_elem (T *obj, void (T::*method) (void))
+      : e_obj (obj), e_method (method) { }
+
+    void run (void) { (e_obj->*e_method) (); }
+
+  private:
+    T *e_obj;
+    void (T::*e_method) (void);
   };
 
   // An element that stores arbitrary variable, and restores it.
@@ -75,21 +107,19 @@
     T *e_ptr, e_val;
   };
 
-  // An element that stores a variable of type T along with a void (*) (T)
-  // function pointer, and calls the function with the parameter.
+  // Deletes a class allocated using new.
 
   template <class T>
-  class action_var_elem : public elem
+  class delete_ptr_elem : public elem
   {
   public:
-    action_var_elem (void (*fcn) (T), T val)
-      : e_fcn (fcn), e_val (val) { }
+    delete_ptr_elem (T *ptr)
+      : e_ptr (ptr) { }
 
-    void run (void) { e_fcn (e_val); }
+    void run (void) { delete e_ptr; }
 
   private:
-    void (*e_fcn) (T);
-    T e_val;
+    T *e_ptr;
   };
 
   typedef size_t frame_id_t;
@@ -161,9 +191,38 @@
         tag_list.pop ();
     }
 
+  // For backward compatibility.
   static void add (void (*fcn) (void *), void *ptr = 0)
     {
-      elt_list.push (new fcn_elem (fcn, ptr));
+      elt_list.push (new fcn_arg_elem<void *> (fcn, ptr));
+    }
+
+  // Call to void func (void).
+  static void add_fcn (void (*fcn) (void))
+    {
+      elt_list.push (new fcn_elem (fcn));
+    }
+
+  // Call to void func (T).
+  template <class T>
+  static void add_fcn (void (*action) (T), T val)
+    {
+      elt_list.push (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))
+    {
+      elt_list.push (new method_elem<T> (obj, method));
+    }
+
+  // Call to delete (T*).
+
+  template <class T>
+  static void add_delete (T *obj)
+    {
+      elt_list.push (new delete_ptr_elem<T> (obj));
     }
 
   // Protect any variable.
@@ -180,13 +239,6 @@
       elt_list.push (new restore_var_elem<T> (var, val));
     }
 
-  // Store a function pointer together with a single argument (passed by value).
-  template <class T>
-  static void add_action_var (void (*action) (T), T val)
-    {
-      elt_list.push (new action_var_elem<T> (action, val));
-    }
-
 private:
 
   static std::stack<elem *> elt_list;
--- a/src/variables.cc	Thu Jun 25 11:41:46 2009 +0200
+++ b/src/variables.cc	Thu Jun 25 13:57:38 2009 +0200
@@ -1389,14 +1389,14 @@
 	      // Set up temporary scope.
 
 	      symbol_table::scope_id tmp_scope = symbol_table::alloc_scope ();
-	      unwind_protect::add_action_var (symbol_table::erase_scope, tmp_scope);
+	      unwind_protect::add_fcn (symbol_table::erase_scope, tmp_scope);
 
 	      symbol_table::set_scope (tmp_scope);
 
 	      octave_call_stack::push (tmp_scope, 0);
-	      unwind_protect::add (octave_call_stack::unwind_pop, 0);
+	      unwind_protect::add_fcn (octave_call_stack::pop);
 
-	      unwind_protect::add (symbol_table::clear_variables);
+	      unwind_protect::add_fcn (symbol_table::clear_variables);
 
 	      feval ("load", octave_value (nm), 0);