changeset 4009:27e461aed956

[project @ 2002-07-31 09:33:03 by jwe]
author jwe
date Wed, 31 Jul 2002 09:33:09 +0000
parents a0e323e959cd
children 0a30852e0249
files src/ChangeLog src/defun.cc src/dynamic-ld.cc src/help.cc src/load-save.cc src/parse.y src/pt-decl.cc src/pt-id.cc src/symtab.cc src/symtab.h src/variables.cc src/variables.h
diffstat 12 files changed, 888 insertions(+), 342 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/ChangeLog	Wed Jul 31 09:33:09 2002 +0000
@@ -1,3 +1,122 @@
+2002-07-31  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* symtab.cc (symbol_table::clear (void)): Clear all records.
+	(symbol_table::clear (const std::string&)): Delete second arg.
+	Clear any symbol that matches, regardless of type.
+
+	* symtab.h (symbol_table::variable_name_list): New function.
+	(symbol_table::global_variable_name_list): Likewise.
+	(symbol_table::user_function_name_list): Likewise.
+
+	* symtab.h, symtab.cc (symbol_table::clear_variables): New function.
+	(symbol_table::clear_functions): Likewise.
+	(symbol_table::clear_globals): Likewise.
+	(symbol_table::clear_variable): New function.
+	(symbol_table::clear_function): Likewise.
+	(symbol_table::clear_global): Likewise.
+	(symbol_table::clear_variable_pattern): New function.
+	(symbol_table::clear_function_pattern): Likewise.
+	(symbol_table::clear_global_pattern): Likewise.
+
+	* variables.cc (name_matches_any_pattern): Rename from
+	var_matches_any_pattern.
+	(is_local_variable): New static inline function.
+	(maybe_warn_exclusive): Likewise.
+	(do_clear_all): Likewise.
+	(do_clear_functions): Likewise.
+	(do_clear_globals): Likewise.
+	(do_clear_variables): Likewise.
+	(do_clear_function): Likewise.
+	(do_clear_global): Likewise.
+	(do_clear_variable): Likewise.
+	(do_clear_symbol): Likewise.
+	(do_clear_function_pattern): Likewise.
+	(do_clear_global_pattern): Likewise.
+	(do_clear_variable_pattern): Likewise.
+	(do_clear_symbol_pattern): Likewise.
+	(do_clear_functions): Likewise.
+	(do_clear_functions): Likewise.
+	(do_clear_globals): Likewise.
+	(do_clear_variables): Likewise.
+	(do_clear_symbols): Likewise.
+	(do_matlab_compatible_clear): Likewise.
+	(CLEAR_OPTION_ERROR): New macro.
+	(Fclear): Rewrite for Matlab compatibility and to cope with new
+	symbol table semantics.
+
+2002-07-30  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* symtab.cc (symbol_table::clear): Simply clear everything.
+	(symbol_table::clear_functions, symbol_table::clear_globals,
+	symbol_table::clear_all): New functions.
+
+	* symtab.h (symbol_record::symbol_def::next_elem): Delete.
+	(symbol_record::symbol_def::symbol_def): Delete intializer.
+
+	* symtab.h, symtab.cc (symbol_record::push_def): Delete.
+	(symbol_record::remove_top_def): Delete.
+	(symbol_record::replace_all_defs): Delete.
+	(symbol_record::hides_fcn): Delete.
+	(symbol_record::hides_builtin): Delete.
+
+	* symtab.h (symbol_table::~symbol_table): Call clear before
+	deleting the table.
+
+	* variables.cc (initialize_symbol_tables): Create fbi_sym_tab too.
+	(Fexist): Look in fbi_sym_tab, not global_sym_tab.
+
+	* parse.y (function_symtab): Rename from global_symtab.
+	Set curr_sym_tab to fbi_sym_tab, not global_sym_tab.
+	Change all uses of global_symtab to be function_symtab instead.
+	(frob_function): Rename and look for function name in fbi_sym_tab,
+	not global_sym_tab.
+	(parse_fcn_file): Clear function name from fbi_sym_tab, not
+	global_sym_tab.
+
+	* load-save.cc (save_vars): Look for built-in vars in fbi_sym_tab.
+	* symtab.cc (symbol_record::link_to_builtin_variable): Likewise.
+	* variables.cc (is_builtin_variable): Likewise.
+	(bind_ans): Likewise.
+	(bind_builtin_constant): Likewise.
+	(bind_builtin_variable): Likewise.
+	(builtin_string_variable): Likewise.
+	(builtin_real_scalar_variable): Likewise.
+	(builtin_any_variable): Likewise.
+	(is_text_function_name): Likewise, for functions.
+	(force_link_to_function): Likewise.
+	(is_builtin_function_name): Likewise.
+	(is_mapper_function_name): Likewise.
+	(is_valid_function): Likewise.
+	(Fclear): Likewise.
+	(F__print_symtab_info__): Likewise.
+	* defun.cc (print_usage): Likewise.
+	(install_builtin_mapper): Likewise.
+	(install_builtin_function): Likewise.
+	(install_dld_function): Likewise.
+	(Falias): Likewise.
+	* dynamic-ld.cc (clear_function): Likewise.
+	* variables.cc (do_who): Likewise, for built-ins and functions.
+	(link_to_builtin_or_function): Likewise.
+	* help.cc (LIST_SYMBOLS): Likewise.
+	(make_name_list): Handle fbi_sym_tab too.
+
+	* variables.cc (fbi_sym_tab): New symbol table.
+	* variables.h (fbi_sym_tab): Provide decl.
+
+2002-07-29  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* symtab.h (symbol_record::alias): Delete unused arg force.
+	Change all callers.
+
+	* variables.cc (link_to_global_variable): Give local variable
+	global value.
+
+	* pt-id.cc (tree_identifier::link_to_global): Warn about global
+	variables that have been defined before being declared global.
+	for a global variable to be used before it is declared global.
+	* pt-decl.cc (tree_global_command::do_init): Handle possible error
+	from tree_identifier::link_to_global.
+
 2002-07-25  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* ov.cc (silent_functions, Vsilent_functions): Move here.
--- a/src/defun.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/defun.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -43,7 +43,7 @@
 void
 print_usage (const std::string& nm, bool just_usage)
 {
-  symbol_record *sym_rec = global_sym_tab->lookup (nm);
+  symbol_record *sym_rec = fbi_sym_tab->lookup (nm);
 
   if (sym_rec)
     {
@@ -83,7 +83,7 @@
 void
 install_builtin_mapper (octave_mapper *mf)
 {
-  symbol_record *sym_rec = global_sym_tab->lookup (mf->name (), true);
+  symbol_record *sym_rec = fbi_sym_tab->lookup (mf->name (), true);
 
   unsigned int t
     = symbol_record::BUILTIN_FUNCTION | symbol_record::MAPPER_FUNCTION;
@@ -99,7 +99,7 @@
 install_builtin_function (octave_builtin::fcn f, const std::string& name,
 			  const std::string& doc, bool is_text_fcn)
 {
-  symbol_record *sym_rec = global_sym_tab->lookup (name, true);
+  symbol_record *sym_rec = fbi_sym_tab->lookup (name, true);
 
   unsigned int t = symbol_record::BUILTIN_FUNCTION;
 
@@ -134,7 +134,7 @@
 		      const octave_shlib& shl,
 		      const std::string& doc, bool is_text_fcn)
 {
-  symbol_record *sym_rec = global_sym_tab->lookup (name, true);
+  symbol_record *sym_rec = fbi_sym_tab->lookup (name, true);
 
   unsigned int t = symbol_record::DLD_FUNCTION;
 
@@ -151,12 +151,12 @@
 void
 alias_builtin (const std::string& alias, const std::string& name)
 {
-  symbol_record *sr_name = global_sym_tab->lookup (name);
+  symbol_record *sr_name = fbi_sym_tab->lookup (name);
 
   if (! sr_name)
     panic ("can't alias to undefined name!");
 
-  symbol_record *sr_alias = global_sym_tab->lookup (alias, true);
+  symbol_record *sr_alias = fbi_sym_tab->lookup (alias, true);
 
   if (sr_alias)
     sr_alias->alias (sr_name);
@@ -187,7 +187,7 @@
 
 	  if (sr_name && sr_name->is_function ())
 	    {
-	      symbol_record *sr_alias = global_sym_tab->lookup (alias, true);
+	      symbol_record *sr_alias = fbi_sym_tab->lookup (alias, true);
 
 	      if (sr_alias)
 		sr_alias->alias (sr_name);
--- a/src/dynamic-ld.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/dynamic-ld.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -203,7 +203,7 @@
   if (curr_sym_tab != top_level_sym_tab)
     top_level_sym_tab->clear (fcn_name);
 
-  global_sym_tab->clear (fcn_name);
+  fbi_sym_tab->clear (fcn_name);
 }
 
 bool
--- a/src/help.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/help.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -347,6 +347,9 @@
   string_vector key = names (keyword_help ());
   int key_len = key.length ();
 
+  string_vector fbi = fbi_sym_tab->name_list ();
+  int fbi_len = fbi.length ();
+
   string_vector glb = global_sym_tab->name_list ();
   int glb_len = glb.length ();
 
@@ -361,7 +364,7 @@
   string_vector ffl = octave_fcn_file_name_cache::list_no_suffix ();
   int ffl_len = ffl.length ();
 
-  int total_len = key_len + glb_len + top_len + lcl_len + ffl_len;
+  int total_len = key_len + fbi_len + glb_len + top_len + lcl_len + ffl_len;
 
   string_vector list (total_len);
 
@@ -372,6 +375,9 @@
   for (i = 0; i < key_len; i++)
     list[j++] = key[i];
 
+  for (i = 0; i < fbi_len; i++)
+    list[j++] = fbi[i];
+
   for (i = 0; i < glb_len; i++)
     list[j++] = glb[i];
 
@@ -438,7 +444,7 @@
   do \
     { \
       string_vector names \
-	= global_sym_tab->name_list (string_vector (), true, type); \
+	= fbi_sym_tab->name_list (string_vector (), true, type); \
       display_symtab_names (octave_stdout, names, msg); \
     } \
   while (0)
--- a/src/load-save.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/load-save.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -4696,7 +4696,7 @@
 
   if (! error_state && save_builtins)
     {
-      vars = global_sym_tab->glob
+      vars = fbi_sym_tab->glob
 	(pattern, symbol_record::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES);
 
       int count = vars.length ();
--- a/src/parse.y	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/parse.y	Wed Jul 31 09:33:09 2002 +0000
@@ -1070,8 +1070,8 @@
 		  }
 		;
 		   
-global_symtab	: // empty
-		  { curr_sym_tab = global_sym_tab; }
+function_symtab	: // empty
+		  { curr_sym_tab = fbi_sym_tab; }
 		;
 
 local_symtab	: // empty
@@ -1187,14 +1187,14 @@
 		  }
 		;
 
-return_list_end	: global_symtab ']'
+return_list_end	: function_symtab ']'
 		;
 
 // ===================
 // Function definition
 // ===================
 
-function_beg	: save_symtab FCN stash_comment global_symtab
+function_beg	: save_symtab FCN stash_comment function_symtab
 		  { $$ = $3; }
 		;
 
@@ -1218,7 +1218,7 @@
 		  }
 		;
 
-function1	: global_symtab '=' function2
+function1	: function_symtab '=' function2
 		  { $$ = $3; }
 		;
 
@@ -2478,7 +2478,7 @@
 	    warning ("function name `%s' does not agree with function\
  file name `%s'", id_name.c_str (), curr_fcn_file_full_name.c_str ());
 
-	  global_sym_tab->rename (id_name, curr_fcn_file_name);
+	  fbi_sym_tab->rename (id_name, curr_fcn_file_name);
 
 	  if (error_state)
 	    return 0;
@@ -2513,7 +2513,7 @@
 
   top_level_sym_tab->clear (id_name);
 
-  symbol_record *sr = global_sym_tab->lookup (id_name);
+  symbol_record *sr = fbi_sym_tab->lookup (id_name);
 
   if (sr)
     fcn->stash_symtab_ptr (sr);
@@ -3224,7 +3224,7 @@
 	    {
 	      error ("parse error while reading function file %s",
 		     ff.c_str ());
-	      global_sym_tab->clear (curr_fcn_file_name);
+	      fbi_sym_tab->clear (curr_fcn_file_name);
 	    }
 	}
       else if (exec_script)
--- a/src/pt-decl.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/pt-decl.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -102,20 +102,24 @@
     {
       id->link_to_global ();
 
-      octave_lvalue ult = id->lvalue ();
+      if (! error_state)
+	{
+	  octave_lvalue ult = id->lvalue ();
 
-      if (ult.is_undefined ())
-	{
-	  tree_expression *expr = elt.expression ();
+	  if (ult.is_undefined ())
+	    {
+	      tree_expression *expr = elt.expression ();
 
-	  octave_value init_val;
+	      octave_value init_val;
 
-	  if (expr)
-	    init_val = expr->rvalue ();
-	  else if (Vinitialize_global_variables)
-	    init_val = builtin_any_variable ("default_global_variable_value");
+	      if (expr)
+		init_val = expr->rvalue ();
+	      else if (Vinitialize_global_variables)
+		init_val
+		  = builtin_any_variable ("default_global_variable_value");
 
-	  ult.assign (octave_value::op_asn_eq, init_val);
+	      ult.assign (octave_value::op_asn_eq, init_val);
+	    }
 	}
     }
 }
--- a/src/pt-id.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/pt-id.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -119,7 +119,15 @@
 tree_identifier::link_to_global (void)
 {
   if (sym)
-    link_to_global_variable (sym);
+    {
+      if (! sym->is_linked_to_global ())
+	{
+	  if (sym->is_defined () && sym->is_variable ())
+	    warning ("local variable value may have changed to match global");
+
+	  link_to_global_variable (sym);
+	}
+    }
 }
 
 void
--- a/src/symtab.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/symtab.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -202,19 +202,6 @@
 {
   if (! (is_variable () && read_only_error ("redefine")))
     {
-      if (is_function () || is_constant ())
-	{
-	  if (Vvariables_can_hide_functions)
-	    {
-	      push_def (new symbol_def ());
-
-	      if (Vvariables_can_hide_functions < 0)
-		warning ("variable `%s' hides function", nm.c_str ());
-	    }
-	  else
-	    error ("variable `%s' hides function", nm.c_str ());
-	}
-
       if (definition->type () == symbol_record::BUILTIN_VARIABLE)
 	sym_type = symbol_record::BUILTIN_VARIABLE;
 
@@ -255,7 +242,9 @@
     {
       octave_value tmp (f);
 
-      replace_all_defs (new symbol_def (tmp, sym_type));
+      delete definition;
+
+      definition = new symbol_def (tmp, sym_type);
 
       retval = true;
     }
@@ -266,30 +255,27 @@
 void
 symbol_record::clear (void)
 {
-  if (linked_to_global)
+  if (! tagged_static)
     {
       if (--definition->count <= 0)
 	delete definition;
 
       definition = new symbol_def ();
+    }
 
-      linked_to_global = 0;
-    }
-  else if (! tagged_static)
-    {
-      remove_top_def ();
-
-      if (! definition)
-	definition = new symbol_def ();
-    }
+  if (linked_to_global)
+    linked_to_global = 0;
 }
 
 void
-symbol_record::alias (symbol_record *s, bool /* force */)
+symbol_record::alias (symbol_record *s)
 {
   chg_fcn = s->chg_fcn;
 
-  replace_all_defs (s->definition);
+  if (--definition->count <= 0)
+    delete definition;
+
+  definition = (s->definition);
 
   definition->count++;
 }
@@ -329,38 +315,6 @@
     tagged_static = 1;
 }
 
-bool
-symbol_record::hides_fcn (void) const
-{
-  bool retval = false;
-
-  if (is_variable () && is_defined ())
-    {
-      symbol_def *hidden_def = definition->next_elem;
-
-      if (hidden_def && hidden_def->is_user_function ())
-	retval = true;
-    }
-
-  return retval;
-}
-
-bool
-symbol_record::hides_builtin (void) const
-{
-  bool retval = false;
-
-  if (is_variable () && is_defined ())
-    {
-      symbol_def *hidden_def = definition->next_elem;
-
-      if (hidden_def && hidden_def->is_builtin_function ())
-	retval = true;
-    }
-
-  return retval;
-}
-
 octave_value&
 symbol_record::variable_value (void)
 {
@@ -372,7 +326,7 @@
 inline void
 symbol_record::link_to_builtin_variable (void)
 {
-  symbol_record *tmp_sym = global_sym_tab->lookup (name ());
+  symbol_record *tmp_sym = fbi_sym_tab->lookup (name ());
 
   if (tmp_sym && tmp_sym->is_builtin_variable ())
     alias (tmp_sym);
@@ -437,7 +391,10 @@
 
   if (! context.empty ())
     {
-      replace_all_defs (context.pop ());
+      if (--definition->count <= 0)
+	delete definition;
+
+      definition = context.pop ();
 
       linked_to_global = global_link_context.pop ();
     }
@@ -448,9 +405,6 @@
 {
   os << (is_read_only () ? " r-" : " rw")
      << (is_eternal () ? "-" : "d")
-#if 0
-     << (hides_fcn () ? "f" : (hides_builtin () ? "F" : "-"))
-#endif
      << "  "
      << std::setiosflags (std::ios::left) << std::setw (24)
      << type_name () . c_str ();
@@ -502,42 +456,6 @@
     return false;
 }
 
-void
-symbol_record::push_def (symbol_def *sd)
-{
-  if (! sd)
-    return;
-
-  assert (definition == 0 || definition->next_elem == 0);
-
-  sd->next_elem = definition;
-
-  definition = sd;
-}
-
-void
-symbol_record::remove_top_def (void)
-{
-  symbol_def *top = definition;
-
-  definition = definition->next_elem;
-
-  if (--top->count <= 0)
-    delete top;
-}
-
-void
-symbol_record::replace_all_defs (symbol_def *sd)
-{
-  while (definition)
-    remove_top_def ();
-
-  if (! sd)
-    sd = new symbol_def ();
-
-  push_def (sd);
-}
-
 // A symbol table.
 
 symbol_record *
@@ -605,8 +523,46 @@
 	 new_name.c_str ());
 }
 
+// XXX FIXME XXX -- it would be nice to eliminate a lot of the
+// following duplicate code.
+
 void
-symbol_table::clear (bool clear_user_functions)
+symbol_table::clear (void)
+{
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  ptr->clear ();
+
+	  ptr = ptr->next ();
+	}
+    }
+}
+
+void
+symbol_table::clear_variables (void)
+{
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  if (ptr->is_user_variable ())
+	    ptr->clear ();
+
+	  ptr = ptr->next ();
+	}
+    }
+}
+
+// Really only clear functions that can be reloaded.
+
+void
+symbol_table::clear_functions (void)
 {
   for (unsigned int i = 0; i < table_size; i++)
     {
@@ -614,12 +570,25 @@
 
       while (ptr)
 	{
-	  if (ptr->is_user_variable ()
-	      || (clear_user_functions
-		  && (ptr->is_user_function () || ptr->is_dld_function ())))
-	    {
-	      ptr->clear ();
-	    }
+	  if (ptr->is_user_function () || ptr->is_dld_function ())
+	    ptr->clear ();
+
+	  ptr = ptr->next ();
+	}
+    }
+}
+
+void
+symbol_table::clear_globals (void)
+{
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  if (ptr->is_user_variable () && ptr->is_linked_to_global ())
+	    ptr->clear ();
 
 	  ptr = ptr->next ();
 	}
@@ -627,7 +596,47 @@
 }
 
 bool
-symbol_table::clear (const std::string& nm, bool clear_user_functions)
+symbol_table::clear (const std::string& nm)
+{
+  unsigned int index = hash (nm);
+
+  symbol_record *ptr = table[index].next ();
+
+  while (ptr)
+    {
+      if (ptr->name () == nm)
+	{
+	  ptr->clear ();
+	  return true;
+	}
+      ptr = ptr->next ();
+    }
+
+  return false;
+}
+
+bool
+symbol_table::clear_variable (const std::string& nm)
+{
+  unsigned int index = hash (nm);
+
+  symbol_record *ptr = table[index].next ();
+
+  while (ptr)
+    {
+      if (ptr->name () == nm && ptr->is_user_variable ())
+	{
+	  ptr->clear ();
+	  return true;
+	}
+      ptr = ptr->next ();
+    }
+
+  return false;
+}
+
+bool
+symbol_table::clear_global (const std::string& nm)
 {
   unsigned int index = hash (nm);
 
@@ -636,9 +645,31 @@
   while (ptr)
     {
       if (ptr->name () == nm
-	  && (ptr->is_user_variable ()
-	      || (clear_user_functions
-		  && (ptr->is_user_function () || ptr->is_dld_function ()))))
+	  && ptr->is_user_variable ()
+	  && ptr->is_linked_to_global ())
+	{
+	  ptr->clear ();
+	  return true;
+	}
+      ptr = ptr->next ();
+    }
+
+  return false;
+}
+
+// Really only clear functions that can be reloaded.
+
+bool
+symbol_table::clear_function (const std::string& nm)
+{
+  unsigned int index = hash (nm);
+
+  symbol_record *ptr = table[index].next ();
+
+  while (ptr)
+    {
+      if (ptr->name () == nm
+	  && (ptr->is_user_function () || ptr->is_dld_function ()))
 	{
 	  ptr->clear ();
 	  return true;
@@ -649,6 +680,98 @@
   return false;
 }
 
+bool
+symbol_table::clear_variable_pattern (const std::string& pat)
+{
+  bool retval = false;
+
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  if (ptr->is_user_variable ())
+	    {
+	      glob_match pattern (pat);
+
+	      if (pattern.match (ptr->name ()))
+		{
+		  ptr->clear ();
+
+		  retval = true;
+		}
+	    }
+
+	  ptr = ptr->next ();
+	}
+    }
+
+  return retval;
+}
+
+bool
+symbol_table::clear_global_pattern (const std::string& pat)
+{
+  bool retval = false;
+
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  if (ptr->is_user_variable () && ptr->is_linked_to_global ())
+	    {
+	      glob_match pattern (pat);
+
+	      if (pattern.match (ptr->name ()))
+		{
+		  ptr->clear ();
+
+		  retval = true;
+		}
+	    }
+
+	  ptr = ptr->next ();
+	}
+    }
+
+  return retval;
+}
+
+// Really only clear functions that can be reloaded.
+
+bool
+symbol_table::clear_function_pattern (const std::string& pat)
+{
+  bool retval = false;
+
+  for (unsigned int i = 0; i < table_size; i++)
+    {
+      symbol_record *ptr = table[i].next ();
+
+      while (ptr)
+	{
+	  if (ptr->is_user_function () || ptr->is_dld_function ())
+	    {
+	      glob_match pattern (pat);
+
+	      if (pattern.match (ptr->name ()))
+		{
+		  ptr->clear ();
+
+		  retval = true;
+		}
+	    }
+
+	  ptr = ptr->next ();
+	}
+    }
+
+  return retval;
+}
+
 int
 symbol_table::size (void) const
 {
--- a/src/symtab.h	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/symtab.h	Wed Jul 31 09:33:09 2002 +0000
@@ -79,7 +79,7 @@
     symbol_def (const octave_value& val = octave_value (),
 		unsigned int sym_type = 0)
       : symbol_type (sym_type), eternal (0), read_only (0), help_string (),
-	definition (val), next_elem (0), count (1) { }
+	definition (val), count (1) { }
 
     ~symbol_def (void) { }
 
@@ -197,11 +197,6 @@
     // The value of this definition.  See ov.h and related files.
     octave_value definition;
 
-    // Pointer to next definition in chain.  This is used so that
-    // variables can hide function definitions, and so that the function
-    // definitions can reappear if the variable is cleared.
-    symbol_def *next_elem;
-
     // Reference count.
     int count;
 
@@ -303,7 +298,7 @@
 
   void clear (void);
 
-  void alias (symbol_record *s, bool force = false);
+  void alias (symbol_record *s);
 
   void mark_as_formal_parameter (void);
   bool is_formal_parameter (void) const { return formal_param; }
@@ -314,9 +309,6 @@
   void mark_as_static (void);
   bool is_static (void) const { return tagged_static; }
 
-  bool hides_fcn (void) const;
-  bool hides_builtin (void) const;
-
   int rows (void) const { return definition->rows (); }
   int columns (void) const { return definition->columns (); }
 
@@ -366,12 +358,6 @@
 
   bool read_only_error (const char *action);
 
-  void push_def (symbol_def *sd);
-
-  void remove_top_def (void);
-
-  void replace_all_defs (symbol_def *sd);
-
   void link_to_builtin_variable (void);
 
   // No copying!
@@ -407,22 +393,36 @@
 
   symbol_table (unsigned int tab_size = 128)
     : table_size (tab_size), table (new symbol_record [table_size])
-  {
-    assert ((tab_size % 2) == 0);
-  }
+    {
+      assert ((tab_size % 2) == 0);
+    }
 
   ~symbol_table (void)
-  {
-    delete [] table;
-  }
+    {
+      clear ();
+      delete [] table;
+    }
 
   symbol_record *lookup (const std::string& nm, bool insert = false,
 			 bool warn = false);
 
   void rename (const std::string& old_name, const std::string& new_name);
 
-  void clear (bool clear_user_functions = true);
-  bool clear (const std::string& nm, bool clear_user_functions = true);
+  void clear (void);
+
+  void clear_variables (void);
+  void clear_functions (void);
+  void clear_globals (void);
+
+  bool clear (const std::string& nm);
+
+  bool clear_variable (const std::string& nm);
+  bool clear_function (const std::string& nm);
+  bool clear_global (const std::string& nm);
+
+  bool clear_variable_pattern (const std::string& pat);
+  bool clear_function_pattern (const std::string& pat);
+  bool clear_global_pattern (const std::string& pat);
 
   int size (void) const;
 
@@ -437,6 +437,28 @@
 	     bool sort = false, unsigned int type = SYMTAB_ALL_TYPES,
 	     unsigned int scope = SYMTAB_ALL_SCOPES) const;
 
+  string_vector
+  user_function_name_list (void) const
+    {
+      return name_list
+	(string_vector (), false,
+	 symbol_record::USER_FUNCTION|symbol_record::DLD_FUNCTION,
+	 SYMTAB_ALL_SCOPES);
+    }
+
+  string_vector
+  global_variable_name_list (void) const
+    {
+      return name_list
+	(string_vector (), false, SYMTAB_VARIABLES, SYMTAB_GLOBAL_SCOPE);
+    }
+
+  string_vector
+  variable_name_list (void) const
+    {
+      return name_list
+	(string_vector (), false, SYMTAB_VARIABLES, SYMTAB_LOCAL_SCOPE);
+    }
 
   int maybe_list (const char *header, const string_vector& argv,
 		  std::ostream& os, bool show_verbose,
--- a/src/variables.cc	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/variables.cc	Wed Jul 31 09:33:09 2002 +0000
@@ -67,6 +67,9 @@
 // Symbol table for global symbols.
 symbol_table *global_sym_tab = 0;
 
+// Symbol table for functions and built-in symbols.
+symbol_table *fbi_sym_tab = 0;
+
 // Initialization.
 
 // Create the initial symbol tables and set the current scope at the
@@ -75,6 +78,9 @@
 void
 initialize_symbol_tables (void)
 {
+  if (! fbi_sym_tab)
+    fbi_sym_tab = new symbol_table (2048);
+
   if (! global_sym_tab)
     global_sym_tab = new symbol_table (2048);
 
@@ -91,7 +97,7 @@
 bool
 is_builtin_variable (const std::string& name)
 {
-  symbol_record *sr = global_sym_tab->lookup (name);
+  symbol_record *sr = fbi_sym_tab->lookup (name);
   return (sr && sr->is_builtin_variable ());
 }
 
@@ -100,7 +106,7 @@
 bool
 is_text_function_name (const std::string& s)
 {
-  symbol_record *sr = global_sym_tab->lookup (s);
+  symbol_record *sr = fbi_sym_tab->lookup (s);
   return (sr && sr->is_text_function ());
 }
 
@@ -109,7 +115,7 @@
 bool
 is_builtin_function_name (const std::string& s)
 {
-  symbol_record *sr = global_sym_tab->lookup (s);
+  symbol_record *sr = fbi_sym_tab->lookup (s);
   return (sr && sr->is_builtin_function ());
 }
 
@@ -118,7 +124,7 @@
 bool
 is_mapper_function_name (const std::string& s)
 {
-  symbol_record *sr = global_sym_tab->lookup (s);
+  symbol_record *sr = fbi_sym_tab->lookup (s);
   return (sr && sr->is_mapper_function ());
 }
 
@@ -142,7 +148,7 @@
 
   if (! fcn_name.empty ())
     {
-      sr = global_sym_tab->lookup (fcn_name, true);
+      sr = fbi_sym_tab->lookup (fcn_name, true);
 
       lookup (sr, false);
     }
@@ -372,7 +378,7 @@
 @code{file_in_path} and @code{stat} instead.\n\
 @end deftypefn")
 {
-  octave_value_list retval;
+  octave_value retval = 0.0;
 
   int nargin = args.length ();
 
@@ -401,29 +407,34 @@
       symbol_name = name.substr (0, pos);
     }
 
+  // We shouldn't need to look in the global symbol table, since any
+  // name that is visible in the current scope will be in the local
+  // symbol table.
+
   symbol_record *sr = curr_sym_tab->lookup (symbol_name);
-  if (! (sr && (sr->is_defined ()
-		|| (curr_sym_tab != top_level_sym_tab))))
-    sr = global_sym_tab->lookup (symbol_name);
 
-  retval = 0.0;
+  if (! (sr && sr->is_defined ()))
+    sr = fbi_sym_tab->lookup (symbol_name);
 
-  if (sr && sr->is_variable () && sr->is_defined ())
+  if (sr && sr->is_defined ())
     {
-      if (struct_elts.empty () || sr->is_map_element (struct_elts))
-	retval = 1.0;
-    }
-  else if (sr && sr->is_builtin_function ())
-    {
-      retval = 5.0;
-    }
-  else if (sr && sr->is_builtin_constant ())
-    {
-      retval = 6.0;
-    }
-  else if (sr && sr->is_user_function ())
-    {
-      retval = 2.0;
+      if (sr->is_variable ())
+	{
+	  if (struct_elts.empty () || sr->is_map_element (struct_elts))
+	    retval = 1.0;
+	}
+      else if (sr->is_builtin_function ())
+	{
+	  retval = 5.0;
+	}
+      else if (sr->is_builtin_constant ())
+	{
+	  retval = 6.0;
+	}
+      else if (sr->is_user_function ())
+	{
+	  retval = 2.0;
+	}
     }
   else
     {
@@ -589,7 +600,7 @@
 std::string
 builtin_string_variable (const std::string& name)
 {
-  symbol_record *sr = global_sym_tab->lookup (name);
+  symbol_record *sr = fbi_sym_tab->lookup (name);
 
   // It is a prorgramming error to look for builtins that aren't.
 
@@ -613,7 +624,7 @@
 builtin_real_scalar_variable (const std::string& name, double& d)
 {
   int status = 0;
-  symbol_record *sr = global_sym_tab->lookup (name);
+  symbol_record *sr = fbi_sym_tab->lookup (name);
 
   // It is a prorgramming error to look for builtins that aren't.
 
@@ -635,7 +646,7 @@
 octave_value
 builtin_any_variable (const std::string& name)
 {
-  symbol_record *sr = global_sym_tab->lookup (name);
+  symbol_record *sr = fbi_sym_tab->lookup (name);
 
   // It is a prorgramming error to look for builtins that aren't.
 
@@ -663,17 +674,12 @@
 
 	  symbol_record *gsr = global_sym_tab->lookup (nm, true);
 
-	  // There must be a better way to do this.   XXX FIXME XXX
-
-	  if (sr->is_variable ())
-	    gsr->define (sr->def ());
-
 	  // Make sure this symbol is a variable.
 
-	  if (! gsr->is_variable ())
+	  if (! gsr->is_user_variable ())
 	    gsr->define (octave_value ());
 
-	  sr->alias (gsr, 1);
+	  sr->alias (gsr);
 	}
     }
 }
@@ -689,7 +695,7 @@
 void
 link_to_builtin_or_function (symbol_record *sr)
 {
-  symbol_record *tmp_sym = global_sym_tab->lookup (sr->name ());
+  symbol_record *tmp_sym = fbi_sym_tab->lookup (sr->name ());
 
   if (tmp_sym
       && (tmp_sym->is_builtin_variable ()
@@ -710,12 +716,12 @@
 void
 force_link_to_function (const std::string& id_name)
 {
-  symbol_record *gsr = global_sym_tab->lookup (id_name, true);
-  if (gsr->is_function ())
+  symbol_record *fsr = fbi_sym_tab->lookup (id_name, true);
+  if (fsr->is_function ())
     {
       curr_sym_tab->clear (id_name);
       symbol_record *csr = curr_sym_tab->lookup (id_name, true);
-      csr->alias (gsr);
+      csr->alias (fsr);
     }
 }
 
@@ -825,22 +831,22 @@
 
   if (show_builtins)
     {
-      pad_after += global_sym_tab->maybe_list
+      pad_after += fbi_sym_tab->maybe_list
 	("*** built-in constants:", pats, octave_stdout,
 	 show_verbose, symbol_record::BUILTIN_CONSTANT, SYMTAB_ALL_SCOPES);
 
-      pad_after += global_sym_tab->maybe_list
+      pad_after += fbi_sym_tab->maybe_list
 	("*** built-in variables:", pats, octave_stdout,
 	 show_verbose, symbol_record::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES);
 
-      pad_after += global_sym_tab->maybe_list
+      pad_after += fbi_sym_tab->maybe_list
 	("*** built-in functions:", pats, octave_stdout,
 	 show_verbose, symbol_record::BUILTIN_FUNCTION, SYMTAB_ALL_SCOPES);
     }
 
   if (show_functions)
     {
-      pad_after += global_sym_tab->maybe_list
+      pad_after += fbi_sym_tab->maybe_list
 	("*** currently compiled functions:", pats,
 	 octave_stdout, show_verbose, symbol_record::USER_FUNCTION,
 	 SYMTAB_ALL_SCOPES);
@@ -948,7 +954,7 @@
 void
 bind_ans (const octave_value& val, bool print)
 {
-  static symbol_record *sr = global_sym_tab->lookup ("ans", true);
+  static symbol_record *sr = fbi_sym_tab->lookup ("ans", true);
 
   if (val.is_defined ())
     {
@@ -969,7 +975,7 @@
 bind_builtin_constant (const std::string& name, const octave_value& val,
 		       bool protect, bool eternal, const std::string& help)
 {
-  symbol_record *sym_rec = global_sym_tab->lookup (name, true);
+  symbol_record *sym_rec = fbi_sym_tab->lookup (name, true);
   sym_rec->unprotect ();
 
   std::string tmp_help = help.empty () ? sym_rec->help () : help;
@@ -997,7 +1003,7 @@
 		       symbol_record::change_function chg_fcn,
 		       const std::string& help)
 {
-  symbol_record *sr = global_sym_tab->lookup (varname, true);
+  symbol_record *sr = fbi_sym_tab->lookup (varname, true);
 
   // It is a programming error for a builtin symbol to be missing.
   // Besides, we just inserted it, so it must be there.
@@ -1027,8 +1033,8 @@
 // Deleting names from the symbol tables.
 
 static inline bool
-var_matches_any_pattern (const std::string& nm,
-			 const string_vector& argv, int argc, int idx)
+name_matches_any_pattern (const std::string& nm,
+			  const string_vector& argv, int argc, int idx)
 {
   bool retval = false;
 
@@ -1051,6 +1057,309 @@
   return retval;
 }
 
+static inline bool
+is_local_variable (const std::string& nm)
+{
+  symbol_record *sr = curr_sym_tab->lookup (nm);
+
+  return (sr && sr->is_variable ());
+}
+
+static inline void
+maybe_warn_exclusive (bool exclusive)
+{
+  if (exclusive)
+    warning ("clear: ignoring --exclusive option");
+}
+
+static inline void
+do_clear_all (void)
+{
+  curr_sym_tab->clear ();
+  fbi_sym_tab->clear_functions ();
+  global_sym_tab->clear ();
+}
+
+static inline void
+do_clear_functions (void)
+{
+  curr_sym_tab->clear_functions ();
+  fbi_sym_tab->clear_functions ();
+}
+
+static inline void
+do_clear_globals (void)
+{
+  curr_sym_tab->clear_globals ();
+  global_sym_tab->clear ();
+}
+
+static inline void
+do_clear_variables (void)
+{
+  curr_sym_tab->clear ();
+}
+
+static inline bool
+do_clear_function (const std::string& nm)
+{
+  bool b1 = curr_sym_tab->clear_function (nm);
+
+  bool b2 = fbi_sym_tab->clear_function (nm);
+
+  return b1 || b2;
+}
+
+static inline bool
+do_clear_global (const std::string& nm)
+{
+  bool b1 = curr_sym_tab->clear_global (nm);
+
+  bool b2 = global_sym_tab->clear_variable (nm);
+
+  return b1 || b2;
+}
+
+static inline bool
+do_clear_variable (const std::string& nm)
+{
+  return curr_sym_tab->clear_variable (nm);
+}
+
+static inline bool
+do_clear_symbol (const std::string& nm)
+{
+  bool cleared = curr_sym_tab->clear_variable (nm);
+
+  if (! cleared)
+    cleared = do_clear_function (nm);
+
+  return cleared;
+}
+
+static inline bool
+do_clear_function_pattern (const std::string& pat)
+{
+  bool b1 = curr_sym_tab->clear_function_pattern (pat);
+
+  bool b2 = fbi_sym_tab->clear_function_pattern (pat);
+
+  return b1 || b2;
+}
+
+static inline bool
+do_clear_global_pattern (const std::string& pat)
+{
+  bool b1 = curr_sym_tab->clear_global_pattern (pat);
+
+  bool b2 = global_sym_tab->clear_variable_pattern (pat);
+
+  return b1 || b2;
+}
+
+static inline bool
+do_clear_variable_pattern (const std::string& pat)
+{
+  return curr_sym_tab->clear_variable_pattern (pat);
+}
+
+static inline bool
+do_clear_symbol_pattern (const std::string& pat)
+{
+  // XXX FIXME XXX -- if we have a variable v1 and a function v2 and
+  // someone says clear v*, we will clear the variable but not the
+  // function.  Is that really what should happen?  (I think it is
+  // what Matlab does.)
+
+  bool cleared = curr_sym_tab->clear_variable_pattern (pat);
+
+  if (! cleared)
+    cleared = do_clear_function_pattern (pat);
+
+  return cleared;
+}
+
+static inline void
+do_clear_functions (const string_vector& argv, int argc, int idx,
+		    bool exclusive = false)
+{
+  if (idx == argc)
+    do_clear_functions ();
+  else
+    {
+      if (exclusive)
+	{
+	  string_vector lfcns = curr_sym_tab->user_function_name_list ();
+
+	  int lcount = lfcns.length ();
+
+	  for (int i = 0; i < lcount; i++)
+	    {
+	      std::string nm = lfcns[i];
+
+	      if (! name_matches_any_pattern (nm, argv, argc, idx))
+		do_clear_function (nm);
+	    }
+
+	  string_vector fcns = fbi_sym_tab->user_function_name_list ();
+
+	  int fcount = fcns.length ();
+
+	  for (int i = 0; i < fcount; i++)
+	    {
+	      std::string nm = fcns[i];
+
+	      if (! name_matches_any_pattern (nm, argv, argc, idx))
+		do_clear_function (nm);
+	    }
+	}
+      else
+	{
+	  while (idx < argc)
+	    do_clear_function_pattern (argv[idx++]);
+	}
+    }
+}
+
+static inline void
+do_clear_globals (const string_vector& argv, int argc, int idx,
+		  bool exclusive = false)
+{
+  if (idx == argc)
+    do_clear_globals ();
+  else
+    {
+      if (exclusive)
+	{
+	  string_vector lvars = curr_sym_tab->global_variable_name_list ();
+
+	  int lcount = lvars.length ();
+
+	  for (int i = 0; i < lcount; i++)
+	    {
+	      std::string nm = lvars[i];
+
+	      if (! name_matches_any_pattern (nm, argv, argc, idx))
+		do_clear_global (nm);
+	    }
+
+	  string_vector gvars = global_sym_tab->global_variable_name_list ();
+
+	  int gcount = gvars.length ();
+
+	  for (int i = 0; i < gcount; i++)
+	    {
+	      std::string nm = gvars[i];
+
+	      if (! name_matches_any_pattern (nm, argv, argc, idx))
+		do_clear_global (nm);
+	    }
+	}
+      else
+	{
+	  while (idx < argc)
+	    do_clear_global_pattern (argv[idx++]);
+	}
+    }
+}
+
+static inline void
+do_clear_variables (const string_vector& argv, int argc, int idx,
+		    bool exclusive = false)
+{
+  if (idx == argc)
+    do_clear_variables ();
+  else
+    {
+      if (exclusive)
+	{
+	  string_vector lvars = curr_sym_tab->variable_name_list ();
+
+	  int lcount = lvars.length ();
+
+	  for (int i = 0; i < lcount; i++)
+	    {
+	      std::string nm = lvars[i];
+
+	      if (! name_matches_any_pattern (nm, argv, argc, idx))
+		do_clear_variable (nm);
+	    }
+	}
+      else
+	{
+	  while (idx < argc)
+	    do_clear_variable_pattern (argv[idx++]);
+	}
+    }
+}
+
+static inline void
+do_clear_symbols (const string_vector& argv, int argc, int idx,
+		  bool exclusive = false)
+{
+  if (idx == argc)
+    do_clear_variables ();
+  else
+    {
+      if (exclusive)
+	{
+	  // XXX FIXME XXX -- is this really what we want, or do we
+	  // somehow want to only clear the functions that are not
+	  // shadowed by local variables?  It seems that would be a
+	  // bit harder to do.
+
+	  do_clear_variables (argv, argc, idx, exclusive);
+	  do_clear_functions (argv, argc, idx, exclusive);
+	}
+      else
+	{
+	  while (idx < argc)
+	    do_clear_symbol_pattern (argv[idx++]);
+	}
+    }
+}
+
+static void
+do_matlab_compatible_clear (const string_vector& argv, int argc, int idx)
+{
+  // This is supposed to be mostly Matlab compatible.
+
+  for (; idx < argc; idx++)
+    {
+      if (argv[idx] == "all" && ! is_local_variable ("all"))
+	{
+	  do_clear_all ();
+	}
+      else if (argv[idx] == "functions" && ! is_local_variable ("functions"))
+	{
+	  do_clear_functions (argv, argc, ++idx);
+	}
+      else if (argv[idx] == "global" && ! is_local_variable ("global"))
+	{
+	  do_clear_globals (argv, argc, ++idx);
+	}
+      else if (argv[idx] == "variables" && ! is_local_variable ("variables"))
+	{
+	  do_clear_variables ();
+	}
+      else
+	{
+	  do_clear_symbol_pattern (argv[idx]);
+	}
+    }
+}
+
+#define CLEAR_OPTION_ERROR(cond) \
+  do \
+    { \
+      if (cond) \
+        { \
+          print_usage ("clear"); \
+          return retval; \
+        } \
+    } \
+  while (0)
+
 DEFUN_TEXT (clear, args, ,
   "-*- texinfo -*-\n\
 @deffn {Command} clear [-x] pattern @dots{}\n\
@@ -1101,147 +1410,97 @@
 
   string_vector argv = args.make_argv ("clear");
 
-  if (error_state)
-    return retval;
-
-  // Always clear the local table, but don't clear currently compiled
-  // functions unless we are at the top level.  (Allowing that to
-  // happen inside functions would result in pretty odd behavior...)
-
-  bool clear_user_functions = (curr_sym_tab == top_level_sym_tab);
-
-  if (argc == 1)
-    {
-      curr_sym_tab->clear ();
-      global_sym_tab->clear (clear_user_functions);
-    }
-  else
+  if (! error_state)
     {
-      int exclusive = 0;
-
-      int idx = 1;
-
-      if (argc > 1)
-	{
-	  if (argv[idx] == "-x")
-	    {
-	      idx++;
-	      exclusive = 1;
-	    }
-	}
-
-      string_vector lvars;
-      string_vector gvars;
-      string_vector fcns;
-
-      if (argc > 0)
+      if (argc == 1)
 	{
-	  string_vector tmp;
-
-	  lvars = curr_sym_tab->name_list
-	    (tmp, false, SYMTAB_VARIABLES, SYMTAB_LOCAL_SCOPE);
-
-	  gvars = curr_sym_tab->name_list
-	    (tmp, false, SYMTAB_VARIABLES, SYMTAB_GLOBAL_SCOPE);
-
-	  fcns = global_sym_tab->name_list
-	    (tmp, false,
-	     symbol_record::USER_FUNCTION|symbol_record::DLD_FUNCTION,
-	     SYMTAB_ALL_SCOPES);
-	}
-
-      // XXX FIXME XXX -- this needs to be optimized to avoid the
-      // pattern matching code if the string doesn't contain any
-      // globbing patterns.
-
-      if (exclusive)
-	{
-	  int lcount = lvars.length ();
-
-	  for (int i = 0; i < lcount; i++)
-	    {
-	      std::string nm = lvars[i];
-
-	      if (! var_matches_any_pattern (nm, argv, argc, idx))
-		curr_sym_tab->clear (nm);
-	    }
-
-	  int gcount = gvars.length ();
-
-	  for (int i = 0; i < gcount; i++)
-	    {
-	      std::string nm = gvars[i];
-
-	      if (! var_matches_any_pattern (nm, argv, argc, idx))
-		{
-		  int count = curr_sym_tab->clear (nm);
-
-		  if (count > 0)
-		    global_sym_tab->clear (nm, clear_user_functions);
-		}
-	    }
-
-	  int fcount = fcns.length ();
-
-	  for (int i = 0; i < fcount; i++)
-	    {
-	      std::string nm = fcns[i];
-
-	      if (! var_matches_any_pattern (nm, argv, argc, idx))
-		{
-		  curr_sym_tab->clear (nm);
-
-		  global_sym_tab->clear (nm, clear_user_functions);
-		}
-	    }
+	  do_clear_variables ();
 	}
       else
 	{
-	  for (int k = idx; k < argc; k++)
-	    {
-	      std::string patstr = argv[k];
+	  int idx = 0;
+
+	  bool clear_all = false;
+	  bool clear_functions = false;
+	  bool clear_globals = false;
+	  bool clear_variables = false;
+	  bool exclusive = false;
+	  bool have_dash_option = false;
 
-	      if (! patstr.empty ())
+	  while (++idx < argc)
+	    {
+	      if (argv[idx] == "--all" || argv[idx] == "-a")
 		{
-		  glob_match pattern (patstr);
+		  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
 
-		  int lcount = lvars.length ();
+		  have_dash_option = true;
+		  clear_all = true;
+		}
+	      else if (argv[idx] == "--exclusive" || argv[idx] == "-x")
+		{
+		  have_dash_option = true;
+		  exclusive = true;
+		}
+	      else if (argv[idx] == "--functions" || argv[idx] == "-f")
+		{
+		  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
 
-		  for (int i = 0; i < lcount; i++)
-		    {
-		      std::string nm = lvars[i];
+		  have_dash_option = true;
+		  clear_functions = true;
+		}
+	      else if (argv[idx] == "--global" || argv[idx] == "-g")
+		{
+		  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
+
+		  have_dash_option = true;
+		  clear_globals = true;
+		}
+	      else if (argv[idx] == "--variables" || argv[idx] == "-v")
+		{
+		  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
 
-		      if (pattern.match (nm))
-			curr_sym_tab->clear (nm);
-		    }
+		  have_dash_option = true;
+		  clear_variables = true;
+		}
+	      else
+		break;
+	    }
 
-		  int gcount = gvars.length ();
-
-		  for (int i = 0; i < gcount; i++)
+	  if (idx < argc)
+	    {
+	      if (! have_dash_option)
+		{
+		  do_matlab_compatible_clear (argv, argc, idx);
+		}
+	      else
+		{
+		  if (clear_all)
 		    {
-		      std::string nm = gvars[i];
+		      maybe_warn_exclusive (exclusive);
 
-		      if (pattern.match (nm))
-			{
-			  int count = curr_sym_tab->clear (nm);
-
-			  if (count > 0)
-			    global_sym_tab->clear (nm, clear_user_functions);
-			}
-		    }
+		      if (++idx < argc)
+			warning
+			  ("clear: ignoring extra arguments after --all");
 
-		  int fcount = fcns.length ();
-
-		  for (int i = 0; i < fcount; i++)
+		      curr_sym_tab->clear ();
+		      fbi_sym_tab->clear_functions ();
+		      global_sym_tab->clear ();
+		    }
+		  else if (clear_functions)
+		    {
+		      do_clear_functions (argv, argc, idx, exclusive);
+		    }
+		  else if (clear_globals)
 		    {
-		      std::string nm = fcns[i];
-
-		      if (pattern.match (nm))
-			{
-			  curr_sym_tab->clear (nm);
-
-			  global_sym_tab->clear (nm, clear_user_functions);
-			}
+		      do_clear_globals (argv, argc, idx, exclusive);
+		    }
+		  else if (clear_variables)
+		    {
+		      do_clear_variables (argv, argc, idx, exclusive);
+		    }
+		  else
+		    {
+		      do_clear_symbols (argv, argc, idx, exclusive);
 		    }
 		}
 	    }
@@ -1265,17 +1524,19 @@
     {
       std::string arg = args(0).string_value ();
 
-      if (arg == "global")
+      if (arg == "fbi")
+	fbi_sym_tab->print_info (octave_stdout);
+      else if (arg == "global")
 	global_sym_tab->print_info (octave_stdout);
       else if (arg == "top-level")
 	top_level_sym_tab->print_info (octave_stdout);
       else
 	{
-	  symbol_record *gsr = global_sym_tab->lookup (arg, true);
+	  symbol_record *fsr = fbi_sym_tab->lookup (arg, true);
 
-	  if (gsr && gsr->is_user_function ())
+	  if (fsr && fsr->is_user_function ())
 	    {
-	      octave_value tmp = gsr->def ();
+	      octave_value tmp = fsr->def ();
 	      const octave_value& rep = tmp.get_rep ();
 	      
 	      const octave_user_function& fcn
--- a/src/variables.h	Fri Jul 26 04:51:03 2002 +0000
+++ b/src/variables.h	Wed Jul 31 09:33:09 2002 +0000
@@ -115,6 +115,9 @@
 // Symbol table for global symbols.
 extern symbol_table *global_sym_tab;
 
+// Symbol table for functions and built-in symbols.
+extern symbol_table *fbi_sym_tab;
+
 #endif
 
 /*