changeset 3355:c4983fc7318f

[project @ 1999-11-18 05:20:50 by jwe]
author jwe
date Thu, 18 Nov 1999 05:20:52 +0000
parents 87721841efd7
children d2e12e998a78
files src/ChangeLog src/help.cc src/load-save.cc src/symtab.cc src/symtab.h src/variables.cc
diffstat 6 files changed, 433 insertions(+), 407 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,33 @@
+1999-11-17  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* symtab.cc (symbol_record::symbol_def::type_as_string): New function.
+
+	* symtab.cc (symbol_record::which): New functions.
+	* help.cc (do_which): New functions.
+	(Fwhich): Use them.
+
+	* help.cc (help_from_symbol_table, help_from_file): New functions.
+	(builtin_help): Use them.
+
+	* help.cc (do_type): New function.
+	(Ftype): Use them.
+
+	* help.cc (print_symbol_type): Delete.
+
+	* symtab.cc (symbol_table::name_list): Delete count arg.
+	(symbol_table::symbol_list): Likewise.
+	(symbol_table::glob): Likewise.  Also return Array<symbol_record *>
+	instead of symbol_record **.
+	Change all callers.
+	* help.cc (names, display_symtab_names): Delete count arg.
+
+	* help.cc (print_symbol_type, Ftype): No longer need to look up
+	fcn_file_name in the loadpath.
+
+	* help.cc (print_symbol_type): Handle dld functions.
+	(help_from_symbol_table, help_from_file): New functions.
+	(builtin_help): Use them.
+
 1999-11-16  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* ov-cell.cc (Fiscell, Fcell): New Functions.
--- a/src/help.cc
+++ b/src/help.cc
@@ -301,11 +301,11 @@
 // Return a copy of the operator or keyword names.
 
 static string_vector
-names (help_list *lst, int& count)
+names (help_list *lst)
 {
   string_vector retval;
 
-  count = 0;
+  int count = 0;
   help_list *ptr = lst;
   while (ptr->name)
     {
@@ -345,30 +345,21 @@
 string_vector
 make_name_list (void)
 {
-  int key_len = 0;
-  int glb_len = 0;
-  int top_len = 0;
-  int lcl_len = 0;
+  string_vector key = names (keyword_help ());
+  int key_len = key.length ();
 
-  string_vector key;
-  string_vector glb;
-  string_vector top;
-  string_vector lcl;
-  string_vector ffl;
+  string_vector glb = global_sym_tab->name_list ();
+  int glb_len = glb.length ();
 
-  // Each of these functions returns a new vector of pointers to new
-  // strings.
-
-  key = names (keyword_help (), key_len);
-
-  glb = global_sym_tab->name_list (glb_len);
+  string_vector top = top_level_sym_tab->name_list ();
+  int top_len = top.length ();
 
-  top = top_level_sym_tab->name_list (top_len);
-
+  string_vector lcl;
   if (top_level_sym_tab != curr_sym_tab)
-    lcl = curr_sym_tab->name_list (lcl_len);
+    lcl = curr_sym_tab->name_list ();
+  int lcl_len = lcl.length ();
 
-  ffl = octave_fcn_file_name_cache::list_no_suffix ();
+  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;
@@ -418,9 +409,7 @@
 display_names_from_help_list (ostream& os, help_list *list,
 			      const char *desc)
 {
-  int count = 0;
-
-  string_vector symbols = names (list, count);
+  string_vector symbols = names (list);
 
   if (! symbols.empty ())
     {
@@ -432,90 +421,9 @@
     }
 }
 
-static string
-print_symbol_type (ostream& os, symbol_record *sym_rec,
-		   const string& name, int print)
-{
-  string retval;
-
-  if (sym_rec->is_user_function ())
-    {
-      octave_value tmp = sym_rec->def ();
-
-      octave_function *defn = tmp.function_value ();
-
-      string fn = defn ? defn->fcn_file_name () : string ();
-
-      if (! fn.empty ())
-	{
-	  string ff = fcn_file_in_path (fn);
-
-	  ff = ff.length () > 0 ? ff : fn;
-
-	  if (print)
-	    os << name
-	       << " is the function defined from: "
-	       << ff << "\n";
-	  else
-	    retval = ff;
-	}
-      else
-	{
-	  if (print)
-	    os << name << " is a user-defined function\n";
-	  else
-	    retval = "user-defined function";
-	}
-    }
-  else if (sym_rec->is_text_function ())
-    {
-      if (print)
-	os << name << " is a built-in text-function\n";
-      else
-	retval = "built-in text-function";
-    }
-  else if (sym_rec->is_builtin_function ())
-    {
-      if (print)
-	os << name << " is a built-in function\n";
-      else
-	retval = "built-in function";
-    }
-  else if (sym_rec->is_user_variable ())
-    {
-      if (print)
-	os << name << " is a user-defined variable\n";
-      else
-	retval = "user-defined variable";
-    }
-  else if (sym_rec->is_builtin_variable ())
-    {
-      if (print)
-	os << name << " is a built-in variable\n";
-      else
-	retval = "built-in variable";
-    }
-  else if (sym_rec->is_builtin_constant ())
-    {
-      if (print)
-	os << name << " is a built-in constant\n";
-      else
-	retval = "built-in variable";
-    }
-  else
-    {
-      if (print)
-	os << "which: `" << name << "' has unknown type\n";
-      else
-	retval = "unknown type";
-    }
-
-  return retval;
-}
-
 static void
 display_symtab_names (ostream& os, const string_vector& names,
-		      int /* count */, const string& desc)
+		      const string& desc)
 {
   if (! names.empty ())
     {
@@ -530,10 +438,9 @@
 #define LIST_SYMBOLS(type, msg) \
   do \
     { \
-      int count; \
       string_vector names \
-	= global_sym_tab->name_list (count, string_vector (), true, type); \
-      display_symtab_names (octave_stdout, names, count, msg); \
+	= global_sym_tab->name_list (string_vector (), true, type); \
+      display_symtab_names (octave_stdout, names, msg); \
     } \
   while (0)
 
@@ -776,6 +683,50 @@
   return false;
 }
 
+static bool
+help_from_symbol_table (ostream& os, const string& nm)
+{
+  bool retval = false;
+
+  symbol_record *sym_rec = lookup_by_name (nm, 0);
+
+  if (sym_rec && sym_rec->is_defined ())
+    {
+      string h = sym_rec->help ();
+
+      if (h.length () > 0)
+	{
+	  sym_rec->which (os);
+	  os << "\n";
+	  display_help_text (os, h);
+	  os << "\n";
+	  retval = true;
+	}
+    }
+
+  return retval;
+}
+
+static bool
+help_from_file (ostream& os, const string& nm)
+{
+  bool retval = false;
+
+  string path = fcn_file_in_path (nm);
+
+  string h = get_help_from_file (path);
+
+  if (! h.empty ())
+    {
+      os << nm << " is the file: " << path << "\n\n";
+      display_help_text (os, h);
+      os << "\n";
+      retval = true;
+    }
+
+  return retval;
+}
+
 static void
 builtin_help (int argc, const string_vector& argv)
 {
@@ -790,34 +741,11 @@
       if (help_from_list (octave_stdout, kw_help_list, argv[i], 0))
 	continue;
 
-      symbol_record *sym_rec = lookup_by_name (argv[i], 0);
-
-      if (sym_rec && sym_rec->is_defined ())
-	{
-	  string h = sym_rec->help ();
+      if (help_from_symbol_table (octave_stdout, argv[i]))
+	continue;
 
-	  if (h.length () > 0)
-	    {
-	      print_symbol_type (octave_stdout, sym_rec, argv[i], 1);
-	      octave_stdout << "\n";
-	      display_help_text (octave_stdout, h);
-	      octave_stdout << "\n";
-	      continue;
-	    }
-	}
-
-      string path = fcn_file_in_path (argv[i]);
-
-      string h = get_help_from_file (path);
-
-      if (! h.empty ())
-	{
-	  octave_stdout << argv[i] << " is the file: "
-	    << path << "\n\n";
-	  display_help_text (octave_stdout, h);
-	  octave_stdout << "\n";
-	  continue;
-	}
+      if (help_from_file (octave_stdout, argv[i]))
+	continue;
 
       octave_stdout << "\nhelp: sorry, `" << argv[i]
 		    << "' is not documented\n"; 
@@ -867,6 +795,122 @@
   return retval;
 }
 
+static void
+do_type (ostream& os, const string& name, bool pr_type_info,
+	 bool quiet, bool pr_orig_txt)
+{
+  symbol_record *sym_rec = lookup_by_name (name, 0);
+
+  if (sym_rec && sym_rec->is_defined ())
+    {
+      if (sym_rec->is_user_function ())
+	{
+	  octave_value tmp = sym_rec->def ();
+		  
+	  octave_function *defn = tmp.function_value ();
+
+	  string fn = defn ? defn->fcn_file_name () : string ();
+
+	  if (pr_orig_txt && ! fn.empty ())
+	    {
+	      ifstream fs (fn.c_str (), ios::in);
+
+	      if (fs)
+		{
+		  if (pr_type_info && ! quiet)
+		    os << name << " is the function defined from: "
+		       << fn << "\n\n";
+
+		  char ch;
+
+		  while (fs.get (ch))
+		    os << ch;
+		}
+	      else
+		os << "unable to open `" << fn << "' for reading!\n";
+	    }
+	  else
+	    {
+	      if (pr_type_info && ! quiet)
+		os << name << " is a user-defined function:\n\n";
+
+	      tree_print_code tpc (os, "", pr_orig_txt);
+
+	      defn->accept (tpc);
+	    }
+	}
+
+      // XXX FIXME XXX -- this code should be shared with
+      // Fwhich.
+
+      else if (sym_rec->is_text_function ())
+	os << name << " is a built-in text-function\n";
+      else if (sym_rec->is_builtin_function ())
+	os << name << " is a built-in function\n";
+      else if (sym_rec->is_user_variable ()
+	       || sym_rec->is_builtin_variable ()
+	       || sym_rec->is_builtin_constant ())
+	{
+	  octave_value defn = sym_rec->def ();
+
+	  int var_ok = 1;
+
+	  if (! error_state)
+	    {
+	      if (pr_type_info && ! quiet)
+		{
+		  if (var_ok)
+		    {
+		      os << name;
+
+		      if (sym_rec->is_user_variable ())
+			os << " is a user-defined variable\n";
+		      else if (sym_rec->is_builtin_variable ())
+			os << " is a built-in variable\n";
+		      else if (sym_rec->is_builtin_constant ())
+			os << " is a built-in constant\n";
+		      else
+			panic_impossible ();
+		    }
+		  else
+		    os << "type: `" << name << "' has unknown type!\n";
+		}
+
+	      defn.print_raw (os, true);
+
+	      if (pr_type_info)
+		os << "\n";
+	    }
+	}
+      else
+	error ("type: `%s' has unknown type!", name.c_str ());
+    }
+  else
+    {
+      string ff = fcn_file_in_path (name);
+
+      if (! ff.empty ())
+	{
+	  ifstream fs (ff.c_str (), ios::in);
+
+	  if (fs)
+	    {
+	      if (pr_type_info && ! quiet)
+		os << name << " is the script file: " << ff << "\n\n";
+
+	      char ch;
+
+	      while (fs.get (ch))
+		os << ch;
+	    }
+	  else
+	    os << "unable to open `" << ff << "' for reading!\n";
+	}
+      else
+	error ("type: `%s' undefined", name.c_str ());
+    }
+}
+
 DEFUN_TEXT (type, args, nargout,
   "type NAME\n\
 \n\
@@ -880,202 +924,108 @@
 
   string_vector argv = args.make_argv ("type");
 
-  if (error_state)
-    return retval;
-
-  if (argc > 1)
+  if (! error_state)
     {
-      // XXX FIXME XXX -- we should really use getopt ()
-
-      bool quiet = false;
-      bool pr_orig_txt = true;
+      if (argc > 1)
+	{
+	  // XXX FIXME XXX -- we should really use getopt ()
 
-      int idx;
-
-      for (idx = 1; idx < argc; idx++)
-	{
-	  if (argv[idx] == "-q" || argv[idx] == "-quiet")
-	    quiet = true;
-	  else if (argv[idx] == "-t" || argv[idx] == "-transformed")
-	    pr_orig_txt = false;
-	  else
-	    break;
-	}
+	  bool quiet = false;
+	  bool pr_orig_txt = true;
 
-      if (idx == argc)
-	{
-	  print_usage ("type");
-	  return retval;
-	}
-
-      ostrstream output_buf;
+	  int idx;
 
-      for (int i = idx; i < argc; i++)
-	{
-	  string id = argv[i];
-	  string elts;
-
-	  if (id[id.length () - 1] != '.')
+	  for (idx = 1; idx < argc; idx++)
 	    {
-	      size_t pos = id.find ('.');
-
-	      if (pos != NPOS)
-		{
-		  elts = id.substr (pos+1);
-		  id = id.substr (0, pos);
-		}
+	      if (argv[idx] == "-q" || argv[idx] == "-quiet")
+		quiet = true;
+	      else if (argv[idx] == "-t" || argv[idx] == "-transformed")
+		pr_orig_txt = false;
+	      else
+		break;
 	    }
 
-	  symbol_record *sym_rec = lookup_by_name (id, 0);
+	  if (idx < argc)
+	    {
+	      ostrstream output_buf;
 
-	  if (sym_rec && sym_rec->is_defined ())
-	    {
-	      if (sym_rec->is_user_function ())
+	      for (int i = idx; i < argc; i++)
 		{
-		  octave_value tmp = sym_rec->def ();
-		  
-		  octave_function *defn = tmp.function_value ();
-
-		  string fn = defn ? defn->fcn_file_name () : string ();
-
-		  string ff = fn.empty () ? string () : fcn_file_in_path (fn);
-
-		  if (pr_orig_txt && ! ff.empty ())
-		    {
-		      ifstream fs (ff.c_str (), ios::in);
+		  string id = argv[i];
 
-		      if (fs)
-			{
-			  if (nargout == 0 && ! quiet)
-			    output_buf << argv[i]
-				       << " is the function defined from: "
-				       << ff << "\n\n";
-
-			  char ch;
+		  if (nargout == 0)
+		    do_type (octave_stdout, id, true, quiet, pr_orig_txt);
+		  else
+		    do_type (output_buf, id, false, quiet, pr_orig_txt);
 
-			  while (fs.get (ch))
-			    output_buf << ch;
-			}
-		      else
-			output_buf << "unable to open `" << ff
-				   << "' for reading!\n";
-		    }
-		  else
-		    {
-		      if (nargout == 0 && ! quiet)
-			output_buf << argv[i]
-				   << " is a user-defined function:\n\n";
-
-		      tree_print_code tpc (output_buf, "", pr_orig_txt);
-
-		      defn->accept (tpc);
-		    }
+		  if (error_state)
+		    goto abort;
 		}
 
-	      // XXX FIXME XXX -- this code should be shared with
-	      // Fwhich.
-
-	      else if (sym_rec->is_text_function ())
-		output_buf << argv[i] << " is a built-in text-function\n";
-	      else if (sym_rec->is_builtin_function ())
-		output_buf << argv[i] << " is a built-in function\n";
-	      else if (sym_rec->is_user_variable ()
-		       || sym_rec->is_builtin_variable ()
-		       || sym_rec->is_builtin_constant ())
+	      if (nargout == 0)
 		{
-		  octave_value defn = sym_rec->def ();
-
-		  int var_ok = 1;
-
-		  // XXX FIXME XXX -- need to handle structure
-		  // references correctly.
-
-		  //if (defn.is_map ())
-		  //  error ("type: operations on structs not implemented");
-
-		  if (! error_state)
-		    {
-		      if (nargout == 0 && ! quiet)
-			{
-			  if (var_ok)
-			    {
-			      output_buf << argv[i];
+		  output_buf << ends;
 
-			      if (sym_rec->is_user_variable ())
-				output_buf << " is a user-defined variable\n";
-			      else if (sym_rec->is_builtin_variable ())
-				output_buf << " is a built-in variable\n";
-			      else if (sym_rec->is_builtin_constant ())
-				output_buf << " is a built-in constant\n";
-			      else
-				panic_impossible ();
-			    }
-			  else
-			    {
-			      if (! elts.empty ())
-				output_buf << "type: structure `" << id
-					   << "' has no member `" << elts
-					   << "'\n";
-			      else
-				output_buf << "type: `" << id
-					   << "' has unknown type!\n";
-			    }
-			}
+		  char *s = output_buf.str ();
 
-		      defn.print_raw (output_buf, true);
+		  retval = s;
 
-		      if (nargout == 0)
-			output_buf << "\n";
-		    }
+		  delete [] s;
 		}
-	      else
-		error ("type: `%s' has unknown type!", argv[i].c_str ());
 	    }
 	  else
-	    {
-	      string ff = fcn_file_in_path (argv[i]);
-
-	      if (! ff.empty ())
-		{
-		  ifstream fs (ff.c_str (), ios::in);
-
-		  if (fs)
-		    {
-		      if (nargout == 0 && ! quiet)
-			output_buf << argv[i] << " is the script file: "
-				   << ff << "\n\n";
-
-		      char ch;
+	    print_usage ("type");
+	}
+      else
+	print_usage ("type");
+    }
 
-		      while (fs.get (ch))
-			output_buf << ch;
-		    }
-		  else
-		    output_buf << "unable to open `" << ff
-			       << "' for reading!\n";
-		}
-	      else
-		error ("type: `%s' undefined", argv[i].c_str ());
-	    }
-	}
-
-      output_buf << ends;
-
-      char *s = output_buf.str ();
-
-      if (nargout == 0)
-	octave_stdout << s;
-      else
-	retval = s;
-
-      delete [] s;
-    }
-  else
-    print_usage ("type");
+ abort:
 
   return retval;
 }
 
+static string
+do_which (const string& name)
+{
+  string retval;
+
+  symbol_record *sym_rec = lookup_by_name (name, 0);
+
+  if (sym_rec && sym_rec->is_defined ())
+    retval = sym_rec->which ();
+  else
+    {
+      string path = fcn_file_in_path (name);
+
+      if (! path.empty ())
+	retval = path;
+      else
+	retval = "undefined";
+    }
+
+  return retval;
+}
+
+static void
+do_which (ostream& os, const string& name)
+{
+  symbol_record *sym_rec = lookup_by_name (name, 0);
+
+  if (sym_rec && sym_rec->is_defined ())
+    sym_rec->which (os);
+  else
+    {
+      string path = fcn_file_in_path (name);
+
+      if (! path.empty ())
+	os << "which: `" << name << "' is the script file\n"
+	   << path << "\n";
+      else
+	os << "which: `" << name << "' is undefined\n";
+    }
+}
+
 DEFUN_TEXT (which, args, nargout,
   "which NAME ...\n\
 \n\
@@ -1084,57 +1034,30 @@
 {
   octave_value_list retval;
 
-  int argc = args.length () + 1;
-
   string_vector argv = args.make_argv ("which");
 
-  if (error_state)
-    return retval;
+  if (! error_state)
+    {
+      int argc = argv.length ();
 
-  if (argc > 1)
-    {
       if (nargout > 0)
 	retval.resize (argc-1, Matrix ());
 
-      for (int i = 1; i < argc; i++)
+      if (argc > 1)
 	{
-	  symbol_record *sym_rec = lookup_by_name (argv[i], 0);
-
-	  if (sym_rec && sym_rec->is_defined ())
+	  for (int i = 1; i < argc; i++)
 	    {
-	      int print = (nargout == 0);
-
-	      string tmp = print_symbol_type (octave_stdout, sym_rec,
-					      argv[i], print);
-	      if (! print)
-		retval(i) = tmp;
-	    }
-	  else
-	    {
-	      string path = fcn_file_in_path (argv[i]);
+	      string id = argv[i];
 
-	      if (! path.empty ())
-		{
-		  if (nargout == 0)
-		    octave_stdout << "which: `" << argv[i]
-				  << "' is the script file: "
-				  << path << "\n";
-		  else
-		    retval(i) = path;
-		}
+	      if (nargout == 0)
+		do_which (octave_stdout, id);
 	      else
-		{
-		  if (nargout == 0)
-		    octave_stdout << "which: `" << argv[i]
-				  << "' is undefined\n";
-		  else
-		    retval(i) = "undefined";
-		}
+		retval(i-1) = do_which (id);
 	    }
 	}
+      else
+	print_usage (argv[0]);
     }
-  else
-    print_usage ("which");
 
   return retval;
 }
--- a/src/load-save.cc
+++ b/src/load-save.cc
@@ -2379,41 +2379,35 @@
 save_vars (ostream& os, const string& pattern, bool save_builtins,
 	   load_save_format fmt, int save_as_floats)
 {
-  int count;
-
-  symbol_record **vars = curr_sym_tab->glob
-    (count, pattern, symbol_record::USER_VARIABLE, SYMTAB_ALL_SCOPES);
-
-  int saved = count;
-
-  int i;
-
-  for (i = 0; i < count; i++)
+  Array<symbol_record *> vars = curr_sym_tab->glob
+    (pattern, symbol_record::USER_VARIABLE, SYMTAB_ALL_SCOPES);
+
+  int saved = vars.length ();
+
+  for (int i = 0; i < saved; i++)
     {
-      do_save (os, vars[i], fmt, save_as_floats);
+      do_save (os, vars(i), fmt, save_as_floats);
 
       if (error_state)
 	break;
     }
 
-  delete [] vars;
-
   if (! error_state && save_builtins)
     {
-      symbol_record **vars = global_sym_tab->glob
-	(count, pattern, symbol_record::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES);
+      vars = global_sym_tab->glob
+	(pattern, symbol_record::BUILTIN_VARIABLE, SYMTAB_ALL_SCOPES);
+
+      int count = vars.length ();
 
       saved += count;
 
-      for (i = 0; i < count; i++)
+      for (int i = 0; i < count; i++)
 	{
-	  do_save (os, vars[i], fmt, save_as_floats);
+	  do_save (os, vars(i), fmt, save_as_floats);
 
 	  if (error_state)
 	    break;
 	}
-
-      delete [] vars;
     }
 
   return saved;
--- a/src/symtab.cc
+++ b/src/symtab.cc
@@ -54,8 +54,76 @@
 octave_allocator
 symbol_record::symbol_def::allocator (sizeof (symbol_record::symbol_def));
 
+#define SYMBOL_DEF symbol_record::symbol_def
+
+string
+SYMBOL_DEF::type_as_string (void) const
+{
+  string retval = "<unknown type>";
+
+  if (is_user_variable ())
+    retval = "user-defined variable";
+  else if (is_text_function ())
+    retval = "built-in text function";
+  else if (is_mapper_function ())
+    retval = "built-in mapper function";
+  else if (is_user_function ())
+    retval = "user-defined function";
+  else if (is_builtin_constant ())
+    retval = "built-in constant";
+  else if (is_builtin_variable ())
+    retval = "built-in variable";
+  else if (is_builtin_function ())
+    retval = "built-in function";
+  else if (is_dld_function ())
+    retval = "dynamically-linked function";
+
+  return retval;
+}
+
+string
+SYMBOL_DEF::which (const string& name)
+{
+  string retval;
+
+  if (is_user_function () || is_dld_function ())
+    {
+      octave_function *defn = definition.function_value ();
+
+      if (defn)
+	retval = defn->fcn_file_name ();
+    }
+  else
+    retval = name + " is a " + type_as_string ();
+
+  return retval;
+}
+
 void
-symbol_record::symbol_def::dump_symbol_info (void)
+SYMBOL_DEF::which (ostream& os, const string& name)
+{
+  os << name;
+
+  if (is_user_function () || is_dld_function ())
+    {
+      octave_function *defn = definition.function_value ();
+
+      string fn = defn ? defn->fcn_file_name () : string ();
+
+      if (! fn.empty ())
+	{
+	  os << " is the " << type_as_string () << " from the file\n"
+	     << fn << "\n";
+
+	  return;
+	}
+    }
+
+  os << " is a " << type_as_string () << "\n";
+}
+
+void
+SYMBOL_DEF::dump_symbol_info (void)
 {
   octave_stdout << "symbol_def::count: " << count << "\n";
   octave_stdout << "def.type_name():   " << definition.type_name () << "\n";
@@ -558,17 +626,17 @@
 }
 
 Array<symbol_record *>
-symbol_table::symbol_list (int& count, const string_vector& pats,
+symbol_table::symbol_list (const string_vector& pats,
 			   unsigned int type, unsigned int scope) const
 {
-  count = 0;
+  int count = 0;
 
   int n = size ();
 
+  Array<symbol_record *> symbols (n);
+
   if (n == 0)
-    return 0;
-
-  Array<symbol_record *> symbols (n);
+    return symbols;
 
   for (unsigned int i = 0; i < table_size; i++)
     {
@@ -598,11 +666,10 @@
 }
 
 string_vector
-symbol_table::name_list (int& count, const string_vector& pats, bool sort,
+symbol_table::name_list (const string_vector& pats, bool sort,
 			 unsigned int type, unsigned int scope) const
 {
-  Array<symbol_record *> symbols
-    = symbol_list (count, pats, type, scope);
+  Array<symbol_record *> symbols = symbol_list (pats, type, scope);
 
   string_vector names;
 
@@ -639,17 +706,15 @@
 			  ostream& os, bool show_verbose,
 			  unsigned type, unsigned scope)
 {
-  int count;
-
   int status = 0;
 
   if (show_verbose)
     {
-      Array<symbol_record *> symbols = symbol_list (count, argv, type, scope);
+      Array<symbol_record *> symbols = symbol_list (argv, type, scope);
 
       int len = symbols.length ();
 
-      if (len > 0 && count > 0)
+      if (len > 0)
 	{
 	  os << "\n" << header << "\n\n"
 		     << "prot  type                       rows   cols  name\n"
@@ -665,9 +730,9 @@
     }
   else
     {
-      string_vector symbols = name_list (count, argv, 1, type, scope);
+      string_vector symbols = name_list (argv, 1, type, scope);
 
-      if (symbols.length () > 0 && count > 0)
+      if (! symbols.empty ())
 	{
 	  os << "\n" << header << "\n\n";
 
@@ -680,16 +745,18 @@
   return status;
 }
 
-symbol_record **
-symbol_table::glob (int& count, const string& pat, unsigned int type,
+Array<symbol_record *>
+symbol_table::glob (const string& pat, unsigned int type,
 		    unsigned int scope) const
 {
-  count = 0;
+  int count = 0;
+
   int n = size ();
+
+  Array<symbol_record *> symbols (n);
+
   if (n == 0)
-    return 0;
-
-  symbol_record **symbols = new symbol_record * [n+1];
+    return symbols;
 
   for (unsigned int i = 0; i < table_size; i++)
     {
@@ -708,13 +775,14 @@
 	  if ((type & my_type) && (scope & my_scope)
 	      && pattern.match (ptr->name ()))
 	    {
-	      symbols[count++] = ptr;
+	      symbols(count++) = ptr;
 	    }
 
 	  ptr = ptr->next ();
 	}
     }
-  symbols[count] = 0;
+
+  symbols.resize (count);
 
   return symbols;
 }
--- a/src/symtab.h
+++ b/src/symtab.h
@@ -141,6 +141,12 @@
 
     string type_name (void) const { return definition.type_name (); }
 
+    string type_as_string (void) const;
+
+    string which (const string& name);
+
+    void which (ostream& os, const string& name);
+
     void define (const octave_value& val, unsigned int sym_type)
       {
 	definition = val;
@@ -308,6 +314,13 @@
 
   string type_name (void) const { return definition->type_name (); }
 
+  string type_as_string (void) const
+    { return definition->type_as_string (); }
+
+  string which (void) { return definition->which (name ()); }
+
+  void which (ostream& os) { definition->which (os, name ()); }
+
   octave_value& variable_value (void);
   octave_lvalue variable_reference (void);
 
@@ -402,13 +415,13 @@
   int size (void) const;
 
   Array<symbol_record *>
-  symbol_list (int& count, const string_vector& pats = string_vector (),
+  symbol_list (const string_vector& pats = string_vector (),
 	       unsigned int type = SYMTAB_ALL_TYPES,
 	       unsigned int scope = SYMTAB_ALL_SCOPES) const;
 
 
   string_vector
-  name_list (int& count, const string_vector& pats = string_vector (),
+  name_list (const string_vector& pats = string_vector (),
 	     bool sort = false, unsigned int type = SYMTAB_ALL_TYPES,
 	     unsigned int scope = SYMTAB_ALL_SCOPES) const;
 
@@ -417,9 +430,9 @@
 		  ostream& os, bool show_verbose,
 		  unsigned type, unsigned scope);
   
-  symbol_record **glob (int& count, const string& pat = string ("*"),
-			unsigned int type = SYMTAB_ALL_TYPES,
-			unsigned int scope = SYMTAB_ALL_SCOPES) const;
+  Array<symbol_record *> glob (const string& pat = string ("*"),
+			       unsigned int type = SYMTAB_ALL_TYPES,
+			       unsigned int scope = SYMTAB_ALL_SCOPES) const;
 
   void push_context (void);
 
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -103,7 +103,7 @@
   return (sr && sr->is_text_function ());
 }
 
-// Is this a mapper function?
+// Is this a built-in function?
 
 bool
 is_builtin_function_name (const string& s)
@@ -1075,10 +1075,6 @@
 	    }
 	}
 
-      int lcount = 0;
-      int gcount = 0;
-      int fcount = 0;
-
       string_vector lvars;
       string_vector gvars;
       string_vector fcns;
@@ -1088,13 +1084,13 @@
 	  string_vector tmp;
 
 	  lvars = curr_sym_tab->name_list
-	    (lcount, tmp, false, SYMTAB_VARIABLES, SYMTAB_LOCAL_SCOPE);
+	    (tmp, false, SYMTAB_VARIABLES, SYMTAB_LOCAL_SCOPE);
 
 	  gvars = curr_sym_tab->name_list
-	    (gcount, tmp, false, SYMTAB_VARIABLES, SYMTAB_GLOBAL_SCOPE);
+	    (tmp, false, SYMTAB_VARIABLES, SYMTAB_GLOBAL_SCOPE);
 
 	  fcns = global_sym_tab->name_list
-	    (fcount, tmp, false,
+	    (tmp, false,
 	     symbol_record::USER_FUNCTION|symbol_record::DLD_FUNCTION,
 	     SYMTAB_ALL_SCOPES);
 	}
@@ -1111,8 +1107,9 @@
 	    {
 	      glob_match pattern (patstr);
 
-	      int i;
-	      for (i = 0; i < lcount; i++)
+	      int lcount = lvars.length ();
+
+	      for (int i = 0; i < lcount; i++)
 		{
 		  string nm = lvars[i];
 		  int match = pattern.match (nm);
@@ -1120,26 +1117,27 @@
 		    curr_sym_tab->clear (nm);
 		}
 
-	      int count;
-	      for (i = 0; i < gcount; i++)
+	      int gcount = gvars.length ();
+	      for (int i = 0; i < gcount; i++)
 		{
 		  string nm = gvars[i];
 		  int match = pattern.match (nm);
 		  if ((exclusive && ! match) || (! exclusive && match))
 		    {
-		      count = curr_sym_tab->clear (nm);
+		      int count = curr_sym_tab->clear (nm);
 		      if (count > 0)
 			global_sym_tab->clear (nm, clear_user_functions);
 		    }
 		}
 
-	      for (i = 0; i < fcount; i++)
+	      int fcount = fcns.length ();
+	      for (int i = 0; i < fcount; i++)
 		{
 		  string nm = fcns[i];
 		  int match = pattern.match (nm);
 		  if ((exclusive && ! match) || (! exclusive && match))
 		    {
-		      count = curr_sym_tab->clear (nm);
+		      curr_sym_tab->clear (nm);
 		      global_sym_tab->clear (nm, clear_user_functions);
 		    }
 		}