changeset 7752:40c428ea3408

initial implementation of dbup and dbdown
author John W. Eaton <jwe@octave.org>
date Sun, 04 May 2008 03:42:19 -0400
parents 7c020c067a60
children e76a4a6e3c47
files scripts/ChangeLog scripts/miscellaneous/Makefile.in scripts/miscellaneous/dbstack.m src/ChangeLog src/debug.cc src/help.cc src/input.cc src/input.h src/load-save.cc src/mex.cc src/octave.cc src/ov-usr-fcn.cc src/ov-usr-fcn.h src/pt-id.cc src/pt-id.h src/pt-stmt.cc src/symtab.cc src/symtab.h src/toplev.cc src/toplev.h src/unwind-prot.cc src/unwind-prot.h src/variables.cc
diffstat 23 files changed, 850 insertions(+), 332 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Sat May 03 22:48:24 2008 -0400
+++ b/scripts/ChangeLog	Sun May 04 03:42:19 2008 -0400
@@ -1,3 +1,8 @@
+2008-05-04  John W. Eaton  <jwe@octave.org>
+
+	* miscellaneous/dbstack.m: Delete.
+	* miscellaneous/Makefile.in (SOURCES): Remove it from the list.
+
 2008-05-01  David Bateman  <dbateman@free.fr>
 
 	* plot/plot.m: Remove documentation of 'L' option.
@@ -26,7 +31,7 @@
 2008-04-25  John W. Eaton  <jwe@octave.org>
 
 	* miscellaneous/dbstack.m: New function.
-	* miscellaneous/Makefile.in: Add it to the list.
+	* miscellaneous/Makefile.in (SOURCES): Add it to the list.
 
 2008-04-21  David Bateman  <dbateman@free.fr>
 
--- a/scripts/miscellaneous/Makefile.in	Sat May 03 22:48:24 2008 -0400
+++ b/scripts/miscellaneous/Makefile.in	Sun May 04 03:42:19 2008 -0400
@@ -35,7 +35,7 @@
 
 SOURCES = ans.m bincoeff.m bug_report.m bunzip2.m cast.m comma.m \
   compare_versions.m computer.m copyfile.m \
-  dbstack.m delete.m dir.m doc.m dos.m dump_prefs.m edit.m \
+  delete.m dir.m doc.m dos.m dump_prefs.m edit.m \
   fileattrib.m fileparts.m flops.m fullfile.m getfield.m gunzip.m gzip.m \
   info.m inputname.m ismac.m ispc.m isunix.m license.m list_primes.m ls.m \
   ls_command.m menu.m mex.m mexext.m mkoctfile.m movefile.m \
--- a/scripts/miscellaneous/dbstack.m	Sat May 03 22:48:24 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-## Copyright (C) 2008 John W. Eaton
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Loadable Function} {[@var{stack}, @var{idx}]} dbstack (@var{n})
-## Print or return current stack information.  With optional argument
-## @var{n}, omit the @var{n} innermost stack frames.
-## @seealso{dbclear, dbstatus, dbstop}
-## @end deftypefn
-
-## Author: jwe
-
-function [stack, idx] = dbstack (n = 0)
-
-  if (n < 0 || round (n) != n)
-    error ("dbstack: expecting N to be a non-negative integer");
-  endif
-
-  ## Add one here to skip the dbstack stack frame.
-  [t_stack, t_idx] = __dbstack__ (n+1);
-
-  if (nargout == 0)
-    nframes = numel (t_stack);
-    if (nframes > 0)
-      puts ("Stopped in:\n\n");
-      for i = 1:nframes
-	if (i == t_idx)
-	  puts ("--> ");
-	else
-	  puts ("    ");
-	endif
-	f = t_stack(i);
-	printf ("%s at line %d column %d\n", f.name, f.line, f.column);
-      endfor
-    endif
-  else
-    stack = t_stack;
-    idx = t_idx;
-  endif
-
-endfunction
--- a/src/ChangeLog	Sat May 03 22:48:24 2008 -0400
+++ b/src/ChangeLog	Sun May 04 03:42:19 2008 -0400
@@ -1,3 +1,158 @@
+2008-05-04  John W. Eaton  <jwe@octave.org>
+
+	* variables.cc (get_global_value): Use symbol_table::global_varval
+	instead of passing scope to symbol_table::varval.
+	(set_global_value): Use symbol_table::global_varref
+	instead of passing scope to symbol_table::varref.
+	(do_who): Use symbol_table::glob_global_variables
+	instead of passing scope to symbol_table::glob_variables.
+	(do_clear_globals):
+	Use symbol_table::global_variable_names and
+	symbol_table::clear_global instead of passing scope to
+	symbol_table::clear_variables.
+	Use symbol_table::global_variable_names instead of passing scope
+	to symbol_table::variable_names.
+
+	* unwind-prot.cc (unwind_protect::save_size_t): New function.
+	(saved_variable::restore_value): Handle size_t values.
+	(saved_variable::saved_variable): New size_t constructor.
+	(saved_variable::size_type): New var_type enum value.
+	(saved_variable::ptr_to_size_t, saved_variable::size_t_value):
+	New union elements.
+	* unwind-prot.h (unwind_protect::save_size_t): Provide decl
+	(unwind_protect_size_t): New macro.
+
+	* toplev.cc (octave_call_stack::do_goto_frame,
+	octave_call_stack::do_goto_frame_relative): New functions.
+	(octave_call_stack::do_backtrace): Also return scope and context ids.
+	* toplev.h 	(octave_call_stack::do_goto_frame,
+	octave_call_stack::do_goto_frame_relative): Provide decls.
+	(octave_call_stack::curr_frame): New data member.
+	(octave_call_stack::octave_call_stack): Initialize it.
+	(octave_call_stack::call_stack_elt::scope,
+	(octave_call_stack::call_stack_elt::context): New data members.,
+	(octave_call_stack::current_frame,
+	(octave_call_stack::do_current_frame
+	octave_call_stack::do_goto_frame,
+	octave_call_stack::do_goto_frame_relative): New functions.
+	(octave_call_stack::push, octave_call_stack::do_push):
+	New args, scope and context.
+	(octave_call_stack::do_push, octave_call_stack::do_pop): Update
+	curr_frame if debugging.
+
+	* symtab.cc (symbol_table::global_table): New map for global values.
+	(symbol_table::xcurrent_context): New variable for context info.
+	* symtab.h: Provide decls.
+	(symbol_table::global_varref, symbol_table::global_varval,
+	symbol_table::current_context,
+	symbol_table::set_scope_and_context,
+	symbol_table::glob_global_variables,
+	symbol_table::global_variable_names,
+	symbol_table::top_leve_variable_names):
+	New functions.
+	(symbol_table::context_id, const_global_table_iterator,
+	global_table_iterator): New typedefs.
+	(symbol_table::xcurrent_context_this_table): New variable.
+	(symbol_table::symbol_table): Initialize it.
+	(symbol_table::set_scope): Use it.
+	(symbol_table::symbol_record::find, symbol_table::do_find):
+	Use symbol_table::global_varref instead of passing scope to
+	symbol_table::varref.
+	(symbol_table::symbol_record::symbol_record_rep::value_stack):
+	Now a std::deque instead of a std::stack.
+	(symbol_table::symbol_record::symbol_record_rep::push_context,
+	symbol_table::symbol_record::symbol_record_rep::pop_context):
+	Don't push or pop persistent of global variables.
+	(symbol_table::symbol_record::symbol_record_rep::varval,
+	Handle context here.  Call symbol_table::global_varval instead of
+	passing scope to symbol_table::varval.
+	(symbol_table::symbol_record::symbol_record_rep::varref):
+	Handle context here.  Call symbol_table::global_varref instead of
+	passing scope to symbol_table::varref.
+	(symbol_table::symbol_record::varref,
+	symbol_table::symbol_record::varval): No need to handle global
+	values specially here.
+	(symbol_table::symbol_record::push_context
+	symbol_table::symbol_record::pop_context: No need to handle global
+	or persistent values specially here.
+	(symbol_table::get_instance): Don't return global scope.
+	(symbol_table::do_push_context, symbol_table::do_pop_context):
+	Increment/decrement xcurrent_context.
+	(symbol_table::do_clear_global, symbol_table::do_clear_global_pattern):
+	Use global_table instead of separate scope.	
+
+	* symtab.h, symtab.cc (symbol_table::fcn_info::fcn_info_rep::find,
+	symbol_table::fcn_info::fcn_info_rep::find_function,
+	symbol_table::fcn_info::find, symbol_table::fcn_info::find_function,
+	symbol_table::find, symbol_table::find_function,
+	symbol_table::do_find, symbol_table::insert, symbol_table::varref,
+	symbol_table::varval, symbol_table::persistent_varref,
+	symbol_table::persistent_varval, symbol_table::erase_persistent,
+	symbol_table::is_variable, symbol_table::clear,
+	symbol_table::clear_variables, symbol_table::clear_global,
+	symbol_table::clear_variable, symbol_table::clear_global_pattern,
+	symbol_table::clear_variable_pattern, symbol_table::push_context,
+	symbol_table::pop_context, symbol_table::mark_hidden,
+	symbol_table::mark_global, symbol_table::glob,
+	symbol_table::glob_variables, symbol_table::variable_names,
+	symbol_table::is_local_variable, symbol_table::is_global):
+	Eliminate scope arg.  Change all uses.
+	(symbol_table::erase_scope, symbol_table::dup_scope):
+	Require scope arg.
+
+	* pt-stmt.cc (tree_statement::eval): Don't update statement info
+	in octave_call_stack if debugging.
+
+	* pt-id.h (tree_identifier::xsym): New function.
+	(tree_identifier::rvalue, tree_identifier::lvalue,
+	tree_identifier::dup, tree_identifier::is_defined,
+	tree_identifier::is_variable, tree_identifier::mark_global,
+	tree_identifier::mark_as_static, tree_identifier::do_lookup,
+	tree_identifier::mark_as_formal_parameter):
+	Use xsym to access symbol.
+	(tree_identifier::scope): New data member.
+	(tree_identifier::tree_identifier): Initialize it.
+
+	* ov-usr-fcn.cc (octave_user_script::octave_user_script,
+	octave_user_function::octave_user_function):
+	Initialize call_depth to -1.
+	(octave_user_script::do_multi_index_op): Fix comparison of
+	call_depth with Vmax_recursion_depth.
+	(octave_user_function::do_multi_index_op):
+	Compare call depth > 0, instead of > 1.
+	* ov-usr-fcn.h (octave_user_function::save_args_passed):
+	Compare call depth > 0, instead of > 1.
+
+	* input.cc (Vdebugging): New variable.
+	(get_user_input): Eliminate DEBUG argument.  Use global Vdebugging
+	variable instead.  Change all callers.
+	(saved_frame): New static variable.
+	(restore_frame): New function.
+	(do_keyboard): Unwind-protect Vdebugging here and set it to TRUE.
+	Save current frame.  Use unwind_protect to restore it.
+	(Fkeyboard): Save current frame.  Use unwind_protect to restore it.
+	Move up the call stack one frame before calling do_keyboard.  
+	* input.h (Vdebugging): Provide decl.
+
+	* mex.cc (mexGetVariable): Handle global vars with get_global_value.
+	(mexPutVariable): Likewise, with set_global_value.
+
+	* octave.cc (intern_argv): Assert that we are at the top level.
+	Don't pass scope to symbol_table::varref or symbol_table::mark_hidden.
+
+	* load-save.cc (install_loaded_variable): Use
+	symbol_table::global_varref instead of passing global scope to
+	symbol_table::varref.
+
+	* help.cc (make_name_list): Call symbol_table::global_variable_names
+	and symbol_table::top_level_variable_names instead of passing
+	scope to symbol_table::variable_names.
+
+	* debug.cc (do_dbupdown, Fdbup, Fdbdown): New functions.
+	(current_stack_frame): Delete static variable.
+	(Fdbstack): Rename from F__dbstack__.  Implement all of dbstack
+	here instead of partially in dbstack.m.
+
 2008-05-03  John W. Eaton  <jwe@octave.org>
 
 	* pt-arg-list.cc (F__end__): If there are more dimensions than
--- a/src/debug.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/debug.cc	Sun May 04 03:42:19 2008 -0400
@@ -57,9 +57,6 @@
 // Initialize the singleton object
 bp_table *bp_table::instance = 0;
 
-// FIXME --  dbup and dbdown will need to modify this variable.
-static int current_stack_frame = 1;
-
 // Return a pointer to the user-defined function FNAME.  If FNAME is
 // empty, search backward for the first user-defined function in the
 // current call stack.
@@ -362,7 +359,7 @@
 
 DEFCMD (dbstop, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Loadable Function} {rline =} dbstop (@var{func}, @var{line}, @dots{})\n\
+@deftypefn {Loadable Function} {@var{rline} =} dbstop (@var{func}, @var{line}, @dots{})\n\
 Set a breakpoint in a function\n\
 @table @code\n\
 @item func\n\
@@ -695,10 +692,12 @@
   return retval;
 }
 
-DEFUN (__dbstack__, args, ,
+DEFCMD (dbstack, args, nargout,
   "-*- texinfo -*-\n\
-@deftypefn {Loadable Function} {[@var{stack}, @var{idx}]} __dbstack__ (@var{n})\n\
-Undocumented internal function.\n\
+@deftypefn {Loadable Function} {[@var{stack}, @var{idx}]} dbstack (@var{n})\n\
+Print or return current stack information.  With optional argument\n\
+@var{n}, omit the @var{n} innermost stack frames.\n\
+@seealso{dbclear, dbstatus, dbstop}\n\
 @end deftypefn")
 {
   octave_value_list retval;
@@ -706,15 +705,130 @@
   int n = 0;
 
   if (args.length () == 1)
-    n = args(0).int_value ();
+    {
+      octave_value arg = args(0);
+
+      if (arg.is_string ())
+	{
+	  std::string s_arg = arg.string_value ();
+
+	  n = atoi (s_arg.c_str ());
+	}
+      else
+	n = args(0).int_value ();
+    }
 
   if (! error_state)
     {
-      retval(1) = current_stack_frame;
+      if (n >= 0)
+	{
+	  size_t curr_frame = octave_call_stack::current_frame ();
+
+	  // Skip dbstack stack frame.
+	  if (! Vdebugging)
+	    curr_frame++;
+
+	  // Adjust so that this is the index of where we are in the array
+	  // that is returned in retval(0).
+	  size_t idx = curr_frame - n;
+
+	  // Add one here to skip the __dbstack__ stack frame.
+	  Octave_map stk = octave_call_stack::backtrace (curr_frame + n);
+
+	  if (nargout == 0)
+	    {
+	      octave_idx_type nframes = stk.numel ();
+
+	      if (nframes > 0)
+		{
+		  octave_stdout << "Stopped in:\n\n";
+
+		  Cell names = stk.contents ("name");
+		  Cell lines = stk.contents ("line");
+		  Cell columns = stk.contents ("column");
+
+		  for (octave_idx_type i = 0; i < nframes; i++)
+		    {
+		      octave_value name = names(i);
+		      octave_value line = lines(i);
+		      octave_value column = columns(i);
+
+		      octave_stdout << (i == idx - 1 ? "--> " : "    ")
+				    << name.string_value ()
+				    << " at line " << line.int_value ()
+				    << " column " << column.int_value ()
+				    << std::endl;
+		    }
+		}
+	    }
+	  else
+	    {
+	      retval(1) = idx;
+	      retval(0) = stk;
+	    }
+	}
+      else
+	error ("dbstack: expecting N to be a nonnegative integer");
+    }
+
+  return retval;
+}
 
-      // Add one here to skip the __dbstack__ stack frame.
-      retval(0) = octave_call_stack::backtrace (n+1);
+static void
+do_dbupdown (const octave_value_list& args, const std::string& who)
+{
+  int n = 1;
+
+  if (args.length () == 1)
+    {
+      octave_value arg = args(0);
+
+      if (arg.is_string ())
+	{
+	  std::string s_arg = arg.string_value ();
+
+	  n = atoi (s_arg.c_str ());
+	}
+      else
+	n = args(0).int_value ();
+    }
+
+  if (! error_state)
+    {
+      if (who == "dbdown")
+	n = -n;
+
+      if (! octave_call_stack::goto_frame_relative (n, true))
+	error ("%s: invalid stack frame", who.c_str ());
     }
+}
+
+DEFCMD (dbup, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} dbup (@var{n})\n\
+In debugging mode, move up the execution stack @var{n} frames.\n\
+If @var{n} is omitted, move up one frame.\n\
+@seealso{dbstack}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  do_dbupdown (args, "dbup");
+
+  return retval;
+}
+
+DEFCMD (dbdown, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {} dbdown (@var{n})\n\
+In debugging mode, move down the execution stack @var{n} frames.\n\
+If @var{n} is omitted, move down one frame.\n\
+@seealso{dbstack}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  do_dbupdown (args, "dbdown");
 
   return retval;
 }
--- a/src/help.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/help.cc	Sun May 04 03:42:19 2008 -0400
@@ -567,12 +567,12 @@
   string_vector bif = symbol_table::built_in_function_names ();
   int bif_len = bif.length ();
 
-  string_vector glb
-    = symbol_table::variable_names (symbol_table::global_scope ());
+  // FIXME -- is this really necessary here?
+  string_vector glb = symbol_table::global_variable_names ();
   int glb_len = glb.length ();
 
-  string_vector top
-    = symbol_table::variable_names (symbol_table::top_scope ());
+  // FIXME -- is this really necessary here?
+  string_vector top = symbol_table::top_level_variable_names ();
   int top_len = top.length ();
 
   string_vector lcl;
--- a/src/input.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/input.cc	Sun May 04 03:42:19 2008 -0400
@@ -67,6 +67,7 @@
 #include "pt-stmt.h"
 #include "sighandlers.h"
 #include "sysdep.h"
+#include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -143,6 +144,9 @@
 // the next user prompt.
 bool Vdrawnow_requested = false;
 
+// TRUE if we are in debugging mode.
+bool Vdebugging = false;
+
 // TRUE if we are running in the Emacs GUD mode.
 static bool Vgud_mode = false;
 
@@ -582,7 +586,7 @@
 // If the user simply hits return, this will produce an empty matrix.
 
 static octave_value_list
-get_user_input (const octave_value_list& args, bool debug, int nargout)
+get_user_input (const octave_value_list& args, int nargout)
 {
   octave_value_list retval;
 
@@ -596,7 +600,7 @@
   std::string nm;
   int line = -1;
 
-  if (debug)
+  if (Vdebugging)
     {
       octave_user_code *caller = octave_call_stack::caller_user_code ();
 
@@ -670,13 +674,13 @@
 
       if (len < 1)
 	{
-	  if (debug)
+	  if (Vdebugging)
 	    goto again;
 	  else
 	    return read_as_string ? octave_value ("") : octave_value (Matrix ());
 	}
 
-      if (debug)
+      if (Vdebugging)
 	{
 	  if (match_sans_spaces_semi ("exit", input_buf)
 	      || match_sans_spaces_semi ("quit", input_buf)
@@ -719,18 +723,18 @@
 	{
 	  int parse_status = 0;
 
-	  bool silent = ! debug;
+	  bool silent = ! Vdebugging;
 
 	  retval = eval_string (input_buf, silent, parse_status, nargout);
 
-	  if (! debug && retval.length () == 0)
+	  if (! Vdebugging && retval.length () == 0)
 	    retval(0) = Matrix ();
 	}
     }
   else
     error ("input: reading user-input failed!");
 
-  if (debug)
+  if (Vdebugging)
     {
       // Clear error_state so that if errors were encountered while
       // evaluating user input, extra error messages will not be
@@ -787,7 +791,7 @@
   int nargin = args.length ();
 
   if (nargin == 1 || nargin == 2)
-    retval = get_user_input (args, false, nargout);
+    retval = get_user_input (args, nargout);
   else
     print_usage ();
 
@@ -855,6 +859,14 @@
   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)
 {
@@ -874,10 +886,16 @@
   unwind_protect::add (restore_command_history, 0);
 
   unwind_protect_bool (Vsaving_history);
+  unwind_protect_bool (Vdebugging);
+
+  saved_frame = octave_call_stack::current_frame ();
+  unwind_protect::add (restore_frame);
+  unwind_protect_size_t (saved_frame);
 
   Vsaving_history = true;
+  Vdebugging = true;
 
-  octave_value_list tmp = get_user_input (args, true, 0);
+  octave_value_list tmp = get_user_input (args, 0);
 
   retval = tmp(0);
 
@@ -906,7 +924,18 @@
   int nargin = args.length ();
 
   if (nargin == 0 || nargin == 1)
-    do_keyboard (args);
+    {
+      saved_frame = octave_call_stack::current_frame ();
+      unwind_protect::add (restore_frame);
+      unwind_protect_size_t (saved_frame);
+
+      // Skip the frame assigned to the keyboard function.
+      octave_call_stack::goto_frame (1);
+
+      do_keyboard (args);
+
+      unwind_protect::run ();
+    }
   else
     print_usage ();
 
--- a/src/input.h	Sat May 03 22:48:24 2008 -0400
+++ b/src/input.h	Sun May 04 03:42:19 2008 -0400
@@ -88,6 +88,9 @@
 // the next user prompt.
 extern OCTINTERP_API bool Vdrawnow_requested;
 
+// TRUE if we are in debugging mode.
+extern bool Vdebugging;
+
 extern std::string gnu_readline (const std::string& s, bool force_readline = false);
 
 extern void initialize_command_input (void);
--- a/src/load-save.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/load-save.cc	Sun May 04 03:42:19 2008 -0400
@@ -144,7 +144,7 @@
     {
       symbol_table::clear (name);
       symbol_table::mark_global (name);
-      symbol_table::varref (name, symbol_table::global_scope ()) = val;
+      symbol_table::global_varref (name) = val;
     }
   else
     symbol_table::varref (name) = val;
--- a/src/mex.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/mex.cc	Sun May 04 03:42:19 2008 -0400
@@ -3262,18 +3262,23 @@
 
   // FIXME -- should this be in variables.cc?
 
-  symbol_table::scope_id scope = -1;
+  octave_value val;
 
   if (! strcmp (space, "global"))
-    scope = symbol_table::global_scope ();
-  else if (! strcmp (space, "caller"))
-    scope = symbol_table::current_caller_scope ();
-  else if (! strcmp (space, "base"))
-    scope = symbol_table::top_scope ();
+    val = get_global_value (name);
   else
-    mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
-
-  octave_value val = symbol_table::varval (name, scope);
+    {
+      symbol_table::scope_id scope = -1;
+
+      if (! strcmp (space, "caller"))
+	scope = symbol_table::current_caller_scope ();
+      else if (! strcmp (space, "base"))
+	scope = symbol_table::top_scope ();
+      else
+	mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
+
+      val = symbol_table::varval (name, scope);
+    }
 
   if (val.is_defined ())
     {
@@ -3314,9 +3319,7 @@
 
       symbol_table::scope_id scope = -1;
 
-      if (! strcmp (space, "global"))
-	scope = symbol_table::global_scope ();
-      else if (! strcmp (space, "caller"))
+      if (! strcmp (space, "caller"))
 	scope = symbol_table::current_caller_scope ();
       else if (! strcmp (space, "base"))
 	scope = symbol_table::top_scope ();
--- a/src/octave.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/octave.cc	Sun May 04 03:42:19 2008 -0400
@@ -189,9 +189,11 @@
 static void
 intern_argv (int argc, char **argv)
 {
-  symbol_table::varref (".nargin.", symbol_table::top_scope ()) = argc - 1;
+  assert (symbol_table::at_top_level ());
 
-  symbol_table::mark_hidden (".nargin.", symbol_table::top_scope ());
+  symbol_table::varref (".nargin.") = argc - 1;
+
+  symbol_table::mark_hidden (".nargin.");
 
   if (argc > 1)
     {
--- a/src/ov-usr-fcn.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/ov-usr-fcn.cc	Sun May 04 03:42:19 2008 -0400
@@ -63,7 +63,7 @@
   : octave_user_code (), cmd_list (0), file_name (),
     t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
-    call_depth (0)
+    call_depth (-1)
 { }
 
 octave_user_script::octave_user_script (const std::string& fnm,
@@ -73,7 +73,7 @@
   : octave_user_code (nm, ds), cmd_list (cmds), file_name (fnm),
     t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
-    call_depth (0)
+    call_depth (-1)
 {
   if (cmd_list)
     cmd_list->mark_as_script_body ();
@@ -85,7 +85,7 @@
   : octave_user_code (nm, ds), cmd_list (0), file_name (fnm), 
     t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
-    call_depth (0)
+    call_depth (-1)
 { }
 
 octave_user_script::~octave_user_script (void)
@@ -121,7 +121,7 @@
 	      unwind_protect_int (call_depth);
 	      call_depth++;
 
-	      if (call_depth <= Vmax_recursion_depth)
+	      if (call_depth < Vmax_recursion_depth)
 		{
 		  octave_call_stack::push (this);
 
@@ -202,7 +202,7 @@
     lead_comm (), trail_comm (), file_name (),
     parent_name (), t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
-    system_fcn_file (false), call_depth (0),
+    system_fcn_file (false), call_depth (-1),
     num_named_args (param_list ? param_list->length () : 0),
     nested_function (false), inline_function (false),
     class_constructor (false), class_method (false), xdispatch_class (),
@@ -367,7 +367,7 @@
   unwind_protect_int (call_depth);
   call_depth++;
 
-  if (call_depth > Vmax_recursion_depth)
+  if (call_depth >= Vmax_recursion_depth)
     {
       ::error ("max_recursion_limit exceeded");
       unwind_protect::run_frame ("user_func_eval");
@@ -377,10 +377,12 @@
   // Save old and set current symbol table context, for
   // eval_undefined_error().
 
+  octave_call_stack::push (this, local_scope, call_depth);
+
   symbol_table::push_scope (local_scope);
   unwind_protect::add (symbol_table::pop_scope);
 
-  if (call_depth > 1)
+  if (call_depth > 0)
     {
       symbol_table::push_context ();
 
@@ -392,8 +394,6 @@
       unwind_protect::add (symbol_table::clear_variables);
     }
 
-  octave_call_stack::push (this);
-
   unwind_protect::add (octave_call_stack::unwind_pop, 0);
 
   if (! (is_nested_function () || is_inline_function ()))
--- a/src/ov-usr-fcn.h	Sat May 03 22:48:24 2008 -0400
+++ b/src/ov-usr-fcn.h	Sun May 04 03:42:19 2008 -0400
@@ -251,7 +251,7 @@
 
   void save_args_passed (const octave_value_list& args)
     {
-      if (call_depth > 1)
+      if (call_depth > 0)
 	saved_args.push (args_passed);
 
       args_passed = args;
--- a/src/pt-id.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/pt-id.cc	Sun May 04 03:42:19 2008 -0400
@@ -65,8 +65,8 @@
   octave_value_list evaluated_args;
   bool args_evaluated;
 
-  octave_value val = sym.find (0, string_vector (), evaluated_args,
-			       args_evaluated);
+  octave_value val = xsym().find (0, string_vector (), evaluated_args,
+				  args_evaluated);
 
   if (val.is_defined ())
     {
@@ -119,7 +119,7 @@
 {
   MAYBE_DO_BREAKPOINT;
 
-  return octave_lvalue (&(sym.varref ()));
+  return octave_lvalue (&(xsym().varref ()));
 }
 
 tree_identifier *
@@ -130,7 +130,7 @@
 
   // FIXME -- is this the best way?
   symbol_table::symbol_record new_sym
-    = symbol_table::find_symbol (sym.name (), scope);
+    = symbol_table::find_symbol (xsym().name (), scope);
 
   tree_identifier *new_id
     = new tree_identifier (new_sym, line (), column ());
--- a/src/pt-id.h	Sat May 03 22:48:24 2008 -0400
+++ b/src/pt-id.h	Sun May 04 03:42:19 2008 -0400
@@ -47,10 +47,15 @@
 public:
 
   tree_identifier (int l = -1, int c = -1)
-    : tree_expression (l, c), sym () { }
+    : tree_expression (l, c), sym (), scope (-1) { }
 
-  tree_identifier (const symbol_table::symbol_record& s, int l = -1, int c = -1)
-    : tree_expression (l, c), sym (s) { }
+  tree_identifier (const symbol_table::symbol_record& s,
+		   int l = -1, int c = -1,
+		   symbol_table::scope_id sc = symbol_table::current_scope ())
+    : tree_expression (l, c), sym (s), scope (sc)
+  {
+    symbol_table::scope_id curr_scope = symbol_table::current_scope ();
+  }
 
   ~tree_identifier (void) { }
 
@@ -58,11 +63,13 @@
 
   bool is_identifier (void) const { return true; }
 
+  // The name doesn't change with scope, so use sym instead of
+  // accessing it through sym so that this function may remain const.
   std::string name (void) const { return sym.name (); }
 
-  bool is_defined (void) { return sym.is_defined (); }
+  bool is_defined (void) { return xsym().is_defined (); }
 
-  bool is_variable (void) { return sym.is_variable (); }
+  bool is_variable (void) { return xsym().is_variable (); }
 
   // Try to find a definition for an identifier.  Here's how:
   //
@@ -85,14 +92,14 @@
   {
     MAYBE_DO_BREAKPOINT;
 
-    return sym.find (args, arg_names, evaluated_args, args_evaluated);
+    return xsym().find (args, arg_names, evaluated_args, args_evaluated);
   }
 
-  void mark_global (void) { sym.mark_global (); }
+  void mark_global (void) { xsym().mark_global (); }
 
-  void mark_as_static (void) { sym.init_persistent (); }
+  void mark_as_static (void) { xsym().init_persistent (); }
 
-  void mark_as_formal_parameter (void) { sym.mark_formal (); }
+  void mark_as_formal_parameter (void) { xsym().mark_formal (); }
 
   // We really need to know whether this symbol referst to a variable
   // or a function, but we may not know that yet.
@@ -116,6 +123,24 @@
   // The symbol record that this identifier references.
   symbol_table::symbol_record sym;
 
+  symbol_table::scope_id scope;
+
+  // A script may be executed in multiple scopes.  If the last one was
+  // different from the one we are in now, update sym to be from the
+  // new scope.
+  symbol_table::symbol_record& xsym (void)
+  {
+    symbol_table::scope_id curr_scope = symbol_table::current_scope ();
+
+    if (scope != curr_scope)
+      {
+	scope = curr_scope;
+	sym = symbol_table::insert (sym.name ());
+      }
+
+    return sym;
+  }
+
   // No copying!
 
   tree_identifier (const tree_identifier&);
--- a/src/pt-stmt.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/pt-stmt.cc	Sun May 04 03:42:19 2008 -0400
@@ -88,7 +88,7 @@
 
   if (cmd || expr)
     {
-      if (in_function_or_script_body)
+      if (! (symbol_table::at_top_level () || Vdebugging))
 	octave_call_stack::set_statement (this);
 
       maybe_echo_code (in_function_or_script_body);
--- a/src/symtab.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/symtab.cc	Sun May 04 03:42:19 2008 -0400
@@ -47,6 +47,8 @@
 
 std::map<symbol_table::scope_id, symbol_table*> symbol_table::all_instances;
 
+std::map<std::string, octave_value> symbol_table::global_table;
+
 std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table;
 
 const symbol_table::scope_id symbol_table::xglobal_scope = 0;
@@ -63,6 +65,8 @@
 std::set<symbol_table::scope_id> symbol_table::scope_ids_in_use;
 std::set<symbol_table::scope_id> symbol_table::scope_ids_free_list;
 
+symbol_table::context_id symbol_table::xcurrent_context = 0;
+
 // Should Octave always check to see if function files have changed
 // since they were last compiled?
 static int Vignore_function_time_stamp = 1;
@@ -76,7 +80,7 @@
   octave_value retval;
 
   if (is_global ())
-    return symbol_table::varref (name (), symbol_table::xglobal_scope);
+    return symbol_table::global_varref (name ());
   else
     {
       octave_value val = varval ();
@@ -366,8 +370,7 @@
 octave_value
 symbol_table::fcn_info::fcn_info_rep::find
   (tree_argument_list *args, const string_vector& arg_names,
-   octave_value_list& evaluated_args, bool& args_evaluated,
-   scope_id scope)
+   octave_value_list& evaluated_args, bool& args_evaluated)
 {
   static bool deja_vu = false;
 
@@ -375,7 +378,7 @@
   // subfunctions if we are currently executing a function defined
   // from a .m file.
 
-  scope_val_iterator r = subfunctions.find (scope);
+  scope_val_iterator r = subfunctions.find (xcurrent_scope);
 
   if (r != subfunctions.end ())
     {
@@ -525,7 +528,7 @@
 	  fname = p->second;
 
 	  octave_value fcn
-	    = symbol_table::find_function (fname, evaluated_args, scope);
+	    = symbol_table::find_function (fname, evaluated_args);
 
 	  if (fcn.is_defined ())
 	    return fcn;
@@ -568,7 +571,7 @@
 
       deja_vu = true;
 
-      retval = find (args, arg_names, evaluated_args, args_evaluated, scope);
+      retval = find (args, arg_names, evaluated_args, args_evaluated);
     }
 
   deja_vu = false;
@@ -672,22 +675,22 @@
 symbol_table::fcn_info::find (tree_argument_list *args,
 			      const string_vector& arg_names,
 			      octave_value_list& evaluated_args,
-			      bool& args_evaluated, scope_id scope)
+			      bool& args_evaluated)
 {
-  return rep->find (args, arg_names, evaluated_args, args_evaluated, scope);
+  return rep->find (args, arg_names, evaluated_args, args_evaluated);
 }
 
 octave_value
 symbol_table::find (const std::string& name, tree_argument_list *args,
 		    const string_vector& arg_names,
 		    octave_value_list& evaluated_args, bool& args_evaluated,
-		    symbol_table::scope_id scope, bool skip_variables)
+		    bool skip_variables)
 {
-  symbol_table *inst = get_instance (scope);
+  symbol_table *inst = get_instance (xcurrent_scope);
 
   return inst
     ? inst->do_find (name, args, arg_names, evaluated_args,
-		       args_evaluated, scope, skip_variables)
+		     args_evaluated, skip_variables)
     : octave_value ();
 }
 
@@ -695,18 +698,16 @@
 symbol_table::find_function (const std::string& name, tree_argument_list *args,
 			     const string_vector& arg_names,
 			     octave_value_list& evaluated_args,
-			     bool& args_evaluated, scope_id scope)
+			     bool& args_evaluated)
 {
-  return find (name, args, arg_names, evaluated_args, args_evaluated,
-	       scope, true);
+  return find (name, args, arg_names, evaluated_args, args_evaluated, true);
 }
 
 octave_value
 symbol_table::do_find (const std::string& name, tree_argument_list *args,
 		       const string_vector& arg_names,
 		       octave_value_list& evaluated_args,
-		       bool& args_evaluated, scope_id scope,
-		       bool skip_variables)
+		       bool& args_evaluated, bool skip_variables)
 {
   octave_value retval;
 
@@ -723,7 +724,7 @@
 	  // FIXME -- should we be using something other than varref here?
 
 	  if (sr.is_global ())
-	    return symbol_table::varref (name, xglobal_scope);
+	    return symbol_table::global_varref (name);
 	  else
 	    {
 	      octave_value& val = sr.varref ();
@@ -741,15 +742,14 @@
       evaluated_args = octave_value_list ();
       args_evaluated = false;
 
-      return p->second.find (args, arg_names, evaluated_args, args_evaluated,
-			     scope);
+      return p->second.find (args, arg_names, evaluated_args, args_evaluated);
     }
   else
     {
       fcn_info finfo (name);
 
       octave_value fcn = finfo.find (args, arg_names, evaluated_args,
-				     args_evaluated, scope);
+				     args_evaluated);
 
       if (fcn.is_defined ())
 	fcn_table[name] = finfo;
--- a/src/symtab.h	Sat May 03 22:48:24 2008 -0400
+++ b/src/symtab.h	Sun May 04 03:42:19 2008 -0400
@@ -28,7 +28,6 @@
 #include <list>
 #include <map>
 #include <set>
-#include <stack>
 #include <string>
 
 #include "glob-match.h"
@@ -45,6 +44,7 @@
 public:
 
   typedef int scope_id;
+  typedef size_t context_id;
 
   class
   symbol_record
@@ -84,19 +84,71 @@
 			 unsigned int sc)
 	: name (nm), value_stack (), storage_class (sc), count (1)
       {
-	value_stack.push (v);
+	value_stack.push_back (v);
+      }
+
+      octave_value& varref (void)
+      {
+	if (is_global ())
+	  return symbol_table::global_varref (name);
+	else if (is_persistent ())
+	  return symbol_table::persistent_varref (name);
+	else
+	  {
+	    context_id n = value_stack.size ();
+	    while (n++ <= symbol_table::xcurrent_context)
+	      value_stack.push_back (octave_value ());
+
+	    return value_stack[symbol_table::xcurrent_context];
+	  }
       }
 
-      octave_value& varref (void) { return value_stack.top (); }
+      octave_value varval (void) const
+      {
+	if (is_global ())
+	  return symbol_table::global_varval (name);
+	else if (is_persistent ())
+	  return symbol_table::persistent_varval (name);
+	else
+	  {
+	    if (symbol_table::xcurrent_context < value_stack.size ())
+	      return value_stack[symbol_table::xcurrent_context];
+	    else
+	      return octave_value ();
+	  }
+      }
 
-      octave_value varval (void) const { return value_stack.top (); }
+      void push_context (void)
+      {
+	if (! (is_persistent () || is_global ()))
+	  value_stack.push_back (octave_value ());
+      }
 
-      void push_context (void) { value_stack.push (octave_value ()); }
+      // If pop_context returns 0, we are out of values and this element
+      // of the symbol table should be deleted.  This can happen for
+      // functions like
+      //
+      //   function foo (n)
+      //     if (n > 0)
+      //       foo (n-1);
+      //     else
+      //       eval ("x = 1");
+      //     endif
+      //   endfunction
+      //
+      // Here, X should only exist in the final stack frame.
 
       size_t pop_context (void)
       {
-	value_stack.pop ();
-	return value_stack.size ();
+	size_t retval = 1;
+
+	if (! (is_persistent () || is_global ()))
+	  {
+	    value_stack.pop_back ();
+	    retval = value_stack.size ();
+	  }
+
+	return retval;
       }
 
       void clear (void)
@@ -185,7 +237,7 @@
 
       std::string name;
 
-      std::stack<octave_value> value_stack;
+      std::deque<octave_value> value_stack;
 
       unsigned int storage_class;
 
@@ -238,44 +290,13 @@
     find (tree_argument_list *args, const string_vector& arg_names,
 	  octave_value_list& evaluated_args, bool& args_evaluated) const;
 
-    octave_value& varref (void)
-    {
-      return is_global ()
-	? symbol_table::varref (name (), symbol_table::global_scope ())
-	: rep->varref ();
-    }
+    octave_value& varref (void) { return rep->varref (); }
 
-    octave_value varval (void) const
-    {
-      return is_global ()
-	? symbol_table::varval (name (), symbol_table::global_scope ())
-	: rep->varval ();
-    }
+    octave_value varval (void) const { return rep->varval (); }
 
-    void push_context (void)
-    {
-      if (! (is_persistent () || is_global ()))
-	rep->push_context ();
-    }
+    void push_context (void) { rep->push_context (); }
 
-    // If pop_context returns 0, we are out of values and this element
-    // of the symbol table should be deleted.  This can happen for
-    // functions like
-    //
-    //   function foo (n)
-    //     if (n > 0)
-    //       foo (n-1);
-    //     else
-    //       eval ("x = 1");
-    //     endif
-    //   endfunction
-    //
-    // Here, X should only exist in the final stack frame.
-
-    size_t pop_context (void)
-    {
-      return (is_persistent () || is_global ()) ? 1 : rep->pop_context ();
-    }
+    size_t pop_context (void) { return rep->pop_context (); }
 
     void clear (void) { rep->clear (); }
 
@@ -356,8 +377,7 @@
 
       octave_value
       find (tree_argument_list *args, const string_vector& arg_names,
-	    octave_value_list& evaluated_args, bool& args_evaluated,
-	    scope_id scope);
+	    octave_value_list& evaluated_args, bool& args_evaluated);
 
       octave_value find_method (const std::string& dispatch_type);
 
@@ -370,21 +390,20 @@
 	return function_on_path.is_defined ();
       }
 
-      octave_value find_function (scope_id scope)
+      octave_value find_function (void)
       {
 	octave_value_list args;
 
-	return find_function (args, scope);
+	return find_function (args);
       }
 
-      octave_value find_function (const octave_value_list& args,
-				  scope_id scope)
+      octave_value find_function (const octave_value_list& args)
       {
 	string_vector arg_names;
 	octave_value_list evaluated_args = args;
 	bool args_evaluated;
 
-	return find (0, arg_names, evaluated_args, args_evaluated, scope);
+	return find (0, arg_names, evaluated_args, args_evaluated);
       }
 
       void install_cmdline_function (const octave_value& f)
@@ -543,8 +562,7 @@
 
     octave_value
     find (tree_argument_list *args, const string_vector& arg_names,
-	  octave_value_list& evaluated_args, bool& args_evaluated,
-	  scope_id scope);
+	  octave_value_list& evaluated_args, bool& args_evaluated);
 
     octave_value find_method (const std::string& dispatch_type) const
     {
@@ -571,15 +589,14 @@
       return rep->is_user_function_defined ();
     }
 
-    octave_value find_function (scope_id scope)
+    octave_value find_function (void)
     {
-      return rep->find_function (scope);
+      return rep->find_function ();
     }
 
-    octave_value find_function (const octave_value_list& args,
-				scope_id scope)
+    octave_value find_function (const octave_value_list& args)
     {
-      return rep->find_function (args, scope);
+      return rep->find_function (args);
     }
 
     void install_cmdline_function (const octave_value& f)
@@ -641,6 +658,8 @@
   static scope_id current_scope (void) { return xcurrent_scope; }
   static scope_id current_caller_scope (void) { return xcurrent_caller_scope; }
 
+  static context_id current_context (void) { return xcurrent_context; }
+
   // We use parent_scope to handle parsing subfunctions.
   static scope_id parent_scope (void) { return xparent_scope; }
 
@@ -681,6 +700,32 @@
 	  instance = p->second;
 
 	xcurrent_scope = scope;
+	xcurrent_context = instance->xcurrent_context_this_table;
+      }
+  }
+
+  static void set_scope_and_context (scope_id scope, context_id context)
+  {
+    if (scope == xglobal_scope)
+      error ("can't set scope to global");
+    else
+      {
+	if (scope != xcurrent_scope)
+	  {
+	    all_instances_iterator p = all_instances.find (scope);
+
+	    if (p == all_instances.end ())
+	      error ("scope not found!");
+	    else
+	      {
+		instance = p->second;
+
+		xcurrent_scope = scope;
+	      }
+	  }
+
+	if (! error_state)
+	  xcurrent_context = context;
       }
   }
 
@@ -728,8 +773,10 @@
     set_parent_scope (-1);
   }
 
-  static void erase_scope (scope_id scope = xcurrent_scope)
+  static void erase_scope (scope_id scope)
   {
+    assert (scope != xglobal_scope);
+
     all_instances_iterator p = all_instances.find (scope);
 
     if (p != all_instances.end ())
@@ -738,7 +785,7 @@
     // free_scope (scope);
   }
 
-  static scope_id dup_scope (scope_id scope = xcurrent_scope)
+  static scope_id dup_scope (scope_id scope)
   {
     scope_id retval = -1;
 
@@ -764,17 +811,12 @@
   }
 
 #if 0
-  static void print_scope (const std::string& tag, scope_id scope)
+  static void print_scope (const std::string& tag)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
-      {
-	std::cerr << "printing " << tag << ", scope: " << scope
-		  << ", inst: " << inst << std::endl;
-
-	inst->do_print_scope (std::cerr);
-      }
+      inst->do_print_scope (std::cerr);
   }
 
   void do_print_scope (std::ostream& os) const
@@ -793,8 +835,8 @@
   }
 #endif
 
-  static symbol_record find_symbol (const std::string& name,
-				    scope_id scope = xcurrent_scope)
+  static symbol_record
+  find_symbol (const std::string& name, scope_id scope = xcurrent_scope)
   {
     symbol_table *inst = get_instance (scope);
 
@@ -816,21 +858,20 @@
   find (const std::string& name, tree_argument_list *args,
 	const string_vector& arg_names,
 	octave_value_list& evaluated_args, bool& args_evaluated,
-	scope_id scope = xcurrent_scope, bool skip_variables = false);
+	bool skip_variables = false);
 
   // Insert a new name in the table.
-  static symbol_record&
-  insert (const std::string& name, scope_id scope = xcurrent_scope)
+  static symbol_record& insert (const std::string& name)
   {
     static symbol_record foobar;
 
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_insert (name) : foobar;
   }
 
-  static octave_value&
-  varref (const std::string& name, scope_id scope = xcurrent_scope)
+  static octave_value& varref (const std::string& name,
+			       scope_id scope = xcurrent_scope)
   {
     static octave_value foobar;
 
@@ -839,8 +880,8 @@
     return inst ? inst->do_varref (name) : foobar;
   }
 
-  static octave_value
-  varval (const std::string& name, scope_id scope = xcurrent_scope)
+  static octave_value varval (const std::string& name,
+			      scope_id scope = xcurrent_scope)
   {
     symbol_table *inst = get_instance (scope);
 
@@ -848,36 +889,48 @@
   }
 
   static octave_value&
-  persistent_varref (const std::string& name, scope_id scope = xcurrent_scope)
+  global_varref (const std::string& name)
+  {
+    global_table_iterator p = global_table.find (name);
+
+    return (p == global_table.end ()) ? global_table[name] : p->second;
+  }
+
+  static octave_value
+  global_varval (const std::string& name)
+  {
+    const_global_table_iterator p = global_table.find (name);
+
+    return (p != global_table.end ()) ? p->second : octave_value ();
+  }
+
+  static octave_value& persistent_varref (const std::string& name)
   {
     static octave_value foobar;
 
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_persistent_varref (name) : foobar;
   }
 
-  static octave_value
-  persistent_varval (const std::string& name, scope_id scope = xcurrent_scope)
+  static octave_value persistent_varval (const std::string& name)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_persistent_varval (name) : octave_value ();
   }
 
-  static void
-  erase_persistent (const std::string& name, scope_id scope = xcurrent_scope)
+  static void erase_persistent (const std::string& name)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_erase_persistent (name);
   }
 
-  static bool
-  is_variable (const std::string& name, scope_id scope = xcurrent_scope)
+  static bool is_variable (const std::string& name)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_is_variable (name) : false;
   }
@@ -931,11 +984,9 @@
   static octave_value
   find_function (const std::string& name, tree_argument_list *args,
 		 const string_vector& arg_names,
-		 octave_value_list& evaluated_args, bool& args_evaluated,
-		 scope_id scope = xcurrent_scope);
+		 octave_value_list& evaluated_args, bool& args_evaluated);
 
-  static octave_value
-  find_user_function (const std::string& name)
+  static octave_value find_user_function (const std::string& name)
   {
     fcn_table_iterator p = fcn_table.find (name);
 
@@ -943,24 +994,21 @@
       ? p->second.find_user_function () : octave_value ();
   }
 
-  static octave_value
-  find_function (const std::string& name, scope_id scope = xcurrent_scope)
+  static octave_value find_function (const std::string& name)
   {
     octave_value_list evaluated_args;
 
-    return find_function (name, evaluated_args, scope);
+    return find_function (name, evaluated_args);
   }
 
   static octave_value
-  find_function (const std::string& name, const octave_value_list& args,
-		 scope_id scope = xcurrent_scope)
+  find_function (const std::string& name, const octave_value_list& args)
   {
     string_vector arg_names;
     octave_value_list evaluated_args = args;
     bool args_evaluated = ! args.empty ();
 
-    return find_function (name, 0, arg_names, evaluated_args,
-			  args_evaluated, scope);
+    return find_function (name, 0, arg_names, evaluated_args, args_evaluated);
   }
 
   static void install_cmdline_function (const std::string& name,
@@ -1048,9 +1096,9 @@
       }
   }
 
-  static void clear (const std::string& name, scope_id scope = xcurrent_scope)
+  static void clear (const std::string& name)
   {
-    clear_variable (name, scope);
+    clear_variable (name);
   }
 
   static void clear_all (void)
@@ -1060,9 +1108,9 @@
     clear_functions ();
   }
 
-  static void clear_variables (scope_id scope = xcurrent_scope)
+  static void clear_variables (void)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_clear_variables ();
@@ -1082,19 +1130,17 @@
     clear_user_function (name);
   }
 
-  static void clear_global (const std::string& name,
-			    scope_id scope = xcurrent_scope)
+  static void clear_global (const std::string& name)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_clear_global (name);
   }
 
-  static void clear_variable (const std::string& name,
-			      scope_id scope = xcurrent_scope)
+  static void clear_variable (const std::string& name)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_clear_variable (name);
@@ -1119,19 +1165,17 @@
       }
   }
 
-  static void clear_global_pattern (const std::string& pat,
-				    scope_id scope = xcurrent_scope)
+  static void clear_global_pattern (const std::string& pat)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_clear_global_pattern (pat);
   }
 
-  static void clear_variable_pattern (const std::string& pat,
-				      scope_id scope = xcurrent_scope)
+  static void clear_variable_pattern (const std::string& pat)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_clear_variable_pattern (pat);
@@ -1264,26 +1308,26 @@
     return retval;
   }
 
-  static void push_context (scope_id scope = xcurrent_scope)
+  static void push_context (void)
   {
-    if (scope == xglobal_scope || scope == xtop_scope)
+    if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
       error ("invalid call to xymtab::push_context");
     else
       {
-	symbol_table *inst = get_instance (scope);
+	symbol_table *inst = get_instance (xcurrent_scope);
 
 	if (inst)
 	  inst->do_push_context ();
       }
   }
 
-  static void pop_context (scope_id scope = xcurrent_scope)
+  static void pop_context (void)
   {
-    if (scope == xglobal_scope || scope == xtop_scope)
-      error ("invalid call to xymtab::push_context");
+    if (xcurrent_scope == xglobal_scope || xcurrent_scope == xtop_scope)
+      error ("invalid call to xymtab::pop_context");
     else
       {
-	symbol_table *inst = get_instance (scope);
+	symbol_table *inst = get_instance (xcurrent_scope);
 
 	if (inst)
 	  inst->do_pop_context ();
@@ -1293,19 +1337,17 @@
   // For unwind_protect.
   static void pop_context (void *) { pop_context (); }
 
-  static void mark_hidden (const std::string& name,
-			   scope_id scope = xcurrent_scope)
+  static void mark_hidden (const std::string& name)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_mark_hidden (name);
   }
 
-  static void mark_global (const std::string& name,
-			   scope_id scope = xcurrent_scope)
+  static void mark_global (const std::string& name)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     if (inst)
       inst->do_mark_global (name);
@@ -1320,25 +1362,43 @@
       ? inst->do_all_variables (defined_only) : std::list<symbol_record> ();
   }
 
-  static std::list<symbol_record>
-  glob (const std::string& pattern, scope_id scope = xcurrent_scope)
+  static std::list<symbol_record> glob (const std::string& pattern)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_glob (pattern) : std::list<symbol_record> ();
   }
 
-  static std::list<symbol_record>
-  glob_variables (const std::string& pattern, scope_id scope = xcurrent_scope)
+  static std::list<symbol_record> glob_variables (const std::string& pattern)
   {
-    symbol_table *inst = get_instance (scope);
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_glob (pattern, true) : std::list<symbol_record> ();
   }
 
   static std::list<symbol_record>
-  glob_variables (const string_vector& patterns,
-		  scope_id scope = xcurrent_scope)
+  glob_global_variables (const std::string& pattern)
+  {
+    std::list<symbol_record> retval;
+
+    glob_match pat (pattern);
+
+    for (const_global_table_iterator p = global_table.begin ();
+	 p != global_table.end (); p++)
+      {
+	// We generate a list of symbol_record objects so that
+	// the results from glob_variables and glob_global_variables
+	// may be handled the same way.
+
+	if (pat.match (p->first))
+	  retval.push_back (symbol_record (p->first, p->second,
+					   symbol_record::global));
+      }
+
+    return retval;
+  }
+
+  static std::list<symbol_record> glob_variables (const string_vector& patterns)
   {
     std::list<symbol_record> retval;
 
@@ -1346,7 +1406,7 @@
 
     for (size_t i = 0; i < len; i++)
       {
-	std::list<symbol_record> tmp = glob_variables (patterns[i], scope);
+	std::list<symbol_record> tmp = glob_variables (patterns[i]);
 
 	retval.insert (retval.begin (), tmp.begin (), tmp.end ());
       }
@@ -1371,10 +1431,29 @@
     return retval;
   }
 
-  static std::list<std::string>
-  variable_names (scope_id scope = xcurrent_scope)
+  static std::list<std::string> global_variable_names (void)
   {
-    symbol_table *inst = get_instance (scope);
+    std::list<std::string> retval;
+
+    for (const_global_table_iterator p = global_table.begin ();
+	 p != global_table.end (); p++)
+      retval.push_back (p->first);
+
+    retval.sort ();
+
+    return retval;
+  }
+
+  static std::list<std::string> top_level_variable_names (void)
+  {
+    symbol_table *inst = get_instance (xtop_scope);
+
+    return inst ? inst->do_variable_names () : std::list<std::string> ();
+  }
+
+  static std::list<std::string> variable_names (void)
+  {
+    symbol_table *inst = get_instance (xcurrent_scope);
 
     return inst ? inst->do_variable_names () : std::list<std::string> ();
   }
@@ -1398,27 +1477,25 @@
     return retval;
   }
 
-  static bool is_local_variable (const std::string& name,
-				 scope_id scope = xcurrent_scope)
+  static bool is_local_variable (const std::string& name)
   {
-    if (scope == xglobal_scope)
+    if (xcurrent_scope == xglobal_scope)
       return false;
     else
       {
-	symbol_table *inst = get_instance (scope);
+	symbol_table *inst = get_instance (xcurrent_scope);
 
 	return inst ? inst->do_is_local_variable (name) : false;
       }
   }
 
-  static bool is_global (const std::string& name,
-			 scope_id scope = xcurrent_scope)
+  static bool is_global (const std::string& name)
   {
-    if (scope == xglobal_scope)
+    if (xcurrent_scope == xglobal_scope)
       return true;
     else
       {
-	symbol_table *inst = get_instance (scope);
+	symbol_table *inst = get_instance (xcurrent_scope);
 
 	return inst ? inst->do_is_global (name) : false;
       }
@@ -1429,6 +1506,9 @@
   typedef std::map<std::string, symbol_record>::const_iterator const_table_iterator;
   typedef std::map<std::string, symbol_record>::iterator table_iterator;
 
+  typedef std::map<std::string, octave_value>::const_iterator const_global_table_iterator;
+  typedef std::map<std::string, octave_value>::iterator global_table_iterator;
+
   typedef std::map<std::string, octave_value>::const_iterator const_persistent_table_iterator;
   typedef std::map<std::string, octave_value>::iterator persistent_table_iterator;
 
@@ -1447,6 +1527,9 @@
   // Map from symbol names to symbol info.
   std::map<std::string, symbol_record> table;
 
+  // Map from names of global variables to values.
+  static std::map<std::string, octave_value> global_table;
+
   // Map from names of persistent variables to values.
   std::map<std::string, octave_value> persistent_table;
 
@@ -1469,6 +1552,10 @@
   // We use parent_scope to handle parsing subfunctions.
   static scope_id xparent_scope;
 
+  // Used to handle recursive calls.
+  context_id xcurrent_context_this_table;
+  static context_id xcurrent_context;
+
   static std::deque<scope_id> scope_stack;
 
   // The next available scope ID.
@@ -1480,7 +1567,7 @@
   // The set of scope IDs that are currently available.
   static std::set<scope_id> scope_ids_free_list;
 
-  symbol_table (void) : table () { }
+  symbol_table (void) : table (), xcurrent_context_this_table () { }
 
   ~symbol_table (void) { }
 
@@ -1506,32 +1593,35 @@
   {
     symbol_table *retval = 0;
 
-    if (scope == xcurrent_scope)
+    if (scope != xglobal_scope)
       {
-	if (! instance)
+	if (scope == xcurrent_scope)
 	  {
-	    instance = new symbol_table ();
-
-	    all_instances[scope] = instance;
-	  }
-
-	if (! instance)
-	  error ("unable to create symbol_table object!");
+	    if (! instance)
+	      {
+		instance = new symbol_table ();
 
-	retval = instance;
-      }
-    else
-      {
-	all_instances_iterator p = all_instances.find (scope);
+		all_instances[scope] = instance;
+	      }
 
-	if (p == all_instances.end ())
-	  {
-	    retval = new symbol_table ();
+	    if (! instance)
+	      error ("unable to create symbol_table object!");
 
-	    all_instances[scope] = retval;
+	    retval = instance;
 	  }
 	else
-	  retval = p->second;
+	  {
+	    all_instances_iterator p = all_instances.find (scope);
+
+	    if (p == all_instances.end ())
+	      {
+		retval = new symbol_table ();
+
+		all_instances[scope] = retval;
+	      }
+	    else
+	      retval = p->second;
+	  }
       }
 
     return retval;
@@ -1585,7 +1675,7 @@
   do_find (const std::string& name, tree_argument_list *args,
 	   const string_vector& arg_names,
 	   octave_value_list& evaluated_args, bool& args_evaluated,
-	   scope_id scope, bool skip_variables);
+	   bool skip_variables);
 
   symbol_record& do_insert (const std::string& name)
   {
@@ -1657,12 +1747,16 @@
 
   void do_push_context (void)
   {
+    xcurrent_context = ++xcurrent_context_this_table;
+
     for (table_iterator p = table.begin (); p != table.end (); p++)
       p->second.push_context ();
   }
 
   void do_pop_context (void)
   {
+    xcurrent_context = --xcurrent_context_this_table;
+
     for (table_iterator p = table.begin (); p != table.end (); )
       {
 	if (p->second.pop_context () == 0)
@@ -1688,7 +1782,10 @@
 
 	if (sr.is_global ())
 	  {
-	    symbol_table::clear_variable (p->first, xglobal_scope);
+	    global_table_iterator q = global_table.find (name);
+
+	    if (q != global_table.end ())
+	      global_table.erase (q);
 
 	    sr.unmark_global ();
 	  }
@@ -1715,7 +1812,10 @@
 	  {
 	    if (pattern.match (sr.name ()))
 	      {
-		symbol_table::clear_variable (p->first, xglobal_scope);
+		global_table_iterator q = global_table.find (sr.name ());
+
+		if (q != global_table.end ())
+		  global_table.erase (q);
 
 		sr.unmark_global ();
 	      }
--- a/src/toplev.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/toplev.cc	Sun May 04 03:42:19 2008 -0400
@@ -181,19 +181,23 @@
 
   int nframes = cs.size () - n;
 
-  if (nframes > 0)
+  if (n >= 0 && nframes > 0)
     {
-      Cell keys (4, 1);
+      Cell keys (6, 1);
 
       keys(0) = "file";
       keys(1) = "name";
       keys(2) = "line";
       keys(3) = "column";
+      keys(4) = "scope";
+      keys(5) = "context";
 
       Cell file (nframes, 1);
       Cell name (nframes, 1);
       Cell line (nframes, 1);
       Cell column (nframes, 1);
+      Cell scope (nframes, 1);
+      Cell context (nframes, 1);
 
       octave_idx_type k = 0;
 
@@ -201,6 +205,9 @@
 	{
 	  const call_stack_elt& elt = *p;
 
+	  scope(k) = elt.scope;
+	  context(k) = elt.context;
+
 	  octave_function *f = elt.fcn;
 
 	  if (f)
@@ -236,11 +243,68 @@
       retval.assign ("name", name);
       retval.assign ("line", line);
       retval.assign ("column", column);
+      retval.assign ("scope", scope);
+      retval.assign ("context", context);
     }
 
   return retval;
 }
 
+bool
+octave_call_stack::do_goto_frame (size_t n, bool verbose)
+{
+  bool retval = false;
+
+  if (n < cs.size ())
+    {
+      retval = true;
+
+      curr_frame = n;
+
+      const call_stack_elt& elt = cs[n];
+
+      symbol_table::set_scope_and_context (elt.scope, elt.context);
+
+      if (verbose)
+	{
+	  octave_function *f = elt.fcn;
+	  std::string nm = f ? f->name () : std::string ("<unknown>");
+
+	  tree_statement *s = elt.stmt;
+	  int l = -1;
+	  int c = -1;
+	  if (s)
+	    {
+	      l = s->line ();
+	      c = s->column ();
+	    }
+
+	  octave_stdout << "stopped in " << nm
+			<< " at line " << l << " column " << c
+			<< " (" << elt.scope << "[" << elt.context << "])"
+			<< std::endl;
+	}
+    }
+
+  return retval;
+}
+
+bool
+octave_call_stack::do_goto_frame_relative (int n, bool verbose)
+{
+  bool retval = false;
+
+  size_t sz = cs.size ();
+
+  if (n == 0)
+    retval = true;
+  else if ((n > 0 && static_cast<size_t> (n) < sz - curr_frame)
+	   || (n < 0 && static_cast<size_t> (-n) < curr_frame))
+    retval = goto_frame (curr_frame + n, verbose);
+
+  return retval;
+}
+
 void
 recover_from_exception (void)
 {
--- a/src/toplev.h	Sat May 03 22:48:24 2008 -0400
+++ b/src/toplev.h	Sun May 04 03:42:19 2008 -0400
@@ -37,6 +37,7 @@
 class tree_statement_list;
 class charMatrix;
 
+#include "input.h"
 #include "oct-map.h"
 
 extern OCTINTERP_API void
@@ -75,15 +76,19 @@
 
   struct call_stack_elt
   {
-    call_stack_elt (octave_function *f) : fcn (f), stmt (0) { }
+    call_stack_elt (octave_function *f, symbol_table::scope_id s,
+		    symbol_table::context_id c)
+      : fcn (f), stmt (0), scope (s), context (c) { }
 
     octave_function *fcn;
     tree_statement *stmt;
+    symbol_table::scope_id scope;
+    symbol_table::context_id context;
   };
 
 protected:
 
-  octave_call_stack (void) : cs () { }
+  octave_call_stack (void) : cs (), curr_frame (0) { }
 
 public:
 
@@ -131,6 +136,11 @@
     return element (1);
   }
 
+  static size_t current_frame (void)
+  {
+    return instance_ok () ? instance->do_current_frame () : 0;
+  }
+
   // Function at location N on the call stack (N == 0 is current), may
   // be built-in.
   static octave_function *element (size_t n)
@@ -156,10 +166,13 @@
     return instance_ok () ? instance->do_caller_user_code () : 0;
   }
 
-  static void push (octave_function *f)
+  static void
+  push (octave_function *f,
+	symbol_table::scope_id scope = symbol_table::current_scope (),
+	symbol_table::context_id context = 0)
   {
     if (instance_ok ())
-      instance->do_push (f);
+      instance->do_push (f, scope, context);
   }
 
   static octave_function *top (void)
@@ -178,6 +191,17 @@
       instance->do_set_statement (s);
   }
 
+  static bool goto_frame (size_t n = 0, bool verbose = false)
+  {
+    return instance_ok () ? instance->do_goto_frame (n, verbose) : false;
+  }
+
+  static bool goto_frame_relative (int n, bool verbose = false)
+  {
+    return instance_ok ()
+      ? instance->do_goto_frame_relative (n, verbose) : false;
+  }
+
   static Octave_map backtrace (int n = 0)
   {
     return instance_ok () ? instance->do_backtrace (n) : Octave_map ();
@@ -204,12 +228,16 @@
   // The current call stack.
   std::deque<call_stack_elt> cs;
 
+  size_t curr_frame;
+
   static octave_call_stack *instance;
 
   int do_current_line (void) const;
 
   int do_current_column (void) const;
 
+  size_t do_current_frame (void) { return curr_frame; }
+
   octave_function *do_element (size_t n)
   {
     octave_function *retval = 0;
@@ -229,9 +257,13 @@
 
   octave_user_code *do_caller_user_code (void) const;
 
-  void do_push (octave_function *f)
+  void do_push (octave_function *f, symbol_table::scope_id scope,
+		symbol_table::context_id context)
   {
-    cs.push_front (call_stack_elt (f));
+    if (Vdebugging)
+      curr_frame++;
+
+    cs.push_front (call_stack_elt (f, scope, context));
   }
 
   octave_function *do_top (void) const
@@ -271,10 +303,19 @@
 
   Octave_map do_backtrace (int n) const;
 
+  bool do_goto_frame (size_t n, bool verbose);
+
+  bool do_goto_frame_relative (int n, bool verbose);
+
   void do_pop (void)
   {
     if (! cs.empty ())
-      cs.pop_front ();
+      {
+	if (Vdebugging)
+	  curr_frame--;
+
+	cs.pop_front ();
+      }
   }
 
   void do_clear (void) { cs.clear (); }
--- a/src/unwind-prot.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/unwind-prot.cc	Sun May 04 03:42:19 2008 -0400
@@ -45,6 +45,7 @@
   {
     boolean,
     integer,
+    size_type,
     string_type,
     generic_ptr,
     generic
@@ -56,6 +57,8 @@
 
   saved_variable (int *p, int v);
 
+  saved_variable (size_t *p, size_t v);
+
   saved_variable (std::string *p, const std::string& v);
 
   saved_variable (void **p, void *v);
@@ -72,6 +75,7 @@
     {
       bool *ptr_to_bool;
       int *ptr_to_int;
+      size_t *ptr_to_size_t;
       void *gen_ptr;
       void **ptr_to_gen_ptr;
     };
@@ -80,6 +84,7 @@
     {
       bool bool_value;
       int int_value;
+      size_t size_t_value;
       std::string *str_value;
       void *gen_ptr_value;
     };
@@ -113,6 +118,14 @@
   size = sizeof (int);  // Is this necessary?
 }
 
+saved_variable::saved_variable (size_t *p, size_t v)
+{
+  type_tag = size_type;
+  ptr_to_size_t = p;
+  size_t_value = v;
+  size = sizeof (size_t);  // Is this necessary?
+}
+
 saved_variable::saved_variable (std::string *p, const std::string& v)
 {
   type_tag = string_type;
@@ -160,6 +173,10 @@
       *ptr_to_int = int_value;
       break;
 
+    case size_type:
+      *ptr_to_size_t = size_t_value;
+      break;
+
     case string_type:
       (static_cast<std::string *> (gen_ptr)) -> assign (*str_value);
       break;
@@ -290,6 +307,13 @@
 }
 
 void
+unwind_protect::save_size_t (size_t *ptr, size_t value)
+{
+  saved_variable *s = new saved_variable (ptr, value);
+  add (saved_variable::restore, s);
+}
+
+void
 unwind_protect::save_str (std::string *ptr, const std::string& value)
 {
   saved_variable *s = new saved_variable (ptr, value);
--- a/src/unwind-prot.h	Sat May 03 22:48:24 2008 -0400
+++ b/src/unwind-prot.h	Sun May 04 03:42:19 2008 -0400
@@ -103,6 +103,8 @@
 
   static void save_int (int *ptr, int value);
 
+  static void save_size_t (size_t *ptr, size_t value);
+
   static void save_str (std::string *ptr, const std::string& value);
 
   static void save_ptr (void **ptr, void *value);
@@ -120,6 +122,9 @@
 #define unwind_protect_int(i) \
   unwind_protect::save_int (&(i), (i))
 
+#define unwind_protect_size_t(i) \
+  unwind_protect::save_size_t (&(i), (i))
+
 #define unwind_protect_str(s) \
   unwind_protect::save_str (&(s), (s))
 
--- a/src/variables.cc	Sat May 03 22:48:24 2008 -0400
+++ b/src/variables.cc	Sun May 04 03:42:19 2008 -0400
@@ -856,7 +856,7 @@
 octave_value
 get_global_value (const std::string& nm, bool silent)
 {
-  octave_value val = symbol_table::varval (nm, symbol_table::global_scope ());
+  octave_value val = symbol_table::global_varval (nm);
 
   if (val.is_undefined () && ! silent)
     error ("get_global_by_name: undefined symbol `%s'", nm.c_str ());
@@ -867,7 +867,7 @@
 void
 set_global_value (const std::string& nm, const octave_value& val)
 {
-  symbol_table::varref (nm, symbol_table::global_scope ()) = val;
+  symbol_table::global_varref (nm) = val;
 }
 
 // Variable values.
@@ -1671,9 +1671,6 @@
       pats[0] = "*";
     }
     
-  symbol_table::scope_id scope = global_only
-    ? symbol_table::global_scope () : symbol_table::current_scope ();
-
   symbol_info_list symbol_stats;
   std::list<std::string> symbol_names;
 
@@ -1718,8 +1715,9 @@
 	}
       else
 	{
-	  std::list<symbol_table::symbol_record> tmp
-	    = symbol_table::glob_variables (pats[j], scope);
+	  std::list<symbol_table::symbol_record> tmp = global_only
+	    ? symbol_table::glob_global_variables (pats[j])
+	    : symbol_table::glob_variables (pats[j]);
 
 	  for (std::list<symbol_table::symbol_record>::const_iterator p = tmp.begin ();
 	       p != tmp.end (); p++)
@@ -2080,13 +2078,19 @@
 		  bool exclusive = false)
 {
   if (idx == argc)
-    symbol_table::clear_variables(symbol_table::global_scope ());
+    {
+      string_vector gvars = symbol_table::global_variable_names ();
+
+      int gcount = gvars.length ();
+
+      for (int i = 0; i < gcount; i++)
+	symbol_table::clear_global (gvars[i]);
+    }
   else
     {
       if (exclusive)
 	{
-	  string_vector gvars
-	    = symbol_table::variable_names (symbol_table::global_scope ());
+	  string_vector gvars = symbol_table::global_variable_names ();
 
 	  int gcount = gvars.length ();