diff libinterp/corefcn/variables.cc @ 16892:68fc671a9339

maint: Collapse interpfcn and interpfcn-core directories into corefcn directory. * libgui/src/module.mk: Remove -I references to interp-core, interpfcn, add reference to corefcn. * libinterp/Makefile.am: Remove -I references to interp-core, interpfcn, add reference to corefcn. * libinterp/corefcn/module.mk: Add files from interp-core, interpfcn to build system. Copy over special rules from module.mk files in interp-core andd interpfcn. * src/Makefile.am: Replace references to interp-core, interpfcn with those to corefcn. * libinterp/corefcn/Cell.cc, libinterp/corefcn/Cell.h, libinterp/corefcn/action-container.h, libinterp/corefcn/c-file-ptr-stream.cc, libinterp/corefcn/c-file-ptr-stream.h, libinterp/corefcn/comment-list.cc, libinterp/corefcn/comment-list.h, libinterp/corefcn/cutils.c, libinterp/corefcn/cutils.h, libinterp/corefcn/data.cc, libinterp/corefcn/data.h, libinterp/corefcn/debug.cc, libinterp/corefcn/debug.h, libinterp/corefcn/defaults.cc, libinterp/corefcn/defaults.in.h, libinterp/corefcn/defun-dld.h, libinterp/corefcn/defun-int.h, libinterp/corefcn/defun.cc, libinterp/corefcn/defun.h, libinterp/corefcn/dirfns.cc, libinterp/corefcn/dirfns.h, libinterp/corefcn/display.cc, libinterp/corefcn/display.h, libinterp/corefcn/dynamic-ld.cc, libinterp/corefcn/dynamic-ld.h, libinterp/corefcn/error.cc, libinterp/corefcn/error.h, libinterp/corefcn/event-queue.h, libinterp/corefcn/file-io.cc, libinterp/corefcn/file-io.h, libinterp/corefcn/gl-render.cc, libinterp/corefcn/gl-render.h, libinterp/corefcn/gl2ps-renderer.cc, libinterp/corefcn/gl2ps-renderer.h, libinterp/corefcn/gl2ps.c, libinterp/corefcn/gl2ps.h, libinterp/corefcn/graphics.cc, libinterp/corefcn/graphics.in.h, libinterp/corefcn/gripes.cc, libinterp/corefcn/gripes.h, libinterp/corefcn/help.cc, libinterp/corefcn/help.h, libinterp/corefcn/hook-fcn.cc, libinterp/corefcn/hook-fcn.h, libinterp/corefcn/input.cc, libinterp/corefcn/input.h, libinterp/corefcn/jit-ir.cc, libinterp/corefcn/jit-ir.h, libinterp/corefcn/jit-typeinfo.cc, libinterp/corefcn/jit-typeinfo.h, libinterp/corefcn/jit-util.cc, libinterp/corefcn/jit-util.h, libinterp/corefcn/load-path.cc, libinterp/corefcn/load-path.h, libinterp/corefcn/load-save.cc, libinterp/corefcn/load-save.h, libinterp/corefcn/ls-ascii-helper.cc, libinterp/corefcn/ls-ascii-helper.h, libinterp/corefcn/ls-hdf5.cc, libinterp/corefcn/ls-hdf5.h, libinterp/corefcn/ls-mat-ascii.cc, libinterp/corefcn/ls-mat-ascii.h, libinterp/corefcn/ls-mat4.cc, libinterp/corefcn/ls-mat4.h, libinterp/corefcn/ls-mat5.cc, libinterp/corefcn/ls-mat5.h, libinterp/corefcn/ls-oct-ascii.cc, libinterp/corefcn/ls-oct-ascii.h, libinterp/corefcn/ls-oct-binary.cc, libinterp/corefcn/ls-oct-binary.h, libinterp/corefcn/ls-utils.cc, libinterp/corefcn/ls-utils.h, libinterp/corefcn/matherr.c, libinterp/corefcn/mex.cc, libinterp/corefcn/mex.h, libinterp/corefcn/mexproto.h, libinterp/corefcn/mxarray.in.h, libinterp/corefcn/oct-errno.h, libinterp/corefcn/oct-errno.in.cc, libinterp/corefcn/oct-fstrm.cc, libinterp/corefcn/oct-fstrm.h, libinterp/corefcn/oct-hdf5.h, libinterp/corefcn/oct-hist.cc, libinterp/corefcn/oct-hist.h, libinterp/corefcn/oct-iostrm.cc, libinterp/corefcn/oct-iostrm.h, libinterp/corefcn/oct-lvalue.cc, libinterp/corefcn/oct-lvalue.h, libinterp/corefcn/oct-map.cc, libinterp/corefcn/oct-map.h, libinterp/corefcn/oct-obj.cc, libinterp/corefcn/oct-obj.h, libinterp/corefcn/oct-prcstrm.cc, libinterp/corefcn/oct-prcstrm.h, libinterp/corefcn/oct-procbuf.cc, libinterp/corefcn/oct-procbuf.h, libinterp/corefcn/oct-stdstrm.h, libinterp/corefcn/oct-stream.cc, libinterp/corefcn/oct-stream.h, libinterp/corefcn/oct-strstrm.cc, libinterp/corefcn/oct-strstrm.h, libinterp/corefcn/oct.h, libinterp/corefcn/octave-link.cc, libinterp/corefcn/octave-link.h, libinterp/corefcn/pager.cc, libinterp/corefcn/pager.h, libinterp/corefcn/pr-output.cc, libinterp/corefcn/pr-output.h, libinterp/corefcn/procstream.cc, libinterp/corefcn/procstream.h, libinterp/corefcn/profiler.cc, libinterp/corefcn/profiler.h, libinterp/corefcn/pt-jit.cc, libinterp/corefcn/pt-jit.h, libinterp/corefcn/sighandlers.cc, libinterp/corefcn/sighandlers.h, libinterp/corefcn/siglist.c, libinterp/corefcn/siglist.h, libinterp/corefcn/sparse-xdiv.cc, libinterp/corefcn/sparse-xdiv.h, libinterp/corefcn/sparse-xpow.cc, libinterp/corefcn/sparse-xpow.h, libinterp/corefcn/symtab.cc, libinterp/corefcn/symtab.h, libinterp/corefcn/sysdep.cc, libinterp/corefcn/sysdep.h, libinterp/corefcn/toplev.cc, libinterp/corefcn/toplev.h, libinterp/corefcn/txt-eng-ft.cc, libinterp/corefcn/txt-eng-ft.h, libinterp/corefcn/txt-eng.h, libinterp/corefcn/unwind-prot.cc, libinterp/corefcn/unwind-prot.h, libinterp/corefcn/utils.cc, libinterp/corefcn/utils.h, libinterp/corefcn/variables.cc, libinterp/corefcn/variables.h, libinterp/corefcn/workspace-element.h, libinterp/corefcn/xdiv.cc, libinterp/corefcn/xdiv.h, libinterp/corefcn/xgl2ps.c, libinterp/corefcn/xnorm.cc, libinterp/corefcn/xnorm.h, libinterp/corefcn/xpow.cc, libinterp/corefcn/xpow.h, libinterp/corefcn/zfstream.cc, libinterp/corefcn/zfstream.h: Files moved from interp-core and interpfcn directories. * libinterp/interp-core/Cell.cc, libinterp/interp-core/Cell.h, libinterp/interp-core/action-container.h, libinterp/interp-core/c-file-ptr-stream.cc, libinterp/interp-core/c-file-ptr-stream.h, libinterp/interp-core/comment-list.cc, libinterp/interp-core/comment-list.h, libinterp/interp-core/cutils.c, libinterp/interp-core/cutils.h, libinterp/interp-core/defun-dld.h, libinterp/interp-core/defun-int.h, libinterp/interp-core/display.cc, libinterp/interp-core/display.h, libinterp/interp-core/dynamic-ld.cc, libinterp/interp-core/dynamic-ld.h, libinterp/interp-core/event-queue.h, libinterp/interp-core/gl-render.cc, libinterp/interp-core/gl-render.h, libinterp/interp-core/gl2ps-renderer.cc, libinterp/interp-core/gl2ps-renderer.h, libinterp/interp-core/gl2ps.c, libinterp/interp-core/gl2ps.h, libinterp/interp-core/gripes.cc, libinterp/interp-core/gripes.h, libinterp/interp-core/jit-ir.cc, libinterp/interp-core/jit-ir.h, libinterp/interp-core/jit-typeinfo.cc, libinterp/interp-core/jit-typeinfo.h, libinterp/interp-core/jit-util.cc, libinterp/interp-core/jit-util.h, libinterp/interp-core/ls-ascii-helper.cc, libinterp/interp-core/ls-ascii-helper.h, libinterp/interp-core/ls-hdf5.cc, libinterp/interp-core/ls-hdf5.h, libinterp/interp-core/ls-mat-ascii.cc, libinterp/interp-core/ls-mat-ascii.h, libinterp/interp-core/ls-mat4.cc, libinterp/interp-core/ls-mat4.h, libinterp/interp-core/ls-mat5.cc, libinterp/interp-core/ls-mat5.h, libinterp/interp-core/ls-oct-binary.cc, libinterp/interp-core/ls-oct-binary.h, libinterp/interp-core/ls-utils.cc, libinterp/interp-core/ls-utils.h, libinterp/interp-core/matherr.c, libinterp/interp-core/mex.cc, libinterp/interp-core/mex.h, libinterp/interp-core/mexproto.h, libinterp/interp-core/module.mk, libinterp/interp-core/mxarray.in.h, libinterp/interp-core/oct-errno.h, libinterp/interp-core/oct-errno.in.cc, libinterp/interp-core/oct-fstrm.cc, libinterp/interp-core/oct-fstrm.h, libinterp/interp-core/oct-hdf5.h, libinterp/interp-core/oct-iostrm.cc, libinterp/interp-core/oct-iostrm.h, libinterp/interp-core/oct-lvalue.cc, libinterp/interp-core/oct-lvalue.h, libinterp/interp-core/oct-map.cc, libinterp/interp-core/oct-map.h, libinterp/interp-core/oct-obj.cc, libinterp/interp-core/oct-obj.h, libinterp/interp-core/oct-prcstrm.cc, libinterp/interp-core/oct-prcstrm.h, libinterp/interp-core/oct-procbuf.cc, libinterp/interp-core/oct-procbuf.h, libinterp/interp-core/oct-stdstrm.h, libinterp/interp-core/oct-stream.cc, libinterp/interp-core/oct-stream.h, libinterp/interp-core/oct-strstrm.cc, libinterp/interp-core/oct-strstrm.h, libinterp/interp-core/oct.h, libinterp/interp-core/procstream.cc, libinterp/interp-core/procstream.h, libinterp/interp-core/pt-jit.cc, libinterp/interp-core/pt-jit.h, libinterp/interp-core/siglist.c, libinterp/interp-core/siglist.h, libinterp/interp-core/sparse-xdiv.cc, libinterp/interp-core/sparse-xdiv.h, libinterp/interp-core/sparse-xpow.cc, libinterp/interp-core/sparse-xpow.h, libinterp/interp-core/txt-eng-ft.cc, libinterp/interp-core/txt-eng-ft.h, libinterp/interp-core/txt-eng.h, libinterp/interp-core/unwind-prot.cc, libinterp/interp-core/unwind-prot.h, libinterp/interp-core/xdiv.cc, libinterp/interp-core/xdiv.h, libinterp/interp-core/xgl2ps.c, libinterp/interp-core/xnorm.cc, libinterp/interp-core/xnorm.h, libinterp/interp-core/xpow.cc, libinterp/interp-core/xpow.h, libinterp/interp-core/zfstream.cc, libinterp/interp-core/zfstream.h, libinterp/interpfcn/data.cc, libinterp/interpfcn/data.h, libinterp/interpfcn/debug.cc, libinterp/interpfcn/debug.h, libinterp/interpfcn/defaults.cc, libinterp/interpfcn/defaults.in.h, libinterp/interpfcn/defun.cc, libinterp/interpfcn/defun.h, libinterp/interpfcn/dirfns.cc, libinterp/interpfcn/dirfns.h, libinterp/interpfcn/error.cc, libinterp/interpfcn/error.h, libinterp/interpfcn/file-io.cc, libinterp/interpfcn/file-io.h, libinterp/interpfcn/graphics.cc, libinterp/interpfcn/graphics.in.h, libinterp/interpfcn/help.cc, libinterp/interpfcn/help.h, libinterp/interpfcn/hook-fcn.cc, libinterp/interpfcn/hook-fcn.h, libinterp/interpfcn/input.cc, libinterp/interpfcn/input.h, libinterp/interpfcn/load-path.cc, libinterp/interpfcn/load-path.h, libinterp/interpfcn/load-save.cc, libinterp/interpfcn/load-save.h, libinterp/interpfcn/ls-oct-ascii.cc, libinterp/interpfcn/ls-oct-ascii.h, libinterp/interpfcn/module.mk, libinterp/interpfcn/oct-hist.cc, libinterp/interpfcn/oct-hist.h, libinterp/interpfcn/octave-link.cc, libinterp/interpfcn/octave-link.h, libinterp/interpfcn/pager.cc, libinterp/interpfcn/pager.h, libinterp/interpfcn/pr-output.cc, libinterp/interpfcn/pr-output.h, libinterp/interpfcn/profiler.cc, libinterp/interpfcn/profiler.h, libinterp/interpfcn/sighandlers.cc, libinterp/interpfcn/sighandlers.h, libinterp/interpfcn/symtab.cc, libinterp/interpfcn/symtab.h, libinterp/interpfcn/sysdep.cc, libinterp/interpfcn/sysdep.h, libinterp/interpfcn/toplev.cc, libinterp/interpfcn/toplev.h, libinterp/interpfcn/utils.cc, libinterp/interpfcn/utils.h, libinterp/interpfcn/variables.cc, libinterp/interpfcn/variables.h, libinterp/interpfcn/workspace-element.h: deleted files.
author Rik <rik@octave.org>
date Wed, 03 Jul 2013 17:43:48 -0700
parents libinterp/interpfcn/variables.cc@6a8e63dadfad
children 99122191d3dd
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/variables.cc	Wed Jul 03 17:43:48 2013 -0700
@@ -0,0 +1,2606 @@
+/*
+
+Copyright (C) 1993-2012 John W. Eaton
+Copyright (C) 2009-2010 VZLU Prague
+
+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/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cstdio>
+#include <cstring>
+
+#include <iomanip>
+#include <set>
+#include <string>
+
+#include "file-stat.h"
+#include "oct-env.h"
+#include "file-ops.h"
+#include "glob-match.h"
+#include "regexp.h"
+#include "str-vec.h"
+
+#include <defaults.h>
+#include "Cell.h"
+#include "defun.h"
+#include "dirfns.h"
+#include "error.h"
+#include "gripes.h"
+#include "help.h"
+#include "input.h"
+#include "lex.h"
+#include "load-path.h"
+#include "octave-link.h"
+#include "oct-map.h"
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-class.h"
+#include "ov-usr-fcn.h"
+#include "pager.h"
+#include "parse.h"
+#include "symtab.h"
+#include "toplev.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+
+// Defines layout for the whos/who -long command
+static std::string Vwhos_line_format
+  = "  %a:4; %ln:6; %cs:16:6:1;  %rb:12;  %lc:-1;\n";
+
+void
+clear_mex_functions (void)
+{
+  symbol_table::clear_mex_functions ();
+}
+
+void
+clear_function (const std::string& nm)
+{
+  symbol_table::clear_function (nm);
+}
+
+void
+clear_variable (const std::string& nm)
+{
+  symbol_table::clear_variable (nm);
+}
+
+void
+clear_symbol (const std::string& nm)
+{
+  symbol_table::clear_symbol (nm);
+}
+
+// Attributes of variables and functions.
+
+// Is this octave_value a valid function?
+
+octave_function *
+is_valid_function (const std::string& fcn_name,
+                   const std::string& warn_for, bool warn)
+{
+  octave_function *ans = 0;
+
+  if (! fcn_name.empty ())
+    {
+      octave_value val = symbol_table::find_function (fcn_name);
+
+      if (val.is_defined ())
+        ans = val.function_value (true);
+    }
+
+  if (! ans && warn)
+    error ("%s: the symbol '%s' is not valid as a function",
+           warn_for.c_str (), fcn_name.c_str ());
+
+  return ans;
+}
+
+octave_function *
+is_valid_function (const octave_value& arg,
+                   const std::string& warn_for, bool warn)
+{
+  octave_function *ans = 0;
+
+  std::string fcn_name;
+
+  if (arg.is_string ())
+    {
+      fcn_name = arg.string_value ();
+
+      if (! error_state)
+        ans = is_valid_function (fcn_name, warn_for, warn);
+      else if (warn)
+        error ("%s: expecting function name as argument", warn_for.c_str ());
+    }
+  else if (warn)
+    error ("%s: expecting function name as argument", warn_for.c_str ());
+
+  return ans;
+}
+
+octave_function *
+extract_function (const octave_value& arg, const std::string& warn_for,
+                  const std::string& fname, const std::string& header,
+                  const std::string& trailer)
+{
+  octave_function *retval = 0;
+
+  retval = is_valid_function (arg, warn_for, 0);
+
+  if (! retval)
+    {
+      std::string s = arg.string_value ();
+
+      std::string cmd = header;
+      cmd.append (s);
+      cmd.append (trailer);
+
+      if (! error_state)
+        {
+          int parse_status;
+
+          eval_string (cmd, true, parse_status, 0);
+
+          if (parse_status == 0)
+            {
+              retval = is_valid_function (fname, warn_for, 0);
+
+              if (! retval)
+                {
+                  error ("%s: '%s' is not valid as a function",
+                         warn_for.c_str (), fname.c_str ());
+                  return retval;
+                }
+
+              warning ("%s: passing function body as a string is obsolete; please use anonymous functions",
+                       warn_for.c_str ());
+            }
+          else
+            error ("%s: '%s' is not valid as a function",
+                   warn_for.c_str (), fname.c_str ());
+        }
+      else
+        error ("%s: expecting first argument to be a string",
+               warn_for.c_str ());
+    }
+
+  return retval;
+}
+
+string_vector
+get_struct_elts (const std::string& text)
+{
+  int n = 1;
+
+  size_t pos = 0;
+
+  size_t len = text.length ();
+
+  while ((pos = text.find ('.', pos)) != std::string::npos)
+    {
+      if (++pos == len)
+        break;
+
+      n++;
+    }
+
+  string_vector retval (n);
+
+  pos = 0;
+
+  for (int i = 0; i < n; i++)
+    {
+      len = text.find ('.', pos);
+
+      if (len != std::string::npos)
+        len -= pos;
+
+      retval[i] = text.substr (pos, len);
+
+      if (len != std::string::npos)
+        pos += len + 1;
+    }
+
+  return retval;
+}
+
+static inline bool
+is_variable (const std::string& name)
+{
+  bool retval = false;
+
+  if (! name.empty ())
+    {
+      octave_value val = symbol_table::varval (name);
+
+      retval = val.is_defined ();
+    }
+
+  return retval;
+}
+
+string_vector
+generate_struct_completions (const std::string& text,
+                             std::string& prefix, std::string& hint)
+{
+  string_vector names;
+
+  size_t pos = text.rfind ('.');
+
+  if (pos != std::string::npos)
+    {
+      if (pos == text.length ())
+        hint = "";
+      else
+        hint = text.substr (pos+1);
+
+      prefix = text.substr (0, pos);
+
+      std::string base_name = prefix;
+
+      pos = base_name.find_first_of ("{(.");
+
+      if (pos != std::string::npos)
+        base_name = base_name.substr (0, pos);
+
+      if (is_variable (base_name))
+        {
+          int parse_status;
+
+          unwind_protect frame;
+
+          frame.protect_var (error_state);
+          frame.protect_var (warning_state);
+
+          frame.protect_var (discard_error_messages);
+          frame.protect_var (discard_warning_messages);
+
+          discard_error_messages = true;
+          discard_warning_messages = true;
+
+          octave_value tmp = eval_string (prefix, true, parse_status);
+
+          frame.run ();
+
+          if (tmp.is_defined () && (tmp.is_map () || tmp.is_java ()))
+            names = tmp.map_keys ();
+        }
+    }
+
+  return names;
+}
+
+// FIXME -- this will have to be much smarter to work
+// "correctly".
+
+bool
+looks_like_struct (const std::string& text)
+{
+  bool retval = (! text.empty ()
+                 && text != "."
+                 && text.find_first_of (file_ops::dir_sep_chars ()) == std::string::npos
+                 && text.find ("..") == std::string::npos
+                 && text.rfind ('.') != std::string::npos);
+
+#if 0
+  symbol_record *sr = curr_sym_tab->lookup (text);
+
+  if (sr && ! sr->is_function ())
+    {
+      int parse_status;
+
+      unwind_protect frame;
+
+      frame.protect_var (discard_error_messages);
+      frame.protect_var (error_state);
+
+      discard_error_messages = true;
+
+      octave_value tmp = eval_string (text, true, parse_status);
+
+      frame.run ();
+
+      retval = (tmp.is_defined () && tmp.is_map ());
+    }
+#endif
+
+  return retval;
+}
+
+static octave_value
+do_isglobal (const octave_value_list& args)
+{
+  octave_value retval = false;
+
+  int nargin = args.length ();
+
+  if (nargin != 1)
+    {
+      print_usage ();
+      return retval;
+    }
+
+  std::string name = args(0).string_value ();
+
+  if (error_state)
+    {
+      error ("isglobal: NAME must be a string");
+      return retval;
+    }
+
+  return symbol_table::is_global (name);
+}
+
+DEFUN (isglobal, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} isglobal (@var{name})\n\
+Return true if @var{name} is a globally visible variable.\n\
+For example:\n\
+\n\
+@example\n\
+@group\n\
+global x\n\
+isglobal (\"x\")\n\
+   @result{} 1\n\
+@end group\n\
+@end example\n\
+@seealso{isvarname, exist}\n\
+@end deftypefn")
+{
+  return do_isglobal (args);
+}
+
+static octave_value
+safe_symbol_lookup (const std::string& symbol_name)
+{
+  octave_value retval;
+
+  unwind_protect frame;
+  interpreter_try (frame);
+
+  retval = symbol_table::find (symbol_name);
+
+  error_state = 0;
+
+  return retval;
+}
+
+int
+symbol_exist (const std::string& name, const std::string& type)
+{
+  int retval = 0;
+
+  std::string struct_elts;
+  std::string symbol_name = name;
+
+  size_t pos = name.find ('.');
+
+  if (pos != std::string::npos && pos > 0)
+    {
+      struct_elts = name.substr (pos+1);
+      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.
+
+  octave_value val = safe_symbol_lookup (symbol_name);
+
+  if (val.is_defined ())
+    {
+      bool not_a_struct = struct_elts.empty ();
+      bool var_ok = not_a_struct /* || val.is_map_element (struct_elts) */;
+
+      if (! retval
+          && var_ok
+          && (type == "any" || type == "var")
+          && (val.is_constant () || val.is_object ()
+              || val.is_function_handle ()
+              || val.is_anonymous_function ()
+              || val.is_inline_function ()))
+        {
+          retval = 1;
+        }
+
+      if (! retval
+          && (type == "any" || type == "builtin"))
+        {
+          if (not_a_struct && val.is_builtin_function ())
+            {
+              retval = 5;
+            }
+        }
+
+      if (! retval
+          && not_a_struct
+          && (type == "any" || type == "file")
+          && (val.is_user_function () || val.is_dld_function ()))
+        {
+          octave_function *f = val.function_value (true);
+          std::string s = f ? f->fcn_file_name () : std::string ();
+
+          retval = s.empty () ? 103 : (val.is_user_function () ? 2 : 3);
+        }
+    }
+
+  if (! (type == "var" || type == "builtin"))
+    {
+      if (! retval)
+        {
+          std::string file_name = lookup_autoload (name);
+
+          if (file_name.empty ())
+            file_name = load_path::find_fcn (name);
+
+          size_t len = file_name.length ();
+
+          if (len > 0)
+            {
+              if (type == "any" || type == "file")
+                {
+                  if (len > 4 && (file_name.substr (len-4) == ".oct"
+                                  || file_name.substr (len-4) == ".mex"))
+                    retval = 3;
+                  else
+                    retval = 2;
+                }
+            }
+        }
+
+      if (! retval)
+        {
+          std::string file_name = file_in_path (name, "");
+
+          if (file_name.empty ())
+            file_name = name;
+
+          file_stat fs (file_name);
+
+          if (fs)
+            {
+              if (type == "any" || type == "file")
+                retval = fs.is_dir () ? 7 : 2;
+              else if (type == "dir" && fs.is_dir ())
+                retval = 7;
+            }
+        }
+    }
+
+  return retval;
+}
+
+#define GET_IDX(LEN) \
+  static_cast<int> ((LEN-1) * static_cast<double> (rand ()) / RAND_MAX)
+
+std::string
+unique_symbol_name (const std::string& basename)
+{
+  static const std::string alpha
+    = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+  static size_t len = alpha.length ();
+
+  std::string nm = basename + alpha[GET_IDX (len)];
+
+  size_t pos = nm.length ();
+
+  if (nm.substr (0, 2) == "__")
+    nm.append ("__");
+
+  while (symbol_exist (nm, "any"))
+    nm.insert (pos++, 1, alpha[GET_IDX (len)]);
+
+  return nm;
+}
+
+DEFUN (exist, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} exist (@var{name}, @var{type})\n\
+Return 1 if the name exists as a variable, 2 if the name is an\n\
+absolute file name, an ordinary file in Octave's @code{path}, or (after\n\
+appending @samp{.m}) a function file in Octave's @code{path}, 3 if the\n\
+name is a @samp{.oct} or @samp{.mex} file in Octave's @code{path},\n\
+5 if the name is a built-in function, 7 if the name is a directory, or 103\n\
+if the name is a function not associated with a file (entered on\n\
+the command line).\n\
+\n\
+Otherwise, return 0.\n\
+\n\
+This function also returns 2 if a regular file called @var{name}\n\
+exists in Octave's search path.  If you want information about\n\
+other types of files, you should use some combination of the functions\n\
+@code{file_in_path} and @code{stat} instead.\n\
+\n\
+If the optional argument @var{type} is supplied, check only for\n\
+symbols of the specified type.  Valid types are\n\
+\n\
+@table @asis\n\
+@item \"var\"\n\
+Check only for variables.\n\
+\n\
+@item \"builtin\"\n\
+Check only for built-in functions.\n\
+\n\
+@item \"file\"\n\
+Check only for files and directories.\n\
+\n\
+@item \"dir\"\n\
+Check only for directories.\n\
+@end table\n\
+\n\
+@seealso{file_in_loadpath, file_in_path, stat}\n\
+@end deftypefn")
+{
+  octave_value retval = false;
+
+  int nargin = args.length ();
+
+  if (nargin == 1 || nargin == 2)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        {
+          std::string type
+            = (nargin == 2) ? args(1).string_value () : std::string ("any");
+
+          if (! error_state)
+            retval = symbol_exist (name, type);
+          else
+            error ("exist: TYPE must be a string");
+        }
+      else
+        error ("exist: NAME must be a string");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+%!test
+%! if (isunix ())
+%!   assert (exist ("/tmp") == 7);
+%!   assert (exist ("/tmp", "file") == 7);
+%!   assert (exist ("/tmp", "dir") == 7);
+%!   assert (exist ("/bin/sh") == 2);
+%!   assert (exist ("/bin/sh", "file") == 2);
+%!   assert (exist ("/bin/sh", "dir") == 0);
+%!   assert (exist ("/dev/null") == 2);
+%!   assert (exist ("/dev/null", "file") == 2);
+%!   assert (exist ("/dev/null", "dir") == 0);
+%! endif
+*/
+
+octave_value
+lookup_function_handle (const std::string& nm)
+{
+  octave_value val = symbol_table::varval (nm);
+
+  return val.is_function_handle () ? val : octave_value ();
+}
+
+octave_value
+get_global_value (const std::string& nm, bool silent)
+{
+  octave_value val = symbol_table::global_varval (nm);
+
+  if (val.is_undefined () && ! silent)
+    error ("get_global_value: undefined symbol '%s'", nm.c_str ());
+
+  return val;
+}
+
+void
+set_global_value (const std::string& nm, const octave_value& val)
+{
+  symbol_table::global_assign (nm, val);
+}
+
+octave_value
+get_top_level_value (const std::string& nm, bool silent)
+{
+  octave_value val = symbol_table::top_level_varval (nm);
+
+  if (val.is_undefined () && ! silent)
+    error ("get_top_level_value: undefined symbol '%s'", nm.c_str ());
+
+  return val;
+}
+
+void
+set_top_level_value (const std::string& nm, const octave_value& val)
+{
+  symbol_table::top_level_assign (nm, val);
+}
+
+// Variable values.
+
+static bool
+wants_local_change (const octave_value_list& args, int& nargin)
+{
+  bool retval = false;
+
+  if (nargin == 2)
+    {
+      if (args(1).is_string () && args(1).string_value () == "local")
+        {
+          nargin = 1;
+          retval = true;
+        }
+      else
+        {
+          error_with_cfn ("expecting second argument to be \"local\"");
+          nargin = 0;
+        }
+    }
+
+  return retval;
+}
+
+template <class T>
+bool try_local_protect (T& var)
+{
+  octave_user_code *curr_usr_code = octave_call_stack::caller_user_code ();
+  octave_user_function *curr_usr_fcn = 0;
+  if (curr_usr_code && curr_usr_code->is_user_function ())
+    curr_usr_fcn = dynamic_cast<octave_user_function *> (curr_usr_code);
+
+  if (curr_usr_fcn && curr_usr_fcn->local_protect (var))
+    return true;
+  else
+    return false;
+}
+
+octave_value
+set_internal_variable (bool& var, const octave_value_list& args,
+                       int nargout, const char *nm)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargout > 0 || nargin == 0)
+    retval = var;
+
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
+  if (nargin == 1)
+    {
+      bool bval = args(0).bool_value ();
+
+      if (! error_state)
+        var = bval;
+      else
+        error ("%s: expecting arg to be a logical value", nm);
+    }
+  else if (nargin > 1)
+    print_usage ();
+
+  return retval;
+}
+
+octave_value
+set_internal_variable (char& var, const octave_value_list& args,
+                       int nargout, const char *nm)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargout > 0 || nargin == 0)
+    retval = var;
+
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
+  if (nargin == 1)
+    {
+      std::string sval = args(0).string_value ();
+
+      if (! error_state)
+        {
+          switch (sval.length ())
+            {
+            case 1:
+              var = sval[0];
+              break;
+
+            case 0:
+              var = '\0';
+              break;
+
+            default:
+              error ("%s: argument must be a single character", nm);
+              break;
+            }
+        }
+      else
+        error ("%s: argument must be a single character", nm);
+    }
+  else if (nargin > 1)
+    print_usage ();
+
+  return retval;
+}
+
+octave_value
+set_internal_variable (int& var, const octave_value_list& args,
+                       int nargout, const char *nm,
+                       int minval, int maxval)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargout > 0 || nargin == 0)
+    retval = var;
+
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
+  if (nargin == 1)
+    {
+      int ival = args(0).int_value ();
+
+      if (! error_state)
+        {
+          if (ival < minval)
+            error ("%s: expecting arg to be greater than %d", nm, minval);
+          else if (ival > maxval)
+            error ("%s: expecting arg to be less than or equal to %d",
+                   nm, maxval);
+          else
+            var = ival;
+        }
+      else
+        error ("%s: expecting arg to be an integer value", nm);
+    }
+  else if (nargin > 1)
+    print_usage ();
+
+  return retval;
+}
+
+octave_value
+set_internal_variable (double& var, const octave_value_list& args,
+                       int nargout, const char *nm,
+                       double minval, double maxval)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargout > 0 || nargin == 0)
+    retval = var;
+
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
+  if (nargin == 1)
+    {
+      double dval = args(0).scalar_value ();
+
+      if (! error_state)
+        {
+          if (dval < minval)
+            error ("%s: expecting arg to be greater than %g", minval);
+          else if (dval > maxval)
+            error ("%s: expecting arg to be less than or equal to %g", maxval);
+          else
+            var = dval;
+        }
+      else
+        error ("%s: expecting arg to be a scalar value", nm);
+    }
+  else if (nargin > 1)
+    print_usage ();
+
+  return retval;
+}
+
+octave_value
+set_internal_variable (std::string& var, const octave_value_list& args,
+                       int nargout, const char *nm, bool empty_ok)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargout > 0 || nargin == 0)
+    retval = var;
+
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
+  if (nargin == 1)
+    {
+      std::string sval = args(0).string_value ();
+
+      if (! error_state)
+        {
+          if (empty_ok || ! sval.empty ())
+            var = sval;
+          else
+            error ("%s: value must not be empty", nm);
+        }
+      else
+        error ("%s: expecting arg to be a character string", nm);
+    }
+  else if (nargin > 1)
+    print_usage ();
+
+  return retval;
+}
+
+octave_value
+set_internal_variable (int& var, const octave_value_list& args,
+                       int nargout, const char *nm, const char **choices)
+{
+  octave_value retval;
+  int nchoices = 0;
+  while (choices[nchoices] != 0)
+    nchoices++;
+
+  int nargin = args.length ();
+  assert (var < nchoices);
+
+  if (nargout > 0 || nargin == 0)
+    retval = choices[var];
+
+  if (wants_local_change (args, nargin))
+    {
+      if (! try_local_protect (var))
+        warning ("\"local\" has no effect outside a function");
+    }
+
+  if (nargin == 1)
+    {
+      std::string sval = args(0).string_value ();
+
+      if (! error_state)
+        {
+          int i = 0;
+          for (; i < nchoices; i++)
+            {
+              if (sval == choices[i])
+                {
+                  var = i;
+                  break;
+                }
+            }
+          if (i == nchoices)
+            error ("%s: value not allowed (\"%s\")", nm, sval.c_str ());
+        }
+      else
+        error ("%s: expecting arg to be a character string", nm);
+    }
+  else if (nargin > 1)
+    print_usage ();
+
+  return retval;
+}
+
+struct
+whos_parameter
+{
+  char command;
+  char modifier;
+  int parameter_length;
+  int first_parameter_length;
+  int balance;
+  std::string text;
+  std::string line;
+};
+
+static void
+print_descriptor (std::ostream& os, std::list<whos_parameter> params)
+{
+  // This method prints a line of information on a given symbol
+  std::list<whos_parameter>::iterator i = params.begin ();
+  std::ostringstream param_buf;
+
+  while (i != params.end ())
+    {
+      whos_parameter param = *i;
+
+      if (param.command != '\0')
+        {
+          // Do the actual printing
+          switch (param.modifier)
+            {
+            case 'l':
+              os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
+              param_buf << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
+              break;
+
+            case 'r':
+              os << std::setiosflags (std::ios::right) << std::setw (param.parameter_length);
+              param_buf << std::setiosflags (std::ios::right) << std::setw (param.parameter_length);
+              break;
+
+            case 'c':
+              if (param.command != 's')
+                {
+                  os << std::setiosflags (std::ios::left)
+                     << std::setw (param.parameter_length);
+                  param_buf << std::setiosflags (std::ios::left)
+                            << std::setw (param.parameter_length);
+                }
+              break;
+
+            default:
+              os << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
+              param_buf << std::setiosflags (std::ios::left) << std::setw (param.parameter_length);
+            }
+
+          if (param.command == 's' && param.modifier == 'c')
+            {
+              int a, b;
+
+              if (param.modifier == 'c')
+                {
+                  a = param.first_parameter_length - param.balance;
+                  a = (a < 0 ? 0 : a);
+                  b = param.parameter_length - a - param.text . length ();
+                  b = (b < 0 ? 0 : b);
+                  os << std::setiosflags (std::ios::left) << std::setw (a)
+                     << "" << std::resetiosflags (std::ios::left) << param.text
+                     << std::setiosflags (std::ios::left)
+                     << std::setw (b) << ""
+                     << std::resetiosflags (std::ios::left);
+                  param_buf << std::setiosflags (std::ios::left) << std::setw (a)
+                     << "" << std::resetiosflags (std::ios::left) << param.line
+                     << std::setiosflags (std::ios::left)
+                     << std::setw (b) << ""
+                     << std::resetiosflags (std::ios::left);
+                }
+            }
+          else
+            {
+              os << param.text;
+              param_buf << param.line;
+            }
+          os << std::resetiosflags (std::ios::left)
+             << std::resetiosflags (std::ios::right);
+          param_buf << std::resetiosflags (std::ios::left)
+                    << std::resetiosflags (std::ios::right);
+          i++;
+        }
+      else
+        {
+          os << param.text;
+          param_buf << param.line;
+          i++;
+        }
+    }
+
+  os << param_buf.str ();
+}
+
+// FIXME -- This is a bit of a kluge.  We'd like to just use val.dims()
+// and if val is an object, expect that dims will call size if it is
+// overloaded by a user-defined method.  But there are currently some
+// unresolved const issues that prevent that solution from working.
+
+std::string
+get_dims_str (const octave_value& val)
+{
+  octave_value tmp = val;
+
+  Matrix sz = tmp.size ();
+
+  dim_vector dv = dim_vector::alloc (sz.numel ());
+
+  for (octave_idx_type i = 0; i < dv.length (); i++)
+    dv(i) = sz(i);
+
+  return dv.str ();
+}
+
+class
+symbol_info_list
+{
+private:
+  struct symbol_info
+  {
+    symbol_info (const symbol_table::symbol_record& sr,
+                 const std::string& expr_str = std::string (),
+                 const octave_value& expr_val = octave_value ())
+      : name (expr_str.empty () ? sr.name () : expr_str),
+        varval (expr_val.is_undefined () ? sr.varval () : expr_val),
+        is_automatic (sr.is_automatic ()),
+        is_complex (varval.is_complex_type ()),
+        is_formal (sr.is_formal ()),
+        is_global (sr.is_global ()),
+        is_persistent (sr.is_persistent ())
+    { }
+
+    void display_line (std::ostream& os,
+                       const std::list<whos_parameter>& params) const
+    {
+      std::string dims_str = get_dims_str (varval);
+
+      std::list<whos_parameter>::const_iterator i = params.begin ();
+
+      while (i != params.end ())
+        {
+          whos_parameter param = *i;
+
+          if (param.command != '\0')
+            {
+              // Do the actual printing.
+
+              switch (param.modifier)
+                {
+                case 'l':
+                  os << std::setiosflags (std::ios::left)
+                     << std::setw (param.parameter_length);
+                  break;
+
+                case 'r':
+                  os << std::setiosflags (std::ios::right)
+                     << std::setw (param.parameter_length);
+                  break;
+
+                case 'c':
+                  if (param.command == 's')
+                    {
+                      int front = param.first_parameter_length
+                        - dims_str.find ('x');
+                      int back = param.parameter_length
+                        - dims_str.length ()
+                        - front;
+                      front = (front > 0) ? front : 0;
+                      back = (back > 0) ? back : 0;
+
+                      os << std::setiosflags (std::ios::left)
+                         << std::setw (front)
+                         << ""
+                         << std::resetiosflags (std::ios::left)
+                         << dims_str
+                         << std::setiosflags (std::ios::left)
+                         << std::setw (back)
+                         << ""
+                         << std::resetiosflags (std::ios::left);
+                    }
+                  else
+                    {
+                      os << std::setiosflags (std::ios::left)
+                         << std::setw (param.parameter_length);
+                    }
+                  break;
+
+                default:
+                  error ("whos_line_format: modifier '%c' unknown",
+                         param.modifier);
+
+                  os << std::setiosflags (std::ios::right)
+                     << std::setw (param.parameter_length);
+                }
+
+              switch (param.command)
+                {
+                case 'a':
+                  {
+                    char tmp[6];
+
+                    tmp[0] = (is_automatic ? 'a' : ' ');
+                    tmp[1] = (is_complex ? 'c' : ' ');
+                    tmp[2] = (is_formal ? 'f' : ' ');
+                    tmp[3] = (is_global ? 'g' : ' ');
+                    tmp[4] = (is_persistent ? 'p' : ' ');
+                    tmp[5] = 0;
+
+                    os << tmp;
+                  }
+                  break;
+
+                case 'b':
+                  os << varval.byte_size ();
+                  break;
+
+                case 'c':
+                  os << varval.class_name ();
+                  break;
+
+                case 'e':
+                  os << varval.capacity ();
+                  break;
+
+                case 'n':
+                  os << name;
+                  break;
+
+                case 's':
+                  if (param.modifier != 'c')
+                    os << dims_str;
+                  break;
+
+                case 't':
+                  os << varval.type_name ();
+                  break;
+
+                default:
+                  error ("whos_line_format: command '%c' unknown",
+                         param.command);
+                }
+
+              os << std::resetiosflags (std::ios::left)
+                 << std::resetiosflags (std::ios::right);
+              i++;
+            }
+          else
+            {
+              os << param.text;
+              i++;
+            }
+        }
+    }
+
+    std::string name;
+    octave_value varval;
+    bool is_automatic;
+    bool is_complex;
+    bool is_formal;
+    bool is_global;
+    bool is_persistent;
+  };
+
+public:
+  symbol_info_list (void) : lst () { }
+
+  symbol_info_list (const symbol_info_list& sil) : lst (sil.lst) { }
+
+  symbol_info_list& operator = (const symbol_info_list& sil)
+  {
+    if (this != &sil)
+      lst = sil.lst;
+
+    return *this;
+  }
+
+  ~symbol_info_list (void) { }
+
+  void append (const symbol_table::symbol_record& sr)
+  {
+    lst.push_back (symbol_info (sr));
+  }
+
+  void append (const symbol_table::symbol_record& sr,
+               const std::string& expr_str,
+               const octave_value& expr_val)
+  {
+    lst.push_back (symbol_info (sr, expr_str, expr_val));
+  }
+
+  size_t size (void) const { return lst.size (); }
+
+  bool empty (void) const { return lst.empty (); }
+
+  octave_map
+  map_value (const std::string& caller_function_name, int nesting_level) const
+  {
+    size_t len = lst.size ();
+
+    Cell name_info (len, 1);
+    Cell size_info (len, 1);
+    Cell bytes_info (len, 1);
+    Cell class_info (len, 1);
+    Cell global_info (len, 1);
+    Cell sparse_info (len, 1);
+    Cell complex_info (len, 1);
+    Cell nesting_info (len, 1);
+    Cell persistent_info (len, 1);
+
+    std::list<symbol_info>::const_iterator p = lst.begin ();
+
+    for (size_t j = 0; j < len; j++)
+      {
+        const symbol_info& si = *p++;
+
+        octave_scalar_map ni;
+
+        ni.assign ("function", caller_function_name);
+        ni.assign ("level", nesting_level);
+
+        name_info(j) = si.name;
+        global_info(j) = si.is_global;
+        persistent_info(j) = si.is_persistent;
+
+        octave_value val = si.varval;
+
+        size_info(j) = val.size ();
+        bytes_info(j) = val.byte_size ();
+        class_info(j) = val.class_name ();
+        sparse_info(j) = val.is_sparse_type ();
+        complex_info(j) = val.is_complex_type ();
+        nesting_info(j) = ni;
+      }
+
+    octave_map info;
+
+    info.assign ("name", name_info);
+    info.assign ("size", size_info);
+    info.assign ("bytes", bytes_info);
+    info.assign ("class", class_info);
+    info.assign ("global", global_info);
+    info.assign ("sparse", sparse_info);
+    info.assign ("complex", complex_info);
+    info.assign ("nesting", nesting_info);
+    info.assign ("persistent", persistent_info);
+
+    return info;
+  }
+
+  void display (std::ostream& os)
+  {
+    if (! lst.empty ())
+      {
+        size_t bytes = 0;
+        size_t elements = 0;
+
+        std::list<whos_parameter> params = parse_whos_line_format ();
+
+        print_descriptor (os, params);
+
+        octave_stdout << "\n";
+
+        for (std::list<symbol_info>::const_iterator p = lst.begin ();
+             p != lst.end (); p++)
+          {
+            p->display_line (os, params);
+
+            octave_value val = p->varval;
+
+            elements += val.capacity ();
+            bytes += val.byte_size ();
+          }
+
+        os << "\nTotal is " << elements
+           << (elements == 1 ? " element" : " elements")
+           << " using " << bytes << (bytes == 1 ? " byte" : " bytes")
+           << "\n";
+      }
+  }
+
+  // Parse the string whos_line_format, and return a parameter list,
+  // containing all information needed to print the given
+  // attributtes of the symbols.
+  std::list<whos_parameter> parse_whos_line_format (void)
+  {
+    int idx;
+    size_t format_len = Vwhos_line_format.length ();
+    char garbage;
+    std::list<whos_parameter> params;
+
+    size_t bytes1;
+    int elements1;
+
+    std::string param_string = "abcenst";
+    Array<int> param_length (dim_vector (param_string.length (), 1));
+    Array<std::string> param_names (dim_vector (param_string.length (), 1));
+    size_t pos_a, pos_b, pos_c, pos_e, pos_n, pos_s, pos_t;
+
+    pos_a = param_string.find ('a'); // Attributes
+    pos_b = param_string.find ('b'); // Bytes
+    pos_c = param_string.find ('c'); // Class
+    pos_e = param_string.find ('e'); // Elements
+    pos_n = param_string.find ('n'); // Name
+    pos_s = param_string.find ('s'); // Size
+    pos_t = param_string.find ('t'); // Type
+
+    param_names(pos_a) = "Attr";
+    param_names(pos_b) = "Bytes";
+    param_names(pos_c) = "Class";
+    param_names(pos_e) = "Elements";
+    param_names(pos_n) = "Name";
+    param_names(pos_s) = "Size";
+    param_names(pos_t) = "Type";
+
+    for (size_t i = 0; i < param_string.length (); i++)
+      param_length(i) = param_names(i).length ();
+
+    // The attribute column needs size 5.
+    param_length(pos_a) = 5;
+
+    // Calculating necessary spacing for name column,
+    // bytes column, elements column and class column
+
+    for (std::list<symbol_info>::const_iterator p = lst.begin ();
+         p != lst.end (); p++)
+      {
+        std::stringstream ss1, ss2;
+        std::string str;
+
+        str = p->name;
+        param_length(pos_n) = ((str.length ()
+                                > static_cast<size_t> (param_length(pos_n)))
+                               ? str.length () : param_length(pos_n));
+
+        octave_value val = p->varval;
+
+        str = val.type_name ();
+        param_length(pos_t) = ((str.length ()
+                                > static_cast<size_t> (param_length(pos_t)))
+                               ? str.length () : param_length(pos_t));
+
+        elements1 = val.capacity ();
+        ss1 << elements1;
+        str = ss1.str ();
+        param_length(pos_e) = ((str.length ()
+                                > static_cast<size_t> (param_length(pos_e)))
+                               ? str.length () : param_length(pos_e));
+
+        bytes1 = val.byte_size ();
+        ss2 << bytes1;
+        str = ss2.str ();
+        param_length(pos_b) = ((str.length ()
+                                > static_cast<size_t> (param_length(pos_b)))
+                               ? str.length () : param_length (pos_b));
+      }
+
+    idx = 0;
+    while (static_cast<size_t> (idx) < format_len)
+      {
+        whos_parameter param;
+        param.command = '\0';
+
+        if (Vwhos_line_format[idx] == '%')
+          {
+            bool error_encountered = false;
+            param.modifier = 'r';
+            param.parameter_length = 0;
+
+            int a = 0, b = -1, balance = 1;
+            unsigned int items;
+            size_t pos;
+            std::string cmd;
+
+            // Parse one command from whos_line_format
+            cmd = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
+            pos = cmd.find (';');
+            if (pos != std::string::npos)
+              cmd = cmd.substr (0, pos+1);
+            else
+              error ("parameter without ; in whos_line_format");
+
+            idx += cmd.length ();
+
+            // FIXME -- use iostream functions instead of sscanf!
+
+            if (cmd.find_first_of ("crl") != 1)
+              items = sscanf (cmd.c_str (), "%c%c:%d:%d:%d;",
+                              &garbage, &param.command, &a, &b, &balance);
+            else
+              items = sscanf (cmd.c_str (), "%c%c%c:%d:%d:%d;",
+                              &garbage, &param.modifier, &param.command,
+                              &a, &b, &balance) - 1;
+
+            if (items < 2)
+              {
+                error ("whos_line_format: parameter structure without command in whos_line_format");
+                error_encountered = true;
+              }
+
+            // Insert data into parameter
+            param.first_parameter_length = 0;
+            pos = param_string.find (param.command);
+            if (pos != std::string::npos)
+              {
+                param.parameter_length = param_length(pos);
+                param.text = param_names(pos);
+                param.line.assign (param_names(pos).length (), '=');
+
+                param.parameter_length = (a > param.parameter_length
+                                          ? a : param.parameter_length);
+                if (param.command == 's' && param.modifier == 'c' && b > 0)
+                  param.first_parameter_length = b;
+              }
+            else
+              {
+                error ("whos_line_format: '%c' is not a command",
+                       param.command);
+                error_encountered = true;
+              }
+
+            if (param.command == 's')
+              {
+                // Have to calculate space needed for printing
+                // matrix dimensions Space needed for Size column is
+                // hard to determine in prior, because it depends on
+                // dimensions to be shown. That is why it is
+                // recalculated for each Size-command int first,
+                // rest = 0, total;
+                int rest = 0;
+                int first = param.first_parameter_length;
+                int total = param.parameter_length;
+
+                for (std::list<symbol_info>::const_iterator p = lst.begin ();
+                     p != lst.end (); p++)
+                  {
+                    octave_value val = p->varval;
+                    std::string dims_str = get_dims_str (val);
+                    int first1 = dims_str.find ('x');
+                    int total1 = dims_str.length ();
+                    int rest1 = total1 - first1;
+                    rest = (rest1 > rest ? rest1 : rest);
+                    first = (first1 > first ? first1 : first);
+                    total = (total1 > total ? total1 : total);
+                  }
+
+                if (param.modifier == 'c')
+                  {
+                    if (first < balance)
+                      first += balance - first;
+                    if (rest + balance < param.parameter_length)
+                      rest += param.parameter_length - rest - balance;
+
+                    param.parameter_length = first + rest;
+                    param.first_parameter_length = first;
+                    param.balance = balance;
+                  }
+                else
+                  {
+                    param.parameter_length = total;
+                    param.first_parameter_length = 0;
+                  }
+              }
+            else if (param.modifier == 'c')
+              {
+                error ("whos_line_format: modifier 'c' not available for command '%c'",
+                       param.command);
+                error_encountered = true;
+              }
+
+            // What happens if whos_line_format contains negative numbers
+            // at param_length positions?
+            param.balance = (b < 0 ? 0 : param.balance);
+            param.first_parameter_length = (b < 0 ? 0 :
+                                            param.first_parameter_length);
+            param.parameter_length = (a < 0
+                                      ? 0
+                                      : (param.parameter_length
+                                         < param_length(pos_s)
+                                         ? param_length(pos_s)
+                                         : param.parameter_length));
+
+            // Parameter will not be pushed into parameter list if ...
+            if (! error_encountered)
+              params.push_back (param);
+          }
+        else
+          {
+            // Text string, to be printed as it is ...
+            std::string text;
+            size_t pos;
+            text = Vwhos_line_format.substr (idx, Vwhos_line_format.length ());
+            pos = text.find ('%');
+            if (pos != std::string::npos)
+              text = text.substr (0, pos);
+
+            // Push parameter into list ...
+            idx += text.length ();
+            param.text=text;
+            param.line.assign (text.length (), ' ');
+            params.push_back (param);
+          }
+      }
+
+    return params;
+  }
+
+private:
+  std::list<symbol_info> lst;
+
+};
+
+static octave_value
+do_who (int argc, const string_vector& argv, bool return_list,
+        bool verbose = false, std::string msg = std::string ())
+{
+  octave_value retval;
+
+  std::string my_name = argv[0];
+
+  bool global_only = false;
+  bool have_regexp = false;
+
+  int i;
+  for (i = 1; i < argc; i++)
+    {
+      if (argv[i] == "-file")
+        {
+          // FIXME. This is an inefficient manner to implement this as the
+          // variables are loaded in to a temporary context and then treated.
+          // It would be better to refecat symbol_info_list to not store the
+          // symbol records and then use it in load-save.cc (do_load) to
+          // implement this option there so that the variables are never
+          // stored at all.
+          if (i == argc - 1)
+            error ("whos: -file argument must be followed by a file name");
+          else
+            {
+              std::string nm = argv[i + 1];
+
+              unwind_protect frame;
+
+              // Set up temporary scope.
+
+              symbol_table::scope_id tmp_scope = symbol_table::alloc_scope ();
+              frame.add_fcn (symbol_table::erase_scope, tmp_scope);
+
+              symbol_table::set_scope (tmp_scope);
+
+              octave_call_stack::push (tmp_scope, 0);
+              frame.add_fcn (octave_call_stack::pop);
+
+              frame.add_fcn (symbol_table::clear_variables);
+
+              feval ("load", octave_value (nm), 0);
+
+              if (! error_state)
+                {
+                  std::string newmsg = std::string ("Variables in the file ") +
+                    nm + ":\n\n";
+
+                  retval =  do_who (i, argv, return_list, verbose, newmsg);
+                }
+            }
+
+          return retval;
+        }
+      else if (argv[i] == "-regexp")
+        have_regexp = true;
+      else if (argv[i] == "global")
+        global_only = true;
+      else if (argv[i][0] == '-')
+        warning ("%s: unrecognized option '%s'", my_name.c_str (),
+                 argv[i].c_str ());
+      else
+        break;
+    }
+
+  int npats = argc - i;
+  string_vector pats;
+  if (npats > 0)
+    {
+      pats.resize (npats);
+      for (int j = 0; j < npats; j++)
+        pats[j] = argv[i+j];
+    }
+  else
+    {
+      pats.resize (++npats);
+      pats[0] = "*";
+    }
+
+  symbol_info_list symbol_stats;
+  std::list<std::string> symbol_names;
+
+  for (int j = 0; j < npats; j++)
+    {
+      std::string pat = pats[j];
+
+      if (have_regexp)
+        {
+          std::list<symbol_table::symbol_record> tmp = global_only
+            ? symbol_table::regexp_global_variables (pat)
+            : symbol_table::regexp_variables (pat);
+
+          for (std::list<symbol_table::symbol_record>::const_iterator p = tmp.begin ();
+               p != tmp.end (); p++)
+            {
+              if (p->is_variable ())
+                {
+                  if (verbose)
+                    symbol_stats.append (*p);
+                  else
+                    symbol_names.push_back (p->name ());
+                }
+            }
+        }
+      else
+        {
+          size_t pos = pat.find_first_of (".({");
+
+          if (pos != std::string::npos && pos > 0)
+            {
+              if (verbose)
+                {
+                  // NOTE: we can only display information for
+                  // expressions based on global values if the variable is
+                  // global in the current scope because we currently have
+                  // no way of looking up the base value in the global
+                  // scope and then evaluating the arguments in the
+                  // current scope.
+
+                  std::string base_name = pat.substr (0, pos);
+
+                  if (symbol_table::is_variable (base_name))
+                    {
+                      symbol_table::symbol_record sr
+                        = symbol_table::find_symbol (base_name);
+
+                      if (! global_only || sr.is_global ())
+                        {
+                          int parse_status;
+
+                          octave_value expr_val
+                            = eval_string (pat, true, parse_status);
+
+                          if (! error_state)
+                            symbol_stats.append (sr, pat, expr_val);
+                          else
+                            return retval;
+                        }
+                    }
+                }
+            }
+          else
+            {
+              std::list<symbol_table::symbol_record> tmp = global_only
+                ? symbol_table::glob_global_variables (pat)
+                : symbol_table::glob_variables (pat);
+
+              for (std::list<symbol_table::symbol_record>::const_iterator p = tmp.begin ();
+                   p != tmp.end (); p++)
+                {
+                  if (p->is_variable ())
+                    {
+                      if (verbose)
+                        symbol_stats.append (*p);
+                      else
+                        symbol_names.push_back (p->name ());
+                    }
+                }
+            }
+        }
+    }
+
+  if (return_list)
+    {
+      if (verbose)
+        {
+          std::string caller_function_name;
+          octave_function *caller = octave_call_stack::caller ();
+          if (caller)
+            caller_function_name = caller->name ();
+
+          retval = symbol_stats.map_value (caller_function_name, 1);
+        }
+      else
+        retval = Cell (string_vector (symbol_names));
+    }
+  else if (! (symbol_stats.empty () && symbol_names.empty ()))
+    {
+      if (msg.length () == 0)
+        if (global_only)
+          octave_stdout << "Global variables:\n\n";
+        else
+          octave_stdout << "Variables in the current scope:\n\n";
+      else
+        octave_stdout << msg;
+
+      if (verbose)
+        symbol_stats.display (octave_stdout);
+      else
+        {
+          string_vector names (symbol_names);
+
+          names.list_in_columns (octave_stdout);
+        }
+
+      octave_stdout << "\n";
+    }
+
+  return retval;
+}
+
+DEFUN (who, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn  {Command} {} who\n\
+@deftypefnx {Command} {} who pattern @dots{}\n\
+@deftypefnx {Command} {} who option pattern @dots{}\n\
+@deftypefnx {Command} {C =} who (\"pattern\", @dots{})\n\
+List currently defined variables matching the given patterns.  Valid\n\
+pattern syntax is the same as described for the @code{clear} command.\n\
+If no patterns are supplied, all variables are listed.\n\
+By default, only variables visible in the local scope are displayed.\n\
+\n\
+The following are valid options but may not be combined.\n\
+\n\
+@table @code\n\
+@item global\n\
+List variables in the global scope rather than the current scope.\n\
+\n\
+@item -regexp\n\
+The patterns are considered to be regular expressions when matching the\n\
+variables to display.  The same pattern syntax accepted by\n\
+the @code{regexp} function is used.\n\
+\n\
+@item -file\n\
+The next argument is treated as a filename.  All variables found within the\n\
+specified file are listed.  No patterns are accepted when reading variables\n\
+from a file.\n\
+@end table\n\
+\n\
+If called as a function, return a cell array of defined variable names\n\
+matching the given patterns.\n\
+@seealso{whos, isglobal, isvarname, exist, regexp}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (nargout < 2)
+    {
+      int argc = args.length () + 1;
+
+      string_vector argv = args.make_argv ("who");
+
+      if (! error_state)
+        retval = do_who (argc, argv, nargout == 1);
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (whos, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn  {Command} {} whos\n\
+@deftypefnx {Command} {} whos pattern @dots{}\n\
+@deftypefnx {Command} {} whos option pattern @dots{}\n\
+@deftypefnx {Command} {S =} whos (\"pattern\", @dots{})\n\
+Provide detailed information on currently defined variables matching the\n\
+given patterns.  Options and pattern syntax are the same as for the\n\
+@code{who} command.  Extended information about each variable is\n\
+summarized in a table with the following default entries.\n\
+\n\
+@table @asis\n\
+@item Attr\n\
+Attributes of the listed variable.  Possible attributes are:\n\
+\n\
+@table @asis\n\
+@item blank\n\
+Variable in local scope\n\
+\n\
+@item @code{a}\n\
+Automatic variable.  An automatic variable is one created by the\n\
+interpreter, for example @code{argn}.\n\
+\n\
+@item @code{c}\n\
+Variable of complex type.\n\
+\n\
+@item @code{f}\n\
+Formal parameter (function argument).\n\
+\n\
+@item @code{g}\n\
+Variable with global scope.\n\
+\n\
+@item @code{p}\n\
+Persistent variable.\n\
+@end table\n\
+\n\
+@item Name\n\
+The name of the variable.\n\
+\n\
+@item Size\n\
+The logical size of the variable.  A scalar is 1x1, a vector is\n\
+@nospell{1xN} or @nospell{Nx1}, a 2-D matrix is @nospell{MxN}.\n\
+\n\
+@item Bytes\n\
+The amount of memory currently used to store the variable.\n\
+\n\
+@item Class\n\
+The class of the variable.  Examples include double, single, char, uint16,\n\
+cell, and struct.\n\
+@end table\n\
+\n\
+The table can be customized to display more or less information through\n\
+the function @code{whos_line_format}.\n\
+\n\
+If @code{whos} is called as a function, return a struct array of defined\n\
+variable names matching the given patterns.  Fields in the structure\n\
+describing each variable are: name, size, bytes, class, global, sparse,\n\
+complex, nesting, persistent.\n\
+@seealso{who, whos_line_format}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (nargout < 2)
+    {
+      int argc = args.length () + 1;
+
+      string_vector argv = args.make_argv ("whos");
+
+      if (! error_state)
+        retval = do_who (argc, argv, nargout == 1, true);
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+// Defining variables.
+
+void
+bind_ans (const octave_value& val, bool print)
+{
+  static std::string ans = "ans";
+
+  if (val.is_defined ())
+    {
+      if (val.is_cs_list ())
+        {
+          octave_value_list lst = val.list_value ();
+
+          for (octave_idx_type i = 0; i < lst.length (); i++)
+            bind_ans (lst(i), print);
+        }
+      else
+        {
+          symbol_table::force_assign (ans, val);
+
+          if (print)
+            val.print_with_name (octave_stdout, ans);
+        }
+    }
+}
+
+void
+bind_internal_variable (const std::string& fname, const octave_value& val)
+{
+  octave_value_list args;
+
+  args(0) = val;
+
+  feval (fname, args, 0);
+}
+
+void
+mlock (void)
+{
+  octave_function *fcn = octave_call_stack::current ();
+
+  if (fcn)
+    fcn->lock ();
+  else
+    error ("mlock: invalid use outside a function");
+}
+
+void
+munlock (const std::string& nm)
+{
+  octave_value val = symbol_table::find_function (nm);
+
+  if (val.is_defined ())
+    {
+      octave_function *fcn = val.function_value ();
+
+      if (fcn)
+        fcn->unlock ();
+    }
+}
+
+bool
+mislocked (const std::string& nm)
+{
+  bool retval = false;
+
+  octave_value val = symbol_table::find_function (nm);
+
+  if (val.is_defined ())
+    {
+      octave_function *fcn = val.function_value ();
+
+      if (fcn)
+        retval = fcn->islocked ();
+    }
+
+  return retval;
+}
+
+DEFUN (mlock, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} mlock ()\n\
+Lock the current function into memory so that it can't be cleared.\n\
+@seealso{munlock, mislocked, persistent}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  if (args.length () == 0)
+    {
+      octave_function *fcn = octave_call_stack::caller ();
+
+      if (fcn)
+        fcn->lock ();
+      else
+        error ("mlock: invalid use outside a function");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (munlock, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {} munlock ()\n\
+@deftypefnx {Built-in Function} {} munlock (@var{fcn})\n\
+Unlock the named function @var{fcn}.  If no function is named\n\
+then unlock the current function.\n\
+@seealso{mlock, mislocked, persistent}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        munlock (name);
+      else
+        error ("munlock: FCN must be a string");
+    }
+  else if (args.length () == 0)
+    {
+      octave_function *fcn = octave_call_stack::caller ();
+
+      if (fcn)
+        fcn->unlock ();
+      else
+        error ("munlock: invalid use outside a function");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+
+DEFUN (mislocked, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {} mislocked ()\n\
+@deftypefnx {Built-in Function} {} mislocked (@var{fcn})\n\
+Return true if the named function @var{fcn} is locked.  If no function is\n\
+named then return true if the current function is locked.\n\
+@seealso{mlock, munlock, persistent}\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        retval = mislocked (name);
+      else
+        error ("mislocked: FCN must be a string");
+    }
+  else if (args.length () == 0)
+    {
+      octave_function *fcn = octave_call_stack::caller ();
+
+      if (fcn)
+        retval = fcn->islocked ();
+      else
+        error ("mislocked: invalid use outside a function");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+// Deleting names from the symbol tables.
+
+static inline bool
+name_matches_any_pattern (const std::string& nm, const string_vector& argv,
+                          int argc, int idx, bool have_regexp = false)
+{
+  bool retval = false;
+
+  for (int k = idx; k < argc; k++)
+    {
+      std::string patstr = argv[k];
+      if (! patstr.empty ())
+        {
+          if (have_regexp)
+            {
+              if (is_regexp_match (patstr, nm))
+                {
+                  retval = true;
+                  break;
+                }
+            }
+          else
+            {
+              glob_match pattern (patstr);
+
+              if (pattern.match (nm))
+                {
+                  retval = true;
+                  break;
+                }
+            }
+        }
+    }
+
+  return retval;
+}
+
+static inline void
+maybe_warn_exclusive (bool exclusive)
+{
+  if (exclusive)
+    warning ("clear: ignoring --exclusive option");
+}
+
+static void
+do_clear_functions (const string_vector& argv, int argc, int idx,
+                    bool exclusive = false)
+{
+  if (idx == argc)
+    symbol_table::clear_functions ();
+  else
+    {
+      if (exclusive)
+        {
+          string_vector fcns = symbol_table::user_function_names ();
+
+          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))
+                symbol_table::clear_function (nm);
+            }
+        }
+      else
+        {
+          while (idx < argc)
+            symbol_table::clear_function_pattern (argv[idx++]);
+        }
+    }
+}
+
+static void
+do_clear_globals (const string_vector& argv, int argc, int idx,
+                  bool exclusive = false)
+{
+  if (idx == argc)
+    {
+      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::global_variable_names ();
+
+          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))
+                symbol_table::clear_global (nm);
+            }
+        }
+      else
+        {
+          while (idx < argc)
+            symbol_table::clear_global_pattern (argv[idx++]);
+        }
+    }
+}
+
+static void
+do_clear_variables (const string_vector& argv, int argc, int idx,
+                    bool exclusive = false, bool have_regexp = false)
+{
+  if (idx == argc)
+    symbol_table::clear_variables ();
+  else
+    {
+      if (exclusive)
+        {
+          string_vector lvars = symbol_table::variable_names ();
+
+          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, have_regexp))
+                symbol_table::clear_variable (nm);
+            }
+        }
+      else
+        {
+          if (have_regexp)
+            while (idx < argc)
+              symbol_table::clear_variable_regexp (argv[idx++]);
+          else
+            while (idx < argc)
+              symbol_table::clear_variable_pattern (argv[idx++]);
+        }
+    }
+}
+
+static void
+do_clear_symbols (const string_vector& argv, int argc, int idx,
+                  bool exclusive = false)
+{
+  if (idx == argc)
+    symbol_table::clear_variables ();
+  else
+    {
+      if (exclusive)
+        {
+          // FIXME -- 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)
+            symbol_table::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"
+          && ! symbol_table::is_local_variable ("all"))
+        {
+          symbol_table::clear_all ();
+        }
+      else if (argv[idx] == "functions"
+               && ! symbol_table::is_local_variable ("functions"))
+        {
+          do_clear_functions (argv, argc, ++idx);
+        }
+      else if (argv[idx] == "global"
+               && ! symbol_table::is_local_variable ("global"))
+        {
+          do_clear_globals (argv, argc, ++idx);
+        }
+      else if (argv[idx] == "variables"
+               && ! symbol_table::is_local_variable ("variables"))
+        {
+          symbol_table::clear_variables ();
+        }
+      else if (argv[idx] == "classes"
+               && ! symbol_table::is_local_variable ("classes"))
+        {
+          symbol_table::clear_objects ();
+          octave_class::clear_exemplar_map ();
+        }
+      else
+        {
+          symbol_table::clear_symbol_pattern (argv[idx]);
+        }
+    }
+}
+
+#define CLEAR_OPTION_ERROR(cond) \
+  do \
+    { \
+      if (cond) \
+        { \
+          print_usage (); \
+          return retval; \
+        } \
+    } \
+  while (0)
+
+DEFUN (clear, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Command} {} clear [options] pattern @dots{}\n\
+Delete the names matching the given patterns from the symbol table.  The\n\
+pattern may contain the following special characters:\n\
+\n\
+@table @code\n\
+@item ?\n\
+Match any single character.\n\
+\n\
+@item *\n\
+Match zero or more characters.\n\
+\n\
+@item [ @var{list} ]\n\
+Match the list of characters specified by @var{list}.  If the first\n\
+character is @code{!} or @code{^}, match all characters except those\n\
+specified by @var{list}.  For example, the pattern @samp{[a-zA-Z]} will\n\
+match all lowercase and uppercase alphabetic characters.\n\
+@end table\n\
+\n\
+For example, the command\n\
+\n\
+@example\n\
+clear foo b*r\n\
+@end example\n\
+\n\
+@noindent\n\
+clears the name @code{foo} and all names that begin with the letter\n\
+@code{b} and end with the letter @code{r}.\n\
+\n\
+If @code{clear} is called without any arguments, all user-defined\n\
+variables (local and global) are cleared from the symbol table.  If\n\
+@code{clear} is called with at least one argument, only the visible\n\
+names matching the arguments are cleared.  For example, suppose you have\n\
+defined a function @code{foo}, and then hidden it by performing the\n\
+assignment @code{foo = 2}.  Executing the command @kbd{clear foo} once\n\
+will clear the variable definition and restore the definition of\n\
+@code{foo} as a function.  Executing @kbd{clear foo} a second time will\n\
+clear the function definition.\n\
+\n\
+The following options are available in both long and short form\n\
+\n\
+@table @code\n\
+@item -all, -a\n\
+Clears all local and global user-defined variables and all functions\n\
+from the symbol table.\n\
+\n\
+@item -exclusive, -x\n\
+Clears the variables that don't match the following pattern.\n\
+\n\
+@item -functions, -f\n\
+Clears the function names and the built-in symbols names.\n\
+\n\
+@item -global, -g\n\
+Clears the global symbol names.\n\
+\n\
+@item -variables, -v\n\
+Clears the local variable names.\n\
+\n\
+@item -classes, -c\n\
+Clears the class structure table and clears all objects.\n\
+\n\
+@item -regexp, -r\n\
+The arguments are treated as regular expressions as any variables that\n\
+match will be cleared.\n\
+@end table\n\
+\n\
+With the exception of @code{exclusive}, all long options can be used\n\
+without the dash as well.\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  int argc = args.length () + 1;
+
+  string_vector argv = args.make_argv ("clear");
+
+  if (! error_state)
+    {
+      if (argc == 1)
+        {
+          do_clear_globals (argv, argc, true);
+          do_clear_variables (argv, argc, true);
+
+          octave_link::clear_workspace ();
+        }
+      else
+        {
+          int idx = 0;
+
+          bool clear_all = false;
+          bool clear_functions = false;
+          bool clear_globals = false;
+          bool clear_variables = false;
+          bool clear_objects = false;
+          bool exclusive = false;
+          bool have_regexp = false;
+          bool have_dash_option = false;
+
+          while (++idx < argc)
+            {
+              if (argv[idx] == "-all" || argv[idx] == "-a")
+                {
+                  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
+
+                  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);
+
+                  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);
+
+                  have_dash_option = true;
+                  clear_variables = true;
+                }
+              else if (argv[idx] == "-classes" || argv[idx] == "-c")
+                {
+                  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
+
+                  have_dash_option = true;
+                  clear_objects = true;
+                }
+              else if (argv[idx] == "-regexp" || argv[idx] == "-r")
+                {
+                  CLEAR_OPTION_ERROR (have_dash_option && ! exclusive);
+
+                  have_dash_option = true;
+                  have_regexp = true;
+                }
+              else
+                break;
+            }
+
+          if (idx <= argc)
+            {
+              if (! have_dash_option)
+                {
+                  do_matlab_compatible_clear (argv, argc, idx);
+                }
+              else
+                {
+                  if (clear_all)
+                    {
+                      maybe_warn_exclusive (exclusive);
+
+                      if (++idx < argc)
+                        warning
+                          ("clear: ignoring extra arguments after -all");
+
+                      symbol_table::clear_all ();
+                    }
+                  else if (have_regexp)
+                    {
+                      do_clear_variables (argv, argc, idx, exclusive, true);
+                    }
+                  else if (clear_functions)
+                    {
+                      do_clear_functions (argv, argc, idx, exclusive);
+                    }
+                  else if (clear_globals)
+                    {
+                      do_clear_globals (argv, argc, idx, exclusive);
+                    }
+                  else if (clear_variables)
+                    {
+                      do_clear_variables (argv, argc, idx, exclusive);
+                    }
+                  else if (clear_objects)
+                    {
+                      symbol_table::clear_objects ();
+                      octave_class::clear_exemplar_map ();
+                    }
+                  else
+                    {
+                      do_clear_symbols (argv, argc, idx, exclusive);
+                    }
+                }
+
+              octave_link::set_workspace ();
+            }
+        }
+    }
+
+  return retval;
+}
+
+DEFUN (whos_line_format, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} whos_line_format ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} whos_line_format (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} whos_line_format (@var{new_val}, \"local\")\n\
+Query or set the format string used by the command @code{whos}.\n\
+\n\
+A full format string is:\n\
+@c Set example in small font to prevent overfull line\n\
+\n\
+@smallexample\n\
+%[modifier]<command>[:width[:left-min[:balance]]];\n\
+@end smallexample\n\
+\n\
+The following command sequences are available:\n\
+\n\
+@table @code\n\
+@item %a\n\
+Prints attributes of variables (g=global, p=persistent,\n\
+f=formal parameter, a=automatic variable).\n\
+\n\
+@item %b\n\
+Prints number of bytes occupied by variables.\n\
+\n\
+@item %c\n\
+Prints class names of variables.\n\
+\n\
+@item %e\n\
+Prints elements held by variables.\n\
+\n\
+@item %n\n\
+Prints variable names.\n\
+\n\
+@item %s\n\
+Prints dimensions of variables.\n\
+\n\
+@item %t\n\
+Prints type names of variables.\n\
+@end table\n\
+\n\
+Every command may also have an alignment modifier:\n\
+\n\
+@table @code\n\
+@item l\n\
+Left alignment.\n\
+\n\
+@item r\n\
+Right alignment (default).\n\
+\n\
+@item c\n\
+Column-aligned (only applicable to command %s).\n\
+@end table\n\
+\n\
+The @code{width} parameter is a positive integer specifying the minimum\n\
+number of columns used for printing.  No maximum is needed as the field will\n\
+auto-expand as required.\n\
+\n\
+The parameters @code{left-min} and @code{balance} are only available when the\n\
+column-aligned modifier is used with the command @samp{%s}.\n\
+@code{balance} specifies the column number within the field width which will\n\
+be aligned between entries.  Numbering starts from 0 which indicates the\n\
+leftmost column.  @code{left-min} specifies the minimum field width to the\n\
+left of the specified balance column.\n\
+\n\
+The default format is\n\
+@code{\"  %a:4; %ln:6; %cs:16:6:1;  %rb:12;  %lc:-1;\\n\"}.\n\
+\n\
+When called from inside a function with the \"local\" option, the variable is\n\
+changed locally for the function and any subroutines it calls.  The original\n\
+variable value is restored when exiting the function.\n\
+@seealso{whos}\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (whos_line_format);
+}
+
+static std::string Vmissing_function_hook = "__unimplemented__";
+
+DEFUN (missing_function_hook, args, nargout,
+    "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} missing_function_hook ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} missing_function_hook (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} missing_function_hook (@var{new_val}, \"local\")\n\
+Query or set the internal variable that specifies the function to call when\n\
+an unknown identifier is requested.\n\
+\n\
+When called from inside a function with the \"local\" option, the variable is\n\
+changed locally for the function and any subroutines it calls.  The original\n\
+variable value is restored when exiting the function.\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (missing_function_hook);
+}
+
+void maybe_missing_function_hook (const std::string& name)
+{
+  // Don't do this if we're handling errors.
+  if (buffer_error_messages == 0 && ! Vmissing_function_hook.empty ())
+    {
+      octave_value val = symbol_table::find_function (Vmissing_function_hook);
+
+      if (val.is_defined ())
+        {
+          // Ensure auto-restoration.
+          unwind_protect frame;
+          frame.protect_var (Vmissing_function_hook);
+
+          // Clear the variable prior to calling the function.
+          const std::string func_name = Vmissing_function_hook;
+          Vmissing_function_hook.clear ();
+
+          // Call.
+          feval (func_name, octave_value (name));
+        }
+    }
+}
+
+DEFUN (__varval__, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __varval__ (@var{name})\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        retval = symbol_table::varval (args(0).string_value ());
+      else
+        error ("__varval__: expecting argument to be variable name");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}