changeset 18943:dff05c124017

maint: periodic merge of gui-release to stable.
author Rik <rik@octave.org>
date Thu, 15 May 2014 08:37:38 -0700
parents fc43c8017e9b (diff) be569698970c (current diff)
children c0270756d609
files libgui/graphics/ContextMenu.cc libgui/src/history-dock-widget.cc libgui/src/main-window.cc libgui/src/settings-dialog.cc libgui/src/shortcut-manager.cc libinterp/octave-value/ov-usr-fcn.cc
diffstat 434 files changed, 17269 insertions(+), 6724 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am
+++ b/Makefile.am
@@ -129,6 +129,11 @@
 check: all
 	$(MAKE) -C test check
 
+if AMCOND_HAVE_LLVM
+check-jit: all
+	$(MAKE) -C test check-jit
+endif
+
 run-octave: run-octave.in Makefile
 	@$(do_subst_script_vals)
 	chmod a+rx "$@"
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,80 @@
+Summary of important user-visible changes for version 4.2:
+---------------------------------------------------------
+
+ ** Interpolation function changes for Matlab compatibility
+
+    The interpolation method 'cubic' is now equivalent to 'pchip'
+    for interp1, interp2, and interp3.  Previously, 'cubic' was equivalent
+    to 'spline' for interp2.  This may produce different results as 'spline'
+    has continuous 1st and 2nd derivatives while 'pchip' only has a continuous
+    1st derivative.
+
+ ** Integer formats used in the printf family of functions now work for
+    64-bit integers and are more compatible with Matlab when printing
+    non-integer values.  Now instead of truncating, Octave will switch
+    the effective format to '%g' in the following circumstances:
+
+      * the value of an integer type (int8, uint32, etc.) value exceeds
+        the maximum for the format specifier.  For '%d', the limit is
+        intmax ('int64') and for '%u' it is intmax ('uint64').
+
+      * round(x) != x or the value is outside the range allowed by the
+        integer format specifier.
+
+    There is still one difference:  Matlab switches to '%e' and Octave
+    is currently switching to '%g'.
+
+ ** linkprop has been completely re-coded for performance and Matlab
+    compatibility.  It now returns a linkprop object which must be stored
+    in a variable for as long as the graphic objects should remain linked.
+    To unlink properties use 'clear hlink' where hlink is the variable
+    containing the linkprop object.
+
+ ** Other new functions added in 4.2:
+
+      dir_in_loadpath    numfields
+      hgload
+      hgsave
+      javachk
+      linkaxes 
+
+ ** Deprecated functions.
+
+    The following functions have been deprecated in Octave 4.2 and will
+    be removed from Octave 4.6 (or whatever version is the second major
+    release after 4.2):
+
+      bicubic
+      find_dir_in_path
+      nfields
+
+    The following functions were deprecated in Octave 3.8 and have been
+    removed from Octave 4.2.
+
+      default_save_options    java_new            
+      gen_doc_cache           java_set                   
+      interp1q                java_unsigned_conversion
+      isequalwithequalnans    javafields                
+      java_convert_matrix     javamethods               
+      java_debug              re_read_readline_init_file
+      java_get                read_readline_init_file   
+      java_invoke             saving_history            
+
+    The following keywords were deprecated in Octave 3.8 and have been
+    removed from Octave 4.2
+
+      static
+
+    The following configuration variables were deprecated in Octave 3.8
+    and have been removed from Octave 4.2
+
+      CC_VERSION  (now GCC_VERSION)
+      CXX_VERSION (now GXX_VERSION)
+
+    The internal class <Octave_map> was deprecated in Octave 3.8 and has
+    been removed from Octave 4.2.  Replacement classes are
+    <octave_map> (struct array) or <octave_scalar_map> for a single structure.
+
 Summary of important user-visible changes for version 4.0:
 ---------------------------------------------------------
 
@@ -27,7 +104,7 @@
 
  ** Other new functions added in 4.0.0:
 
-    validateattributes
+      validateattributes
 
  ** Deprecated functions.
 
--- a/build-aux/common.mk
+++ b/build-aux/common.mk
@@ -107,8 +107,6 @@
 # C compiler flags.
 
 CC = @CC@
-## FIXME: CC_VERSION is deprecated and should be removed in version 3.12
-CC_VERSION = @CC_VERSION@
 GCC_VERSION = @GCC_VERSION@
 CPICFLAG = @CPICFLAG@
 XTRA_CFLAGS = @XTRA_CFLAGS@
@@ -131,8 +129,6 @@
 # C++ compiler flags.
 
 CXX = @CXX@
-## FIXME: CXX_VERSION is deprecated and should be removed in version 3.12
-CXX_VERSION = @CXX_VERSION@
 GXX_VERSION = @GXX_VERSION@
 CXXCPP = @CXXCPP@
 CXXPICFLAG = @CXXPICFLAG@
@@ -518,7 +514,6 @@
   -e "s|%OCTAVE_CONF_CANONICAL_HOST_TYPE%|\"${canonical_host_type}\"|" \
   -e "s|%OCTAVE_CONF_CARBON_LIBS%|\"${CARBON_LIBS}\"|" \
   -e "s|%OCTAVE_CONF_CC%|\"${CC}\"|" \
-  -e "s|%OCTAVE_CONF_CC_VERSION%|\"${CC_VERSION}\"|" \
   -e "s|%OCTAVE_CONF_CCOLAMD_CPPFLAGS%|\"${CCOLAMD_CPPFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_CCOLAMD_LDFLAGS%|\"${CCOLAMD_LDFLAGS}\"|" \
   -e "s|%OCTAVE_CONF_CCOLAMD_LIBS%|\"${CCOLAMD_LIBS}\"|" \
--- a/configure.ac
+++ b/configure.ac
@@ -19,13 +19,13 @@
 ### <http://www.gnu.org/licenses/>.
 
 AC_PREREQ([2.62])
-AC_INIT([GNU Octave], [3.9.0+], [http://octave.org/bugs.html], [octave])
+AC_INIT([GNU Octave], [4.1.0+], [http://octave.org/bugs.html], [octave])
 
 dnl Note that the version number is duplicated here and in AC_INIT
 dnl because AC_INIT requires it to be static, not computed from
 dnl shell variables.
-OCTAVE_MAJOR_VERSION=3
-OCTAVE_MINOR_VERSION=9
+OCTAVE_MAJOR_VERSION=4
+OCTAVE_MINOR_VERSION=1
 OCTAVE_PATCH_VERSION=0+
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION arg
@@ -329,10 +329,6 @@
 fi
 AC_SUBST(GXX_VERSION)
 
-## FIXME: CXX_VERSION is deprecated and should be removed in Octave version 3.12
-CXX_VERSION=$gxx_version
-AC_SUBST(CXX_VERSION)
-
 ### Determine which C compiler to use (we expect to find gcc).
 
 AC_PROG_CC
@@ -379,10 +375,6 @@
 fi
 AC_SUBST(GCC_VERSION)
 
-## FIXME: CC_VERSION is deprecated and should be removed in Octave version 3.12
-CC_VERSION=$GCC_VERSION
-AC_SUBST(CC_VERSION)
-
 ### Also check g++ version number, it might be different from the
 ## gcc version number.
 
@@ -895,6 +887,7 @@
 AC_SUBST(LLVM_CXXFLAGS)
 AC_SUBST(LLVM_LDFLAGS)
 AC_SUBST(LLVM_LIBS)
+AM_CONDITIONAL([AMCOND_HAVE_LLVM], [test -z "$warn_llvm"])
 
 ### Check for HDF5 library.
 
@@ -2186,7 +2179,7 @@
 AC_CHECK_FUNCS([log1p log1pf pipe])
 AC_CHECK_FUNCS([realpath resolvepath roundl])
 AC_CHECK_FUNCS([select setgrent setpwent siglongjmp strsignal])
-AC_CHECK_FUNCS([tcgetattr tcsetattr tempnam tgammaf toascii])
+AC_CHECK_FUNCS([tcgetattr tcsetattr tgammaf toascii])
 AC_CHECK_FUNCS([umask waitpid])
 AC_CHECK_FUNCS([_kbhit])
 
@@ -2845,7 +2838,8 @@
 fi
 
 AM_CONDITIONAL([AMCOND_BUILD_GUI], [test $build_gui = yes])
-AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA], [test "$octave_cv_lib_qscintilla" = yes])
+AM_CONDITIONAL([AMCOND_HAVE_QSCINTILLA],
+               [test "$octave_cv_lib_qscintilla" = yes])
 AM_CONDITIONAL([WIN32_TERMINAL], [test $win32_terminal = yes])
 AC_SUBST(QT_CPPFLAGS)
 AC_SUBST(QT_LDFLAGS)
--- a/doc/interpreter/container.txi
+++ b/doc/interpreter/container.txi
@@ -507,7 +507,7 @@
 
 Other functions that can manipulate the fields of a structure are given below.
 
-@DOCSTRING(nfields)
+@DOCSTRING(numfields)
 
 @DOCSTRING(fieldnames)
 
--- a/doc/interpreter/contributors.in
+++ b/doc/interpreter/contributors.in
@@ -15,6 +15,7 @@
 Heinz Bauschke
 Julien Bect
 Roman Belov
+Markus Bergholz
 Karl Berry
 David Billinghurst
 Don Bindner
@@ -69,6 +70,7 @@
 Peter Ekberg
 Rolf Fabian
 Gunnar Farnebäck
+Massimiliano Fasi
 Stephen Fegan
 Ramon Garcia Fernandez
 Torsten Finke
@@ -80,6 +82,7 @@
 Walter Gautschi
 Klaus Gebhardt
 Driss Ghaddab
+Eugenio Gianniti 
 Nicolo Giorgetti
 Arun Giridhar
 Michael D. Godfrey
@@ -88,6 +91,7 @@
 Tomislav Goles
 Keith Goodman
 Brian Gough
+Michael C. Grant
 Steffen Groot
 Etienne Grossmann
 David Grundberg
@@ -119,6 +123,7 @@
 John Hunt
 Teemu Ikonen
 Alan W. Irwin
+Allan Jacobs
 Geoff Jacobsen
 Mats Jansson
 Cai Jianming
@@ -188,6 +193,7 @@
 Júlio Hoffimann Mendes
 Ed Meyer
 Thorsten Meyer
+Stefan Miereis
 Petr Mikulik
 Mike Miller
 Stefan Monnier
@@ -210,6 +216,7 @@
 Michael O'Brien
 Peter O'Gorman
 Thorsten Ohl
+Kai T. Ohlhus
 Arno Onken
 Valentin Ortega-Clavero
 Luis F. Ortiz
@@ -234,6 +241,7 @@
 Francesco Potortì
 Konstantinos Poulios
 Jarno Rajahalme
+Eduardo Ramos
 James B. Rawlings
 Eric S. Raymond
 Balint Reczey
@@ -266,6 +274,7 @@
 Julian Schnidder
 Nicol N. Schraudolph
 Sebastian Schubert
+Lasse Schuirmann
 Ludwig Schwardt
 Thomas L. Scofield
 Daniel J. Sebald
@@ -282,6 +291,7 @@
 Joerg Specht
 Quentin H. Spencer
 Christoph Spiel
+David Spies
 Richard Stallman
 Russell Standish
 Brett Stewart
@@ -325,6 +335,7 @@
 Martin Weiser
 Michael Weitzel
 David Wells
+Joachim Wiesemann
 Fook Fah Yap
 Sean Young
 Michael Zeising
--- a/doc/interpreter/errors.txi
+++ b/doc/interpreter/errors.txi
@@ -285,7 +285,7 @@
 @group
 function rand42
   old_state = rand ("state");
-  restore_state = onCleanup (@@() rand ("state", old_state);
+  restore_state = onCleanup (@@() rand ("state", old_state));
   rand ("state", 42);
   @dots{}
 endfunction  # rand generator state restored by onCleanup
--- a/doc/interpreter/func.txi
+++ b/doc/interpreter/func.txi
@@ -802,7 +802,7 @@
 
 @DOCSTRING(command_line_path)
 
-@DOCSTRING(find_dir_in_path)
+@DOCSTRING(dir_in_loadpath)
 
 @node Subfunctions
 @subsection Subfunctions
--- a/doc/interpreter/grammar.txi
+++ b/doc/interpreter/grammar.txi
@@ -49,9 +49,8 @@
 @item @code{function} @tab @code{global} @tab @code{if}
 @item @code{methods} @tab @code{otherwise} @tab @code{parfor}
 @item @code{persistent} @tab @code{properties} @tab @code{return}
-@item @code{static} @tab @code{switch} @tab @code{try}
-@item @code{until} @tab @code{unwind_protect} @tab @code{unwind_protect_cleanup}
-@item @code{while}
+@item @code{switch} @tab @code{try} @tab @code{until}
+@item @code{unwind_protect} @tab @code{unwind_protect_cleanup} @tab @code{while}
 @end multitable
 
 The function @code{iskeyword} can be used to quickly check whether an
--- a/doc/interpreter/install.txi
+++ b/doc/interpreter/install.txi
@@ -846,7 +846,7 @@
 
 @noindent
 in the kernel configuration files (typically found in the directory
-@file{/sys/i386/conf}.  After making this change, you'll need to rebuild
+@file{/sys/i386/conf}).  After making this change, you'll need to rebuild
 the kernel, install it, and reboot.
 
 @item
--- a/doc/interpreter/java.txi
+++ b/doc/interpreter/java.txi
@@ -95,9 +95,11 @@
 @cindex path, removing from classpath
 @DOCSTRING(javarmpath)
 
-The following four functions provide information and control over the interface
+The following functions provide information and control over the interface
 between Octave and the Java Virtual Machine.
 
+@DOCSTRING(javachk)
+
 @DOCSTRING(usejava)
 
 @cindex memory, displaying Java memory status
--- a/doc/interpreter/macros.texi
+++ b/doc/interpreter/macros.texi
@@ -28,14 +28,14 @@
 @c which is `XXX'.  This looks particularly bad when the macro body is 
 @c single or double-quoted text, such as a property value `"position"'
 @ifinfo
-@rmacro qcode{arg}
+@macro qcode{arg}
 \arg\
-@end rmacro
+@end macro
 @end ifinfo
 @ifnotinfo
-@rmacro qcode{arg}
+@macro qcode{arg}
 @code{\arg\}
-@end rmacro
+@end macro
 @end ifnotinfo
 
 @c The following macro is used for the on-line help system, but we don't
--- a/doc/interpreter/plot.txi
+++ b/doc/interpreter/plot.txi
@@ -937,6 +937,17 @@
 
 @DOCSTRING(orient)
 
+@code{print} and @code{saveas} are used when work on a plot has finished
+and the output must be in a publication-ready format.  During intermediate
+stages it is often better to save the graphics object and all of its
+associated information so that changes---to colors, axis limits, marker styles,
+etc.---can be made easily from within Octave.  The @code{hgsave}/@code{hgload}
+commands can be used to save and re-create a graphics object.
+
+@DOCSTRING(hgsave)
+
+@DOCSTRING(hgload)
+
 @node Interacting with Plots
 @subsection Interacting with Plots
 
@@ -1233,18 +1244,21 @@
 
 @noindent
 sets the range of the x-axis for the current axes object in the current
-figure to @samp{[-10, 10]}.  Additionally, calling set with a graphics
-object index as the only argument returns a structure containing the
-default values for all the properties for the given object type.  For
-example,
+figure to @samp{[-10, 10]}.
+
+Default property values can also be queried if the @code{set} function is
+called without a value argument.  When only one argument is given (a graphic
+handle) then a structure with defaults for all properties of the given object
+type is returned.  For example,
 
 @example
 set (gca ())
 @end example
 
 @noindent
-returns a structure containing the default property values for axes
-objects.
+returns a structure containing the default property values for axes objects.
+If @code{set} is called with two arguments (a graphic handle and a property
+name) then only the defaults for the requested property are returned.
 
 @DOCSTRING(get)
 
@@ -2868,6 +2882,8 @@
 
 @DOCSTRING(linkprop)
 
+@DOCSTRING(linkaxes)
+
 These capabilities are used in a number of basic graphics objects.
 The @code{hggroup} objects created by the functions of Octave contain
 one or more graphics object and are used to:
--- a/doc/interpreter/sparse.txi
+++ b/doc/interpreter/sparse.txi
@@ -793,8 +793,8 @@
 
 @item If the matrix is not square, or any of the previous solvers flags
 a singular or near singular matrix, find a minimum norm solution using
-@sc{cxsparse}@footnote{The @sc{cholmod}, @sc{umfpack} and @sc{cxsparse} packages were
-written by Tim Davis and are available at
+@sc{cxsparse}@footnote{The @sc{cholmod}, @sc{umfpack} and @sc{cxsparse}
+packages were written by Tim Davis and are available at
 @url{http://www.cise.ufl.edu/research/sparse/}}.
 @end enumerate
 
@@ -997,7 +997,7 @@
 as constant on each simplex (represented by the vector @code{conductivity}).
 Based on the finite element geometry, we first calculate a system (or
 stiffness) matrix for each simplex (represented as 3-by-3 elements on the
-diagonal of the element-wise system matrix @code{SE}.  Based on @code{SE} 
+diagonal of the element-wise system matrix @code{SE}).  Based on @code{SE} 
 and a N-by-DE connectivity matrix @code{C}, representing the connections 
 between simplices and vertices, the global connectivity matrix @code{S} is
 calculated.
--- a/doc/interpreter/var.txi
+++ b/doc/interpreter/var.txi
@@ -221,8 +221,7 @@
 @end example
 
 The behavior of persistent variables is equivalent to the behavior of
-static variables in C@.  The command @code{static} in Octave is also
-recognized and is equivalent to @code{persistent}.
+static variables in C@.
 
 Like global variables, a persistent variable may only be initialized once.
 For example, after executing the following code
--- a/doc/interpreter/vectorize.txi
+++ b/doc/interpreter/vectorize.txi
@@ -697,7 +697,7 @@
 for i = 1:length (A)
   ## this will be two columns, the first is the difference and
   ## the second the mean of the two elements used for the diff.
-  B(i,:) = [A(i+1)-A(i), (A(i+1) + A(i))/2)];
+  B(i,:) = [A(i+1)-A(i), (A(i+1) + A(i))/2];
 endfor
 @end group
 @end example
--- a/libgui/graphics/Backend.cc
+++ b/libgui/graphics/Backend.cc
@@ -53,16 +53,16 @@
   if (go.isa ("figure"))
     return std::string ("__plot_stream__");
   else if (go.isa ("uicontrol")
-	   || go.isa ("uipanel")
-	   || go.isa ("uimenu")
-	   || go.isa ("uicontextmenu")
-	   || go.isa ("uitoolbar")
-	   || go.isa ("uipushtool")
-	   || go.isa ("uitoggletool"))
+           || go.isa ("uipanel")
+           || go.isa ("uimenu")
+           || go.isa ("uicontextmenu")
+           || go.isa ("uitoolbar")
+           || go.isa ("uipushtool")
+           || go.isa ("uitoggletool"))
     return std::string ("__object__");
   else
     qCritical ("QtHandles::Backend: no __object__ property known for object "
-	       "of type %s", go.type ().c_str ());
+               "of type %s", go.type ().c_str ());
 
   return std::string ();
 }
@@ -73,7 +73,7 @@
   ObjectFactory* factory = ObjectFactory::instance ();
 
   connect (this, SIGNAL (createObject (double)),
-	   factory, SLOT (createObject (double)));
+           factory, SLOT (createObject (double)));
 }
 
 Backend::~Backend (void)
@@ -92,13 +92,13 @@
       || go.isa ("uitoggletool"))
     {
       Logger::debug ("Backend::initialize %s from thread %08x",
-		     go.type ().c_str (), QThread::currentThreadId ());
+                     go.type ().c_str (), QThread::currentThreadId ());
 
       ObjectProxy* proxy = new ObjectProxy ();
       graphics_object gObj (go);
 
       gObj.get_properties ().set(toolkitObjectProperty (go),
-				 OCTAVE_PTR_TYPE ((OCTAVE_INTPTR_TYPE) proxy));
+                                 OCTAVE_PTR_TYPE ((OCTAVE_INTPTR_TYPE) proxy));
 
       emit createObject (go.get_handle ().value ());
 
@@ -123,30 +123,30 @@
     return;
 
   Logger::debug ("Backend::update %s(%d) from thread %08x",
-		 go.type ().c_str (), pId, QThread::currentThreadId ());
+                 go.type ().c_str (), pId, QThread::currentThreadId ());
 
   ObjectProxy* proxy = toolkitObjectProxy (go);
 
   if (proxy)
     {
       if (go.isa ("uicontrol")
-	  && pId == uicontrol::properties::ID_STYLE)
-	{
-	  // Special case: we need to recreate the control widget
-	  // associated with the octave graphics_object
+          && pId == uicontrol::properties::ID_STYLE)
+        {
+          // Special case: we need to recreate the control widget
+          // associated with the octave graphics_object
 
-	  finalize (go);
-	  initialize (go);
-	}
+          finalize (go);
+          initialize (go);
+        }
       else
-	proxy->update (pId);
+        proxy->update (pId);
     }
 }
 
 void Backend::finalize (const graphics_object& go)
 {
   Logger::debug ("Backend::finalize %s from thread %08x",
-		 go.type ().c_str (), QThread::currentThreadId ());
+                 go.type ().c_str (), QThread::currentThreadId ());
 
   ObjectProxy* proxy = toolkitObjectProxy (go);
 
@@ -168,7 +168,7 @@
       ObjectProxy* proxy = toolkitObjectProxy (go);
 
       if (proxy)
-	proxy->redraw ();
+        proxy->redraw ();
     }
 }
 
@@ -189,12 +189,12 @@
       octave_value ov = go.get (toolkitObjectProperty (go));
 
       if (ov.is_defined () && ! ov.is_empty ())
-	{
-	  OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value ();
+        {
+          OCTAVE_INTPTR_TYPE ptr = ov.OCTAVE_PTR_SCALAR ().value ();
 
-	  if (! error_state)
-	    return reinterpret_cast<ObjectProxy*> (ptr);
-	}
+          if (! error_state)
+            return reinterpret_cast<ObjectProxy*> (ptr);
+        }
     }
 
   return 0;
--- a/libgui/graphics/BaseControl.cc
+++ b/libgui/graphics/BaseControl.cc
@@ -45,24 +45,24 @@
       || props.style_is ("popupmenu"))
     {
       p.setColor (QPalette::Base,
-		  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
       p.setColor (QPalette::Text,
-		  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
     }
   else if (props.style_is ("pushbutton")
-	   || props.style_is ("togglebutton"))
+           || props.style_is ("togglebutton"))
     {
       p.setColor (QPalette::Button,
-		  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
       p.setColor (QPalette::ButtonText,
-		  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
     }
   else
     {
       p.setColor (QPalette::Window,
-		  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_backgroundcolor_rgb ()));
       p.setColor (QPalette::WindowText,
-		  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
+                  Utils::fromRgb (props.get_foregroundcolor_rgb ()));
     }
 
   w->setPalette (p);
@@ -83,7 +83,7 @@
 
   Matrix bb = up.get_boundingbox (false);
   w->setGeometry (xround (bb(0)), xround (bb(1)),
-		  xround (bb(2)), xround (bb(3)));
+                  xround (bb(2)), xround (bb(3)));
   w->setFont (Utils::computeFont<uicontrol> (up, bb(3)));
   updatePalette (up, w);
   w->setEnabled (up.enable_is ("on"));
@@ -108,11 +108,11 @@
    switch (pId)
     {
     case uicontrol::properties::ID_POSITION:
-	{
-	  Matrix bb = up.get_boundingbox (false);
-	  w->setGeometry (xround (bb(0)), xround (bb(1)),
-			  xround (bb(2)), xround (bb(3)));
-	}
+        {
+          Matrix bb = up.get_boundingbox (false);
+          w->setGeometry (xround (bb(0)), xround (bb(1)),
+                          xround (bb(2)), xround (bb(3)));
+        }
       break;
     case uicontrol::properties::ID_FONTNAME:
     case uicontrol::properties::ID_FONTSIZE:
@@ -153,56 +153,56 @@
     {
     case QEvent::Resize:
       if (m_normalizedFont)
-	{
-	  gh_manager::auto_lock lock;
+        {
+          gh_manager::auto_lock lock;
 
-	  qWidget<QWidget> ()->setFont (Utils::computeFont<uicontrol>
-					(properties<uicontrol> ()));
-	}
+          qWidget<QWidget> ()->setFont (Utils::computeFont<uicontrol>
+                                        (properties<uicontrol> ()));
+        }
       break;
     case QEvent::MouseButtonPress:
-	{
-	  gh_manager::auto_lock lock;
+        {
+          gh_manager::auto_lock lock;
 
-	  QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
-	  graphics_object go = object ();
-	  uicontrol::properties& up = Utils::properties<uicontrol> (go);
-	  graphics_object fig = go.get_ancestor ("figure");
+          QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
+          graphics_object go = object ();
+          uicontrol::properties& up = Utils::properties<uicontrol> (go);
+          graphics_object fig = go.get_ancestor ("figure");
 
-	  if (m->button () != Qt::LeftButton
-	      || ! up.enable_is ("on"))
-	    {
-	      gh_manager::post_set (fig.get_handle (), "selectiontype",
-				    Utils::figureSelectionType (m), false);
-	      gh_manager::post_set (fig.get_handle (), "currentpoint",
-				    Utils::figureCurrentPoint (fig, m),
-				    false);
-	      gh_manager::post_callback (fig.get_handle (),
-					 "windowbuttondownfcn");
-	      gh_manager::post_callback (m_handle, "buttondownfcn");
+          if (m->button () != Qt::LeftButton
+              || ! up.enable_is ("on"))
+            {
+              gh_manager::post_set (fig.get_handle (), "selectiontype",
+                                    Utils::figureSelectionType (m), false);
+              gh_manager::post_set (fig.get_handle (), "currentpoint",
+                                    Utils::figureCurrentPoint (fig, m),
+                                    false);
+              gh_manager::post_callback (fig.get_handle (),
+                                         "windowbuttondownfcn");
+              gh_manager::post_callback (m_handle, "buttondownfcn");
 
-	      if (m->button () == Qt::RightButton)
-		ContextMenu::executeAt (up, m->globalPos ());
-	    }
-	  else
-	    {
-	      if (up.style_is ("listbox"))
-		gh_manager::post_set (fig.get_handle (), "selectiontype",
-				      Utils::figureSelectionType (m), false);
-	      else
-		gh_manager::post_set (fig.get_handle (), "selectiontype",
-				      octave_value ("normal"), false);
-	    }
-	}
+              if (m->button () == Qt::RightButton)
+                ContextMenu::executeAt (up, m->globalPos ());
+            }
+          else
+            {
+              if (up.style_is ("listbox"))
+                gh_manager::post_set (fig.get_handle (), "selectiontype",
+                                      Utils::figureSelectionType (m), false);
+              else
+                gh_manager::post_set (fig.get_handle (), "selectiontype",
+                                      octave_value ("normal"), false);
+            }
+        }
       break;
     case QEvent::MouseMove:
       if (qWidget<QWidget> ()->hasMouseTracking ())
         {
-	  gh_manager::auto_lock lock;
+          gh_manager::auto_lock lock;
 
-	  QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
-	  graphics_object go = object ();
-	  graphics_object fig = go.get_ancestor ("figure");
+          QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
+          graphics_object go = object ();
+          graphics_object fig = go.get_ancestor ("figure");
 
           gh_manager::post_set (fig.get_handle (), "currentpoint",
                                 Utils::figureCurrentPoint (fig, m), false);
--- a/libgui/graphics/ButtonControl.cc
+++ b/libgui/graphics/ButtonControl.cc
@@ -46,7 +46,7 @@
       Matrix value = up.get_value ().matrix_value ();
 
       if (value.numel () > 0 && value(0) == up.get_max ())
-	btn->setChecked (true);
+        btn->setChecked (true);
     }
 
   connect (btn, SIGNAL (clicked (void)), SLOT (clicked (void)));
@@ -70,19 +70,19 @@
     case uicontrol::properties::ID_VALUE:
       m_blockCallback = true;
       if (btn->isCheckable ())
-	{
-	  Matrix value = up.get_value ().matrix_value ();
+        {
+          Matrix value = up.get_value ().matrix_value ();
 
-	  if (value.numel () > 0)
-	    {
-	      double dValue = value(0);
+          if (value.numel () > 0)
+            {
+              double dValue = value(0);
 
-	      if (dValue == up.get_min () && btn->isChecked ())
-		btn->setChecked (false);
-	      else if (dValue == up.get_max () && ! btn->isChecked ())
-		btn->setChecked (true);
-	    }
-	}
+              if (dValue == up.get_min () && btn->isChecked ())
+                btn->setChecked (false);
+              else if (dValue == up.get_max () && ! btn->isChecked ())
+                btn->setChecked (true);
+            }
+        }
       m_blockCallback = false;
       break;
     default:
@@ -105,8 +105,8 @@
       double newValue = (checked ? up.get_max () : up.get_min ());
 
       if (oldValue.numel() != 1
-	  || (newValue != oldValue(0)))
-	gh_manager::post_set (m_handle, "value", newValue, false);
+          || (newValue != oldValue(0)))
+        gh_manager::post_set (m_handle, "value", newValue, false);
       gh_manager::post_callback (m_handle, "callback");
     }
 }
--- a/libgui/graphics/Canvas.cc
+++ b/libgui/graphics/Canvas.cc
@@ -95,7 +95,7 @@
       draw (m_handle);
 
       if (m_mouseMode == ZoomMode && m_mouseAxes.ok ())
-	drawZoomBox (m_mouseAnchor, m_mouseCurrent);
+        drawZoomBox (m_mouseAnchor, m_mouseCurrent);
     }
 }
 
@@ -109,65 +109,65 @@
       axes::properties& ap = Utils::properties<axes> (ax);
 
       switch (m_mouseMode)
-	{
-	case RotateMode:
-	    {
-	      Matrix bb = ap.get_boundingbox (true);
-	      Matrix view = ap.get_view ().matrix_value ();
+        {
+        case RotateMode:
+            {
+              Matrix bb = ap.get_boundingbox (true);
+              Matrix view = ap.get_view ().matrix_value ();
 
-	      // Compute new view angles
-	      view(0) += ((m_mouseCurrent.x () - event->x ())
-			  * (180.0 / bb(2)));
-	      view(1) += ((event->y () - m_mouseCurrent.y ())
-			  * (180.0 / bb(3)));
+              // Compute new view angles
+              view(0) += ((m_mouseCurrent.x () - event->x ())
+                          * (180.0 / bb(2)));
+              view(1) += ((event->y () - m_mouseCurrent.y ())
+                          * (180.0 / bb(3)));
 
-	      // Clipping
-	      view(1) = std::min (view(1), 90.0);
-	      view(1) = std::max (view(1), -90.0);
-	      if (view(0) > 180.0)
-		view(0) -= 360.0;
-	      else if (view(0) < -180.0)
-		view(0) += 360.0;
+              // Clipping
+              view(1) = std::min (view(1), 90.0);
+              view(1) = std::max (view(1), -90.0);
+              if (view(0) > 180.0)
+                view(0) -= 360.0;
+              else if (view(0) < -180.0)
+                view(0) += 360.0;
 
-	      // Snapping
-	      double snapMargin = 1.0;
-	      for (int a = -90; a <= 90; a += 90)
-		if ((a - snapMargin) < view(1)
-		    && view(1) < (a + snapMargin))
-		  {
-		    view(1) = a;
-		    break;
-		  }
-	      for (int a = -180; a <= 180; a += 180)
-		if ((a - snapMargin) < view(0)
-		    && view(0) < (a + snapMargin))
-		  {
-		    if (a == 180)
-		      view(0) = -180;
-		    else
-		      view(0) = a;
-		    break;
-		  }
+              // Snapping
+              double snapMargin = 1.0;
+              for (int a = -90; a <= 90; a += 90)
+                if ((a - snapMargin) < view(1)
+                    && view(1) < (a + snapMargin))
+                  {
+                    view(1) = a;
+                    break;
+                  }
+              for (int a = -180; a <= 180; a += 180)
+                if ((a - snapMargin) < view(0)
+                    && view(0) < (a + snapMargin))
+                  {
+                    if (a == 180)
+                      view(0) = -180;
+                    else
+                      view(0) = a;
+                    break;
+                  }
 
-	      // Update axes properties
-	      ap.set_view (view);
+              // Update axes properties
+              ap.set_view (view);
 
-	      // Update current mouse position
-	      m_mouseCurrent = event->pos ();
+              // Update current mouse position
+              m_mouseCurrent = event->pos ();
 
-	      // Force immediate redraw
-	      redraw (true);
-	    }
-	  break;
-	case ZoomMode:
-	  m_mouseCurrent = event->pos();
-	  redraw (true);
-	  break;
-	case PanMode:
-	  break;
-	default:
-	  break;
-	}
+              // Force immediate redraw
+              redraw (true);
+            }
+          break;
+        case ZoomMode:
+          m_mouseCurrent = event->pos();
+          redraw (true);
+          break;
+        case PanMode:
+          break;
+        default:
+          break;
+        }
     }
   else if (m_mouseMode == NoMode)
     {
@@ -178,8 +178,8 @@
           graphics_object figObj (obj.get_ancestor ("figure"));
 
           updateCurrentPoint (figObj, obj, event);
-	  gh_manager::post_callback (figObj.get_handle (),
-				     "windowbuttonmotionfcn");
+          gh_manager::post_callback (figObj.get_handle (),
+                                     "windowbuttonmotionfcn");
         }
     }
 }
@@ -199,24 +199,24 @@
       octave_idx_type num_children = children.numel ();
 
       for (int i = 0; i < num_children; i++)
-	{
-	  graphics_object childObj (gh_manager::get_object (children(i)));
+        {
+          graphics_object childObj (gh_manager::get_object (children(i)));
 
           if (childObj.isa ("axes"))
             axesList.append (childObj);
-	  else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel"))
-	    {
-	      Matrix bb = childObj.get_properties ().get_boundingbox (false);
-	      QRectF r (bb(0), bb(1), bb(2), bb(3));
+          else if (childObj.isa ("uicontrol") || childObj.isa ("uipanel"))
+            {
+              Matrix bb = childObj.get_properties ().get_boundingbox (false);
+              QRectF r (bb(0), bb(1), bb(2), bb(3));
 
-	      r.adjust (-5, -5, 5, 5);
-	      if (r.contains (event->posF ()))
-		{
-		  currentObj = childObj;
-		  break;
-		}
-	    }
-	}
+              r.adjust (-5, -5, 5, 5);
+              if (r.contains (event->posF ()))
+                {
+                  currentObj = childObj;
+                  break;
+                }
+            }
+        }
 
       if (! currentObj)
         {
@@ -269,61 +269,61 @@
       MouseMode newMouseMode = NoMode;
 
       if (fig)
-	newMouseMode = fig->mouseMode ();
+        newMouseMode = fig->mouseMode ();
 
       switch (newMouseMode)
-	{
-	case NoMode:
-	  gh_manager::post_set (figObj.get_handle (), "selectiontype",
-				Utils::figureSelectionType (event), false);
+        {
+        case NoMode:
+          gh_manager::post_set (figObj.get_handle (), "selectiontype",
+                                Utils::figureSelectionType (event), false);
           updateCurrentPoint (figObj, obj, event);
-	  gh_manager::post_callback (figObj.get_handle (),
-				     "windowbuttondownfcn");
+          gh_manager::post_callback (figObj.get_handle (),
+                                     "windowbuttondownfcn");
           gh_manager::post_callback (currentObj.get_handle (),
                                      "buttondownfcn");
-	  if (event->button () == Qt::RightButton)
-	    ContextMenu::executeAt (currentObj.get_properties (),
-				    event->globalPos ());
-	  break;
-	case RotateMode:
-	case ZoomMode:
-	case PanMode:
-	  if (axesObj)
-	    {
-	      if (event->buttons () == Qt::LeftButton
-		  && event->modifiers () == Qt::NoModifier)
-		{
-		  m_mouseAnchor = m_mouseCurrent = event->pos ();
-		  m_mouseAxes = axesObj.get_handle ();
-		  m_mouseMode = newMouseMode;
-		}
-	      else if (newMouseMode == ZoomMode
-		       && event->modifiers () == Qt::NoModifier)
-		{
-		  switch (event->buttons ())
-		    {
-		    case Qt::RightButton:
-		      Utils::properties<axes> (axesObj).unzoom ();
-		      break;
-		    case Qt::MidButton:
-			{
-			  axes::properties& ap =
-			    Utils::properties<axes> (axesObj);
+          if (event->button () == Qt::RightButton)
+            ContextMenu::executeAt (currentObj.get_properties (),
+                                    event->globalPos ());
+          break;
+        case RotateMode:
+        case ZoomMode:
+        case PanMode:
+          if (axesObj)
+            {
+              if (event->buttons () == Qt::LeftButton
+                  && event->modifiers () == Qt::NoModifier)
+                {
+                  m_mouseAnchor = m_mouseCurrent = event->pos ();
+                  m_mouseAxes = axesObj.get_handle ();
+                  m_mouseMode = newMouseMode;
+                }
+              else if (newMouseMode == ZoomMode
+                       && event->modifiers () == Qt::NoModifier)
+                {
+                  switch (event->buttons ())
+                    {
+                    case Qt::RightButton:
+                      Utils::properties<axes> (axesObj).unzoom ();
+                      break;
+                    case Qt::MidButton:
+                        {
+                          axes::properties& ap =
+                            Utils::properties<axes> (axesObj);
 
-			  ap.clear_zoom_stack ();
-			  ap.set_xlimmode ("auto");
-			  ap.set_ylimmode ("auto");
-			  ap.set_zlimmode ("auto");
-			}
-		      break;
-		    }
-		  redraw (false);
-		}
-	    }
-	  break;
-	default:
-	  break;
-	}
+                          ap.clear_zoom_stack ();
+                          ap.set_xlimmode ("auto");
+                          ap.set_ylimmode ("auto");
+                          ap.set_zlimmode ("auto");
+                        }
+                      break;
+                    }
+                  redraw (false);
+                }
+            }
+          break;
+        default:
+          break;
+        }
     }
 }
 
@@ -337,26 +337,26 @@
       graphics_object ax = gh_manager::get_object (m_mouseAxes);
 
       if (ax.valid_object ())
-	{
-	  axes::properties& ap = Utils::properties<axes> (ax);
+        {
+          axes::properties& ap = Utils::properties<axes> (ax);
 
-	  ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (),
-					    m_mouseAnchor.y ());
-	  ColumnVector p1 = ap.pixel2coord (event->x (),
-					    event->y ());
+          ColumnVector p0 = ap.pixel2coord (m_mouseAnchor.x (),
+                                            m_mouseAnchor.y ());
+          ColumnVector p1 = ap.pixel2coord (event->x (),
+                                            event->y ());
 
-	  Matrix xl (1, 2, 0.0);
-	  Matrix yl (1, 2, 0.0);
+          Matrix xl (1, 2, 0.0);
+          Matrix yl (1, 2, 0.0);
 
-	  xl(0) = std::min (p0(0), p1(0));
-	  xl(1) = std::max (p0(0), p1(0));
-	  yl(0) = std::min (p0(1), p1(1));
-	  yl(1) = std::max (p0(1), p1(1));
+          xl(0) = std::min (p0(0), p1(0));
+          xl(1) = std::max (p0(0), p1(0));
+          yl(0) = std::min (p0(1), p1(1));
+          yl(1) = std::max (p0(1), p1(1));
 
-	  ap.zoom (xl, yl);
+          ap.zoom (xl, yl);
 
-	  redraw (false);
-	}
+          redraw (false);
+        }
     }
   else if (m_mouseMode == NoMode)
     {
@@ -407,7 +407,7 @@
 }
 
 Canvas* Canvas::create (const std::string& /* name */, QWidget* parent,
-			const graphics_handle& handle)
+                        const graphics_handle& handle)
 {
   // Only OpenGL
   return new GLCanvas (parent, handle);
--- a/libgui/graphics/Canvas.h
+++ b/libgui/graphics/Canvas.h
@@ -58,7 +58,7 @@
   virtual QWidget* qWidget (void) = 0;
 
   static Canvas* create (const std::string& name, QWidget* parent,
-			 const graphics_handle& handle);
+                         const graphics_handle& handle);
 
 protected:
   virtual void draw (const graphics_handle& handle) = 0;
--- a/libgui/graphics/CheckBoxControl.cc
+++ b/libgui/graphics/CheckBoxControl.cc
@@ -41,7 +41,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new CheckBoxControl (go, new QCheckBox (container));
+        return new CheckBoxControl (go, new QCheckBox (container));
     }
 
   return 0;
--- a/libgui/graphics/Container.cc
+++ b/libgui/graphics/Container.cc
@@ -54,18 +54,18 @@
       graphics_object go = gh_manager::get_object (handle);
 
       if (go)
-	{
-	  graphics_object fig = go.get_ancestor ("figure");
+        {
+          graphics_object fig = go.get_ancestor ("figure");
 
-	  m_canvas = Canvas::create (fig.get("renderer").string_value (),
-				     this, handle);
+          m_canvas = Canvas::create (fig.get("renderer").string_value (),
+                                     this, handle);
 
-	  QWidget* canvasWidget = m_canvas->qWidget ();
+          QWidget* canvasWidget = m_canvas->qWidget ();
 
-	  canvasWidget->lower ();
-	  canvasWidget->show ();
-	  canvasWidget->setGeometry (0, 0, width (), height ());
-	}
+          canvasWidget->lower ();
+          canvasWidget->show ();
+          canvasWidget->setGeometry (0, 0, width (), height ());
+        }
     }
 
   return m_canvas;
@@ -81,18 +81,18 @@
   foreach (QObject* qObj, children ())
     {
       if (qObj->isWidgetType ())
-	{
-	  Object* obj = Object::fromQObject (qObj);
+        {
+          Object* obj = Object::fromQObject (qObj);
 
-	  if (obj)
-	    {
-	      Matrix bb = obj->properties ().get_boundingbox (false);
+          if (obj)
+            {
+              Matrix bb = obj->properties ().get_boundingbox (false);
 
-	      obj->qWidget<QWidget> ()
-		->setGeometry (xround (bb(0)), xround (bb(1)),
-			       xround (bb(2)), xround (bb(3)));
-	    }
-	}
+              obj->qWidget<QWidget> ()
+                ->setGeometry (xround (bb(0)), xround (bb(1)),
+                               xround (bb(2)), xround (bb(3)));
+            }
+        }
     }
 }
 
--- a/libgui/graphics/ContextMenu.cc
+++ b/libgui/graphics/ContextMenu.cc
@@ -69,19 +69,19 @@
     {
     case base_properties::ID_VISIBLE:
       if (up.is_visible ())
-	{
-	  Matrix pos = up.get_position ().matrix_value ();
-	  QWidget* parentW = menu->parentWidget ();
-	  QPoint pt;
+        {
+          Matrix pos = up.get_position ().matrix_value ();
+          QWidget* parentW = menu->parentWidget ();
+          QPoint pt;
 
-	  pt.rx () = xround (pos(0));
-	  pt.ry () = parentW->height () - xround (pos(1));
-	  pt = parentW->mapToGlobal (pt);
+          pt.rx () = xround (pos(0));
+          pt.ry () = parentW->height () - xround (pos(1));
+          pt = parentW->mapToGlobal (pt);
 
-	  menu->popup (pt);
-	}
+          menu->popup (pt);
+        }
       else
-	menu->hide ();
+        menu->hide ();
       break;
     default:
       Object::update (pId);
@@ -114,18 +114,18 @@
       graphics_object go = gh_manager::get_object (h);
 
       if (go.valid_object ())
-	{
-	  ContextMenu* cMenu =
-	    dynamic_cast<ContextMenu*> (Backend::toolkitObject (go));
+        {
+          ContextMenu* cMenu =
+            dynamic_cast<ContextMenu*> (Backend::toolkitObject (go));
 
-	  if (cMenu)
-	    {
-	      QMenu* menu = cMenu->qWidget<QMenu> ();
+          if (cMenu)
+            {
+              QMenu* menu = cMenu->qWidget<QMenu> ();
 
-	      if (menu)
-		menu->popup (pt);
-	    }
-	}
+              if (menu)
+                menu->popup (pt);
+            }
+        }
     }
 }
 
--- a/libgui/graphics/EditControl.cc
+++ b/libgui/graphics/EditControl.cc
@@ -43,14 +43,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	{
-	  uicontrol::properties& up = Utils::properties<uicontrol> (go);
+        {
+          uicontrol::properties& up = Utils::properties<uicontrol> (go);
 
-	  if ((up.get_max () - up.get_min ()) > 1)
-	    return new EditControl (go, new TextEdit (container));
-	  else
-	    return new EditControl (go, new QLineEdit (container));
-	}
+          if ((up.get_max () - up.get_min ()) > 1)
+            return new EditControl (go, new TextEdit (container));
+          else
+            return new EditControl (go, new QLineEdit (container));
+        }
     }
 
   return 0;
@@ -74,12 +74,12 @@
 
   edit->setText (Utils::fromStdString (up.get_string_string ()));
   edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					  up.get_verticalalignment ()));
+                                          up.get_verticalalignment ()));
 
   connect (edit, SIGNAL (textEdited (const QString&)),
-	   SLOT (textChanged (void)));
+           SLOT (textChanged (void)));
   connect (edit, SIGNAL (editingFinished (void)),
-	   SLOT (editingFinished (void)));
+           SLOT (editingFinished (void)));
 }
 
 EditControl::EditControl (const graphics_object& go, TextEdit* edit)
@@ -103,9 +103,9 @@
   edit->setPlainText (Utils::fromStdString (up.get_string_string ()));
   
   connect (edit, SIGNAL (textChanged (void)),
-	   SLOT (textChanged (void)));
+           SLOT (textChanged (void)));
   connect (edit, SIGNAL (editingFinished (void)),
-	   SLOT (editingFinished (void)));
+           SLOT (editingFinished (void)));
 }
 
 EditControl::~EditControl (void)
@@ -129,11 +129,11 @@
   if (! handled)
     {
       switch (pId)
-	{
-	default:
-	  BaseControl::update (pId);
-	  break;
-	}
+        {
+        default:
+          BaseControl::update (pId);
+          break;
+        }
     }
 }
 
@@ -150,17 +150,17 @@
     case uicontrol::properties::ID_HORIZONTALALIGNMENT:
     case uicontrol::properties::ID_VERTICALALIGNMENT:
       edit->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					      up.get_verticalalignment ()));
+                                              up.get_verticalalignment ()));
       return true;
     case uicontrol::properties::ID_MIN:
     case uicontrol::properties::ID_MAX:
       if ((up.get_max () - up.get_min ()) > 1)
-	{
-	  QWidget* container = edit->parentWidget ();
+        {
+          QWidget* container = edit->parentWidget ();
 
-	  delete edit;
-	  init (new TextEdit (container), true);
-	}
+          delete edit;
+          init (new TextEdit (container), true);
+        }
       return true;
     default:
       break;
@@ -182,12 +182,12 @@
     case uicontrol::properties::ID_MIN:
     case uicontrol::properties::ID_MAX:
       if ((up.get_max () - up.get_min ()) <= 1)
-	{
-	  QWidget* container = edit->parentWidget ();
+        {
+          QWidget* container = edit->parentWidget ();
 
-	  delete edit;
-	  init (new QLineEdit (container), true);
-	}
+          delete edit;
+          init (new QLineEdit (container), true);
+        }
       return true;
     default:
       break;
@@ -206,8 +206,8 @@
   if (m_textChanged)
     {
       QString txt = (m_multiLine
-		     ? qWidget<TextEdit> ()->toPlainText ()
-		     : qWidget<QLineEdit> ()->text ());
+                     ? qWidget<TextEdit> ()->toPlainText ()
+                     : qWidget<QLineEdit> ()->text ());
 
       gh_manager::post_set (m_handle, "string", Utils::toStdString (txt), false);
       gh_manager::post_callback (m_handle, "callback");
--- a/libgui/graphics/Figure.cc
+++ b/libgui/graphics/Figure.cc
@@ -61,8 +61,8 @@
       graphics_object go (gh_manager::get_object (kids(i)));
 
       if (go && (go.isa ("uicontrol") || go.isa ("uipanel")
-		 || go.isa ("uibuttongroup")))
-	return true;
+                 || go.isa ("uibuttongroup")))
+        return true;
     }
 
   return false;
@@ -77,7 +77,7 @@
       graphics_object go (gh_manager::get_object (kids(i)));
 
       if (go && go.isa ("uimenu"))
-	return true;
+        return true;
     }
 
   return false;
@@ -173,7 +173,7 @@
 
   MouseModeActionGroup* mouseModeGroup = new MouseModeActionGroup (win);
   connect (mouseModeGroup, SIGNAL (modeChanged (MouseMode)),
-	   SLOT (setMouseMode (MouseMode)));
+           SLOT (setMouseMode (MouseMode)));
   m_figureToolBar->addActions (mouseModeGroup->actions ());
 
   m_menuBar = new MenuBar (win);
@@ -188,23 +188,23 @@
   fileMenu->addAction (tr ("Save &As"))->setEnabled (false);
   fileMenu->addSeparator ();
   fileMenu->addAction (tr ("&Close Figure"), this,
-		       SLOT (fileCloseFigure (void)), Qt::CTRL|Qt::Key_W);
+                       SLOT (fileCloseFigure (void)), Qt::CTRL|Qt::Key_W);
 
   QMenu* editMenu = m_menuBar->addMenu (tr ("&Edit"));
   editMenu->menuAction ()->setObjectName ("builtinMenu");
   editMenu->addAction (tr ("Cop&y"), this, SLOT (editCopy (void)),
-		       Qt::CTRL|Qt::Key_C)->setEnabled (false);
+                       Qt::CTRL|Qt::Key_C)->setEnabled (false);
   editMenu->addAction (tr ("Cu&t"), this, SLOT (editCut (void)),
-		       Qt::CTRL|Qt::Key_X)->setEnabled (false);
+                       Qt::CTRL|Qt::Key_X)->setEnabled (false);
   editMenu->addAction (tr ("&Paste"), this, SLOT (editPaste(void)),
-		       Qt::CTRL|Qt::Key_V)->setEnabled (false);
+                       Qt::CTRL|Qt::Key_V)->setEnabled (false);
   editMenu->addSeparator ();
   editMenu->addActions (mouseModeGroup->actions ());
 
   QMenu* helpMenu = m_menuBar->addMenu (tr ("&Help"));
   helpMenu->menuAction ()->setObjectName ("builtinMenu");
   helpMenu->addAction (tr ("&About QtHandles"), this,
-		       SLOT (helpAboutQtHandles (void)));
+                       SLOT (helpAboutQtHandles (void)));
   helpMenu->addAction (tr ("About &Qt"), qApp, SLOT (aboutQt (void)));
 
   m_menuBar->addReceiver (this);
@@ -226,12 +226,12 @@
     }
 
   foreach (QFrame* frame,
-	   qWidget<QWidget> ()->findChildren<QFrame*> ("UIPanel"))
+           qWidget<QWidget> ()->findChildren<QFrame*> ("UIPanel"))
     {
       Object* obj = Object::fromQObject (frame);
 
       if (obj)
-	obj->slotRedraw ();
+        obj->slotRedraw ();
     }
 }
 
@@ -260,20 +260,20 @@
   switch (pId)
     {
     case figure::properties::ID_POSITION:
-	{
+        {
           m_innerRect = boundingBoxToRect (fp.get_boundingbox (true));
           //qDebug () << "Figure::update(position):" << m_innerRect;
-	  int offset = 0;
+          int offset = 0;
 
           foreach (QToolBar* tb, win->findChildren<QToolBar*> ())
             if (! tb->isHidden ())
               offset += tb->sizeHint ().height ();
-	  if (! m_menuBar->isHidden ())
-	    offset += m_menuBar->sizeHint ().height () + 1;
+          if (! m_menuBar->isHidden ())
+            offset += m_menuBar->sizeHint ().height () + 1;
           //qDebug () << "Figure::update(position)(adjusted):" << m_innerRect.adjusted (0, -offset, 0, 0);
-	  win->setGeometry (m_innerRect.adjusted (0, -offset, 0, 0));
+          win->setGeometry (m_innerRect.adjusted (0, -offset, 0, 0));
           //qDebug () << "Figure::update(position): done";
-	}
+        }
       break;
     case figure::properties::ID_NAME:
     case figure::properties::ID_NUMBERTITLE:
@@ -281,17 +281,17 @@
       break;
     case figure::properties::ID_VISIBLE:
       if (fp.is_visible ())
-	QTimer::singleShot (0, win, SLOT (show ()));
+        QTimer::singleShot (0, win, SLOT (show ()));
       else
-	win->hide ();
+        win->hide ();
       break;
     case figure::properties::ID_TOOLBAR:
       if (fp.toolbar_is ("none"))
-	showFigureToolBar (false);
+        showFigureToolBar (false);
       else if (fp.toolbar_is ("figure"))
-	showFigureToolBar (true);
+        showFigureToolBar (true);
       else // "auto"
-	showFigureToolBar (! hasUiControlChildren (fp));
+        showFigureToolBar (! hasUiControlChildren (fp));
       break;
     case figure::properties::ID_MENUBAR:
       showMenuBar (fp.menubar_is ("figure"));
@@ -332,9 +332,9 @@
       QRect r = qWidget<QWidget> ()->geometry ();
 
       if (! visible)
-	r.adjust (0, dy, 0, 0);
+        r.adjust (0, dy, 0, 0);
       else
-	r.adjust (0, -dy, 0, 0);
+        r.adjust (0, -dy, 0, 0);
 
       m_blockUpdates = true;
       qWidget<QWidget> ()->setGeometry (r);
@@ -344,12 +344,12 @@
       updateBoundingBox (false);
 
       if (visible)
-	m_mouseMode = m_lastMouseMode;
+        m_mouseMode = m_lastMouseMode;
       else
-	{
-	  m_lastMouseMode = m_mouseMode;
-	  m_mouseMode = NoMode;
-	}
+        {
+          m_lastMouseMode = m_mouseMode;
+          m_mouseMode = NoMode;
+        }
     }
 }
 
@@ -373,9 +373,9 @@
 
       //qDebug () << "Figure::showMenuBar:" << r;
       if (! visible)
-	r.adjust (0, dy, 0, 0);
+        r.adjust (0, dy, 0, 0);
       else
-	r.adjust (0, -dy, 0, 0);
+        r.adjust (0, -dy, 0, 0);
       //qDebug () << "Figure::showMenuBar(adjusted):" << r;
 
       m_blockUpdates = true;
@@ -467,7 +467,7 @@
       if (flags & UpdateBoundingBoxSize)
         r.setSize (win->frameGeometry ().size ());
 
-      if (r.isValid () && r != m_outerRect )
+      if (r.isValid () && r != m_outerRect)
         {
           //qDebug() << "outer rect changed:" << m_outerRect << "->>" << r;
           m_outerRect = r;
@@ -498,38 +498,38 @@
   if (! m_blockUpdates)
     {
       if (obj == m_container)
-	{
+        {
           // Do nothing...
-	}
+        }
       else if (obj == m_menuBar)
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::ActionRemoved:
-		{
-		  QAction* a = dynamic_cast<QActionEvent*> (event)->action ();
+        {
+          switch (event->type ())
+            {
+            case QEvent::ActionRemoved:
+                {
+                  QAction* a = dynamic_cast<QActionEvent*> (event)->action ();
 
-		  if (! a->isSeparator ()
-		      && a->objectName () != "builtinMenu")
+                  if (! a->isSeparator ()
+                      && a->objectName () != "builtinMenu")
                     updateMenuBar ();
-		}
-	      break;
-	    default:
-	      break;
-	    }
-	}
+                }
+              break;
+            default:
+              break;
+            }
+        }
       else
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::Close:
-	      event->ignore ();
-	      gh_manager::post_callback (m_handle, "closerequestfcn");
-	      return true;
-	    default:
-	      break;
-	    }
-	}
+        {
+          switch (event->type ())
+            {
+            case QEvent::Close:
+              event->ignore ();
+              gh_manager::post_callback (m_handle, "closerequestfcn");
+              return true;
+            default:
+              break;
+            }
+        }
     }
 
   return false;
@@ -541,55 +541,55 @@
     {
       if (watched == m_container)
         {
-	  switch (event->type ())
-	    {
-	    case QEvent::Resize:
-	      updateBoundingBox (true, UpdateBoundingBoxSize);
-	      break;
-	    case QEvent::ChildAdded:
-	      if (dynamic_cast<QChildEvent*> (event)->child
-		  ()->isWidgetType())
-		{
-		  gh_manager::auto_lock lock;
-		  const figure::properties& fp = properties<figure> ();
+          switch (event->type ())
+            {
+            case QEvent::Resize:
+              updateBoundingBox (true, UpdateBoundingBoxSize);
+              break;
+            case QEvent::ChildAdded:
+              if (dynamic_cast<QChildEvent*> (event)->child
+                  ()->isWidgetType())
+                {
+                  gh_manager::auto_lock lock;
+                  const figure::properties& fp = properties<figure> ();
 
-		  showFigureToolBar (! hasUiControlChildren (fp));
-		}
-	    default:
-	      break;
-	    }
+                  showFigureToolBar (! hasUiControlChildren (fp));
+                }
+            default:
+              break;
+            }
         }
       else if (watched == m_menuBar)
         {
-	  switch (event->type ())
-	    {
-	    case QEvent::ActionAdded:
-		{
-		  QAction* a = dynamic_cast<QActionEvent*> (event)->action ();
+          switch (event->type ())
+            {
+            case QEvent::ActionAdded:
+                {
+                  QAction* a = dynamic_cast<QActionEvent*> (event)->action ();
 
-		  if (! a->isSeparator ()
+                  if (! a->isSeparator ()
                       && a->objectName () != "builtinMenu")
                     updateMenuBar ();
-		}
-	      break;
-	    default:
-	      break;
-	    }
+                }
+              break;
+            default:
+              break;
+            }
         }
       else
         {
-	  switch (event->type ())
-	    {
-	    case QEvent::Move:
-	      updateBoundingBox (false, UpdateBoundingBoxPosition);
-	      updateBoundingBox (true, UpdateBoundingBoxPosition);
-	      break;
-	    case QEvent::Resize:
-	      updateBoundingBox (false, UpdateBoundingBoxSize);
-	      break;
-	    default:
-	      break;
-	    }
+          switch (event->type ())
+            {
+            case QEvent::Move:
+              updateBoundingBox (false, UpdateBoundingBoxPosition);
+              updateBoundingBox (true, UpdateBoundingBoxPosition);
+              break;
+            case QEvent::Resize:
+              updateBoundingBox (false, UpdateBoundingBoxSize);
+              break;
+            default:
+              break;
+            }
         }
     }
 }
@@ -597,7 +597,7 @@
 void Figure::helpAboutQtHandles (void)
 {
   QMessageBox::about (qWidget<QMainWindow> (), tr ("About QtHandles"),
-		      ABOUT_TEXT);
+                      ABOUT_TEXT);
 }
 
 void Figure::fileNewFigure (void)
@@ -656,9 +656,9 @@
       QRect r = win->geometry ();
 
       if (visible)
-	r.adjust (0, -sz.height (), 0, 0);
+        r.adjust (0, -sz.height (), 0, 0);
       else
-	r.adjust (0, sz.height (), 0, 0);
+        r.adjust (0, sz.height (), 0, 0);
 
       m_blockUpdates = true;
       win->setGeometry (r);
--- a/libgui/graphics/Figure.h
+++ b/libgui/graphics/Figure.h
@@ -37,11 +37,11 @@
 
 enum MouseMode
 {
-  NoMode	= 0,
-  RotateMode	= 1,
-  ZoomMode	= 2,
-  PanMode	= 3,
-  SelectMode	= 4
+  NoMode        = 0,
+  RotateMode    = 1,
+  ZoomMode      = 2,
+  PanMode       = 3,
+  SelectMode    = 4
 };
 
 class Container;
--- a/libgui/graphics/GLCanvas.h
+++ b/libgui/graphics/GLCanvas.h
@@ -39,7 +39,7 @@
   void draw (const graphics_handle& handle);
   void drawZoomBox (const QPoint& p1, const QPoint& p2);
   void resize (int /* x */, int /* y */,
-	       int /* width */, int /* height */) { }
+               int /* width */, int /* height */) { }
   graphics_object selectFromAxes (const graphics_object& ax,
                                   const QPoint& pt);
   QWidget* qWidget (void) { return this; }
--- a/libgui/graphics/ListBoxControl.cc
+++ b/libgui/graphics/ListBoxControl.cc
@@ -69,7 +69,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new ListBoxControl (go, new QListWidget (container));
+        return new ListBoxControl (go, new QListWidget (container));
     }
 
   return 0;
@@ -92,25 +92,25 @@
       int lc = list->count ();
 
       for (octave_idx_type i = 0; i < n; i++)
-	{
-	  int idx = xround (value(i));
+        {
+          int idx = xround (value(i));
 
-	  if (1 <= idx && idx <= lc)
-	    {
-	      list->item (idx-1)->setSelected (true);
-	      if (i == 0
-		  && list->selectionMode () ==
-		  	QAbstractItemView::SingleSelection)
-		break;
-	    }
-	}
+          if (1 <= idx && idx <= lc)
+            {
+              list->item (idx-1)->setSelected (true);
+              if (i == 0
+                  && list->selectionMode () ==
+                        QAbstractItemView::SingleSelection)
+                break;
+            }
+        }
     }
 
   list->removeEventFilter (this);
   list->viewport ()->installEventFilter (this);
 
   connect (list, SIGNAL (itemSelectionChanged (void)),
-	   SLOT (itemSelectionChanged (void)));
+           SLOT (itemSelectionChanged (void)));
 }
 
 ListBoxControl::~ListBoxControl (void)
@@ -134,9 +134,9 @@
     case uicontrol::properties::ID_MIN:
     case uicontrol::properties::ID_MAX:
       if ((up.get_max () - up.get_min ()) > 1)
-	list->setSelectionMode (QAbstractItemView::ExtendedSelection);
+        list->setSelectionMode (QAbstractItemView::ExtendedSelection);
       else
-	list->setSelectionMode (QAbstractItemView::SingleSelection);
+        list->setSelectionMode (QAbstractItemView::SingleSelection);
       break;
     case uicontrol::properties::ID_VALUE:
       m_blockCallback = true;
--- a/libgui/graphics/Menu.cc
+++ b/libgui/graphics/Menu.cc
@@ -46,11 +46,11 @@
       int keyMod = Qt::CTRL;
 
       if (c >= 'A' && c <= 'Z')
-	keyMod |= Qt::SHIFT;
+        keyMod |= Qt::SHIFT;
       if (c >= 'a' && c <= 'z')
-	c -= ('a' - 'A');
+        c -= ('a' - 'A');
       if (c >= 'A' && c <= 'Z')
-	return QKeySequence (keyMod | static_cast<int> (c));
+        return QKeySequence (keyMod | static_cast<int> (c));
     }
 
   return QKeySequence ();
@@ -65,7 +65,7 @@
       QObject* qObj = parent->qObject ();
 
       if (qObj)
-	return new Menu (go, new QAction (qObj), parent);
+        return new Menu (go, new QAction (qObj), parent);
     }
 
   return 0;
@@ -102,46 +102,46 @@
       int pos = static_cast<int> (up.get_position ());
 
       if (pos <= 0)
-	{
-	  if (m_separator)
-	    m_parent->insertAction (0, m_separator);
-	  m_parent->insertAction (0, action);
+        {
+          if (m_separator)
+            m_parent->insertAction (0, m_separator);
+          m_parent->insertAction (0, action);
 
-	  int count = 0;
+          int count = 0;
 
-	  foreach (QAction* a, m_parent->actions ())
-	    if (! a->isSeparator () && a->objectName () != "builtinMenu")
-	      count++;
-	  up.get_property ("position").set
-	    (octave_value (static_cast<double> (count)), true, false);
-	}
+          foreach (QAction* a, m_parent->actions ())
+            if (! a->isSeparator () && a->objectName () != "builtinMenu")
+              count++;
+          up.get_property ("position").set
+            (octave_value (static_cast<double> (count)), true, false);
+        }
       else
-	{
+        {
 
-	  int count = 0;
-	  QAction* before = 0;
+          int count = 0;
+          QAction* before = 0;
 
-	  foreach (QAction* a, m_parent->actions ())
-	    if (! a->isSeparator () && a->objectName () != "builtinMenu")
-	      {
-		count++;
-		if (pos <= count)
-		  {
-		    before = a;
-		    break;
-		  }
-	      }
+          foreach (QAction* a, m_parent->actions ())
+            if (! a->isSeparator () && a->objectName () != "builtinMenu")
+              {
+                count++;
+                if (pos <= count)
+                  {
+                    before = a;
+                    break;
+                  }
+              }
 
-	  if (m_separator)
-	    m_parent->insertAction (before, m_separator);
-	  m_parent->insertAction (before, action);
+          if (m_separator)
+            m_parent->insertAction (before, m_separator);
+          m_parent->insertAction (before, action);
 
-	  if (before)
-	    updateSiblingPositions ();
-	  else
-	    up.get_property ("position").set
-	      (octave_value (static_cast<double> (count+1)), true, false);
-	}
+          if (before)
+            updateSiblingPositions ();
+          else
+            up.get_property ("position").set
+              (octave_value (static_cast<double> (count+1)), true, false);
+        }
     }
 
   connect (action, SIGNAL (triggered (bool)), SLOT (actionTriggered (void)));
@@ -163,76 +163,76 @@
       break;
     case uimenu::properties::ID_CHECKED:
       if (up.is_checked ())
-	{
-	  action->setCheckable (true);
-	  action->setChecked (up.is_checked ());
-	}
+        {
+          action->setCheckable (true);
+          action->setChecked (up.is_checked ());
+        }
       else
-	{
-	  action->setChecked (false);
-	  action->setCheckable (false);
-	}
+        {
+          action->setChecked (false);
+          action->setCheckable (false);
+        }
       break;
     case uimenu::properties::ID_ENABLE:
       action->setEnabled (up.is_enable ());
       break;
     case uimenu::properties::ID_ACCELERATOR:
       if (! action->menu ())
-	action->setShortcut (accelSequence (up));
+        action->setShortcut (accelSequence (up));
       break;
     case uimenu::properties::ID_SEPARATOR:
       if (up.is_separator ())
-	{
-	  if (! m_separator)
-	    {
-	      m_separator = new QAction (action);
-	      m_separator->setSeparator (true);
-	      m_separator->setVisible (up.is_visible ());
-	      if (m_parent)
-		m_parent->insertAction (action, m_separator);
-	    }
-	}
+        {
+          if (! m_separator)
+            {
+              m_separator = new QAction (action);
+              m_separator->setSeparator (true);
+              m_separator->setVisible (up.is_visible ());
+              if (m_parent)
+                m_parent->insertAction (action, m_separator);
+            }
+        }
       else
-	{
-	  if (m_separator)
-	    delete m_separator;
-	  m_separator = 0;
-	}
+        {
+          if (m_separator)
+            delete m_separator;
+          m_separator = 0;
+        }
       break;
     case uimenu::properties::ID_VISIBLE:
       action->setVisible (up.is_visible ());
       if (m_separator)
-	m_separator->setVisible (up.is_visible ());
+        m_separator->setVisible (up.is_visible ());
       break;
     case uimenu::properties::ID_POSITION:
       if (m_separator)
-	m_parent->removeAction (m_separator);
+        m_parent->removeAction (m_separator);
       m_parent->removeAction (action);
-	{
-	  int pos = static_cast<int> (up.get_position ());
-	  QAction* before = 0;
+        {
+          int pos = static_cast<int> (up.get_position ());
+          QAction* before = 0;
 
-	  if (pos > 0)
-	    {
-	      int count = 0;
+          if (pos > 0)
+            {
+              int count = 0;
 
-	      foreach (QAction* a, m_parent->actions ())
-		if (! a->isSeparator () && a->objectName () != "builtinMenu")
-		  {
-		    count++;
-		    if (pos <= count)
-		      {
-			before = a;
-			break;
-		      }
-		  }
-	    }
+              foreach (QAction* a, m_parent->actions ())
+                if (! a->isSeparator () && a->objectName () != "builtinMenu")
+                  {
+                    count++;
+                    if (pos <= count)
+                      {
+                        before = a;
+                        break;
+                      }
+                  }
+            }
 
-	  if (m_separator)
-	    m_parent->insertAction (before, m_separator);
-	  m_parent->insertAction (before, action);
-	  updateSiblingPositions ();
-	}
+          if (m_separator)
+            m_parent->insertAction (before, m_separator);
+          m_parent->insertAction (before, action);
+          updateSiblingPositions ();
+        }
       break;
     default:
       Object::update (pId);
@@ -251,7 +251,7 @@
       action->setMenu (_menu);
       action->setShortcut (QKeySequence ());
       connect (_menu, SIGNAL (aboutToShow (void)),
-	       this, SLOT (actionHovered (void)));
+               this, SLOT (actionHovered (void)));
     }
 
   return _menu;
@@ -278,29 +278,29 @@
       double count = 1.0;
 
       foreach (QAction* a, m_parent->actions ())
-	{
-	  if (! a->isSeparator () && a->objectName () != "builtinMenu")
-	    {
-	      Object* aObj = Object::fromQObject (a);
+        {
+          if (! a->isSeparator () && a->objectName () != "builtinMenu")
+            {
+              Object* aObj = Object::fromQObject (a);
 
-	      if (aObj)
-		{
-		  graphics_object go = aObj->object ();
+              if (aObj)
+                {
+                  graphics_object go = aObj->object ();
 
-		  // Probably overkill as a uimenu child can only be another
-		  // uimenu object.
-		  if (go.isa ("uimenu"))
-		    {
-		      uimenu::properties& up = Utils::properties<uimenu> (go);
+                  // Probably overkill as a uimenu child can only be another
+                  // uimenu object.
+                  if (go.isa ("uimenu"))
+                    {
+                      uimenu::properties& up = Utils::properties<uimenu> (go);
 
-		      up.get_property ("position").set
-			(octave_value (count), true, false);
-		    }
-		}
+                      up.get_property ("position").set
+                        (octave_value (count), true, false);
+                    }
+                }
 
-	      count++;
-	    }
-	}
+              count++;
+            }
+        }
     }
 }
 
--- a/libgui/graphics/MouseModeActionGroup.cc
+++ b/libgui/graphics/MouseModeActionGroup.cc
@@ -37,13 +37,13 @@
   : QObject (parent), m_current (0)
 {
   m_actions.append (new QAction (QIcon (":/images/rotate.png"),
-				 tr ("Rotate"), this));
+                                 tr ("Rotate"), this));
   m_actions.append (new QAction (QIcon (":/images/zoom.png"),
-				 tr ("Zoom"), this));
+                                 tr ("Zoom"), this));
   m_actions.append (new QAction (QIcon (":/images/pan.png"),
-				 tr ("Pan"), this));
+                                 tr ("Pan"), this));
   m_actions.append (new QAction (QIcon (":/images/select.png"),
-				 tr ("Select"), this));
+                                 tr ("Select"), this));
   m_actions[2]->setEnabled (false);
   m_actions[3]->setEnabled (false);
 
@@ -63,23 +63,23 @@
   if (! checked)
     {
       if (sender () == m_current)
-	{
-	  m_current = 0;
-	  emit modeChanged (NoMode);
-	}
+        {
+          m_current = 0;
+          emit modeChanged (NoMode);
+        }
     }
   else
     {
       int i = m_actions.indexOf (qobject_cast<QAction*> (sender ()));
 
       if (i >= 0)
-	{
-	  m_current = m_actions[i];
-	  for (int j = 0; j < m_actions.size (); j++)
-	    if (j != i)
-	      m_actions[j]->setChecked (false);
-	  emit modeChanged (static_cast<MouseMode> (i+1));
-	}
+        {
+          m_current = m_actions[i];
+          for (int j = 0; j < m_actions.size (); j++)
+            if (j != i)
+              m_actions[j]->setChecked (false);
+          emit modeChanged (static_cast<MouseMode> (i+1));
+        }
     }
 }
 
--- a/libgui/graphics/Object.cc
+++ b/libgui/graphics/Object.cc
@@ -40,8 +40,8 @@
 
   if (! lock)
     qCritical ("QtHandles::Object::Object: "
-	       "creating Object (h=%g) without a valid lock!!!",
-	       m_handle.value ());
+               "creating Object (h=%g) without a valid lock!!!",
+               m_handle.value ());
 
   init (obj);
 }
@@ -50,16 +50,16 @@
 {
   if (m_qobject)
     qCritical ("QtHandles::Object::init: "
-	       "resetting QObject while in invalid state");
+               "resetting QObject while in invalid state");
 
   m_qobject = obj;
 
   if (m_qobject)
     {
       m_qobject->setProperty ("QtHandles::Object",
-			      qVariantFromValue<void*> (this));
+                              qVariantFromValue<void*> (this));
       connect (m_qobject, SIGNAL (destroyed (QObject*)),
-	       SLOT (objectDestroyed (QObject*)));
+               SLOT (objectDestroyed (QObject*)));
     }
 }
 
@@ -73,8 +73,8 @@
 
   if (! lock)
     qCritical ("QtHandles::Object::object: "
-	       "accessing graphics object (h=%g) without a valid lock!!!",
-	       m_handle.value ());
+               "accessing graphics object (h=%g) without a valid lock!!!",
+               m_handle.value ());
 
   return gh_manager::get_object (m_handle);
 }
@@ -93,7 +93,7 @@
       break;
     default:
       if (object ().valid_object ())
-	update (pId);
+        update (pId);
       break;
     }
 }
--- a/libgui/graphics/Object.h
+++ b/libgui/graphics/Object.h
@@ -55,14 +55,14 @@
   typename T::properties& properties (void)
     {
       return dynamic_cast<typename T::properties&>
-	(object ().get_properties ());
+        (object ().get_properties ());
     }
   
   template <class T>
   const typename T::properties& properties (void) const
     {
       return dynamic_cast<const typename T::properties&>
-	(object ().get_properties ());
+        (object ().get_properties ());
     }
 
   graphics_object object (void) const;
--- a/libgui/graphics/ObjectFactory.cc
+++ b/libgui/graphics/ObjectFactory.cc
@@ -62,7 +62,7 @@
   if (! s_instanceCreated)
     {
       if (QThread::currentThread () != QApplication::instance ()->thread ())
-	s_instance.moveToThread (QApplication::instance ()->thread ());
+        s_instance.moveToThread (QApplication::instance ()->thread ());
       s_instanceCreated = true;
     }
 
@@ -78,72 +78,72 @@
   if (go.valid_object ())
     {
       if (go.get_properties ().is_beingdeleted ())
-	qWarning ("ObjectFactory::createObject: object is being deleted");
+        qWarning ("ObjectFactory::createObject: object is being deleted");
       else
-	{
-	  ObjectProxy* proxy = Backend::toolkitObjectProxy (go);
+        {
+          ObjectProxy* proxy = Backend::toolkitObjectProxy (go);
 
-	  if (proxy)
-	    {
-	      Logger::debug ("ObjectFactory::createObject: "
-			     "create %s from thread %08x",
-			     go.type ().c_str (), QThread::currentThreadId ());
+          if (proxy)
+            {
+              Logger::debug ("ObjectFactory::createObject: "
+                             "create %s from thread %08x",
+                             go.type ().c_str (), QThread::currentThreadId ());
 
-	      Object* obj = 0;
+              Object* obj = 0;
 
-	      if (go.isa ("figure"))
-		obj = Figure::create (go);
-	      else if (go.isa ("uicontrol"))
-		{
-		  uicontrol::properties& up =
-		   Utils::properties<uicontrol> (go);
+              if (go.isa ("figure"))
+                obj = Figure::create (go);
+              else if (go.isa ("uicontrol"))
+                {
+                  uicontrol::properties& up =
+                   Utils::properties<uicontrol> (go);
 
-		  if (up.style_is ("pushbutton"))
-		    obj = PushButtonControl::create (go);
-		  else if (up.style_is ("edit"))
-		    obj = EditControl::create (go);
-		  else if (up.style_is ("checkbox"))
-		    obj = CheckBoxControl::create (go);
-		  else if (up.style_is ("radiobutton"))
-		    obj = RadioButtonControl::create (go);
-		  else if (up.style_is ("togglebutton"))
-		    obj = ToggleButtonControl::create (go);
-		  else if (up.style_is ("text"))
-		    obj = TextControl::create (go);
-		  else if (up.style_is ("popupmenu"))
-		    obj = PopupMenuControl::create (go);
-		  else if (up.style_is ("slider"))
-		    obj = SliderControl::create (go);
-		  else if (up.style_is ("listbox"))
-		    obj = ListBoxControl::create (go);
-		}
-	      else if (go.isa ("uipanel"))
-		obj = Panel::create (go);
-	      else if (go.isa ("uimenu"))
-		obj = Menu::create (go);
-	      else if (go.isa ("uicontextmenu"))
-		obj = ContextMenu::create (go);
-	      else if (go.isa ("uitoolbar"))
-		obj = ToolBar::create (go);
-	      else if (go.isa ("uipushtool"))
-		obj = PushTool::create (go);
-	      else if (go.isa ("uitoggletool"))
-		obj = ToggleTool::create (go);
-	      else
-		qWarning ("ObjectFactory::createObject: unsupported type `%s'",
-			  go.type ().c_str ());
+                  if (up.style_is ("pushbutton"))
+                    obj = PushButtonControl::create (go);
+                  else if (up.style_is ("edit"))
+                    obj = EditControl::create (go);
+                  else if (up.style_is ("checkbox"))
+                    obj = CheckBoxControl::create (go);
+                  else if (up.style_is ("radiobutton"))
+                    obj = RadioButtonControl::create (go);
+                  else if (up.style_is ("togglebutton"))
+                    obj = ToggleButtonControl::create (go);
+                  else if (up.style_is ("text"))
+                    obj = TextControl::create (go);
+                  else if (up.style_is ("popupmenu"))
+                    obj = PopupMenuControl::create (go);
+                  else if (up.style_is ("slider"))
+                    obj = SliderControl::create (go);
+                  else if (up.style_is ("listbox"))
+                    obj = ListBoxControl::create (go);
+                }
+              else if (go.isa ("uipanel"))
+                obj = Panel::create (go);
+              else if (go.isa ("uimenu"))
+                obj = Menu::create (go);
+              else if (go.isa ("uicontextmenu"))
+                obj = ContextMenu::create (go);
+              else if (go.isa ("uitoolbar"))
+                obj = ToolBar::create (go);
+              else if (go.isa ("uipushtool"))
+                obj = PushTool::create (go);
+              else if (go.isa ("uitoggletool"))
+                obj = ToggleTool::create (go);
+              else
+                qWarning ("ObjectFactory::createObject: unsupported type `%s'",
+                          go.type ().c_str ());
 
-	      if (obj)
-		proxy->setObject (obj);
-	    }
-	  else
-	    qWarning ("ObjectFactory::createObject: no proxy for handle %g",
-		      handle);
-	}
+              if (obj)
+                proxy->setObject (obj);
+            }
+          else
+            qWarning ("ObjectFactory::createObject: no proxy for handle %g",
+                      handle);
+        }
     }
   else
     qWarning ("ObjectFactory::createObject: invalid object for handle %g",
-	      handle);
+              handle);
 }
 
 };
--- a/libgui/graphics/ObjectProxy.cc
+++ b/libgui/graphics/ObjectProxy.cc
@@ -43,26 +43,26 @@
   if (obj != m_object)
     {
       if (m_object)
-	{
-	  disconnect (this, SIGNAL (sendUpdate (int)),
-		      m_object, SLOT (slotUpdate (int)));
-	  disconnect (this, SIGNAL (sendFinalize (void)),
-		      m_object, SLOT (slotFinalize (void)));
-	  disconnect (this, SIGNAL (sendRedraw (void)),
-		      m_object, SLOT (slotRedraw (void)));
-	}
+        {
+          disconnect (this, SIGNAL (sendUpdate (int)),
+                      m_object, SLOT (slotUpdate (int)));
+          disconnect (this, SIGNAL (sendFinalize (void)),
+                      m_object, SLOT (slotFinalize (void)));
+          disconnect (this, SIGNAL (sendRedraw (void)),
+                      m_object, SLOT (slotRedraw (void)));
+        }
 
       m_object = obj;
 
       if (m_object)
-	{
-	  connect (this, SIGNAL (sendUpdate (int)),
-		   m_object, SLOT (slotUpdate (int)));
-	  connect (this, SIGNAL (sendFinalize (void)),
-		   m_object, SLOT (slotFinalize (void)));
-	  connect (this, SIGNAL (sendRedraw (void)),
-		   m_object, SLOT (slotRedraw (void)));
-	}
+        {
+          connect (this, SIGNAL (sendUpdate (int)),
+                   m_object, SLOT (slotUpdate (int)));
+          connect (this, SIGNAL (sendFinalize (void)),
+                   m_object, SLOT (slotFinalize (void)));
+          connect (this, SIGNAL (sendRedraw (void)),
+                   m_object, SLOT (slotRedraw (void)));
+        }
     }
 }
 
--- a/libgui/graphics/Panel.cc
+++ b/libgui/graphics/Panel.cc
@@ -58,13 +58,13 @@
 static void setupPalette (const uipanel::properties& pp, QPalette& p)
 {
   p.setColor (QPalette::Window,
-	      Utils::fromRgb (pp.get_backgroundcolor_rgb ()));
+              Utils::fromRgb (pp.get_backgroundcolor_rgb ()));
   p.setColor (QPalette::WindowText,
-	      Utils::fromRgb (pp.get_foregroundcolor_rgb ()));
+              Utils::fromRgb (pp.get_foregroundcolor_rgb ()));
   p.setColor (QPalette::Light,
-	      Utils::fromRgb (pp.get_highlightcolor_rgb ()));
+              Utils::fromRgb (pp.get_highlightcolor_rgb ()));
   p.setColor (QPalette::Dark,
-	      Utils::fromRgb (pp.get_shadowcolor_rgb ()));
+              Utils::fromRgb (pp.get_shadowcolor_rgb ()));
 }
 
 static int borderWidthFromProperties (const uipanel::properties& pp)
@@ -75,7 +75,7 @@
     {
       bw = xround (pp.get_borderwidth ());
       if (pp.bordertype_is ("etchedin") || pp.bordertype_is ("etchedout"))
-	bw *= 2;
+        bw *= 2;
     }
 
   return bw;
@@ -90,7 +90,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new Panel (go, new QFrame (container));
+        return new Panel (go, new QFrame (container));
     }
 
   return 0;
@@ -105,7 +105,7 @@
   frame->setAutoFillBackground (true);
   Matrix bb = pp.get_boundingbox (false);
   frame->setGeometry (xround (bb(0)), xround (bb(1)),
-		      xround (bb(2)), xround (bb(3)));
+                      xround (bb(2)), xround (bb(3)));
   frame->setFrameStyle (frameStyleFromProperties (pp));
   frame->setLineWidth (xround (pp.get_borderwidth ()));
   QPalette pal = frame->palette ();
@@ -149,66 +149,66 @@
   if (! m_blockUpdates)
     {
       if (watched == qObject ())
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::Resize:
-		{
-		  gh_manager::auto_lock lock;
-		  graphics_object go = object ();
+        {
+          switch (event->type ())
+            {
+            case QEvent::Resize:
+                {
+                  gh_manager::auto_lock lock;
+                  graphics_object go = object ();
 
-		  if (go.valid_object ())
-		    {
-		      if (m_title)
-			{
-			  const uipanel::properties& pp =
-			    Utils::properties<uipanel> (go);
+                  if (go.valid_object ())
+                    {
+                      if (m_title)
+                        {
+                          const uipanel::properties& pp =
+                            Utils::properties<uipanel> (go);
 
-			  if (pp.fontunits_is ("normalized"))
-			    {
-			      QFrame* frame = qWidget<QFrame> ();
+                          if (pp.fontunits_is ("normalized"))
+                            {
+                              QFrame* frame = qWidget<QFrame> ();
 
-			      m_title->setFont (Utils::computeFont<uipanel>
-						(pp, frame->height ()));
-			      m_title->resize (m_title->sizeHint ());
-			    }
-			}
-		      updateLayout ();
-		    }
-		}
-	      break;
-	    case QEvent::MouseButtonPress:
-		{
-		  QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
+                              m_title->setFont (Utils::computeFont<uipanel>
+                                                (pp, frame->height ()));
+                              m_title->resize (m_title->sizeHint ());
+                            }
+                        }
+                      updateLayout ();
+                    }
+                }
+              break;
+            case QEvent::MouseButtonPress:
+                {
+                  QMouseEvent* m = dynamic_cast<QMouseEvent*> (event);
 
-		  if (m->button () == Qt::RightButton)
-		    {
-		      gh_manager::auto_lock lock;
+                  if (m->button () == Qt::RightButton)
+                    {
+                      gh_manager::auto_lock lock;
 
-		      ContextMenu::executeAt (properties (), m->globalPos ());
-		    }
-		}
-	      break;
-	    default:
-	      break;
-	    }
-	}
+                      ContextMenu::executeAt (properties (), m->globalPos ());
+                    }
+                }
+              break;
+            default:
+              break;
+            }
+        }
       else if (watched == m_container)
-	{
-	  switch (event->type ())
-	    {
-	    case QEvent::Resize:
-	      if (qWidget<QWidget> ()->isVisible ())
-		{
-		  gh_manager::auto_lock lock;
+        {
+          switch (event->type ())
+            {
+            case QEvent::Resize:
+              if (qWidget<QWidget> ()->isVisible ())
+                {
+                  gh_manager::auto_lock lock;
 
-		  properties ().update_boundingbox ();
-		}
-	      break;
-	    default:
-	      break;
-	    }
-	}
+                  properties ().update_boundingbox ();
+                }
+              break;
+            default:
+              break;
+            }
+        }
     }
 
   return false;
@@ -224,13 +224,13 @@
   switch (pId)
     {
     case uipanel::properties::ID_POSITION:
-	{
-	  Matrix bb = pp.get_boundingbox (false);
+        {
+          Matrix bb = pp.get_boundingbox (false);
 
-	  frame->setGeometry (xround (bb(0)), xround (bb(1)),
-			      xround (bb(2)), xround (bb(3)));
-	  updateLayout ();
-	}
+          frame->setGeometry (xround (bb(0)), xround (bb(1)),
+                              xround (bb(2)), xround (bb(3)));
+          updateLayout ();
+        }
       break;
     case uipanel::properties::ID_BORDERWIDTH:
       frame->setLineWidth (xround (pp.get_borderwidth ()));
@@ -240,46 +240,46 @@
     case uipanel::properties::ID_FOREGROUNDCOLOR:
     case uipanel::properties::ID_HIGHLIGHTCOLOR:
     case uipanel::properties::ID_SHADOWCOLOR:
-	{
-	  QPalette pal = frame->palette ();
+        {
+          QPalette pal = frame->palette ();
 
-	  setupPalette (pp, pal);
-	  frame->setPalette (pal);
-	  if (m_title)
-	    m_title->setPalette (pal);
-	}
+          setupPalette (pp, pal);
+          frame->setPalette (pal);
+          if (m_title)
+            m_title->setPalette (pal);
+        }
       break;
     case uipanel::properties::ID_TITLE:
-	{
-	  QString title = Utils::fromStdString (pp.get_title ());
+        {
+          QString title = Utils::fromStdString (pp.get_title ());
 
-	  if (title.isEmpty ())
-	    {
-	      if (m_title)
-		delete m_title;
-	      m_title = 0;
-	    }
-	  else
-	    {
-	      if (! m_title)
-		{
-		  QPalette pal = frame->palette ();
+          if (title.isEmpty ())
+            {
+              if (m_title)
+                delete m_title;
+              m_title = 0;
+            }
+          else
+            {
+              if (! m_title)
+                {
+                  QPalette pal = frame->palette ();
 
-		  m_title = new QLabel (title, frame);
-		  m_title->setAutoFillBackground (true);
-		  m_title->setContentsMargins (4, 0, 4, 0);
-		  m_title->setPalette (pal);
-		  m_title->setFont (Utils::computeFont<uipanel> (pp));
-		  m_title->show ();
-		}
-	      else
-		{
-		  m_title->setText (title);
-		  m_title->resize (m_title->sizeHint ());
-		}
-	    }
-	  updateLayout ();
-	}
+                  m_title = new QLabel (title, frame);
+                  m_title->setAutoFillBackground (true);
+                  m_title->setContentsMargins (4, 0, 4, 0);
+                  m_title->setPalette (pal);
+                  m_title->setFont (Utils::computeFont<uipanel> (pp));
+                  m_title->show ();
+                }
+              else
+                {
+                  m_title->setText (title);
+                  m_title->resize (m_title->sizeHint ());
+                }
+            }
+          updateLayout ();
+        }
     case uipanel::properties::ID_TITLEPOSITION:
       updateLayout ();
       break;
@@ -292,11 +292,11 @@
     case uipanel::properties::ID_FONTWEIGHT:
     case uipanel::properties::ID_FONTANGLE:
       if (m_title)
-	{
-	  m_title->setFont (Utils::computeFont<uipanel> (pp));
-	  m_title->resize (m_title->sizeHint ());
-	  updateLayout ();
-	}
+        {
+          m_title->setFont (Utils::computeFont<uipanel> (pp));
+          m_title->resize (m_title->sizeHint ());
+          updateLayout ();
+        }
       break;
     case uipanel::properties::ID_VISIBLE:
       frame->setVisible (pp.is_visible ());
@@ -326,9 +326,9 @@
   int bw = borderWidthFromProperties (pp);
 
   frame->setFrameRect (QRect (xround (bb(0)) - bw, xround (bb(1)) - bw,
-			      xround (bb(2)) + 2*bw, xround (bb(3)) + 2*bw));
+                              xround (bb(2)) + 2*bw, xround (bb(3)) + 2*bw));
   m_container->setGeometry (xround (bb(0)), xround (bb(1)),
-			    xround (bb(2)), xround (bb(3)));
+                            xround (bb(2)), xround (bb(3)));
 
   if (m_blockUpdates)
     pp.update_boundingbox ();
@@ -339,19 +339,19 @@
       int offset = 5;
 
       if (pp.titleposition_is ("lefttop"))
-	m_title->move (bw+offset, 0);
+        m_title->move (bw+offset, 0);
       else if (pp.titleposition_is ("righttop"))
-	m_title->move (frame->width () - bw - offset - sz.width (), 0);
+        m_title->move (frame->width () - bw - offset - sz.width (), 0);
       else if (pp.titleposition_is ("leftbottom"))
-	m_title->move (bw+offset, frame->height () - sz.height ());
+        m_title->move (bw+offset, frame->height () - sz.height ());
       else if (pp.titleposition_is ("rightbottom"))
-	m_title->move (frame->width () - bw - offset - sz.width (),
-		       frame->height () - sz.height ());
+        m_title->move (frame->width () - bw - offset - sz.width (),
+                       frame->height () - sz.height ());
       else if (pp.titleposition_is ("centertop"))
-	m_title->move (frame->width () / 2 - sz.width () / 2, 0);
+        m_title->move (frame->width () / 2 - sz.width () / 2, 0);
       else if (pp.titleposition_is ("centerbottom"))
-	m_title->move (frame->width () / 2 - sz.width () / 2,
-		       frame->height () - sz.height ());
+        m_title->move (frame->width () / 2 - sz.width () / 2,
+                       frame->height () - sz.height ());
     }
 }
 
--- a/libgui/graphics/PopupMenuControl.cc
+++ b/libgui/graphics/PopupMenuControl.cc
@@ -42,7 +42,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new PopupMenuControl (go, new QComboBox (container));
+        return new PopupMenuControl (go, new QComboBox (container));
     }
 
   return 0;
@@ -56,7 +56,7 @@
   box->addItems (Utils::fromStdString (up.get_string_string ()).split ('|'));
 
   connect (box, SIGNAL (currentIndexChanged (int)),
-	   SLOT (currentIndexChanged (int)));
+           SLOT (currentIndexChanged (int)));
 }
 
 PopupMenuControl::~PopupMenuControl (void)
@@ -72,43 +72,43 @@
     {
     case uicontrol::properties::ID_STRING:
       m_blockUpdate = true;
-	{
-	  int oldCurrent = box->currentIndex ();
+        {
+          int oldCurrent = box->currentIndex ();
 
-	  box->clear ();
-	  box->addItems (Utils::fromStdString
-			 (up.get_string_string ()).split ('|'));
-	  if (box->count() > 0
-	      && oldCurrent >= 0
-	      && oldCurrent < box->count ())
-	    {
-	      box->setCurrentIndex (oldCurrent);
-	    }
-	  else
-	    {
-	      gh_manager::post_set (m_handle, "value",
-				    octave_value (box->count () > 0
-						  ? 1.0 : 0.0),
-				    false);
-	    }
-	}
+          box->clear ();
+          box->addItems (Utils::fromStdString
+                         (up.get_string_string ()).split ('|'));
+          if (box->count() > 0
+              && oldCurrent >= 0
+              && oldCurrent < box->count ())
+            {
+              box->setCurrentIndex (oldCurrent);
+            }
+          else
+            {
+              gh_manager::post_set (m_handle, "value",
+                                    octave_value (box->count () > 0
+                                                  ? 1.0 : 0.0),
+                                    false);
+            }
+        }
       m_blockUpdate = false;
       break;
     case uicontrol::properties::ID_VALUE:
-	{
-	  Matrix value = up.get_value ().matrix_value ();
+        {
+          Matrix value = up.get_value ().matrix_value ();
 
-	  if (value.numel () > 0)
-	    {
-	      int newIndex = int (value(0)) - 1;
+          if (value.numel () > 0)
+            {
+              int newIndex = int (value(0)) - 1;
 
-	      if (newIndex >= 0 && newIndex < box->count ()
-		  && newIndex != box->currentIndex ())
-		{
-		  box->setCurrentIndex (newIndex);
-		}
-	    }
-	}
+              if (newIndex >= 0 && newIndex < box->count ()
+                  && newIndex != box->currentIndex ())
+                {
+                  box->setCurrentIndex (newIndex);
+                }
+            }
+        }
       break;
     default:
       BaseControl::update (pId);
@@ -121,8 +121,8 @@
   if (! m_blockUpdate)
     {
       gh_manager::post_set (m_handle, "value",
-			    octave_value (double (index + 1)),
-			    false);
+                            octave_value (double (index + 1)),
+                            false);
       gh_manager::post_callback (m_handle, "callback");
     }
 }
--- a/libgui/graphics/PushButtonControl.cc
+++ b/libgui/graphics/PushButtonControl.cc
@@ -43,7 +43,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new PushButtonControl (go, new QPushButton (container));
+        return new PushButtonControl (go, new QPushButton (container));
     }
 
   return 0;
--- a/libgui/graphics/PushTool.cc
+++ b/libgui/graphics/PushTool.cc
@@ -40,7 +40,7 @@
       QWidget* parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-	return new PushTool (go, new QAction (parentWidget));
+        return new PushTool (go, new QAction (parentWidget));
     }
 
   return 0;
--- a/libgui/graphics/QtHandlesUtils.cc
+++ b/libgui/graphics/QtHandlesUtils.cc
@@ -108,9 +108,9 @@
 }
 
 template QFont computeFont<uicontrol> (const uicontrol::properties& props,
-				       int height);
+                                       int height);
 template QFont computeFont<uipanel> (const uipanel::properties& props,
-				     int height);
+                                     int height);
 
 QColor fromRgb (const Matrix& rgb)
 {
@@ -142,26 +142,26 @@
       Qt::KeyboardModifiers mods = event->modifiers ();
 
       if (mods == Qt::NoModifier)
-	{
-	  if (buttons == Qt::LeftButton)
-	    return std::string ("normal");
-	  else if (buttons == Qt::RightButton)
-	    return std::string ("alt");
+        {
+          if (buttons == Qt::LeftButton)
+            return std::string ("normal");
+          else if (buttons == Qt::RightButton)
+            return std::string ("alt");
 #if defined (Q_WS_WIN)
-	  else if (buttons == (Qt::LeftButton|Qt::RightButton))
-	    return std::string ("extend");
+          else if (buttons == (Qt::LeftButton|Qt::RightButton))
+            return std::string ("extend");
 #elif defined (Q_WS_X11)
-	  else if (buttons == Qt::MidButton)
-	    return std::string ("extend");
+          else if (buttons == Qt::MidButton)
+            return std::string ("extend");
 #endif
-	}
+        }
       else if (buttons == Qt::LeftButton)
-	{
-	  if (mods == Qt::ShiftModifier)
-	    return std::string ("extend");
-	  else if (mods == Qt::ControlModifier)
-	    return std::string ("alt");
-	}
+        {
+          if (mods == Qt::ShiftModifier)
+            return std::string ("extend");
+          else if (mods == Qt::ControlModifier)
+            return std::string ("alt");
+        }
     }
 
   return std::string ("normal");
@@ -176,20 +176,20 @@
       Container* c = tkFig->innerContainer ();
 
       if (c)
-	{
-	  QPoint qp = c->mapFromGlobal (event->globalPos ());
+        {
+          QPoint qp = c->mapFromGlobal (event->globalPos ());
 
-	  return
-	    tkFig->properties<figure> ().map_from_boundingbox (qp.x (),
-							       qp.y ());
-	}
+          return
+            tkFig->properties<figure> ().map_from_boundingbox (qp.x (),
+                                                               qp.y ());
+        }
     }
 
   return Matrix (1, 2, 0.0);
 }
 
 Qt::Alignment fromHVAlign (const caseless_str& halign,
-			   const caseless_str& valign)
+                           const caseless_str& valign)
 {
   Qt::Alignment flags;
 
@@ -230,58 +230,58 @@
       img.fill (qRgba (0, 0, 0, 0));
 
       if (v.is_uint8_type ())
-	{
-	  uint8NDArray d = v.uint8_array_value ();
+        {
+          uint8NDArray d = v.uint8_array_value ();
 
-	  for (int i = 0; i < w; i++)
-	    for (int j = 0; j < h; j++)
-	      {
-		int r = d(j, i, 0);
-		int g = d(j, i, 1);
-		int b = d(j, i, 2);
-		int a = 255;
+          for (int i = 0; i < w; i++)
+            for (int j = 0; j < h; j++)
+              {
+                int r = d(j, i, 0);
+                int g = d(j, i, 1);
+                int b = d(j, i, 2);
+                int a = 255;
 
-		img.setPixel (x_off + i, y_off + j, qRgba (r, g, b, a));
-	      }
-	}
+                img.setPixel (x_off + i, y_off + j, qRgba (r, g, b, a));
+              }
+        }
       else if (v.is_single_type ())
-	{
-	  FloatNDArray f = v.float_array_value ();
+        {
+          FloatNDArray f = v.float_array_value ();
 
-	  for (int i = 0; i < w; i++)
-	    for (int j = 0; j < h; j++)
-	      {
-		float r = f(j, i, 0);
-		float g = f(j, i, 1);
-		float b = f(j, i, 2);
-		int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
+          for (int i = 0; i < w; i++)
+            for (int j = 0; j < h; j++)
+              {
+                float r = f(j, i, 0);
+                float g = f(j, i, 1);
+                float b = f(j, i, 2);
+                int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
 
-		img.setPixel (x_off + i, y_off + j,
-			      qRgba (xround (r * 255),
-				     xround (g * 255),
-				     xround (b * 255),
-				     a));
-	      }
-	}
+                img.setPixel (x_off + i, y_off + j,
+                              qRgba (xround (r * 255),
+                                     xround (g * 255),
+                                     xround (b * 255),
+                                     a));
+              }
+        }
       else if (v.is_real_type ())
-	{
-	  NDArray d = v.array_value ();
+        {
+          NDArray d = v.array_value ();
 
-	  for (int i = 0; i < w; i++)
-	    for (int j = 0; j < h; j++)
-	      {
-		double r = d(j, i, 0);
-		double g = d(j, i, 1);
-		double b = d(j, i, 2);
-		int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
+          for (int i = 0; i < w; i++)
+            for (int j = 0; j < h; j++)
+              {
+                double r = d(j, i, 0);
+                double g = d(j, i, 1);
+                double b = d(j, i, 2);
+                int a = (xisnan (r) || xisnan (g) || xisnan (b) ? 0 : 255);
 
-		img.setPixel (x_off + i, y_off + j,
-			      qRgba (xround (r * 255),
-				     xround (g * 255),
-				     xround (b * 255),
-				     a));
-	      }
-	}
+                img.setPixel (x_off + i, y_off + j,
+                              qRgba (xround (r * 255),
+                                     xround (g * 255),
+                                     xround (b * 255),
+                                     a));
+              }
+        }
 
       return img;
     }
--- a/libgui/graphics/QtHandlesUtils.h
+++ b/libgui/graphics/QtHandlesUtils.h
@@ -54,10 +54,10 @@
   Matrix toRgb (const QColor& c);
 
   Qt::Alignment fromHVAlign (const caseless_str& halign,
-			     const caseless_str& valign);
+                             const caseless_str& valign);
 
   std::string figureSelectionType (QMouseEvent* event,
-				   bool isDoubleClick = false);
+                                   bool isDoubleClick = false);
 
   Matrix figureCurrentPoint (const graphics_object& fig, QMouseEvent* event);
 
@@ -72,7 +72,7 @@
     { return Utils::properties<T> (gh_manager::get_object (h)); }
 
   QImage makeImageFromCData (const octave_value& v, int width = -1,
-			     int height = -1);
+                             int height = -1);
 
   octave_scalar_map makeKeyEventStruct (QKeyEvent* event);
 };
--- a/libgui/graphics/RadioButtonControl.cc
+++ b/libgui/graphics/RadioButtonControl.cc
@@ -42,14 +42,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new RadioButtonControl (go, new QRadioButton (container));
+        return new RadioButtonControl (go, new QRadioButton (container));
     }
 
   return 0;
 }
 
 RadioButtonControl::RadioButtonControl (const graphics_object& go,
-					QRadioButton* radio)
+                                        QRadioButton* radio)
     : ButtonControl (go, radio)
 {
   radio->setAutoFillBackground (true);
--- a/libgui/graphics/SliderControl.cc
+++ b/libgui/graphics/SliderControl.cc
@@ -44,14 +44,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new SliderControl (go, new QScrollBar (container));
+        return new SliderControl (go, new QScrollBar (container));
     }
 
   return 0;
 }
 
 SliderControl::SliderControl (const graphics_object& go,
-			      QAbstractSlider* slider)
+                              QAbstractSlider* slider)
     : BaseControl (go, slider), m_blockUpdates (false)
 {
   uicontrol::properties& up = properties<uicontrol> ();
@@ -70,7 +70,7 @@
       double dmin = up.get_min (), dmax = up.get_max ();
 
       slider->setValue (xround (((value(0) - dmin) / (dmax - dmin))
-				* RANGE_INT_MAX));
+                                * RANGE_INT_MAX));
     }
 
   connect (slider, SIGNAL (valueChanged (int)), SLOT (valueChanged (int)));
@@ -88,28 +88,28 @@
   switch (pId)
     {
     case uicontrol::properties::ID_SLIDERSTEP:
-	{
-	  Matrix steps = up.get_sliderstep ().matrix_value ();
+        {
+          Matrix steps = up.get_sliderstep ().matrix_value ();
 
-	  slider->setSingleStep (xround (steps(0) * RANGE_INT_MAX));
-	  slider->setPageStep (xround (steps(1) * RANGE_INT_MAX));
-	}
+          slider->setSingleStep (xround (steps(0) * RANGE_INT_MAX));
+          slider->setPageStep (xround (steps(1) * RANGE_INT_MAX));
+        }
       break;
     case uicontrol::properties::ID_VALUE:
-	{
-	  Matrix value = up.get_value ().matrix_value ();
-	  double dmax = up.get_max (), dmin = up.get_min ();
+        {
+          Matrix value = up.get_value ().matrix_value ();
+          double dmax = up.get_max (), dmin = up.get_min ();
 
-	  if (value.numel () > 0)
-	    {
-	      int ival = xround (((value(0) - dmin) / (dmax - dmin))
-				 * RANGE_INT_MAX);
+          if (value.numel () > 0)
+            {
+              int ival = xround (((value(0) - dmin) / (dmax - dmin))
+                                 * RANGE_INT_MAX);
 
-	      m_blockUpdates = true;
-	      slider->setValue (ival);
-	      m_blockUpdates = false;
-	    }
-	}
+              m_blockUpdates = true;
+              slider->setValue (ival);
+              m_blockUpdates = false;
+            }
+        }
       break;
     default:
       BaseControl::update (pId);
@@ -125,25 +125,25 @@
       graphics_object go = object ();
 
       if (go.valid_object ())
-	{
-	  uicontrol::properties& up = Utils::properties<uicontrol> (go);
+        {
+          uicontrol::properties& up = Utils::properties<uicontrol> (go);
 
-	  Matrix value = up.get_value ().matrix_value ();
-	  double dmin = up.get_min (), dmax = up.get_max ();
+          Matrix value = up.get_value ().matrix_value ();
+          double dmin = up.get_min (), dmax = up.get_max ();
 
-	  int ival_tmp = (value.numel () > 0 ?
-			  xround (((value(0) - dmin) / (dmax - dmin))
-				  * RANGE_INT_MAX) :
-			  0);
+          int ival_tmp = (value.numel () > 0 ?
+                          xround (((value(0) - dmin) / (dmax - dmin))
+                                  * RANGE_INT_MAX) :
+                          0);
 
-	  if (ival != ival_tmp || value.numel () > 0)
-	    {
-	      double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX);
+          if (ival != ival_tmp || value.numel () > 0)
+            {
+              double dval = dmin + (ival * (dmax - dmin) / RANGE_INT_MAX);
 
-	      gh_manager::post_set (m_handle, "value", octave_value (dval));
-	      gh_manager::post_callback (m_handle, "callback");
-	    }
-	}
+              gh_manager::post_set (m_handle, "value", octave_value (dval));
+              gh_manager::post_callback (m_handle, "callback");
+            }
+        }
     }
 }
 
--- a/libgui/graphics/TextControl.cc
+++ b/libgui/graphics/TextControl.cc
@@ -42,7 +42,7 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new TextControl (go, new QLabel (container));
+        return new TextControl (go, new QLabel (container));
     }
 
   return 0;
@@ -57,7 +57,7 @@
   label->setTextFormat (Qt::PlainText);
   label->setWordWrap (false);
   label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					   up.get_verticalalignment ()));
+                                           up.get_verticalalignment ()));
   // FIXME: support string_vector
   label->setText (Utils::fromStdString (up.get_string_string ()));
 }
@@ -80,7 +80,7 @@
     case uicontrol::properties::ID_HORIZONTALALIGNMENT:
     case uicontrol::properties::ID_VERTICALALIGNMENT:
       label->setAlignment (Utils::fromHVAlign (up.get_horizontalalignment (),
-					       up.get_verticalalignment ()));
+                                               up.get_verticalalignment ()));
       break;
     default:
       BaseControl::update (pId);
--- a/libgui/graphics/ToggleButtonControl.cc
+++ b/libgui/graphics/ToggleButtonControl.cc
@@ -42,14 +42,14 @@
       Container* container = parent->innerContainer ();
 
       if (container)
-	return new ToggleButtonControl (go, new QPushButton (container));
+        return new ToggleButtonControl (go, new QPushButton (container));
     }
 
   return 0;
 }
 
 ToggleButtonControl::ToggleButtonControl (const graphics_object& go,
-					  QPushButton* btn)
+                                          QPushButton* btn)
     : ButtonControl (go, btn)
 {
   btn->setCheckable (true);
--- a/libgui/graphics/ToggleTool.cc
+++ b/libgui/graphics/ToggleTool.cc
@@ -40,7 +40,7 @@
       QWidget* parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-	return new ToggleTool (go, new QAction (parentWidget));
+        return new ToggleTool (go, new QAction (parentWidget));
     }
 
   return 0;
@@ -55,7 +55,7 @@
   action->setChecked (tp.is_state ());
 
   connect (action, SIGNAL (toggled (bool)),
-	   this, SLOT (triggered (bool)));
+           this, SLOT (triggered (bool)));
 }
 
 ToggleTool::~ToggleTool (void)
@@ -82,9 +82,9 @@
 {
   gh_manager::post_set (m_handle, "state", checked, false);
   gh_manager::post_callback (m_handle,
-			     checked
-			     ? "oncallback"
-			     : "offcallback");
+                             checked
+                             ? "oncallback"
+                             : "offcallback");
   gh_manager::post_callback (m_handle, "clickedcallback");
 }
 
--- a/libgui/graphics/ToolBar.cc
+++ b/libgui/graphics/ToolBar.cc
@@ -71,7 +71,7 @@
       QWidget* parentWidget = parent->qWidget<QWidget> ();
 
       if (parentWidget)
-	return new ToolBar (go, new QToolBar (parentWidget));
+        return new ToolBar (go, new QToolBar (parentWidget));
     }
 
   return 0;
@@ -110,7 +110,7 @@
     {
     case base_properties::ID_VISIBLE:
       if (m_figure)
-	m_figure->showCustomToolBar (bar, tp.is_visible ());
+        m_figure->showCustomToolBar (bar, tp.is_visible ());
       break;
     default:
       Object::update (pId);
@@ -123,31 +123,31 @@
   if (watched == qObject ())
     {
       switch (event->type ())
-	{
-	case QEvent::ActionAdded:
-	case QEvent::ActionRemoved:
-	    {
-	      QActionEvent* ae = dynamic_cast<QActionEvent*> (event);
-	      QToolBar* bar = qWidget<QToolBar> ();
+        {
+        case QEvent::ActionAdded:
+        case QEvent::ActionRemoved:
+            {
+              QActionEvent* ae = dynamic_cast<QActionEvent*> (event);
+              QToolBar* bar = qWidget<QToolBar> ();
 
-	      if (ae->action () != m_empty)
-		{
-		  if (event->type () == QEvent::ActionAdded)
-		    {
-		      if (bar->actions ().size () == 2)
-			QTimer::singleShot (0, this, SLOT (hideEmpty (void)));
-		    }
-		  else
-		    {
-		      if (bar->actions ().size () == 1)
-			m_empty->setVisible (true);
-		    }
-		}
-	    }
-	  break;
-	default:
-	  break;
-	}
+              if (ae->action () != m_empty)
+                {
+                  if (event->type () == QEvent::ActionAdded)
+                    {
+                      if (bar->actions ().size () == 2)
+                        QTimer::singleShot (0, this, SLOT (hideEmpty (void)));
+                    }
+                  else
+                    {
+                      if (bar->actions ().size () == 1)
+                        m_empty->setVisible (true);
+                    }
+                }
+            }
+          break;
+        default:
+          break;
+        }
     }
 
   return false;
@@ -165,7 +165,7 @@
       QToolBar* bar = qWidget<QToolBar> ();
 
       if (bar)
-	m_figure->showCustomToolBar (bar, false);
+        m_figure->showCustomToolBar (bar, false);
     }
 }
 
--- a/libgui/graphics/ToolBarButton.cc
+++ b/libgui/graphics/ToolBarButton.cc
@@ -74,38 +74,38 @@
     case base_properties::ID_VISIBLE:
       action->setVisible (tp.is_visible ());
       if (m_separator)
-	m_separator->setVisible (tp.is_visible ());
+        m_separator->setVisible (tp.is_visible ());
       break;
     case T::properties::ID_TOOLTIPSTRING:
       action->setToolTip (Utils::fromStdString (tp.get_tooltipstring ()));
       break;
     case T::properties::ID_CDATA:
-	{
-	  QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16);
+        {
+          QImage img = Utils::makeImageFromCData (tp.get_cdata (), 16, 16);
 
-	  action->setIcon (QIcon (QPixmap::fromImage (img)));
-	}
+          action->setIcon (QIcon (QPixmap::fromImage (img)));
+        }
       break;
     case T::properties::ID_SEPARATOR:
       if (tp.is_separator ())
-	{
-	  if (! m_separator)
-	    {
-	      m_separator = new QAction (action);
-	      m_separator->setSeparator (true);
-	      m_separator->setVisible (tp.is_visible ());
+        {
+          if (! m_separator)
+            {
+              m_separator = new QAction (action);
+              m_separator->setSeparator (true);
+              m_separator->setVisible (tp.is_visible ());
 
-	      QWidget* w = qobject_cast<QWidget*> (action->parent ());
+              QWidget* w = qobject_cast<QWidget*> (action->parent ());
 
-	      w->insertAction (action, m_separator);
-	    }
-	}
+              w->insertAction (action, m_separator);
+            }
+        }
       else
-	{
-	  if (m_separator)
-	    delete m_separator;
-	  m_separator = 0;
-	}
+        {
+          if (m_separator)
+            delete m_separator;
+          m_separator = 0;
+        }
       break;
     case T::properties::ID_ENABLE:
       action->setEnabled (tp.is_enable ());
--- a/libgui/graphics/__init_qt__.cc
+++ b/libgui/graphics/__init_qt__.cc
@@ -48,45 +48,45 @@
   if (! qtHandlesInitialized)
     {
       if (qApp)
-	{
-	  qRegisterMetaType<graphics_object> ("graphics_object");
+        {
+          qRegisterMetaType<graphics_object> ("graphics_object");
 
-	  gh_manager::enable_event_processing (true);
+          gh_manager::enable_event_processing (true);
 
-	  graphics_toolkit tk (new Backend ());
+          graphics_toolkit tk (new Backend ());
           gtk_manager::load_toolkit (tk);
 
-	  octave_add_atexit_function ("__shutdown_qt__");
+          octave_add_atexit_function ("__shutdown_qt__");
 
-	  // Change some default settings to use Qt default colors
-	  QPalette p;
-	  graphics_object root = gh_manager::get_object (0);
+          // Change some default settings to use Qt default colors
+          QPalette p;
+          graphics_object root = gh_manager::get_object (0);
 
-	  /*
-	  root.set ("defaultfigurecolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Window))));
-	  */
-	  root.set ("defaultuicontrolbackgroundcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Window))));
-	  root.set ("defaultuicontrolforegroundcolor",
-		    octave_value (Utils::toRgb
-				  (p.color (QPalette::WindowText))));
-	  root.set ("defaultuipanelbackgroundcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Window))));
-	  root.set ("defaultuipanelforegroundcolor",
-		    octave_value (Utils::toRgb
-				  (p.color (QPalette::WindowText))));
-	  root.set ("defaultuipanelhighlightcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Light))));
-	  root.set ("defaultuipanelshadowcolor",
-		    octave_value (Utils::toRgb (p.color (QPalette::Dark))));
+          /*
+          root.set ("defaultfigurecolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Window))));
+          */
+          root.set ("defaultuicontrolbackgroundcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Window))));
+          root.set ("defaultuicontrolforegroundcolor",
+                    octave_value (Utils::toRgb
+                                  (p.color (QPalette::WindowText))));
+          root.set ("defaultuipanelbackgroundcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Window))));
+          root.set ("defaultuipanelforegroundcolor",
+                    octave_value (Utils::toRgb
+                                  (p.color (QPalette::WindowText))));
+          root.set ("defaultuipanelhighlightcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Light))));
+          root.set ("defaultuipanelshadowcolor",
+                    octave_value (Utils::toRgb (p.color (QPalette::Dark))));
 
-	  qtHandlesInitialized = true;
+          qtHandlesInitialized = true;
 
-	  return true;
-	}
+          return true;
+        }
       else
-	error ("__init_qt__: QApplication object must exist.");
+        error ("__init_qt__: QApplication object must exist.");
     }
 
   return false;
@@ -213,45 +213,45 @@
       QString filter;
       QStringList files =
         QFileDialog::getOpenFileNames (0, caption, defaultFileName,
-				       filterSpecs.join (";;"), &filter, 0);
+                                       filterSpecs.join (";;"), &filter, 0);
 
       if (! files.isEmpty ())
-	{
-	  Cell cFiles (1, files.length ());
-	  QString dirName;
-	  int i = 0;
+        {
+          Cell cFiles (1, files.length ());
+          QString dirName;
+          int i = 0;
 
-	  foreach (const QString& s, files)
-	    {
-	      QFileInfo fi (s);
+          foreach (const QString& s, files)
+            {
+              QFileInfo fi (s);
 
-	      if (dirName.isEmpty ())
-		dirName = appendDirSep (fi.canonicalPath ());
-	      cFiles(i++) = toStdString (fi.fileName ());
-	    }
+              if (dirName.isEmpty ())
+                dirName = appendDirSep (fi.canonicalPath ());
+              cFiles(i++) = toStdString (fi.fileName ());
+            }
 
-	  retval(0) = cFiles;
-	  retval(1) = toStdString (dirName);
-	  if (! filter.isEmpty ())
-	    retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
-	}
+          retval(0) = cFiles;
+          retval(1) = toStdString (dirName);
+          if (! filter.isEmpty ())
+            retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
+        }
     }
   else
     {
       QString filter;
       QString fileName =
         QFileDialog::getOpenFileName (0, caption, defaultFileName,
-				      filterSpecs.join (";;"), &filter, 0);
+                                      filterSpecs.join (";;"), &filter, 0);
 
       if (! fileName.isNull ())
-	{
-	  QFileInfo fi (fileName);
+        {
+          QFileInfo fi (fileName);
 
-	  retval(0) = toStdString (fi.fileName ());
-	  retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
-	  if (! filter.isEmpty ())
-	    retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
-	}
+          retval(0) = toStdString (fi.fileName ());
+          retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
+          if (! filter.isEmpty ())
+            retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
+        }
     }
 
   return retval;
@@ -289,7 +289,7 @@
   QString filter;
   QString fileName =
     QFileDialog::getSaveFileName (0, caption, defaultFileName,
-				  filterSpecs.join (";;"), &filter, 0);
+                                  filterSpecs.join (";;"), &filter, 0);
 
   if (! fileName.isNull ())
     {
@@ -297,11 +297,11 @@
 
       retval(0) = toStdString (fi.fileName ());
       if (fi.exists ())
-	retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
+        retval(1) = toStdString (appendDirSep (fi.canonicalPath ()));
       else
-	retval(1) = toStdString (appendDirSep (fi.absolutePath ()));
+        retval(1) = toStdString (appendDirSep (fi.absolutePath ()));
       if (! filter.isEmpty ())
-	retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
+        retval(2) = static_cast<double> (filterSpecs.indexOf (filter) + 1);
     }
 
   return retval;
@@ -321,7 +321,7 @@
   QString defaultDirectory = fromStdString (args(0).string_value ());
 
   QString dirName = QFileDialog::getExistingDirectory (0, caption,
-						       defaultDirectory);
+                                                       defaultDirectory);
 
   if (! dirName.isNull ())
     retval = toStdString (dirName);
--- a/libgui/qterminal/libqterminal/QTerminal.cc
+++ b/libgui/qterminal/libqterminal/QTerminal.cc
@@ -118,5 +118,5 @@
     (cursorUseForegroundColor,
      settings->value ("terminal/color_c",
                       QVariant (colors.at (3))).value<QColor> ());
-  setScrollBufferSize (settings->value ("terminal/history_buffer",1000).toInt() );
+  setScrollBufferSize (settings->value ("terminal/history_buffer",1000).toInt () );
 }
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp
@@ -1,5 +1,5 @@
 /*  Copyright (C) 2008 e_k (e_k@users.sourceforge.net)
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h
@@ -1,5 +1,5 @@
 /*  Copyright (C) 2008 e_k (e_k@users.sourceforge.net)
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
--- a/libgui/qterminal/libqterminal/unix/SelfListener.cpp
+++ b/libgui/qterminal/libqterminal/unix/SelfListener.cpp
@@ -1,5 +1,5 @@
 /* qterminal - a terminal widget for Qt
- * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@googlemail.com)
+ * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
--- a/libgui/qterminal/libqterminal/unix/SelfListener.h
+++ b/libgui/qterminal/libqterminal/unix/SelfListener.h
@@ -1,5 +1,5 @@
 /* qterminal - a terminal widget for Qt
- * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@googlemail.com)
+ * Copyright (C) 2011, 2013 Jacob Dawid (jacob.dawid@cybercatalyst.com)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
--- a/libgui/qterminal/libqterminal/unix/TerminalModel.cpp
+++ b/libgui/qterminal/libqterminal/unix/TerminalModel.cpp
@@ -5,7 +5,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/qterminal/libqterminal/unix/TerminalModel.h
+++ b/libgui/qterminal/libqterminal/unix/TerminalModel.h
@@ -5,7 +5,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/qterminal/libqterminal/unix/TerminalView.cpp
+++ b/libgui/qterminal/libqterminal/unix/TerminalView.cpp
@@ -5,7 +5,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/qterminal/libqterminal/unix/TerminalView.h
+++ b/libgui/qterminal/libqterminal/unix/TerminalView.h
@@ -3,7 +3,7 @@
     Copyright (C) 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
 
     Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
-    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@googlemail.com>
+    Copyright (C) 2012-2013 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
--- a/libgui/src/files-dock-widget.cc
+++ b/libgui/src/files-dock-widget.cc
@@ -551,7 +551,7 @@
   QItemSelectionModel *m = _file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
 
-  for ( QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+  for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
     {
       QFileInfo file = _file_system_model->fileInfo (*it);
       if (file.exists ())
@@ -661,7 +661,7 @@
   QItemSelectionModel *m = _file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
 
-  for ( QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
+  for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++)
     {
       QModelIndex index = *it;
 
--- a/libgui/src/find-files-model.cc
+++ b/libgui/src/find-files-model.cc
@@ -101,7 +101,7 @@
 void
 find_files_model::addFile (const QFileInfo &info)
 {
-  beginInsertRows (QModelIndex (), _files.size (), _files.size () );
+  beginInsertRows (QModelIndex (), _files.size (), _files.size ());
 
   QList<QFileInfo>::Iterator it;
   find_file_less_than less_than (_sortorder);
--- a/libgui/src/history-dock-widget.cc
+++ b/libgui/src/history-dock-widget.cc
@@ -214,7 +214,7 @@
   if (_filter_line_edit->hasFocus () && _filter_line_edit->hasSelectedText ())
     {
       QClipboard *clipboard = QApplication::clipboard ();
-      clipboard->setText ( _filter_line_edit->selectedText ());
+      clipboard->setText (_filter_line_edit->selectedText ());
     }
 }
 
--- a/libgui/src/m-editor/file-editor-interface.h
+++ b/libgui/src/m-editor/file-editor-interface.h
@@ -40,7 +40,7 @@
 
   virtual ~file_editor_interface () { }
 
-  virtual QMenu *get_mru_menu ( ) = 0;
+  virtual QMenu *get_mru_menu () = 0;
   virtual QMenu *debug_menu () = 0;
   virtual QToolBar *toolbar () = 0;
 
--- a/libgui/src/m-editor/find-dialog.cc
+++ b/libgui/src/m-editor/find-dialog.cc
@@ -211,7 +211,8 @@
 void
 find_dialog::find (bool forward)
 {
-  int line = -1, col = -1;
+  int line, col;
+  line = col = -1;
   bool do_wrap = _wrap_check_box->isChecked ();
   bool do_forward = forward;
 
--- a/libgui/src/m-editor/octave-qscintilla.cc
+++ b/libgui/src/m-editor/octave-qscintilla.cc
@@ -158,7 +158,7 @@
 octave_qscintilla::contextMenuEvent (QContextMenuEvent *e)
 {
   QPoint global_pos, local_pos;                         // the menu's position
-  QMenu *context_menu = createStandardContextMenu ( );  // standard menu
+  QMenu *context_menu = createStandardContextMenu ();  // standard menu
 
   // fill context menu with editor's standard actions
   emit create_context_menu_signal (context_menu);
@@ -247,7 +247,7 @@
 {
   QStringList commands = selectedText ().split (QRegExp("[\r\n]"),
                                                 QString::SkipEmptyParts);
-  for (int i = 0; i < commands.size (); i++ )
+  for (int i = 0; i < commands.size (); i++)
     emit execute_command_in_terminal_signal (commands.at (i));
 }
 
--- a/libgui/src/main-window.cc
+++ b/libgui/src/main-window.cc
@@ -1895,7 +1895,7 @@
 main_window::show_gui_info (void)
 {
   QString gui_info
-    ( QObject::tr ("<p><strong>A Note about Octave's New GUI</strong></p>"
+    (QObject::tr ("<p><strong>A Note about Octave's New GUI</strong></p>"
          "<p>One of the biggest new features for Octave 3.8 is a graphical "
          "user interface.  It is the one thing that users have requested "
          "most often over the last few years and now it is almost ready.  "
@@ -2370,7 +2370,7 @@
 
   QSettings *settings = resource_manager::get_settings ();
 
-  if (settings->value ("prompt_to_exit", false ).toBool())
+  if (settings->value ("prompt_to_exit", false).toBool ())
     {
       int ans = QMessageBox::question (this, tr ("Octave"),
          tr ("Are you sure you want to exit Octave?"),
--- a/libgui/src/octave-dock-widget.cc
+++ b/libgui/src/octave-dock-widget.cc
@@ -66,7 +66,7 @@
   _dock_button->setIconSize (QSize (12,12));
 
   _close_action = new QAction
-                   (QIcon (":/actions/icons/widget-close.png"), "", this );
+                   (QIcon (":/actions/icons/widget-close.png"), "", this);
   _close_action-> setToolTip (tr ("Hide widget"));
   connect (_close_action, SIGNAL (triggered (bool)),
            this, SLOT (change_visibility (bool)));
@@ -178,7 +178,7 @@
   _dock_action->setIcon (QIcon (":/actions/icons/widget-dock"+_icon_color+".png"));
   _dock_action->setToolTip (tr ("Dock widget"));
 
-  // restore the last geometry( when floating
+  // restore the last geometry when floating
   setGeometry (settings->value ("DockWidgets/" + objectName ()
                        + "_floating_geometry",QRect(50,100,480,480)).toRect ());
 
@@ -202,7 +202,7 @@
 {
 #if defined (Q_OS_WIN32)
 
-  // windows: Since floating widget has no parent, we have to readd it
+  // windows: Since floating widget has no parent, we have to read it
 
   QSettings *settings = resource_manager::get_settings ();
 
--- a/libgui/src/octave-qt-link.cc
+++ b/libgui/src/octave-qt-link.cc
@@ -100,7 +100,7 @@
     tr ("File\n%1\ndoes not exist. Do you want to create it?").
     arg (QDir::currentPath () + QDir::separator ()
          + QString::fromStdString (file)),
-    tr ("Octave Editor"), "quest", btn, tr ("Yes"), role );
+    tr ("Octave Editor"), "quest", btn, tr ("Yes"), role);
 
   // Wait while the user is responding to message box.
   uiwidget_creator.wait ();
--- a/libgui/src/qtinfo/parser.cc
+++ b/libgui/src/qtinfo/parser.cc
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: Jacob Dawid <jacob.dawid@gmail.com>
+// Author: Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -77,7 +77,7 @@
 parser::open_file (QFileInfo & file_info)
 {
   QIODevice *iodevice = 0;
-  if ( _compressors_map.contains(file_info.suffix ()))
+  if (_compressors_map.contains (file_info.suffix ()))
     {
       QProcess gzip;
       gzip.start (_compressors_map.value (file_info.suffix ()).arg (file_info.absoluteFilePath ()));
@@ -277,7 +277,7 @@
   QRegExp re ("(\\*[N|n]ote|\n\\*)([ |\n]+)([^:]+):([^:\\.,]*)([:,\\.]+)");
   int i = 0, f;
 
-  while ( (i = re.indexIn (text,i)) != -1)
+  while ((i = re.indexIn (text,i)) != -1)
     {
       QString type     = re.cap (1);
       QString note     = re.cap (3);
@@ -330,7 +330,7 @@
 {
   QRegExp re ("`([^']+)'");
   int i = 0, f;
-  while ( (i = re.indexIn (text, i)) != -1)
+  while ((i = re.indexIn (text, i)) != -1)
     {
       QString t = re.cap (1);
       QString bold = "<font style=\"color:SteelBlue;font-weight:bold\">" + t +
@@ -436,7 +436,7 @@
       while (! (nodeText=get_next_node (io)).isEmpty () && foundCount < 2)
         {
           QString first_line = get_first_line (nodeText);
-          if (first_line.startsWith ("Tag") )
+          if (first_line.startsWith ("Tag"))
             {
               foundCount++;
               int pos = 0;
@@ -471,7 +471,7 @@
               foundCount++;
               int pos = 0;
 
-              while ( (pos = re_files.indexIn (nodeText, pos)) != -1)
+              while ((pos = re_files.indexIn (nodeText, pos)) != -1)
                 {
                   QString fileCap = re_files.cap (1).trimmed ();
                   int index = re_files.cap (2).toInt ();
@@ -501,7 +501,8 @@
 void
 parser::real_position (int pos, QFileInfo & file_info, int & real_pos)
 {
-  int header = -1, sum = 0;
+  int header = -1;
+  int sum = 0;
   for (int i = 0; i < _info_file_real_size_list.size (); i++)
     {
       info_file_item item = _info_file_real_size_list.at (i);
@@ -538,7 +539,7 @@
 {
   int pos = 0;
 
-  while ( (pos = re.indexIn (text, pos)) != -1)
+  while ((pos = re.indexIn (text, pos)) != -1)
     {
       QString cap = text.mid (pos,re.matchedLength ());
       QString a (after);
@@ -578,7 +579,7 @@
         }
 
       QString node_text;
-      while ( !(node_text = get_next_node (io)).isEmpty ())
+      while (! (node_text = get_next_node (io)).isEmpty ())
         {
           QString firstLine = get_first_line (node_text);
           QString node = get_node_name (node_text);
--- a/libgui/src/qtinfo/parser.h
+++ b/libgui/src/qtinfo/parser.h
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: Jacob Dawid <jacob.dawid@gmail.com>
+// Author: Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #include <QStringList>
 #include <QIODevice>
--- a/libgui/src/qtinfo/webinfo.cc
+++ b/libgui/src/qtinfo/webinfo.cc
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: Jacob Dawid <jacob.dawid@gmail.com>
+// Author: Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -181,7 +181,7 @@
   _text_browser->show ();
 
   connect (_text_browser, SIGNAL (anchorClicked (const QUrl &)), this,
-           SLOT (link_clicked (const QUrl &)) );
+           SLOT (link_clicked (const QUrl &)));
   disconnect(_tab_bar, SIGNAL (currentChanged(int)), this,
              SLOT (current_tab_changed (int)));
 
--- a/libgui/src/qtinfo/webinfo.h
+++ b/libgui/src/qtinfo/webinfo.h
@@ -22,7 +22,7 @@
 */
 
 // Author: P. L. Lucas
-// Author: 2012 Jacob Dawid <jacob.dawid@gmail.com>
+// Author: 2012 Jacob Dawid <jacob.dawid@cybercatalyst.com>
 
 #include <QTextBrowser>
 #include "parser.h"
--- a/libgui/src/settings-dialog.cc
+++ b/libgui/src/settings-dialog.cc
@@ -140,7 +140,7 @@
   ui->customFileEditor->setText (
     settings->value ("customFileEditor").toString ());
   ui->editor_showLineNumbers->setChecked (
-    settings->value ("editor/showLineNumbers",true).toBool () );
+    settings->value ("editor/showLineNumbers",true).toBool ());
 
   default_var = QColor (240, 240, 240);
   QColor setting_color = settings->value ("editor/highlight_current_line_color",
@@ -152,7 +152,7 @@
   connect (ui->editor_highlightCurrentLine, SIGNAL (toggled (bool)),
            _editor_current_line_color, SLOT (setEnabled (bool)));
   ui->editor_highlightCurrentLine->setChecked (
-    settings->value ("editor/highlightCurrentLine",true).toBool () );
+    settings->value ("editor/highlightCurrentLine",true).toBool ());
   ui->editor_long_line_marker->setChecked (
     settings->value ("editor/long_line_marker",true).toBool ());
   ui->editor_long_line_column->setValue (
@@ -163,7 +163,7 @@
     settings->value ("editor/code_folding",true).toBool ());
 
   ui->editor_codeCompletion->setChecked (
-    settings->value ("editor/codeCompletion", true).toBool () );
+    settings->value ("editor/codeCompletion", true).toBool ());
   ui->editor_spinbox_ac_threshold->setValue (
     settings->value ("editor/codeCompletion_threshold",2).toInt ());
   ui->editor_checkbox_ac_keywords->setChecked (
@@ -203,7 +203,7 @@
 
   // terminal
   ui->terminal_fontName->setCurrentFont (QFont (
-    settings->value ("terminal/fontName","Courier New").toString ()) );
+    settings->value ("terminal/fontName","Courier New").toString ()));
   ui->terminal_fontSize->setValue (
     settings->value ("terminal/fontSize", 10).toInt ());
   ui->terminal_history_buffer->setValue (
@@ -262,7 +262,7 @@
 
   int currentIndex = 0;
   QString proxyTypeString = settings->value ("proxyType").toString ();
-  while ( (currentIndex < ui->proxyType->count ())
+  while ((currentIndex < ui->proxyType->count ())
           && (ui->proxyType->currentText () != proxyTypeString))
     {
       currentIndex++;
@@ -558,7 +558,7 @@
   settings->setValue ("toolbar_icon_size", ui->toolbar_icon_size->value ());
 
   // promp to exit
-  settings->setValue ( "prompt_to_exit", ui->cb_prompt_to_exit->isChecked ());
+  settings->setValue ("prompt_to_exit", ui->cb_prompt_to_exit->isChecked ());
 
   // status bar
   settings->setValue ( "show_status_bar", ui->cb_status_bar->isChecked ());
@@ -661,7 +661,7 @@
   settings->setValue ("terminal/focus_after_command",
                       ui->terminal_focus_command->isChecked ());
   settings->setValue ("terminal/history_buffer",
-                      ui->terminal_history_buffer->value() );
+                      ui->terminal_history_buffer->value ());
 
   // the cursor
   QString cursorType;
--- a/libgui/src/shortcut-manager.cc
+++ b/libgui/src/shortcut-manager.cc
@@ -82,25 +82,29 @@
   // actions of the main window
 
   // file
-  init (tr ("New File"), "main_file:new_file", QKeySequence::New );
-  init (tr ("New Function"), "main_file:new_function", QKeySequence ("Ctrl+Shift+N") );
-  init (tr ("New Figure"), "main_file:new_figure", QKeySequence () );
-  init (tr ("Open File"), "main_file:open_file", QKeySequence::Open );
-  init (tr ("Load Workspace"), "main_file:load_workspace", QKeySequence () );
-  init (tr ("Save Workspace As"), "main_file:save_workspace", QKeySequence () );
-  init (tr ("Preferences"), "main_file:preferences", QKeySequence () );
-  init (tr ("Exit Octave"), "main_file:exit", QKeySequence::Quit );
+  init (tr ("New File"), "main_file:new_file", QKeySequence::New);
+  init (tr ("New Function"), "main_file:new_function",
+        QKeySequence ("Ctrl+Shift+N"));
+  init (tr ("New Figure"), "main_file:new_figure", QKeySequence ());
+  init (tr ("Open File"), "main_file:open_file", QKeySequence::Open);
+  init (tr ("Load Workspace"), "main_file:load_workspace", QKeySequence ());
+  init (tr ("Save Workspace As"), "main_file:save_workspace", QKeySequence ());
+  init (tr ("Preferences"), "main_file:preferences", QKeySequence ());
+  init (tr ("Exit Octave"), "main_file:exit", QKeySequence::Quit);
 
   // edit
   init (tr ("Copy"), "main_edit:copy", QKeySequence::Copy);
   init (tr ("Paste"), "main_edit:paste", QKeySequence::Paste);
   init (tr ("Undo"), "main_edit:undo", QKeySequence::Undo);
-  init (tr ("Select All"), "main_edit:select_all", QKeySequence () );
-  init (tr ("Clear Clipboard"), "main_edit:clear_clipboard", QKeySequence () );
-  init (tr ("Find in Files"), "main_edit:find_in_files", QKeySequence (Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_F) );
-  init (tr ("Clear Command Window"), "main_edit:clear_command_window", QKeySequence () );
-  init (tr ("Clear Command History"), "main_edit:clear_history", QKeySequence () );
-  init (tr ("Clear Workspace"), "main_edit:clear_workspace", QKeySequence () );
+  init (tr ("Select All"), "main_edit:select_all", QKeySequence ());
+  init (tr ("Clear Clipboard"), "main_edit:clear_clipboard", QKeySequence ());
+  init (tr ("Find in Files"), "main_edit:find_in_files",
+        QKeySequence (Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_F));
+  init (tr ("Clear Command Window"), "main_edit:clear_command_window",
+        QKeySequence ());
+  init (tr ("Clear Command History"), "main_edit:clear_history",
+        QKeySequence ());
+  init (tr ("Clear Workspace"), "main_edit:clear_workspace", QKeySequence ());
 
   // debug
   init (tr ("Step Over"), "main_debug:step_over", QKeySequence (Qt::Key_F10));
@@ -143,68 +147,96 @@
   // actions of the editor
 
   // file
-  init (tr ("Edit Function"), "editor_file:edit_function", QKeySequence (Qt::ControlModifier + Qt::Key_E) );
-  init (tr ("Save File"), "editor_file:save", QKeySequence::Save );
-  init (tr ("Save File As"), "editor_file:save_as", QKeySequence::SaveAs );
-  init (tr ("Close"), "editor_file:close", QKeySequence::Close );
-  init (tr ("Close All"), "editor_file:close_all", QKeySequence () );
-  init (tr ("Close Other"), "editor_file:close_other",  QKeySequence () );
-  init (tr ("Print"), "editor_file:print",  QKeySequence::Print );
+  init (tr ("Edit Function"), "editor_file:edit_function",
+        QKeySequence (Qt::ControlModifier + Qt::Key_E));
+  init (tr ("Save File"), "editor_file:save", QKeySequence::Save);
+  init (tr ("Save File As"), "editor_file:save_as", QKeySequence::SaveAs);
+  init (tr ("Close"), "editor_file:close", QKeySequence::Close);
+  init (tr ("Close All"), "editor_file:close_all", QKeySequence ());
+  init (tr ("Close Other"), "editor_file:close_other", QKeySequence ());
+  init (tr ("Print"), "editor_file:print", QKeySequence::Print);
 
   // edit
-  init (tr ("Undo"), "editor_edit:undo",  QKeySequence::Undo );
-  init (tr ("Redo"), "editor_edit:redo",  QKeySequence::Redo );
-  init (tr ("Copy"), "editor_edit:copy",  QKeySequence::Copy );
-  init (tr ("Cuy"), "editor_edit:cut",  QKeySequence::Cut );
-  init (tr ("Paste"), "editor_edit:paste",  QKeySequence::Paste );
-  init (tr ("Select All"), "editor_edit:select_all",  QKeySequence::SelectAll );
-  init (tr ("Find and Replace"), "editor_edit:find_replace",  QKeySequence::Find );
+  init (tr ("Undo"), "editor_edit:undo", QKeySequence::Undo);
+  init (tr ("Redo"), "editor_edit:redo", QKeySequence::Redo);
+  init (tr ("Copy"), "editor_edit:copy", QKeySequence::Copy);
+  init (tr ("Cuy"), "editor_edit:cut", QKeySequence::Cut);
+  init (tr ("Paste"), "editor_edit:paste", QKeySequence::Paste);
+  init (tr ("Select All"), "editor_edit:select_all", QKeySequence::SelectAll);
+  init (tr ("Find and Replace"), "editor_edit:find_replace",
+        QKeySequence::Find);
 
-  init (tr ("Delete to Start of Word"), "editor_edit:delete_start_word",  QKeySequence::DeleteStartOfWord );
-  init (tr ("Delete to End of Word"), "editor_edit:delete_end_word",  QKeySequence::DeleteEndOfWord );
-  init (tr ("Delete to Start of Line"), "editor_edit:delete_start_line",  QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Backspace) );
-  init (tr ("Delete to End of Line"), "editor_edit:delete_end_line",  QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Delete) );
-  init (tr ("Delete Line"), "editor_edit:delete_line",  QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_L) );
-  init (tr ("Copy Line"), "editor_edit:copy_line",  QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_C) );
-  init (tr ("Cut Line"), "editor_edit:cut_line",  QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_X) );
-  init (tr ("Duplicate Selection/Line"), "editor_edit:duplicate_selection",  QKeySequence (Qt::ControlModifier + Qt::Key_D) );
-  init (tr ("Transpose Line"), "editor_edit:transpose_line",  QKeySequence (Qt::ControlModifier + Qt::Key_T) );
-  init (tr ("Completion List"), "editor_edit:completion_list",  QKeySequence (Qt::ControlModifier + Qt::Key_Space) );
+  init (tr ("Delete to Start of Word"), "editor_edit:delete_start_word", 
+        QKeySequence::DeleteStartOfWord);
+  init (tr ("Delete to End of Word"), "editor_edit:delete_end_word", 
+        QKeySequence::DeleteEndOfWord);
+  init (tr ("Delete to Start of Line"), "editor_edit:delete_start_line",
+        QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Backspace));
+  init (tr ("Delete to End of Line"), "editor_edit:delete_end_line",
+        QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_Delete));
+  init (tr ("Delete Line"), "editor_edit:delete_line", 
+        QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_L));
+  init (tr ("Copy Line"), "editor_edit:copy_line",
+        QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_C));
+  init (tr ("Cut Line"), "editor_edit:cut_line",
+        QKeySequence (Qt::ControlModifier + Qt::SHIFT + Qt::Key_X));
+  init (tr ("Duplicate Selection/Line"), "editor_edit:duplicate_selection", 
+        QKeySequence (Qt::ControlModifier + Qt::Key_D));
+  init (tr ("Transpose Line"), "editor_edit:transpose_line", 
+        QKeySequence (Qt::ControlModifier + Qt::Key_T));
+  init (tr ("Completion List"), "editor_edit:completion_list",
+        QKeySequence (Qt::ControlModifier + Qt::Key_Space));
 
-  init (tr ("Comment Selection"), "editor_edit:comment_selection",  QKeySequence (Qt::ControlModifier + Qt::Key_R) );
-  init (tr ("Uncomment Selection"), "editor_edit:uncomment_selection",  QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_R) );
-  init (tr ("Uppercase Selection"), "editor_edit:upper_case",  QKeySequence (Qt::ControlModifier + Qt::Key_U) );
-  init (tr ("Lowercase Selection"), "editor_edit:lower_case",  QKeySequence (Qt::ControlModifier + Qt::AltModifier + Qt::Key_U) );
-  init (tr ("Indent Selection"), "editor_edit:indent_selection",  QKeySequence (Qt::ControlModifier + Qt::Key_Tab) );
-  init (tr ("Unindent Selection"), "editor_edit:unindent_selection",  QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_Tab) );
+  init (tr ("Comment Selection"), "editor_edit:comment_selection",
+        QKeySequence (Qt::ControlModifier + Qt::Key_R));
+  init (tr ("Uncomment Selection"), "editor_edit:uncomment_selection", 
+        QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_R));
+  init (tr ("Uppercase Selection"), "editor_edit:upper_case",
+        QKeySequence (Qt::ControlModifier + Qt::Key_U));
+  init (tr ("Lowercase Selection"), "editor_edit:lower_case",
+        QKeySequence (Qt::ControlModifier + Qt::AltModifier + Qt::Key_U));
+  init (tr ("Indent Selection"), "editor_edit:indent_selection", 
+        QKeySequence (Qt::ControlModifier + Qt::Key_Tab));
+  init (tr ("Unindent Selection"), "editor_edit:unindent_selection",
+        QKeySequence (Qt::SHIFT + Qt::ControlModifier + Qt::Key_Tab));
 
-  init (tr ("Goto Line"), "editor_edit:goto_line",  QKeySequence (Qt::ControlModifier+ Qt::Key_G) );
-  init (tr ("Toggle Bookmark"), "editor_edit:toggle_bookmark",  QKeySequence (Qt::Key_F7) );
-  init (tr ("Next Bookmark"), "editor_edit:next_bookmark",  QKeySequence (Qt::Key_F2) );
-  init (tr ("Previous Bookmark"), "editor_edit:previous_bookmark",  QKeySequence (Qt::SHIFT + Qt::Key_F2) );
-  init (tr ("Remove All Bookmark"), "editor_edit:remove_bookmark",  QKeySequence () );
+  init (tr ("Goto Line"), "editor_edit:goto_line",
+        QKeySequence (Qt::ControlModifier+ Qt::Key_G));
+  init (tr ("Toggle Bookmark"), "editor_edit:toggle_bookmark",
+        QKeySequence (Qt::Key_F7));
+  init (tr ("Next Bookmark"), "editor_edit:next_bookmark",
+        QKeySequence (Qt::Key_F2));
+  init (tr ("Previous Bookmark"), "editor_edit:previous_bookmark",
+        QKeySequence (Qt::SHIFT + Qt::Key_F2));
+  init (tr ("Remove All Bookmark"), "editor_edit:remove_bookmark",
+        QKeySequence ());
 
-  init (tr ("Preferences"), "editor_edit:preferences",  QKeySequence () );
-  init (tr ("Styles Preferences"), "editor_edit:styles_preferences",  QKeySequence () );
+  init (tr ("Preferences"), "editor_edit:preferences", QKeySequence ());
+  init (tr ("Styles Preferences"), "editor_edit:styles_preferences",
+        QKeySequence ());
 
   // view
-  init (tr ("Zoom In"), "editor_view:zoom_in",  QKeySequence::ZoomIn );
-  init (tr ("Zoom Out"), "editor_view:zoom_out",  QKeySequence::ZoomOut );
+  init (tr ("Zoom In"), "editor_view:zoom_in", QKeySequence::ZoomIn);
+  init (tr ("Zoom Out"), "editor_view:zoom_out", QKeySequence::ZoomOut);
   init (tr ("Zoom Normal"), "editor_view:zoom_normal",  QKeySequence (Qt::ControlModifier + Qt::AltModifier + Qt::Key_0));
 
   // debug
-  init (tr ("Toggle Breakpoint"), "editor_debug:toggle_breakpoint",  QKeySequence () );
-  init (tr ("Next Breakpoint"), "editor_debug:next_breakpoint",  QKeySequence () );
-  init (tr ("Previous Breakpoint"), "editor_debug:previous_breakpoint",  QKeySequence () );
-  init (tr ("Remove All Breakpoints"), "editor_debug:remove_breakpoints",  QKeySequence () );
+  init (tr ("Toggle Breakpoint"), "editor_debug:toggle_breakpoint",
+        QKeySequence ());
+  init (tr ("Next Breakpoint"), "editor_debug:next_breakpoint",
+        QKeySequence ());
+  init (tr ("Previous Breakpoint"), "editor_debug:previous_breakpoint",
+        QKeySequence ());
+  init (tr ("Remove All Breakpoints"), "editor_debug:remove_breakpoints",
+        QKeySequence ());
 
   // run
-  init (tr ("Run File"), "editor_run:run_file", QKeySequence (Qt::Key_F5) );
-  init (tr ("Run Selection"), "editor_run:run_selection", QKeySequence (Qt::Key_F9) );
+  init (tr ("Run File"), "editor_run:run_file", QKeySequence (Qt::Key_F5));
+  init (tr ("Run Selection"), "editor_run:run_selection", QKeySequence (Qt::Key_F9));
 
   // help
-  init (tr ("Help on Keyword"), "editor_help:help_keyword", QKeySequence::HelpContents );
-  init (tr ("Document on Keyword"), "editor_help:doc_keyword", QKeySequence (Qt::SHIFT + Qt::Key_F1) );
+  init (tr ("Help on Keyword"), "editor_help:help_keyword", QKeySequence::HelpContents);
+  init (tr ("Document on Keyword"), "editor_help:doc_keyword", QKeySequence (Qt::SHIFT + Qt::Key_F1));
 }
 
 void
@@ -342,7 +374,7 @@
     key_set = key+"_1";
 
   if (index > -1 && index < _sc.count ())
-    action->setShortcut ( QKeySequence (
+    action->setShortcut (QKeySequence (
       _settings->value ("shortcuts/" + key_set, _sc.at (index).default_sc[set]).toString ()));
   else
     qDebug () << "Key: " << key_set << " not found in _action_hash";
--- a/libgui/src/workspace-model.cc
+++ b/libgui/src/workspace-model.cc
@@ -141,7 +141,7 @@
 
       if (role == Qt::DisplayRole
           || (idx.column () == 0 && role == Qt::EditRole)
-          || (idx.column () == 0 && role == Qt::ToolTipRole) )
+          || (idx.column () == 0 && role == Qt::ToolTipRole))
         {
           switch (idx.column ())
             {
--- a/libinterp/corefcn/__contourc__.cc
+++ b/libinterp/corefcn/__contourc__.cc
@@ -307,10 +307,10 @@
 
   if (args.length () == 4)
     {
-      RowVector X = args (0).row_vector_value ();
-      RowVector Y = args (1).row_vector_value ();
-      Matrix Z = args (2).matrix_value ();
-      RowVector L = args (3).row_vector_value ();
+      RowVector X = args(0).row_vector_value ();
+      RowVector Y = args(1).row_vector_value ();
+      Matrix Z = args(2).matrix_value ();
+      RowVector L = args(3).row_vector_value ();
 
       if (! error_state)
         {
--- a/libinterp/corefcn/__pchip_deriv__.cc
+++ b/libinterp/corefcn/__pchip_deriv__.cc
@@ -59,7 +59,7 @@
   octave_value retval;
   const int nargin = args.length ();
 
-  bool rows = (nargin == 3 && args (2).uint_value () == 2);
+  bool rows = (nargin == 3 && args(2).uint_value () == 2);
 
   if (nargin >= 2)
     {
--- a/libinterp/corefcn/balance.cc
+++ b/libinterp/corefcn/balance.cc
@@ -144,7 +144,8 @@
   if (AEPcase)
     {
       // Algebraic eigenvalue problem.
-      bool noperm = false, noscal = false;
+      bool noperm = false;
+      bool noscal = false;
       if (nargin > 1)
         {
           std::string a1s = args(1).string_value ();
--- a/libinterp/corefcn/besselj.cc
+++ b/libinterp/corefcn/besselj.cc
@@ -598,7 +598,7 @@
         {
           int idx = nargin == 1 ? 0 : 1;
 
-          if (args (idx).is_single_type ())
+          if (args(idx).is_single_type ())
             {
               FloatComplexNDArray z = args(idx).float_complex_array_value ();
 
--- a/libinterp/corefcn/betainc.cc
+++ b/libinterp/corefcn/betainc.cc
@@ -32,8 +32,6 @@
 #include "oct-obj.h"
 #include "utils.h"
 
-// FIXME: These functions do not need to be dynamically loaded.  They should
-//        be placed elsewhere in the Octave code hierarchy.
 
 DEFUN (betainc, args, ,
        "-*- texinfo -*-\n\
--- a/libinterp/corefcn/bitfcns.cc
+++ b/libinterp/corefcn/bitfcns.cc
@@ -595,7 +595,7 @@
           int bits_in_type = sizeof (double)
                              * std::numeric_limits<unsigned char>::digits;
           NDArray m = m_arg.array_value ();
-          DO_BITSHIFT ( );
+          DO_BITSHIFT ();
         }
       else if (cname == "single")
         {
--- a/libinterp/corefcn/bsxfun.cc
+++ b/libinterp/corefcn/bsxfun.cc
@@ -201,7 +201,8 @@
   bsxfun_builtin_op op = bsxfun_builtin_lookup (name);
   if (op != bsxfun_builtin_unknown)
     {
-      builtin_type_t btyp_a = a.builtin_type (), btyp_b = b.builtin_type ();
+      builtin_type_t btyp_a = a.builtin_type ();
+      builtin_type_t btyp_b = b.builtin_type ();
 
       // Simplify single/double combinations.
       if (btyp_a == btyp_float && btyp_b == btyp_double)
@@ -351,8 +352,8 @@
                || args(0).is_inline_function ()))
         error ("bsxfun: F must be a string or function handle");
 
-      const octave_value A = args (1);
-      const octave_value B = args (2);
+      const octave_value A = args(1);
+      const octave_value B = args(2);
 
       if (func.is_builtin_function ()
           || (func.is_function_handle ()
--- a/libinterp/corefcn/cellfun.cc
+++ b/libinterp/corefcn/cellfun.cc
@@ -1227,7 +1227,7 @@
       // fewer polymorphic function calls as the function gets called
       // for each value of the array.
 
-      if (! symbol_table_lookup )
+      if (! symbol_table_lookup)
         {
           if (func.is_function_handle ())
             {
@@ -1783,7 +1783,8 @@
 
       NDA parray = array.permute (perm);
 
-      octave_idx_type nela = arraydv.numel (), nelc = celldv.numel ();
+      octave_idx_type nela = arraydv.numel ();
+      octave_idx_type nelc = celldv.numel ();
       parray = parray.reshape (dim_vector (nela, nelc));
 
       Cell retval (celldv);
@@ -1901,7 +1902,7 @@
       octave_value array = args(0);
       Array<int> dimv;
       if (nargin > 1)
-        dimv = args (1).int_vector_value (true);
+        dimv = args(1).int_vector_value (true);
 
       if (error_state)
         ;
@@ -2036,7 +2037,8 @@
   if (ivec >= 0)
     {
       // Vector split. Use 1D indexing.
-      octave_idx_type l = 0, nidx = (ivec == 0 ? nridx : ncidx);
+      octave_idx_type l = 0;
+      octave_idx_type nidx = (ivec == 0 ? nridx : ncidx);
       for (octave_idx_type i = 0; i < nidx; i++)
         {
           octave_idx_type u = l + d[ivec](i);
--- a/libinterp/corefcn/data.cc
+++ b/libinterp/corefcn/data.cc
@@ -120,7 +120,7 @@
 \n\
 @example\n\
 @group\n\
-all ([2, 3; 1, 0]))\n\
+all ([2, 3; 1, 0])\n\
     @result{} [ 1, 0 ]\n\
 @end group\n\
 @end example\n\
@@ -302,7 +302,8 @@
 {
   octave_value retval;
 
-  octave_value arg0 = x, arg1 = y;
+  octave_value arg0 = x;
+  octave_value arg1 = y;
   if (! arg0.is_numeric_type ())
     gripe_wrong_type_arg ("hypot", arg0);
   else if (! arg1.is_numeric_type ())
@@ -561,7 +562,7 @@
                     X##NDArray a1 = args(1).X##_array_value (); \
                     retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, rem, "rem"); \
                     } \
-                  break
+                  break;
                 MAKE_INT_BRANCH (int8);
                 MAKE_INT_BRANCH (int16);
                 MAKE_INT_BRANCH (int32);
@@ -695,7 +696,7 @@
                     X##NDArray a1 = args(1).X##_array_value (); \
                     retval = binmap<octave_##X,octave_##X,octave_##X> (a0, a1, mod, "mod"); \
                     } \
-                  break
+                  break;
                 MAKE_INT_BRANCH (int8);
                 MAKE_INT_BRANCH (int16);
                 MAKE_INT_BRANCH (int32);
@@ -1177,7 +1178,7 @@
                 retval = arg.X ## _array_value ().cumsum (dim); \
               else \
                 retval = arg.array_value ().cumsum (dim); \
-              break
+              break;
             MAKE_INT_BRANCH (int8);
             MAKE_INT_BRANCH (int16);
             MAKE_INT_BRANCH (int32);
@@ -1353,6 +1354,11 @@
 %!assert (diag ({1}, 2, 3), {1,[],[]; [],[],[]});
 %!assert (diag ({1,2}, 3, 4), {1,[],[],[]; [],2,[],[]; [],[],[],[]});
 
+## Test out-of-range diagonals
+%!assert (diag (ones (3,3), 4), zeros (0, 1))
+%!assert (diag (cell (3,3), 4), cell (0, 1))
+%!assert (diag (sparse (ones (3,3)), 4), sparse (zeros (0, 1)))
+
 %% Test input validation
 %!error <Invalid call to diag> diag ()
 %!error <Invalid call to diag> diag (1,2,3,4)
@@ -1373,12 +1379,144 @@
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} prod (@var{x})\n\
 @deftypefnx {Built-in Function} {} prod (@var{x}, @var{dim})\n\
-Product of elements along dimension @var{dim}.  If @var{dim} is\n\
-omitted, it defaults to the first non-singleton dimension.\n\
+@deftypefnx {Built-in Function} {} prod (@dots{}, \"native\")\n\
+@deftypefnx {Built-in Function} {} prod (@dots{}, \"double\")\n\
+Product of elements along dimension @var{dim}.\n\
+\n\
+If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
+\n\
+The optional @qcode{\"type\"} input determines the class of the variable used for\n\
+calculations.  If the argument @qcode{\"native\"} is given, then the operation is\n\
+performed in the same type as the original argument, rather than the default double\n\
+type.\n\
+\n\
+For example:\n\
+\n\
+@example\n\
+@group\n\
+prod ([true, true])\n\
+   @result{} 1\n\
+prod ([true, true], \"native\")\n\
+   @result{} true\n\
+@end group\n\
+@end example\n\
+\n\
+On the contrary, if @qcode{\"double\"} is given, the operation is performed in\n\
+double precision even for single precision inputs.\n\
 @seealso{cumprod, sum}\n\
 @end deftypefn")
 {
-  DATA_REDUCTION (prod);
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  bool isnative = false;
+  bool isdouble = false;
+
+  if (nargin > 1 && args(nargin - 1).is_string ())
+    {
+      std::string str = args(nargin - 1).string_value ();
+
+      if (! error_state)
+        {
+          if (str == "native")
+            isnative = true;
+          else if (str == "double")
+            isdouble = true;
+          else
+            error ("prod: unrecognized type argument '%s'", str.c_str ());
+          nargin --;
+        }
+    }
+
+  if (error_state)
+    return retval;
+
+  if (nargin == 1 || nargin == 2)
+    {
+      octave_value arg = args(0);
+
+      int dim = -1;
+      if (nargin == 2)
+        {
+          dim = args(1).int_value () - 1;
+          if (dim < 0)
+            error ("prod: invalid dimension DIM = %d", dim + 1);
+        }
+
+      if (! error_state)
+        {
+          switch (arg.builtin_type ())
+            {
+            case btyp_double:
+              if (arg.is_sparse_type ())
+                retval = arg.sparse_matrix_value ().prod (dim);
+              else
+                retval = arg.array_value ().prod (dim);
+              break;
+            case btyp_complex:
+              if (arg.is_sparse_type ())
+                retval = arg.sparse_complex_matrix_value ().prod (dim);
+              else
+                retval = arg.complex_array_value ().prod (dim);
+              break;
+            case btyp_float:
+              if (isdouble)
+                retval = arg.float_array_value ().dprod (dim);
+              else
+                retval = arg.float_array_value ().prod (dim);
+              break;
+            case btyp_float_complex:
+              if (isdouble)
+                retval = arg.float_complex_array_value ().dprod (dim);
+              else
+                retval = arg.float_complex_array_value ().prod (dim);
+              break;
+
+#define MAKE_INT_BRANCH(X) \
+            case btyp_ ## X: \
+              if (isnative) \
+                retval = arg.X ## _array_value ().prod (dim); \
+              else \
+                retval = arg.array_value ().prod (dim); \
+              break;
+            MAKE_INT_BRANCH (int8);
+            MAKE_INT_BRANCH (int16);
+            MAKE_INT_BRANCH (int32);
+            MAKE_INT_BRANCH (int64);
+            MAKE_INT_BRANCH (uint8);
+            MAKE_INT_BRANCH (uint16);
+            MAKE_INT_BRANCH (uint32);
+            MAKE_INT_BRANCH (uint64);
+#undef MAKE_INT_BRANCH
+
+            // GAGME: Accursed Matlab compatibility...
+            case btyp_char:
+              retval = arg.array_value (true).prod (dim);
+              break;
+            case btyp_bool:
+              if (arg.is_sparse_type ())
+                {
+                  if (isnative)
+                    retval = arg.sparse_bool_matrix_value ().all (dim);
+                  else
+                    retval = arg.sparse_matrix_value ().prod (dim);
+                }
+              else if (isnative)
+                retval = arg.bool_array_value ().all (dim);
+              else
+                retval = NDArray (arg.bool_array_value ().all (dim));
+              break;
+
+            default:
+              gripe_wrong_type_arg ("prod", arg);
+            }
+        }
+    }
+  else
+    print_usage ();
+
+  return retval;
 }
 
 /*
@@ -1392,6 +1530,13 @@
 %!assert (prod (single ([i, 2+i, -3+2i, 4])), single (-4 - 32i))
 %!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), single ([-1+i, -8+8i, -27+27i]))
 
+%% Test sparse
+%!assert (prod (sparse ([1, 2, 3])), sparse (6))
+%!assert (prod (sparse ([-1; -2; -3])), sparse (-6))
+## Commented out until bug #42290 is fixed
+#%!assert (prod (sparse ([i, 2+i, -3+2i, 4])), sparse (-4 - 32i))
+#%!assert (prod (sparse ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i])), sparse ([-1+i, -8+8i, -27+27i]))
+
 %!assert (prod ([1, 2; 3, 4], 1), [3, 8])
 %!assert (prod ([1, 2; 3, 4], 2), [2; 12])
 %!assert (prod (zeros (1, 0)), 1)
@@ -1422,7 +1567,24 @@
 %!assert (prod (zeros (0, 2, "single"), 1), single ([1, 1]))
 %!assert (prod (zeros (0, 2, "single"), 2), zeros (0, 1, "single"))
 
+%% Test "double" type argument
+%!assert (prod (single ([1, 2, 3]), "double"), 6)
+%!assert (prod (single ([-1; -2; -3]), "double"), -6)
+%!assert (prod (single ([i, 2+i, -3+2i, 4]), "double"), -4 - 32i)
+%!assert (prod (single ([1, 2, 3; i, 2i, 3i; 1+i, 2+2i, 3+3i]), "double"), [-1+i, -8+8i, -27+27i])
+
+%% Test "native" type argument
+%!assert (prod (uint8 ([1, 2, 3]), "native"), uint8 (6))
+%!assert (prod (uint8 ([-1; -2; -3]), "native"), uint8 (0))
+%!assert (prod (int8 ([1, 2, 3]), "native"), int8 (6))
+%!assert (prod (int8 ([-1; -2; -3]), "native"), int8 (-6))
+%!assert (prod ([true false; true true], "native"), [true false])
+%!assert (prod ([true false; true true], 2, "native"), [false; true])
+
+%% Test input validation
 %!error prod ()
+%!error prod (1,2,3)
+%!error <unrecognized type argument 'foobar'> prod (1, "foobar")
 */
 
 static bool
@@ -1836,7 +1998,7 @@
           // and then directly resize. However, for some types there might
           // be some additional setup needed, and so this should be avoided.
 
-          octave_value tmp = args (0);
+          octave_value tmp = args(0);
           tmp = tmp.resize (dim_vector (0,0)).resize (dv);
 
           if (error_state)
@@ -1850,12 +2012,12 @@
               // Can't fast return here to skip empty matrices as something
               // like cat (1,[],single ([])) must return an empty matrix of
               // the right type.
-              tmp = do_cat_op (tmp, args (j), ra_idx);
+              tmp = do_cat_op (tmp, args(j), ra_idx);
 
               if (error_state)
                 return retval;
 
-              dim_vector dv_tmp = args (j).dims ();
+              dim_vector dv_tmp = args(j).dims ();
 
               if (dim >= dv_len)
                 {
@@ -2314,8 +2476,8 @@
 %!assert (cat (3, [], [], [1,2;3,4]), [1,2;3,4])
 %!assert (cat (4, [], [], [1,2;3,4]), [1,2;3,4])
 
-%!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2]) )
-%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2)) )
+%!assert ([zeros(3,2,2); ones(1,2,2)], repmat ([0;0;0;1],[1,2,2]))
+%!assert ([zeros(3,2,2); ones(1,2,2)], vertcat (zeros (3,2,2), ones (1,2,2)))
 
 %!error <dimension mismatch> cat (3, cat (3, [], []), [1,2;3,4])
 %!error <dimension mismatch> cat (3, zeros (0, 0, 2), [1,2;3,4])
@@ -2677,12 +2839,16 @@
 @deftypefnx {Built-in Function} {} sum (@dots{}, \"native\")\n\
 @deftypefnx {Built-in Function} {} sum (@dots{}, \"double\")\n\
 @deftypefnx {Built-in Function} {} sum (@dots{}, \"extra\")\n\
-Sum of elements along dimension @var{dim}.  If @var{dim} is\n\
-omitted, it defaults to the first non-singleton dimension.\n\
-\n\
-If the optional argument @qcode{\"native\"} is given, then the sum is\n\
-performed in the same type as the original argument, rather than in the\n\
-default double type.  For example:\n\
+Sum of elements along dimension @var{dim}.\n\
+\n\
+If @var{dim} is omitted, it defaults to the first non-singleton dimension.\n\
+\n\
+The optional @qcode{\"type\"} input determines the class of the variable used for\n\
+calculations.  If the argument @qcode{\"native\"} is given, then the operation is\n\
+performed in the same type as the original argument, rather than the default double\n\
+type.\n\
+\n\
+For example:\n\
 \n\
 @example\n\
 @group\n\
@@ -2696,10 +2862,10 @@
 On the contrary, if @qcode{\"double\"} is given, the sum is performed in\n\
 double precision even for single precision inputs.\n\
 \n\
-For double precision inputs, @qcode{\"extra\"} indicates that a more accurate\n\
-algorithm than straightforward summation is to be used.  For single precision\n\
-inputs, @qcode{\"extra\"} is the same as @qcode{\"double\"}.  Otherwise,\n\
-@qcode{\"extra\"} has no effect.\n\
+For double precision inputs, the @qcode{\"extra\"} option will use a more accurate\n\
+algorithm than straightforward summation.  For single precision inputs,\n\
+@qcode{\"extra\"} is the same as @qcode{\"double\"}.  Otherwise, @qcode{\"extra\"}\n\
+has no effect.\n\
 @seealso{cumsum, sumsq, prod}\n\
 @end deftypefn")
 {
@@ -2724,7 +2890,7 @@
           else if (str == "extra")
             isextra = true;
           else
-            error ("sum: unrecognized string argument");
+            error ("sum: unrecognized type argument '%s'", str.c_str ());
           nargin --;
         }
     }
@@ -2791,7 +2957,7 @@
                 retval = arg.X ## _array_value ().sum (dim); \
               else \
                 retval = arg.X ## _array_value ().dsum (dim); \
-              break
+              break;
             MAKE_INT_BRANCH (int8);
             MAKE_INT_BRANCH (int16);
             MAKE_INT_BRANCH (int32);
@@ -2801,7 +2967,8 @@
             MAKE_INT_BRANCH (uint32);
             MAKE_INT_BRANCH (uint64);
 #undef MAKE_INT_BRANCH
-              // GAGME: Accursed Matlab compatibility...
+            
+            // GAGME: Accursed Matlab compatibility...
             case btyp_char:
               if (isextra)
                 retval = arg.array_value (true).xsum (dim);
@@ -2834,11 +3001,6 @@
 }
 
 /*
-%!assert (sum ([true,true]), 2)
-%!assert (sum ([true,true],"native"), true)
-%!assert (sum (int8 ([127,10,-20])), 117)
-%!assert (sum (int8 ([127,10,-20]),'native'), int8 (107))
-
 %!assert (sum ([1, 2, 3]), 6)
 %!assert (sum ([-1; -2; -3]), -6)
 %!assert (sum ([i, 2+i, -3+2i, 4]), 3+4i)
@@ -2889,10 +3051,18 @@
 %!assert (sum (zeros (2, 2, 0, 3, "single"), 4), zeros (2, 2, 0, "single"))
 %!assert (sum (zeros (2, 2, 0, 3, "single"), 7), zeros (2, 2, 0, 3, "single"))
 
+## Test "native"
+%!assert (sum ([true,true]), 2)
+%!assert (sum ([true,true], "native"), true)
+%!assert (sum (int8 ([127,10,-20])), 117)
+%!assert (sum (int8 ([127,10,-20]), "native"), int8 (107))
+
 ;-)
 %!assert (sum ("Octave") + "8", sumsq (primes (17)))
 
 %!error sum ()
+%!error sum (1,2,3)
+%!error <unrecognized type argument 'foobar'> sum (1, "foobar")
 */
 
 DEFUN (sumsq, args, ,
@@ -4601,7 +4771,7 @@
 @equiv{}\n\
 eye (2, 2)\n\
 @equiv{}\n\
-eye (size ([1, 2; 3, 4])\n\
+eye (size ([1, 2; 3, 4]))\n\
 @end group\n\
 @end example\n\
 \n\
@@ -5347,7 +5517,7 @@
 %!assert (norm (x,"inf"), single (7))
 %!assert (norm (x,"fro"), single (10), -eps ("single"))
 %!assert (norm (x), single (10))
-%!assert (norm (single ([1e200, 1])), single (1e200))
+%!assert (norm (single ([1e38, 1])), single (1e38))
 %!assert (norm (single ([3+4i, 3-4i, sqrt(31)])), single (9), -4*eps ("single"))
 %!shared m
 %! m = single (magic (4));
@@ -6564,7 +6734,7 @@
 #define MAKE_INT_BRANCH(X) \
         case btyp_ ## X: \
           retval = argx.X ## _array_value ().nth_element (n, dim); \
-          break
+          break;
 
         MAKE_INT_BRANCH (int8);
         MAKE_INT_BRANCH (int16);
@@ -6708,7 +6878,8 @@
 
       if (! error_state)
         {
-          octave_value vals = args(1), zero = args (2);
+          octave_value vals = args(1);
+          octave_value zero = args(2);
 
           switch (vals.builtin_type ())
             {
@@ -6735,7 +6906,7 @@
               retval = do_accumarray_minmax (idx, vals.X ## _array_value (), \
                                              n, ismin, \
                                              zero.X ## _scalar_value ()); \
-              break
+              break;
 
             MAKE_INT_BRANCH (int8);
             MAKE_INT_BRANCH (int16);
@@ -6790,7 +6961,8 @@
   else if (idx.extent (n) > n)
     error ("accumdim: index out of range");
 
-  dim_vector vals_dim = vals.dims (), rdv = vals_dim;
+  dim_vector vals_dim = vals.dims ();
+  dim_vector rdv = vals_dim;
 
   if (dim < 0)
     dim = vals.dims ().first_non_singleton ();
@@ -6869,7 +7041,8 @@
   dim_vector dv = mask.dims ();
   NDT retval (dv);
 
-  bool tscl = tval.numel () == 1, fscl = fval.numel () == 1;
+  bool tscl = tval.numel () == 1;
+  bool fscl = fval.numel () == 1;
 
   if ((! tscl && tval.dims () != dv)
       || (! fscl && fval.dims () != dv))
@@ -6879,14 +7052,16 @@
       T *rv = retval.fortran_vec ();
       octave_idx_type n = retval.numel ();
 
-      const T *tv = tval.data (), *fv = fval.data ();
+      const T *tv = tval.data ();
+      const T *fv = fval.data ();
       const bool *mv = mask.data ();
 
       if (tscl)
         {
           if (fscl)
             {
-              T ts = tv[0], fs = fv[0];
+              T ts = tv[0];
+              T fs = fv[0];
               for (octave_idx_type i = 0; i < n; i++)
                 rv[i] = mv[i] ? ts : fs;
             }
@@ -6963,7 +7138,8 @@
       else
         {
           boolNDArray mask = mask_val.bool_array_value ();
-          octave_value tval = args(1), fval = args(2);
+          octave_value tval = args(1);
+          octave_value fval = args(2);
           if (tval.is_double_type () && fval.is_double_type ())
             {
               if (tval.is_complex_type () || fval.is_complex_type ())
@@ -7241,7 +7417,8 @@
 
   assert (rep.ndims () == 2 && rep.rows () == 2);
 
-  octave_idx_type n = rep.columns (), l = 0;
+  octave_idx_type n = rep.columns ();
+  octave_idx_type l = 0;
   for (octave_idx_type i = 0; i < n; i++)
     {
       octave_idx_type k = rep(1, i);
@@ -7328,7 +7505,7 @@
 #define BTYP_BRANCH(X, EX) \
             case btyp_ ## X: \
               retval = do_repelems (x.EX ## _value (), r); \
-              break
+              break;
 
               BTYP_BRANCH (double, array);
               BTYP_BRANCH (float, float_array);
--- a/libinterp/corefcn/debug.cc
+++ b/libinterp/corefcn/debug.cc
@@ -85,7 +85,6 @@
           if (file.eof ())
             {
               // Expected to read the entire file.
-
               retval = buf;
             }
           else
@@ -99,8 +98,7 @@
 static std::deque<size_t>
 get_line_offsets (const std::string& buf)
 {
-  // This could maybe be smarter.  Is deque the right thing to use
-  // here?
+  // This could maybe be smarter.  Is deque the right thing to use here?
 
   std::deque<size_t> offsets;
 
@@ -207,28 +205,47 @@
   if (args.length () == 0)
     return;
 
-  // If we are already in a debugging function.
-  if (octave_call_stack::caller_user_code ())
-    {
-      idx = 0;
-      symbol_name = get_user_code ()->name ();
-    }
+  if (args(0).is_string ())
+  {
+    // string could be function name or line number
+    int isint = atoi (args(0).string_value ().c_str ());
+
+    if (error_state)
+      return;
+
+    if (isint == 0)
+      {
+        // It was a function name
+        symbol_name = args(0).string_value ();
+        if (error_state)
+          return;
+        idx = 1;
+      }
+    else
+      {
+        // It was a line number.  Need to get function name from debugger.
+        if (Vdebugging)
+          {
+            symbol_name = get_user_code ()->name ();
+            idx = 0;
+          }
+        else
+          {
+            error ("%s: no function specified", who);
+          }
+      }
+  }
   else if (args(0).is_map ())
     {
-      // Problem because parse_dbfunction_params() can only pass out a
-      // single function
-    }
-  else if (args(0).is_string ())
-    {
-      symbol_name = args(0).string_value ();
-      if (error_state)
-        return;
-      idx = 1;
+      // This is a problem because parse_dbfunction_params()
+      // can only pass out a single function.
+      error ("%s: struct input not implemented", who);
+      return;
     }
   else
     error ("%s: invalid parameter specified", who);
 
-  for (int i = idx; i < nargin; i++ )
+  for (int i = idx; i < nargin; i++)
     {
       if (args(i).is_string ())
         {
@@ -238,7 +255,7 @@
           lines[list_idx++] = line;
         }
       else if (args(i).is_map ())
-        octave_stdout << who << ": accepting a struct" << std::endl;
+        octave_stdout << who << ": skipping struct input" << std::endl;
       else
         {
           const NDArray arg = args(i).array_value ();
@@ -356,7 +373,6 @@
   return retval;
 }
 
-
 int
 bp_table::do_remove_breakpoint_1 (octave_user_code *fcn,
                                   const std::string& fname,
@@ -522,9 +538,12 @@
 void
 bp_table::do_remove_all_breakpoints (void)
 {
-  for (const_bp_set_iterator it = bp_set.begin (); it != bp_set.end (); it++)
-    remove_all_breakpoints_in_file (*it);
-
+  // Odd loop structure required because delete will invalidate bp_set iterators
+  for (const_bp_set_iterator it=bp_set.begin (), it_next=it; it != bp_set.end (); it=it_next)
+    {
+      ++it_next;
+      remove_all_breakpoints_in_file (*it);
+    }
 
   tree_evaluator::debug_mode = bp_table::have_breakpoints () || Vdebugging;
 }
@@ -537,7 +556,7 @@
 
   for (int i = 0; i < slist.length (); i++)
     {
-      if (slist (i).string_value () == match)
+      if (slist(i).string_value () == match)
         {
           retval = slist(i).string_value ();
           break;
@@ -547,7 +566,6 @@
   return retval;
 }
 
-
 bp_table::fname_line_map
 bp_table::do_get_breakpoint_list (const octave_value_list& fname_list)
 {
@@ -576,7 +594,7 @@
                       bp_table::intmap bkpts_vec;
 
                       for (int i = 0; i < len; i++)
-                        bkpts_vec[i] = bkpts (i).double_value ();
+                        bkpts_vec[i] = bkpts(i).double_value ();
 
                       std::string symbol_name = f->name ();
 
@@ -615,31 +633,36 @@
 
 DEFUN (dbstop, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\")\n\
+@deftypefn  {Command} dbstop @var{func}\n\
+@deftypefnx {Command} dbstop @var{func} @var{line}\n\
+@deftypefnx {Command} dbstop @var{func} @var{line1} @var{line2} @dots{}\n\
+@deftypefnx {Command} {} dbstop @var{line} @dots{}\n\
+@deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\")\n\
 @deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\", @var{line})\n\
 @deftypefnx {Built-in Function} {@var{rline} =} dbstop (\"@var{func}\", @var{line1}, @var{line2}, @dots{})\n\
-Set a breakpoint in function @var{func}.\n\
+@deftypefnx {Built-in Function} {} dbstop (\"@var{func}\", [@var{line1}, @dots{}])\n\
+@deftypefnx {Built-in Function} {} dbstop (@var{line}, @dots{})\n\
+Set a breakpoint at line number @var{line} in function @var{func}.\n\
 \n\
 Arguments are\n\
 \n\
 @table @var\n\
 @item func\n\
-Function name as a string variable.  When already in debug\n\
-mode this should be left out and only the line should be given.\n\
+Function name as a string variable.  When already in debug mode this argument\n\
+can be omitted and the current function will be used.\n\
 \n\
 @item line\n\
-Line number where the breakpoint should be set.  Multiple\n\
-lines may be given as separate arguments or as a vector.\n\
+Line number where the breakpoint should be set.  Multiple lines may be given\n\
+as separate arguments or as a vector.\n\
 @end table\n\
 \n\
-When called with a single argument @var{func}, the breakpoint\n\
-is set at the first executable line in the named function.\n\
+When called with a single argument @var{func}, the breakpoint is set at the\n\
+first executable line in the named function.\n\
 \n\
-The optional output @var{rline} is the real line number where the\n\
-breakpoint was set.  This can differ from specified line if\n\
-the line is not executable.  For example, if a breakpoint attempted on a\n\
-blank line then Octave will set the real breakpoint at the\n\
-next executable line.\n\
+The optional output @var{rline} is the real line number where the breakpoint\n\
+was set.  This can differ from the specified line if the line is not\n\
+executable.  For example, if a breakpoint attempted on a blank line then\n\
+Octave will set the real breakpoint at the next executable line.\n\
 @seealso{dbclear, dbstatus, dbstep, debug_on_error, debug_on_warning, debug_on_interrupt}\n\
 @end deftypefn")
 {
@@ -660,28 +683,38 @@
 
 DEFUN (dbclear, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} dbclear (\"@var{func}\")\n\
-@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line}, @dots{})\n\
+@deftypefn  {Command} {} dbclear @var{func}\n\
+@deftypefnx {Command} {} dbclear @var{func} @var{line}\n\
+@deftypefnx {Command} {} dbclear @var{func} @var{line1} @var{line2} @dots{}\n\
+@deftypefnx {Command} {} dbclear @var{line} @dots{}\n\
+@deftypefnx {Command} {} dbclear all\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\")\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line})\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", @var{line1}, @var{line2}, @dots{})\n\
+@deftypefnx {Built-in Function} {} dbclear (\"@var{func}\", [@var{line1}, @dots{}])\n\
 @deftypefnx {Built-in Function} {} dbclear (@var{line}, @dots{})\n\
-Delete a breakpoint in the function @var{func}.\n\
+@deftypefnx {Built-in Function} {} dbclear (\"all\")\n\
+Delete a breakpoint at line number @var{line} in the function @var{func}.\n\
 \n\
 Arguments are\n\
 \n\
 @table @var\n\
 @item func\n\
-Function name as a string variable.  When already in debug\n\
-mode this argument should be omitted and only the line number should be\n\
-given.\n\
+Function name as a string variable.  When already in debug mode this argument\n\
+can be omitted and the current function will be used.\n\
 \n\
 @item line\n\
-Line number from which to remove a breakpoint.  Multiple\n\
-lines may be given as separate arguments or as a vector.\n\
+Line number from which to remove a breakpoint.  Multiple lines may be given\n\
+as separate arguments or as a vector.\n\
 @end table\n\
 \n\
-When called without a line number specification all breakpoints\n\
-in the named function are cleared.\n\
+When called without a line number specification all breakpoints in the named\n\
+function are cleared.\n\
 \n\
 If the requested line is not a breakpoint no action is performed.\n\
+\n\
+The special keyword @qcode{\"all\"} will clear all breakpoints from all\n\
+files.\n\
 @seealso{dbstop, dbstatus, dbwhere}\n\
 @end deftypefn")
 {
@@ -689,10 +722,17 @@
   std::string symbol_name = "";
   bp_table::intmap lines;
 
+  int nargin = args.length (); 
+
   parse_dbfunction_params ("dbclear", args, symbol_name, lines);
 
-  if (! error_state)
-    bp_table::remove_breakpoint (symbol_name, lines);
+  if (nargin == 1 && symbol_name == "all")
+    bp_table::remove_all_breakpoints ();
+  else
+  {
+    if (! error_state)
+      bp_table::remove_breakpoint (symbol_name, lines);
+  }
 
   return retval;
 }
@@ -724,6 +764,9 @@
 A line number, or vector of line numbers, with a breakpoint.\n\
 @end table\n\
 \n\
+Note: When @code{dbstatus} is called from the debug prompt within a function,\n\
+the list of breakpoints is automatically trimmed to the breakpoints in the\n\
+current function.\n\
 @seealso{dbclear, dbwhere}\n\
 @end deftypefn")
 {
@@ -752,11 +795,14 @@
     }
   else
     {
-      octave_user_code *dbg_fcn = get_user_code ();
-      if (dbg_fcn)
+      if (Vdebugging)
         {
-          symbol_name = dbg_fcn->name ();
-          fcn_list(0) = symbol_name;
+          octave_user_code *dbg_fcn = get_user_code ();
+          if (dbg_fcn)
+            {
+              symbol_name = dbg_fcn->name ();
+              fcn_list(0) = symbol_name;
+            }
         }
 
       bp_list = bp_table::get_breakpoint_list (fcn_list);
@@ -844,7 +890,7 @@
 
       if (l > 0)
         {
-          octave_stdout << " line " << l << std::endl;
+          octave_stdout << "line " << l << std::endl;
 
           if (have_file)
             {
@@ -855,7 +901,7 @@
             }
         }
       else
-        octave_stdout << " <unknown line>" << std::endl;
+        octave_stdout << "<unknown line>" << std::endl;
     }
   else
     error ("dbwhere: must be inside a user function to use dbwhere\n");
@@ -863,8 +909,6 @@
   return retval;
 }
 
-// Copied and modified from the do_type command in help.cc
-// Maybe we could share some code?
 void
 do_dbtype (std::ostream& os, const std::string& name, int start, int end)
 {
@@ -876,30 +920,16 @@
 
       if (fs)
         {
-          char ch;
           int line = 1;
-          bool isnewline = true;
+          std::string text;  
 
-          // FIXME: Why not use line-oriented input here [getline()]?
-          while (fs.get (ch) && line <= end)
-            {
-              if (isnewline && line >= start)
-                {
-                  os << line << "\t";
-                  isnewline = false;
-                }
-
-              if (line >= start)
-                {
-                  os << ch;
-                }
-
-              if (ch == '\n')
-                {
-                  line++;
-                  isnewline = true;
-                }
-            }
+          while (std::getline (fs, text) && line <= end)
+          {
+            if (line >= start)
+              os << line << "\t" << text << "\n";
+            
+            line++;
+          }
         }
       else
         os << "dbtype: unable to open '" << ff << "' for reading!\n";
@@ -946,13 +976,14 @@
           dbg_fcn = get_user_code ();
 
           if (dbg_fcn)
-            do_dbtype (octave_stdout, dbg_fcn->name (), 0,
-                       std::numeric_limits<int>::max ());
+            do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                       0, std::numeric_limits<int>::max ());
           else
             error ("dbtype: must be inside a user function to give no arguments to dbtype\n");
+
           break;
 
-        case 1: // (dbtype func) || (dbtype start:end)
+        case 1: // (dbtype start:end) || (dbtype func) || (dbtype lineno)
           {
             std::string arg = argv[1];
 
@@ -975,28 +1006,51 @@
                       end = atoi (end_str.c_str ());
 
                     if (std::min (start, end) <= 0)
-                      error ("dbtype: start and end lines must be >= 1\n");
+                      {
+                        error ("dbtype: start and end lines must be >= 1\n");
+                        break;
+                      }
 
                     if (start <= end)
-                      do_dbtype (octave_stdout, dbg_fcn->name (), start, end);
+                      do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                                 start, end);
                     else
                       error ("dbtype: start line must be less than end line\n");
                   }
               }
-            else  // (dbtype func)
+            else  // (dbtype func) || (dbtype lineno)
               {
-                dbg_fcn = get_user_code (arg);
+                int line = atoi (arg.c_str ());
+
+                if (line == 0)  // (dbtype func)
+                  {
+                    dbg_fcn = get_user_code (arg);
 
-                if (dbg_fcn)
-                  do_dbtype (octave_stdout, dbg_fcn->name (), 0,
-                             std::numeric_limits<int>::max ());
-                else
-                  error ("dbtype: function <%s> not found\n", arg.c_str ());
+                    if (dbg_fcn)
+                      do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                                 0, std::numeric_limits<int>::max ());
+                    else
+                      error ("dbtype: function <%s> not found\n", arg.c_str ());
+                  }
+                else  // (dbtype lineno)
+                  {
+                    if (line <= 0)
+                      {
+                        error ("dbtype: start and end lines must be >= 1\n");
+                        break;
+                      }
+
+                    dbg_fcn = get_user_code ();
+
+                    if (dbg_fcn)
+                      do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                                 line, line);
+                  }
               }
           }
           break;
 
-        case 2: // (dbtype func start:end) , (dbtype func start)
+        case 2: // (dbtype func start:end) || (dbtype func start)
           dbg_fcn = get_user_code (argv[1]);
 
           if (dbg_fcn)
@@ -1023,10 +1077,14 @@
                 }
 
               if (std::min (start, end) <= 0)
-                error ("dbtype: start and end lines must be >= 1\n");
+                {
+                  error ("dbtype: start and end lines must be >= 1\n");
+                  break;
+                }
 
               if (start <= end)
-                do_dbtype (octave_stdout, dbg_fcn->name (), start, end);
+                do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
+                           start, end);
               else
                 error ("dbtype: start line must be less than end line\n");
             }
@@ -1096,13 +1154,13 @@
             {
               int l_min = std::max (l - n/2, 0);
               int l_max = l + n/2;
-              do_dbtype (octave_stdout, dbg_fcn->name (), l_min, l-1);
+              do_dbtype (octave_stdout, name, l_min, l-1);
 
               std::string line = get_file_line (name, l);
               if (! line.empty ())
                 octave_stdout << l << "-->\t" << line << std::endl;
 
-              do_dbtype (octave_stdout, dbg_fcn->name (), l+1, l_max);
+              do_dbtype (octave_stdout, name, l+1, l_max);
             }
         }
       else
@@ -1166,10 +1224,9 @@
 
   if (! error_state)
     {
-      octave_map stk = octave_call_stack::backtrace (nskip, curr_frame);
-
       if (nargout == 0)
         {
+          octave_map stk = octave_call_stack::backtrace (nskip, curr_frame);
           octave_idx_type nframes_to_display = stk.numel ();
 
           if (nframes_to_display > 0)
@@ -1215,6 +1272,10 @@
         }
       else
         {
+          octave_map stk = octave_call_stack::backtrace (nskip,
+                                                         curr_frame,
+                                                         false);
+
           retval(1) = curr_frame < 0 ? 1 : curr_frame + 1;
           retval(0) = stk;
         }
@@ -1309,8 +1370,8 @@
 
 DEFUN (dbup, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} dbup\n\
-@deftypefnx {Built-in Function} {} dbup (@var{n})\n\
+@deftypefn  {Command} {} dbup\n\
+@deftypefnx {Command} {} dbup @var{n}\n\
 In debugging mode, move up the execution stack @var{n} frames.\n\
 If @var{n} is omitted, move up one frame.\n\
 @seealso{dbstack, dbdown}\n\
@@ -1325,8 +1386,8 @@
 
 DEFUN (dbdown, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} dbdown\n\
-@deftypefnx {Built-in Function} {} dbdown (@var{n})\n\
+@deftypefn  {Command} {} dbdown\n\
+@deftypefnx {Command} {} dbdown @var{n}\n\
 In debugging mode, move down the execution stack @var{n} frames.\n\
 If @var{n} is omitted, move down one frame.\n\
 @seealso{dbstack, dbup}\n\
--- a/libinterp/corefcn/dlmread.cc
+++ b/libinterp/corefcn/dlmread.cc
@@ -264,12 +264,15 @@
     }
 
   // Take a subset if a range was given.
-  octave_idx_type r0 = 0, c0 = 0, r1 = idx_max-1, c1 = idx_max-1;
+  octave_idx_type r0 = 0;
+  octave_idx_type c0 = 0;
+  octave_idx_type r1 = idx_max-1;
+  octave_idx_type c1 = idx_max-1;
   if (nargin > 2)
     {
       if (nargin == 3)
         {
-          if (!parse_range_spec (args (2), r0, c0, r1, c1))
+          if (!parse_range_spec (args(2), r0, c0, r1, c1))
             error ("dlmread: error parsing RANGE");
         }
       else if (nargin == 4)
@@ -287,7 +290,12 @@
 
   if (!error_state)
     {
-      octave_idx_type i = 0, j = 0, r = 1, c = 1, rmax = 0, cmax = 0;
+      octave_idx_type i = 0;
+      octave_idx_type j = 0;
+      octave_idx_type r = 1;
+      octave_idx_type c = 1;
+      octave_idx_type rmax = 0;
+      octave_idx_type cmax = 0;
 
       Matrix rdata;
       ComplexMatrix cdata;
--- a/libinterp/corefcn/dot.cc
+++ b/libinterp/corefcn/dot.cc
@@ -128,11 +128,13 @@
       return retval;
     }
 
-  octave_value argx = args(0), argy = args(1);
+  octave_value argx = args(0);
+  octave_value argy = args(1);
 
   if (argx.is_numeric_type () && argy.is_numeric_type ())
     {
-      dim_vector dimx = argx.dims (), dimy = argy.dims ();
+      dim_vector dimx = argx.dims ();
+      dim_vector dimy = argy.dims ();
       bool match = dimx == dimy;
       if (! match && nargin == 2
           && dimx.is_vector () && dimy.is_vector ())
@@ -301,13 +303,18 @@
       return retval;
     }
 
-  octave_value argx = args(0), argy = args(1);
+  octave_value argx = args(0);
+  octave_value argy = args(1);
 
   if (argx.is_numeric_type () && argy.is_numeric_type ())
     {
-      const dim_vector dimx = argx.dims (), dimy = argy.dims ();
+      const dim_vector dimx = argx.dims ();
+      const dim_vector dimy = argy.dims ();
       int nd = dimx.length ();
-      octave_idx_type m = dimx(0), k = dimx(1), n = dimy(1), np = 1;
+      octave_idx_type m = dimx(0);
+      octave_idx_type k = dimx(1);
+      octave_idx_type n = dimy(1);
+      octave_idx_type np = 1;
       bool match = dimy(0) == k && nd == dimy.length ();
       dim_vector dimz = dim_vector::alloc (nd);
       dimz(0) = m;
--- a/libinterp/corefcn/eig.cc
+++ b/libinterp/corefcn/eig.cc
@@ -62,8 +62,8 @@
 
   octave_value arg_a, arg_b;
 
-  octave_idx_type nr_a = 0, nr_b = 0;
-  octave_idx_type nc_a = 0, nc_b = 0;
+  octave_idx_type nr_a, nr_b, nc_a, nc_b;
+  nr_a = nr_b = nc_a = nc_b = 0;
 
   arg_a = args(0);
   nr_a = arg_a.rows ();
--- a/libinterp/corefcn/error.cc
+++ b/libinterp/corefcn/error.cc
@@ -40,6 +40,7 @@
 #include "utils.h"
 #include "ov.h"
 #include "ov-usr-fcn.h"
+#include "pt-eval.h"
 #include "pt-pr-code.h"
 #include "pt-stmt.h"
 #include "toplev.h"
@@ -66,8 +67,7 @@
 // TRUE means that Octave will print a verbose warning.  Currently unused.
 static bool Vverbose_warning;
 
-// TRUE means that Octave will print no warnings, but lastwarn will be
-//updated
+// TRUE means that Octave will print no warnings, but lastwarn will be updated
 static bool Vquiet_warning = false;
 
 // A structure containing (most of) the current state of warnings.
@@ -469,6 +469,10 @@
 
       pr_where ("error");
 
+      tree_evaluator::debug_mode = true;
+
+      tree_evaluator::current_frame = octave_call_stack::current_frame ();
+
       do_keyboard (octave_value_list ());
     }
 }
@@ -657,6 +661,10 @@
           frame.protect_var (Vdebug_on_warning);
           Vdebug_on_warning = false;
 
+          tree_evaluator::debug_mode = true;
+
+          tree_evaluator::current_frame = octave_call_stack::current_frame ();
+
           do_keyboard (octave_value_list ());
         }
     }
--- a/libinterp/corefcn/file-io.cc
+++ b/libinterp/corefcn/file-io.cc
@@ -271,7 +271,7 @@
 
   if (nargin == 1)
     {
-      int fid = octave_stream_list::get_file_number (args (0));
+      int fid = octave_stream_list::get_file_number (args(0));
 
       octave_stream os = octave_stream_list::lookup (fid, "fclear");
 
@@ -305,7 +305,7 @@
     {
       // FIXME: any way to avoid special case for stdout?
 
-      int fid = octave_stream_list::get_file_number (args (0));
+      int fid = octave_stream_list::get_file_number (args(0));
 
       if (fid == 1)
         {
@@ -1338,7 +1338,7 @@
 
   tmp_args (0) = 0.0;
   for (int i = 0; i < nargin; i++)
-    tmp_args (i+1) = args (i);
+    tmp_args(i+1) = args(i);
 
   return Ffscanf (tmp_args, nargout);
 }
@@ -1404,9 +1404,13 @@
 
 DEFUN (fread, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {[@var{val}, @var{count}] =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\
-Read binary data of type @var{precision} from the specified file ID\n\
-@var{fid}.\n\
+@deftypefn  {Built-in Function} {@var{val} =} fread (@var{fid})\n\
+@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size})\n\
+@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision})\n\
+@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip})\n\
+@deftypefnx {Built-in Function} {@var{val} =} fread (@var{fid}, @var{size}, @var{precision}, @var{skip}, @var{arch})\n\
+@deftypefnx {Built-in Function} {[@var{val}, @var{count}] =} fread (@dots{})\n\
+Read binary data from the specified file ID @var{fid}.\n\
 \n\
 The optional argument @var{size} specifies the amount of data to read\n\
 and may be one of\n\
@@ -1559,8 +1563,8 @@
 IEEE little endian.\n\
 @end table\n\
 \n\
-The data read from the file is returned in @var{val}, and the number of\n\
-values read is returned in @code{count}\n\
+The output argument @var{val} contains the data read from the file.\n\
+The optional return value @var{count} contains the number of elements read.\n\
 @seealso{fwrite, fgets, fgetl, fscanf, fopen}\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/find.cc
+++ b/libinterp/corefcn/find.cc
@@ -61,7 +61,8 @@
     case 2:
       {
         Array<octave_idx_type> jdx (idx.dims ());
-        octave_idx_type n = idx.length (), nr = nda.rows ();
+        octave_idx_type n = idx.length ();
+        octave_idx_type nr = nda.rows ();
         for (octave_idx_type i = 0; i < n; i++)
           {
             jdx.xelem (i) = idx.xelem (i) / nr;
@@ -168,7 +169,7 @@
       // there are elements to be found using the count that we want
       // to find.
       for (octave_idx_type j = start_nc, cx = 0; j < end_nc; j++)
-        for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++ )
+        for (octave_idx_type i = v.cidx (j); i < v.cidx (j+1); i++)
           {
             OCTAVE_QUIT;
             if (direction < 0 && i < nz - count)
@@ -238,7 +239,6 @@
   if (n_to_find < 0 || n_to_find >= nc)
     {
       start_nc = 0;
-      n_to_find = nc;
       count = nc;
     }
   else if (direction > 0)
--- a/libinterp/corefcn/gcd.cc
+++ b/libinterp/corefcn/gcd.cc
@@ -125,8 +125,9 @@
   double aa = fabs (a);
   double bb = fabs (b);
 
-  double xx = 0, yy = 1;
-  double lx = 1, ly = 0;
+  double xx, lx, yy, ly;
+  xx = 0, lx = 1;
+  yy = 1, ly = 0;
 
   while (bb != 0)
     {
@@ -161,7 +162,8 @@
     (*current_liboctave_error_handler)
       ("gcd: all complex parts must be integers");
 
-  std::complex<FP> aa = a, bb = b;
+  std::complex<FP> aa = a;
+  std::complex<FP> bb = b;
   bool swapped = false;
   if (abs (aa) < abs (bb))
     {
@@ -169,8 +171,9 @@
       swapped = true;
     }
 
-  std::complex<FP> xx = 0, lx = 1;
-  std::complex<FP> yy = 1, ly = 0;
+  std::complex<FP> xx, lx, yy, ly;
+  xx = 0, lx = 1;
+  yy = 1, ly = 0;
 
   while (abs(bb) != 0)
     {
@@ -204,8 +207,9 @@
 {
   T aa = a.abs ().value ();
   T bb = b.abs ().value ();
-  T xx = 0, lx = 1;
-  T yy = 1, ly = 0;
+  T xx, lx, yy, ly;
+  xx = 0, lx = 1;
+  yy = 1, ly = 0;
 
   while (bb != 0)
     {
@@ -347,7 +351,8 @@
       bool incb = bb.numel () != 1;
 
       T *gptr = gg.fortran_vec ();
-      T *xptr = xx.fortran_vec (), *yptr = yy.fortran_vec ();
+      T *xptr = xx.fortran_vec ();
+      T *yptr = yy.fortran_vec ();
 
       octave_idx_type n = gg.numel ();
       for (octave_idx_type i = 0; i < n; i++)
--- a/libinterp/corefcn/gl-render.cc
+++ b/libinterp/corefcn/gl-render.cc
@@ -147,7 +147,8 @@
     {
       // FIXME: dim_vectors hold octave_idx_type values.
       //        Should we check for dimensions larger than intmax?
-      int h = dv(0), w = dv(1), tw, th;
+      int h, w, tw, th;
+      h = dv(0), w = dv(1);
       GLuint id;
       bool ok = true;
 
@@ -436,12 +437,11 @@
       = reinterpret_cast<vertex_data::vertex_data_rep *> (data);
     //printf ("patch_tesselator::vertex (%g, %g, %g)\n", v->coords(0), v->coords(1), v->coords(2));
 
-    // FIXME: why did I need to keep the first vertex of the face
-    // in JHandles? I think it's related to the fact that the
-    // tessellation process might re-order the vertices, such that
-    // the first one you get here might not be the first one of the face;
-    // but I can't figure out the actual reason.
-    if (color_mode > 0 && (first || color_mode == 2))
+    // NOTE: OpenGL can re-order vertices so "first" is basically meaningless
+    // in this callback routine.  For "flat" coloring of FaceColor the first
+    // vertex must be identified in the draw_patch routine.
+
+    if (color_mode == 2 || (color_mode == 1 && ! is_filled ()))
       {
         Matrix col = v->color;
 
@@ -458,7 +458,7 @@
 
                 for (int k = 0; k < 3; k++)
                   buf[k] = (v->diffuse * col(k));
-                glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf);
+                glMaterialfv (LIGHT_MODE, GL_DIFFUSE, buf);
               }
           }
       }
@@ -471,8 +471,7 @@
     first = false;
   }
 
-  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4],
-                void **out_data)
+  void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data)
   {
     //printf ("patch_tesselator::combine\n");
 
@@ -765,7 +764,7 @@
           label.erase (0, label.find_first_not_of (" "));
           label = label.substr (0, label.find_last_not_of (" ")+1);
 
-          // FIXME: as tick text is transparent, shouldn't it be
+          // FIXME: As tick text is transparent, shouldn't it be
           //        drawn after axes object, for correct rendering?
           if (xyz == 0) // X
             {
@@ -829,6 +828,10 @@
 void
 opengl_renderer::draw_axes_planes (const axes::properties& props)
 {
+  Matrix axe_color = props.get_color_rgb ();
+  if (axe_color.numel () == 0 || ! props.is_visible ())
+    return;
+
   double xPlane = props.get_xPlane ();
   double yPlane = props.get_yPlane ();
   double zPlane = props.get_zPlane ();
@@ -837,42 +840,43 @@
   double zPlaneN = props.get_zPlaneN ();
 
   // Axes planes
-  Matrix axe_color = props.get_color_rgb ();
-  if (axe_color.numel () > 0 && props.is_visible ())
-    {
-      set_color (axe_color);
-      set_polygon_offset (true, 2.5);
-
-      glBegin (GL_QUADS);
-
-      // X plane
-      glVertex3d (xPlane, yPlaneN, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlane, yPlaneN, zPlane);
-
-      // Y plane
-      glVertex3d (xPlaneN, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlaneN);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlaneN, yPlane, zPlane);
-
-      // Z plane
-      glVertex3d (xPlaneN, yPlaneN, zPlane);
-      glVertex3d (xPlane, yPlaneN, zPlane);
-      glVertex3d (xPlane, yPlane, zPlane);
-      glVertex3d (xPlaneN, yPlane, zPlane);
-
-      glEnd ();
-
-      set_polygon_offset (false);
-    }
+  set_color (axe_color);
+  set_polygon_offset (true, 2.5);
+
+  glBegin (GL_QUADS);
+
+  // X plane
+  glVertex3d (xPlane, yPlaneN, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlane);
+  glVertex3d (xPlane, yPlaneN, zPlane);
+
+  // Y plane
+  glVertex3d (xPlaneN, yPlane, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlaneN);
+  glVertex3d (xPlane, yPlane, zPlane);
+  glVertex3d (xPlaneN, yPlane, zPlane);
+
+  // Z plane
+  glVertex3d (xPlaneN, yPlaneN, zPlane);
+  glVertex3d (xPlane, yPlaneN, zPlane);
+  glVertex3d (xPlane, yPlane, zPlane);
+  glVertex3d (xPlaneN, yPlane, zPlane);
+
+  glEnd ();
+
+  set_polygon_offset (false);
 }
 
 void
 opengl_renderer::draw_axes_boxes (const axes::properties& props)
 {
+  if (! props.is_visible ())
+    return;
+
   bool xySym = props.get_xySym ();
+  bool layer2Dtop = props.get_layer2Dtop ();
+  bool is2d = props.get_is2D ();
   double xPlane = props.get_xPlane ();
   double yPlane = props.get_yPlane ();
   double zPlane = props.get_zPlane ();
@@ -893,106 +897,114 @@
   set_linestyle ("-", true);
   set_linewidth (props.get_linewidth ());
 
-  if (props.is_visible ())
+  glBegin (GL_LINES);
+
+  if (layer2Dtop)
+    std::swap (zpTick, zpTickN);
+
+  // X box
+  set_color (props.get_xcolor_rgb ());
+  glVertex3d (xPlaneN, ypTick, zpTick);
+  glVertex3d (xPlane, ypTick, zpTick);
+
+  if (props.is_box ())
     {
-      glBegin (GL_LINES);
-
-      // X box
-      set_color (props.get_xcolor_rgb ());
-      glVertex3d (xPlaneN, ypTick, zpTick);
-      glVertex3d (xPlane, ypTick, zpTick);
-
-      if (props.is_box ())
+      glVertex3d (xPlaneN, ypTickN, zpTick);
+      glVertex3d (xPlane, ypTickN, zpTick);
+      if (! is2d)
         {
-          glVertex3d (xPlaneN, ypTickN, zpTick);
-          glVertex3d (xPlane, ypTickN, zpTick);
           glVertex3d (xPlaneN, ypTickN, zpTickN);
           glVertex3d (xPlane, ypTickN, zpTickN);
           glVertex3d (xPlaneN, ypTick, zpTickN);
           glVertex3d (xPlane, ypTick, zpTickN);
         }
-
-      // Y box
-      set_color (props.get_ycolor_rgb ());
-      glVertex3d (xpTick, yPlaneN, zpTick);
-      glVertex3d (xpTick, yPlane, zpTick);
-
-      if (props.is_box () && ! plotyy)
+    }
+
+  // Y box
+  set_color (props.get_ycolor_rgb ());
+  glVertex3d (xpTick, yPlaneN, zpTick);
+  glVertex3d (xpTick, yPlane, zpTick);
+
+  if (props.is_box () && ! plotyy)
+    {
+      glVertex3d (xpTickN, yPlaneN, zpTick);
+      glVertex3d (xpTickN, yPlane, zpTick);
+
+      if (! is2d)
         {
-          glVertex3d (xpTickN, yPlaneN, zpTick);
-          glVertex3d (xpTickN, yPlane, zpTick);
           glVertex3d (xpTickN, yPlaneN, zpTickN);
           glVertex3d (xpTickN, yPlane, zpTickN);
           glVertex3d (xpTick, yPlaneN, zpTickN);
           glVertex3d (xpTick, yPlane, zpTickN);
         }
-
-      // Z box
-      set_color (props.get_zcolor_rgb ());
+    }
+
+  // Z box
+  set_color (props.get_zcolor_rgb ());
+
+  if (xySym)
+    {
+      glVertex3d (xPlaneN, yPlane, zPlaneN);
+      glVertex3d (xPlaneN, yPlane, zPlane);
+    }
+  else
+    {
+      glVertex3d (xPlane, yPlaneN, zPlaneN);
+      glVertex3d (xPlane, yPlaneN, zPlane);
+    }
+
+  if (props.is_box ())
+    {
+      glVertex3d (xPlane, yPlane, zPlaneN);
+      glVertex3d (xPlane, yPlane, zPlane);
 
       if (xySym)
         {
-          glVertex3d (xPlaneN, yPlane, zPlaneN);
-          glVertex3d (xPlaneN, yPlane, zPlane);
-        }
-      else
-        {
           glVertex3d (xPlane, yPlaneN, zPlaneN);
           glVertex3d (xPlane, yPlaneN, zPlane);
         }
-
-      if (props.is_box ())
+      else
         {
-          glVertex3d (xPlane, yPlane, zPlaneN);
-          glVertex3d (xPlane, yPlane, zPlane);
-
-          if (xySym)
-            {
-              glVertex3d (xPlane, yPlaneN, zPlaneN);
-              glVertex3d (xPlane, yPlaneN, zPlane);
-            }
-          else
-            {
-              glVertex3d (xPlaneN, yPlane, zPlaneN);
-              glVertex3d (xPlaneN, yPlane, zPlane);
-            }
-
-          glVertex3d (xPlaneN, yPlaneN, zPlaneN);
-          glVertex3d (xPlaneN, yPlaneN, zPlane);
+          glVertex3d (xPlaneN, yPlane, zPlaneN);
+          glVertex3d (xPlaneN, yPlane, zPlane);
         }
 
-      glEnd ();
+      glVertex3d (xPlaneN, yPlaneN, zPlaneN);
+      glVertex3d (xPlaneN, yPlaneN, zPlane);
     }
+
+  glEnd ();
 }
 
 void
 opengl_renderer::draw_axes_x_grid (const axes::properties& props)
 {
   int xstate = props.get_xstate ();
-  int zstate = props.get_zstate ();
-  bool x2Dtop = props.get_x2Dtop ();
-  bool layer2Dtop = props.get_layer2Dtop ();
-  bool xyzSym = props.get_xyzSym ();
-  bool nearhoriz = props.get_nearhoriz ();
-  double xticklen = props.get_xticklen ();
-  double xtickoffset = props.get_xtickoffset ();
-  double fy = props.get_fy ();
-  double fz = props.get_fz ();
-  double x_min = props.get_x_min ();
-  double x_max = props.get_x_max ();
-  double yPlane = props.get_yPlane ();
-  double yPlaneN = props.get_yPlaneN ();
-  double ypTick = props.get_ypTick ();
-  double ypTickN = props.get_ypTickN ();
-  double zPlane = props.get_zPlane ();
-  double zPlaneN = props.get_zPlaneN ();
-  double zpTick = props.get_zpTick ();
-  double zpTickN = props.get_zpTickN ();
-
-  // X grid
 
   if (props.is_visible () && xstate != AXE_DEPTH_DIR)
     {
+      int zstate = props.get_zstate ();
+      bool x2Dtop = props.get_x2Dtop ();
+      bool layer2Dtop = props.get_layer2Dtop ();
+      bool xyzSym = props.get_xyzSym ();
+      bool nearhoriz = props.get_nearhoriz ();
+      double xticklen = props.get_xticklen ();
+      double xtickoffset = props.get_xtickoffset ();
+      double fy = props.get_fy ();
+      double fz = props.get_fz ();
+      double x_min = props.get_x_min ();
+      double x_max = props.get_x_max ();
+      double yPlane = props.get_yPlane ();
+      double yPlaneN = props.get_yPlaneN ();
+      double ypTick = props.get_ypTick ();
+      double ypTickN = props.get_ypTickN ();
+      double zPlane = props.get_zPlane ();
+      double zPlaneN = props.get_zPlaneN ();
+      double zpTick = props.get_zpTick ();
+      double zpTickN = props.get_zpTickN ();
+
+      // X grid
+
       std::string gridstyle = props.get_gridlinestyle ();
       std::string minorgridstyle = props.get_minorgridlinestyle ();
       bool do_xgrid = (props.is_xgrid () && (gridstyle != "none"));
@@ -1002,7 +1014,8 @@
       Matrix xticks = xform.xscale (props.get_xtick ().matrix_value ());
       Matrix xmticks = xform.xscale (props.get_xmtick ().matrix_value ());
       string_vector xticklabels = props.get_xticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
+      int wmax = 0;
+      int hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fy);
       bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
 
@@ -1077,30 +1090,31 @@
 opengl_renderer::draw_axes_y_grid (const axes::properties& props)
 {
   int ystate = props.get_ystate ();
-  int zstate = props.get_zstate ();
-  bool y2Dright = props.get_y2Dright ();
-  bool layer2Dtop = props.get_layer2Dtop ();
-  bool xyzSym = props.get_xyzSym ();
-  bool nearhoriz = props.get_nearhoriz ();
-  double yticklen = props.get_yticklen ();
-  double ytickoffset = props.get_ytickoffset ();
-  double fx = props.get_fx ();
-  double fz = props.get_fz ();
-  double xPlane = props.get_xPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double xpTick = props.get_xpTick ();
-  double xpTickN = props.get_xpTickN ();
-  double y_min = props.get_y_min ();
-  double y_max = props.get_y_max ();
-  double zPlane = props.get_zPlane ();
-  double zPlaneN = props.get_zPlaneN ();
-  double zpTick = props.get_zpTick ();
-  double zpTickN = props.get_zpTickN ();
-
-  // Y grid
 
   if (ystate != AXE_DEPTH_DIR && props.is_visible ())
     {
+      int zstate = props.get_zstate ();
+      bool y2Dright = props.get_y2Dright ();
+      bool layer2Dtop = props.get_layer2Dtop ();
+      bool xyzSym = props.get_xyzSym ();
+      bool nearhoriz = props.get_nearhoriz ();
+      double yticklen = props.get_yticklen ();
+      double ytickoffset = props.get_ytickoffset ();
+      double fx = props.get_fx ();
+      double fz = props.get_fz ();
+      double xPlane = props.get_xPlane ();
+      double xPlaneN = props.get_xPlaneN ();
+      double xpTick = props.get_xpTick ();
+      double xpTickN = props.get_xpTickN ();
+      double y_min = props.get_y_min ();
+      double y_max = props.get_y_max ();
+      double zPlane = props.get_zPlane ();
+      double zPlaneN = props.get_zPlaneN ();
+      double zpTick = props.get_zpTick ();
+      double zpTickN = props.get_zpTickN ();
+
+      // Y grid
+
       std::string gridstyle = props.get_gridlinestyle ();
       std::string minorgridstyle = props.get_minorgridlinestyle ();
       bool do_ygrid = (props.is_ygrid () && (gridstyle != "none"));
@@ -1110,7 +1124,8 @@
       Matrix yticks = xform.yscale (props.get_ytick ().matrix_value ());
       Matrix ymticks = xform.yscale (props.get_ymtick ().matrix_value ());
       string_vector yticklabels = props.get_yticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
+      int wmax = 0;
+      int hmax = 0;
       bool tick_along_z = nearhoriz || xisinf (fx);
       bool mirror = props.is_box () && ystate != AXE_ANY_DIR
                     && (! props.has_property ("__plotyy_axes__"));
@@ -1183,23 +1198,24 @@
 opengl_renderer::draw_axes_z_grid (const axes::properties& props)
 {
   int zstate = props.get_zstate ();
-  bool xySym = props.get_xySym ();
-  bool zSign = props.get_zSign ();
-  double zticklen = props.get_zticklen ();
-  double ztickoffset = props.get_ztickoffset ();
-  double fx = props.get_fx ();
-  double fy = props.get_fy ();
-  double xPlane = props.get_xPlane ();
-  double xPlaneN = props.get_xPlaneN ();
-  double yPlane = props.get_yPlane ();
-  double yPlaneN = props.get_yPlaneN ();
-  double z_min = props.get_z_min ();
-  double z_max = props.get_z_max ();
-
-  // Z Grid
 
   if (zstate != AXE_DEPTH_DIR && props.is_visible ())
     {
+      bool xySym = props.get_xySym ();
+      bool zSign = props.get_zSign ();
+      double zticklen = props.get_zticklen ();
+      double ztickoffset = props.get_ztickoffset ();
+      double fx = props.get_fx ();
+      double fy = props.get_fy ();
+      double xPlane = props.get_xPlane ();
+      double xPlaneN = props.get_xPlaneN ();
+      double yPlane = props.get_yPlane ();
+      double yPlaneN = props.get_yPlaneN ();
+      double z_min = props.get_z_min ();
+      double z_max = props.get_z_max ();
+
+      // Z Grid
+
       std::string gridstyle = props.get_gridlinestyle ();
       std::string minorgridstyle = props.get_minorgridlinestyle ();
       bool do_zgrid = (props.is_zgrid () && (gridstyle != "none"));
@@ -1209,7 +1225,8 @@
       Matrix zticks = xform.zscale (props.get_ztick ().matrix_value ());
       Matrix zmticks = xform.zscale (props.get_zmtick ().matrix_value ());
       string_vector zticklabels = props.get_zticklabel ().all_strings ();
-      int wmax = 0, hmax = 0;
+      int wmax = 0;
+      int hmax = 0;
       bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
 
       set_color (props.get_zcolor_rgb ());
@@ -1337,11 +1354,11 @@
   // 1st pass: draw light objects
 
   // Start with the last element of the array of child objects to
-  // display them in the oder they were added to the array.
+  // display them in the order they were added to the array.
 
   for (octave_idx_type i = children.numel () - 1; i >= 0; i--)
     {
-      graphics_object go = gh_manager::get_object (children (i));
+      graphics_object go = gh_manager::get_object (children(i));
 
       if (go.get_properties ().is_visible ())
         {
@@ -1407,7 +1424,7 @@
   if (x_max > floatmax || y_max > floatmax || z_max > floatmax
       || x_min < -floatmax || y_min < -floatmax || z_min < -floatmax)
     {
-      warning ("gl-render: data values greater than float capacity.  (1) Scale data, or (2) Use gnuplot");
+      warning ("opengl_renderer: data values greater than float capacity.  (1) Scale data, or (2) Use gnuplot");
       return;
     }
 
@@ -1545,7 +1562,7 @@
         {
           if (clip[i] == clip_ok)
             draw_marker (x(i), y(i),
-                         has_z ? z(i) : static_cast<double> (i) / n,
+                         has_z ? z(i) : 0.0,
                          lc, fc);
         }
 
@@ -1562,7 +1579,8 @@
   const Matrix y = xform.yscale (props.get_ydata ().matrix_value ());
   const Matrix z = xform.zscale (props.get_zdata ().matrix_value ());
 
-  int zr = z.rows (), zc = z.columns ();
+  int zr = z.rows ();
+  int zc = z.columns ();
 
   NDArray c;
   const NDArray n = props.get_vertexnormals ().array_value ();
@@ -1571,7 +1589,7 @@
   Matrix a;
 
   if (props.facelighting_is ("phong") || props.edgelighting_is ("phong"))
-    warning ("opengl_renderer::draw: phong light model not supported");
+    warning ("opengl_renderer: phong light model not supported");
 
   int fc_mode = (props.facecolor_is_rgb () ? 0 :
                  (props.facecolor_is ("flat") ? 1 :
@@ -1641,8 +1659,8 @@
       glMaterialf (LIGHT_MODE, GL_SHININESS, se);
     }
 
-  // FIXME: good candidate for caching, transfering pixel
-  // data to OpenGL is time consuming.
+  // FIXME: good candidate for caching,
+  //        transferring pixel data to OpenGL is time consuming.
   if (fc_mode == 3)
     tex = opengl_texture::create (props.get_color_data ());
 
@@ -2150,8 +2168,8 @@
     }
 }
 
-// FIXME: global optimization (rendering, data structures...), there
-// is probably a smarter/faster/less-memory-consuming way to do this.
+// FIXME: global optimization (rendering, data structures...),
+// there is probably a smarter/faster/less-memory-consuming way to do this.
 void
 opengl_renderer::draw_patch (const patch::properties &props)
 {
@@ -2260,7 +2278,7 @@
 
         Matrix vv (1, 3, 0.0);
         Matrix cc;
-        Matrix nn(1, 3, 0.0);
+        Matrix nn (1, 3, 0.0);
         double aa = 1.0;
 
         vv(0) = v(idx,0); vv(1) = v(idx,1);
@@ -2284,8 +2302,7 @@
               aa = a(idx);
           }
 
-        vdata[i+j*fr] =
-          vertex_data (vv, cc, nn, aa, as, ds, ss, se);
+        vdata[i+j*fr] = vertex_data (vv, cc, nn, aa, as, ds, ss, se);
       }
 
   if (fl_mode > 0 || el_mode > 0)
@@ -2322,7 +2339,10 @@
             glEnable (GL_LIGHTING);
 
           // FIXME: use __index__ property from patch object
-          patch_tesselator tess (this, fc_mode, fl_mode, 0);
+          // -1.25 chosen to provide sufficient Z-offset for
+          // 'layer' property of 2-D plots and not to provoke
+          // Z-fighting with tesselator outline.
+          patch_tesselator tess (this, fc_mode, fl_mode, -1.25);
 
           for (int i = 0; i < nf; i++)
             {
@@ -2332,13 +2352,44 @@
               tess.begin_polygon (true);
               tess.begin_contour ();
 
-              for (int j = 0; j < count_f(i); j++)
+              // Add vertices in reverse order for Matlab compatibility
+              for (int j = count_f(i)-1; j > 0; j--)
                 {
                   vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
 
                   tess.add_vertex (vv->coords.fortran_vec (), vv);
                 }
 
+              if (count_f(i) > 0)
+                {
+                  vertex_data::vertex_data_rep *vv = vdata[i].get_rep ();
+
+                  if (fc_mode == 1)
+                    {
+                      // For "flat" shading, use color of 1st vertex.
+                      Matrix col = vv->color;
+
+                      if (col.numel () == 3)
+                        {
+                          glColor3dv (col.data ());
+                          if (fl_mode > 0)
+                            {
+                              float cb[4] = { 0, 0, 0, 1 };
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = (vv->ambient * col(k));
+                              glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb);
+
+                              for (int k = 0; k < 3; k++)
+                                cb[k] = (vv->diffuse * col(k));
+                              glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb);
+                            }
+                        }
+                    }
+
+                  tess.add_vertex (vv->coords.fortran_vec (), vv);
+                }
+
               tess.end_contour ();
               tess.end_polygon ();
             }
@@ -2381,15 +2432,15 @@
           set_linewidth (props.get_linewidth ());
 
 
-          // FIXME: use __index__ property from patch object; should we
-          // offset patch contour as well?
+          // FIXME: use __index__ property from patch object;
+          //        should we offset patch contour as well?
           patch_tesselator tess (this, ec_mode, el_mode);
 
           for (int i = 0; i < nf; i++)
             {
               if (clip_f(i))
                 {
-                  // This is an unclosed contour. Draw it as a line
+                  // This is an unclosed contour. Draw it as a line.
                   bool flag = false;
 
                   for (int j = 0; j < count_f(i); j++)
@@ -2421,7 +2472,7 @@
                   tess.begin_polygon (false);
                   tess.begin_contour ();
 
-                  for (int j = 0; j < count_f(i); j++)
+                  for (int j = count_f(i)-1; j >= 0; j--)
                     {
                       vertex_data::vertex_data_rep *vv
                         = vdata[i+j*fr].get_rep ();
@@ -2552,7 +2603,8 @@
 {
   octave_value cdata = props.get_color_data ();
   dim_vector dv (cdata.dims ());
-  int h = dv(0), w = dv(1);
+  int h = dv(0);
+  int w = dv(1);
 
   Matrix x = props.get_xdata ().matrix_value ();
   Matrix y = props.get_ydata ().matrix_value ();
@@ -2572,7 +2624,7 @@
 
   if (xisnan (p0(0)) || xisnan (p0(1)) || xisnan (p1(0)) || xisnan (p1(1)))
     {
-      warning ("gl-render: image x,y data too large to draw");
+      warning ("opengl_renderer: image X,Y data too large to draw");
       return;
     }
 
@@ -2605,13 +2657,12 @@
       nor_dy = 1;
     }
 
-
-  // OpenGL won't draw the image if it's origin is outside the
-  // viewport/clipping plane so we must do the clipping
-  // ourselfes - only draw part of the image
-
-  int j0 = 0, j1 = w;
-  int i0 = 0, i1 = h;
+  // OpenGL won't draw any of the image if it's origin is outside the
+  // viewport/clipping plane so we must do the clipping ourselves.
+
+  int j0, j1, i0, i1;
+  j0 = 0, j1 = w;
+  i0 = 0, i1 = h;
 
   float im_xmin = x(0) - nor_dx/2;
   float im_xmax = x(1) + nor_dx/2;
@@ -2644,7 +2695,7 @@
   glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
 
   // by default this is 4
-  glPixelStorei (GL_UNPACK_ALIGNMENT,1);
+  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
 
   // Expect RGB data
   if (dv.length () == 3 && dv(2) == 3)
@@ -2668,6 +2719,44 @@
           draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
 
         }
+      else if (cdata.is_single_type ())
+        {
+          const FloatNDArray xcdata = cdata.float_array_value ();
+
+          OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
+
+          for (int i = i0; i < i1; i++)
+            {
+              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                {
+                  a[idx]   = xcdata(i,j,0);
+                  a[idx+1] = xcdata(i,j,1);
+                  a[idx+2] = xcdata(i,j,2);
+                }
+            }
+
+          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
+
+        }
+      else if (cdata.is_uint8_type ())
+        {
+          const uint8NDArray xcdata = cdata.uint8_array_value ();
+
+          OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
+
+          for (int i = i0; i < i1; i++)
+            {
+              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
+                {
+                  a[idx]   = xcdata(i,j,0);
+                  a[idx+1] = xcdata(i,j,1);
+                  a[idx+2] = xcdata(i,j,2);
+                }
+            }
+
+          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
+
+        }
       else if (cdata.is_uint16_type ())
         {
           const uint16NDArray xcdata = cdata.uint16_array_value ();
@@ -2687,29 +2776,11 @@
           draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a);
 
         }
-      else if (cdata.is_uint8_type ())
-        {
-          const uint8NDArray xcdata = cdata.uint8_array_value ();
-
-          OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
-
-          for (int i = i0; i < i1; i++)
-            {
-              for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
-                {
-                  a[idx]   = xcdata(i,j,0);
-                  a[idx+1] = xcdata(i,j,1);
-                  a[idx+2] = xcdata(i,j,2);
-                }
-            }
-
-          draw_pixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
-        }
       else
-        warning ("opengl_texture::draw: invalid image data type (expected double, uint16, or uint8)");
+        warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)");
     }
   else
-    warning ("opengl_texture::draw: invalid image size (expected n*m*3 or n*m)");
+    warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)");
 
   glPixelZoom (1, 1);
 }
@@ -3057,8 +3128,7 @@
       }
       break;
     default:
-      warning ("opengl_renderer: unsupported marker '%s'",
-               marker.c_str ());
+      warning ("opengl_renderer: unsupported marker '%s'", marker.c_str ());
       break;
     }
 
@@ -3106,7 +3176,7 @@
 
   return bbox;
 #else
-  ::warning ("render_text: cannot render text, Freetype library not available");
+  warning ("opengl_renderer: cannot render text, FreeType library not available");
   return Matrix (1, 4, 0.0);
 #endif
 }
--- a/libinterp/corefcn/gl-render.h
+++ b/libinterp/corefcn/gl-render.h
@@ -200,7 +200,7 @@
   ColumnVector camera_pos, camera_dir;
 
 #if HAVE_FREETYPE
-  // freetype render, used for text rendering
+  // FreeType render, used for text rendering
   ft_render text_renderer;
 #endif
 
--- a/libinterp/corefcn/gl2ps-renderer.cc
+++ b/libinterp/corefcn/gl2ps-renderer.cc
@@ -44,7 +44,8 @@
     {
       in_draw = true;
 
-      GLint buffsize = 0, state = GL2PS_OVERFLOW;
+      GLint buffsize = 0;
+      GLint state = GL2PS_OVERFLOW;
       GLint viewport[4];
 
       glGetIntegerv (GL_VIEWPORT, viewport);
@@ -52,8 +53,8 @@
       GLint gl2ps_term;
       if (term.find ("eps") != std::string::npos) gl2ps_term = GL2PS_EPS;
       else if (term.find ("pdf") != std::string::npos) gl2ps_term = GL2PS_PDF;
+      else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS;
       else if (term.find ("svg") != std::string::npos) gl2ps_term = GL2PS_SVG;
-      else if (term.find ("ps") != std::string::npos) gl2ps_term = GL2PS_PS;
       else if (term.find ("pgf") != std::string::npos) gl2ps_term = GL2PS_PGF;
       else if (term.find ("tex") != std::string::npos) gl2ps_term = GL2PS_TEX;
       else
@@ -67,7 +68,9 @@
 
       // Default sort order optimizes for 3D plots
       GLint gl2ps_sort = GL2PS_BSP_SORT;
-      if (term.find ("is2D") != std::string::npos) gl2ps_sort = GL2PS_NO_SORT;
+      // For 2D plots we can use a simpler Z-depth sorting algorithm
+      if (term.find ("is2D") != std::string::npos)
+        gl2ps_sort = GL2PS_SIMPLE_SORT;
 
       while (state == GL2PS_OVERFLOW)
         {
@@ -94,7 +97,7 @@
           buffsize += 1024*1024;
           gl2psBeginPage ("glps_renderer figure", "Octave", viewport,
                           gl2ps_term, gl2ps_sort,
-                          (GL2PS_SILENT | GL2PS_SIMPLE_LINE_OFFSET
+                          (GL2PS_SILENT 
                            | GL2PS_NO_BLENDING | GL2PS_OCCLUSION_CULL
                            | GL2PS_BEST_ROOT | gl2ps_text
                            | GL2PS_NO_PS3_SHADING),
@@ -158,7 +161,7 @@
                 alignment_to_mode (ha, va), rotation);
 
   // FIXME?
-  // We have no way of getting a bounding box from gl2ps, so we use freetype.
+  // We have no way of getting a bounding box from gl2ps, so we use FreeType.
   Matrix bbox;
   uint8NDArray pixels;
   text_to_pixels (txt, pixels, bbox, 0, 0, rotation);
@@ -195,7 +198,7 @@
   OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*w*h);
 
   // Convert to GL_FLOAT as it is the only type gl2ps accepts.
-  for (unsigned int i = 0; i < 3*w*h; i++)
+  for (int i = 0; i < 3*w*h; i++)
     a[i] = data[i] / maxval;
   
   gl2psDrawPixels (w, h, 0, 0, format, GL_FLOAT, a);
@@ -225,7 +228,8 @@
   set_color (props.get_color_rgb ());
 
   const Matrix pos = get_transform ().scale (props.get_data_position ());
-  int halign = 0, valign = 0;
+  int halign = 0;
+  int valign = 0;
 
   if (props.horizontalalignment_is ("center"))
     halign = 1;
--- a/libinterp/corefcn/graphics.cc
+++ b/libinterp/corefcn/graphics.cc
@@ -58,6 +58,7 @@
 #include "toplev.h"
 #include "txt-eng-ft.h"
 #include "unwind-prot.h"
+#include "octave-default-image.h"
 
 // forward declarations
 static octave_value xget (const graphics_handle& h, const caseless_str& name);
@@ -255,6 +256,77 @@
 }
 
 static Matrix
+default_image_cdata (void)
+{
+  Matrix m (64, 64, 0.0);
+  int i = 0;
+  for (int col = 0; col < 64; col++)
+    for (int row = 0; row < 64; row++)
+      {
+        m(col,row) = static_cast<double> (default_im_data[i]);
+        i++;
+      }
+
+  return m;
+}
+
+static Matrix
+default_surface_xdata (void)
+{
+  Matrix m (3, 3, 0.0);
+  for (int col = 0; col < 3; col++)
+    for (int row = 0; row < 3; row++)
+      m(row,col) = col+1;
+
+  return m;
+}
+
+static Matrix
+default_surface_ydata (void)
+{
+  Matrix m (3, 3, 0.0);
+  for (int row = 0; row < 3; row++)
+    for (int col = 0; col < 3; col++)
+      m(row,col) = row+1;
+
+  return m;
+}
+
+static Matrix
+default_surface_zdata (void)
+{
+  Matrix m (3, 3, 0.0);
+  for (int row = 0; row < 3; row++)
+    m(row,row) = 1.0;
+  return m;
+}
+
+static Matrix
+default_surface_cdata (void)
+{
+  return default_surface_zdata ();
+}
+
+static Matrix
+default_patch_faces (void)
+{
+  Matrix m (1, 3, 1.0);
+  m(1) = 2.0;
+  m(2) = 3.0;
+  return m;
+}
+
+static Matrix
+default_patch_vertices (void)
+{
+  Matrix m (3, 2, 0);
+  m(1) = 1.0;
+  m(3) = 1.0;
+  m(4) = 1.0;
+  return m;
+}
+
+static Matrix
 default_axes_position (void)
 {
   Matrix m (1, 4, 0.0);
@@ -274,6 +346,14 @@
 }
 
 static Matrix
+default_axes_view (void)
+{
+  Matrix m (1, 2, 0.0);
+  m(1) = 90.0;
+  return m;
+}
+
+static Matrix
 default_axes_tick (void)
 {
   Matrix m (1, 6, 0.0);
@@ -668,13 +748,13 @@
 }
 
 static void
-convert_cdata_2 (bool is_scaled, double clim_0, double clim_1,
+convert_cdata_2 (bool is_scaled, bool is_real, double clim_0, double clim_1,
                  const double *cmapv, double x, octave_idx_type lda,
                  octave_idx_type nc, octave_idx_type i, double *av)
 {
   if (is_scaled)
     x = xround ((nc - 1) * (x - clim_0) / (clim_1 - clim_0));
-  else
+  else if (is_real)
     x = xround (x - 1);
 
   if (xisnan (x))
@@ -700,12 +780,13 @@
 
 template <class T>
 void
-convert_cdata_1 (bool is_scaled, double clim_0, double clim_1,
+convert_cdata_1 (bool is_scaled, bool is_real, double clim_0, double clim_1,
                  const double *cmapv, const T *cv, octave_idx_type lda,
                  octave_idx_type nc, double *av)
 {
   for (octave_idx_type i = 0; i < lda; i++)
-    convert_cdata_2 (is_scaled, clim_0, clim_1, cmapv, cv[i], lda, nc, i, av);
+    convert_cdata_2 (is_scaled, is_real,
+                     clim_0, clim_1, cmapv, cv[i], lda, nc, i, av);
 }
 
 static octave_value
@@ -714,6 +795,7 @@
 {
   dim_vector dv (cdata.dims ());
 
+  // TrueColor data doesn't require conversion
   if (dv.length () == cdim && dv(cdim-1) == 3)
     return cdata;
 
@@ -758,22 +840,34 @@
   double clim_0 = clim(0);
   double clim_1 = clim(1);
 
-#define CONVERT_CDATA_1(ARRAY_T, VAL_FN) \
+  // FIXME: There is a lot of processing time spent just on data conversion
+  //        both here in graphics.cc and again in gl-render.cc.  There must
+  //        be room for improvement!  Here a macro expands to a templated
+  //        function which in turn calls another function (covert_cdata_2).
+  //        And in gl-render.cc (opengl_renderer::draw_image), only GLfloat
+  //        is supported anyways so there is another double for loop across
+  //        height and width to convert all of the input data to GLfloat.
+
+#define CONVERT_CDATA_1(ARRAY_T, VAL_FN, IS_REAL) \
   do \
     { \
       ARRAY_T tmp = cdata. VAL_FN ## array_value (); \
  \
-      convert_cdata_1 (is_scaled, clim_0, clim_1, cmapv, \
+      convert_cdata_1 (is_scaled, IS_REAL, clim_0, clim_1, cmapv, \
                        tmp.data (), lda, nc, av); \
     } \
   while (0)
 
   if (cdata.is_uint8_type ())
-    CONVERT_CDATA_1 (uint8NDArray, uint8_);
+    CONVERT_CDATA_1 (uint8NDArray, uint8_, false);
+  else if (cdata.is_uint16_type ())
+    CONVERT_CDATA_1 (uint16NDArray, uint16_, false);
+  else if (cdata.is_double_type ())
+    CONVERT_CDATA_1 (NDArray, , true);
   else if (cdata.is_single_type ())
-    CONVERT_CDATA_1 (FloatNDArray, float_);
-  else if (cdata.is_double_type ())
-    CONVERT_CDATA_1 (NDArray, );
+    CONVERT_CDATA_1 (FloatNDArray, float_, true);
+  else if (cdata.is_bool_type ())
+    CONVERT_CDATA_1 (boolNDArray, bool_, false);
   else
     error ("unsupported type for cdata (= %s)", cdata.type_name ().c_str ());
 
@@ -1012,7 +1106,7 @@
   for (std::set<caseless_str>::const_iterator it = possible_vals.begin ();
        it != possible_vals.end (); it++)
     {
-      if (retval == "")
+      if (retval.empty ())
         {
           if (*it == default_value ())
             retval = "{" + *it + "}";
@@ -1027,8 +1121,10 @@
             retval += " | " + *it;
         }
     }
-  if (retval != "")
+
+  if (! retval.empty ())
     retval = "[ " + retval + " ]";
+
   return retval;
 }
 
@@ -1044,10 +1140,13 @@
 }
 
 bool
-color_values::str2rgb (std::string str)
-{
+color_values::str2rgb (const std::string& str_arg)
+{
+  bool retval = true;
+
   double tmp_rgb[3] = {0, 0, 0};
-  bool retval = true;
+
+  std::string str = str_arg;
   unsigned int len = str.length ();
 
   std::transform (str.begin (), str.end (), str.begin (), tolower);
@@ -1232,7 +1331,7 @@
 
       // check dimensional size constraints until a match is found
       for (std::list<dim_vector>::const_iterator it = size_constraints.begin ();
-           ! xok && it != size_constraints.end (); ++it)
+           ! xok && it != size_constraints.end ();++it)
         {
           dim_vector itdims = (*it);
 
@@ -2772,7 +2871,13 @@
               // Remove child from current parent
               graphics_object old_parent_obj;
               old_parent_obj = gh_manager::get_object (get_parent ());
-              old_parent_obj.remove_child (__myhandle__);
+
+               
+              if (old_parent_obj.get_handle () != hnp) 
+                old_parent_obj.remove_child (__myhandle__);
+              else
+                // Do nothing more
+                return;
 
               // Check new parent's parent is not this child to avoid recursion
               graphics_object new_parent_obj;
@@ -2795,6 +2900,18 @@
     error ("set: expecting parent to be a graphics handle");
 }
 
+/*
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   set (hax, "parent", gcf ())
+%!   assert (gca (), hax)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+*/
+
 void
 base_properties::mark_modified (void)
 {
@@ -2961,10 +3078,12 @@
   if (valid_object ())
     {
       octave_map m = get ().map_value ();
+      graphics_object obj = gh_manager::get_object (get_handle ());
 
       for (octave_map::const_iterator pa = m.begin (); pa != m.end (); pa++)
         {
-          if (pa->first != "children")
+          if (pa->first != "children" &&
+              ! obj.has_readonly_property (pa->first))
             {
               property p = get_properties ().get_property (pa->first);
 
@@ -2976,7 +3095,8 @@
                 }
             }
         }
-      if (retval != "")
+
+      if (! retval.empty ())
         retval += "\n";
     }
   else
@@ -2985,6 +3105,35 @@
   return retval;
 }
 
+std::string
+base_graphics_object::value_as_string (const std::string& prop)
+{
+  std::string retval;
+
+  if (valid_object ())
+    {
+      graphics_object obj = gh_manager::get_object (get_handle ());
+
+      if (prop != "children" && ! obj.has_readonly_property (prop))
+        {
+          property p = get_properties ().get_property (prop);
+
+          if (p.ok () && ! p.is_hidden ())
+            {
+              if (p.is_radio ())
+                retval += p.values_as_string ();
+            }
+        }
+
+      if (! retval.empty ())
+        retval += "\n";
+    }
+  else
+    error ("base_graphics_object::value_as_string: invalid graphics object");
+
+  return retval;
+}
+
 octave_scalar_map
 base_graphics_object::values_as_struct (void)
 {
@@ -2993,11 +3142,13 @@
   if (valid_object ())
     {
       octave_scalar_map m = get ().scalar_map_value ();
+      graphics_object obj = gh_manager::get_object (get_handle ());
 
       for (octave_scalar_map::const_iterator pa = m.begin ();
            pa != m.end (); pa++)
         {
-          if (pa->first != "children")
+          if (pa->first != "children"
+              && ! obj.has_readonly_property (pa->first))
             {
               property p = get_properties ().get_property (pa->first);
 
@@ -3017,6 +3168,25 @@
   return retval;
 }
 
+/*
+%!test
+%! hfig = figure ("visible", "off");
+%! unwind_protect
+%!   hax = axes ();
+%!   ret = set (hax, "tightinset");
+%!   assert (isempty (ret));
+%!   ret = set (hax, "type");
+%!   assert (isempty (ret));
+%!   ret = set (hfig, "__graphics_toolkit__");
+%!   assert (isempty (ret));
+%!   ret = set (0, "commandwindowsize");
+%!   assert (isempty (ret));
+%!   ret = set (0);
+%!   assert (! isfield (ret, "commandwindowsize"));
+%! unwind_protect_cleanup
+%!   close (hfig);
+%! end_unwind_protect
+*/
 graphics_object
 graphics_object::get_ancestor (const std::string& obj_type) const
 {
@@ -3038,25 +3208,6 @@
 // ---------------------------------------------------------------------
 
 void
-root_figure::properties::set_currentfigure (const octave_value& v)
-{
-  graphics_handle val (v);
-
-  if (error_state)
-    return;
-
-  if (xisnan (val.value ()) || is_handle (val))
-    {
-      currentfigure = val;
-
-      if (val.ok ())
-        gh_manager::push_figure (val);
-    }
-  else
-    gripe_set_invalid ("currentfigure");
-}
-
-void
 root_figure::properties::set_callbackobject (const octave_value& v)
 {
   graphics_handle val (v);
@@ -3087,6 +3238,80 @@
 }
 
 void
+root_figure::properties::set_currentfigure (const octave_value& v)
+{
+  graphics_handle val (v);
+
+  if (error_state)
+    return;
+
+  if (xisnan (val.value ()) || is_handle (val))
+    {
+      currentfigure = val;
+
+      if (val.ok ())
+        gh_manager::push_figure (val);
+    }
+  else
+    gripe_set_invalid ("currentfigure");
+}
+
+std::string
+root_figure::properties::get_format (void) const
+{
+  return F__formatstring__ ()(0).string_value ();
+}
+
+void
+root_figure::properties::set_format (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      format.set (val, false);
+      
+      if (! error_state)
+        {
+          Fformat (ovl (format.current_value ()));     
+
+          format.run_listeners ();
+        }
+    }
+}
+
+std::string
+root_figure::properties::get_formatspacing (void) const
+{
+  bool iscompact = F__compactformat__ ()(0).bool_value ();
+  if (iscompact)
+    return std::string ("compact");
+  else
+    return std::string ("loose");
+}
+
+void
+root_figure::properties::set_formatspacing (const octave_value& val)
+{
+  if (! error_state)
+    {
+      // Input checking and abrev. matching
+      formatspacing.set (val, false);
+      
+      if (! error_state)
+        {
+          std::string strval = formatspacing.current_value ();
+
+          if (strval == "compact")
+            F__compactformat__ (ovl (true));
+          else
+            F__compactformat__ (ovl (false));
+
+          formatspacing.run_listeners ();
+        }
+    }
+}
+
+void
 figure::properties::set_integerhandle (const octave_value& val)
 {
   if (! error_state)
@@ -4704,7 +4929,8 @@
   if (camerapositionmode_is ("auto"))
     {
       Matrix tview = get_view ().matrix_value ();
-      double az = tview(0), el = tview(1);
+      double az = tview(0);
+      double el = tview(1);
       double d = 5 * sqrt (pb(0)*pb(0)+pb(1)*pb(1)+pb(2)*pb(2));
 
       if (el == 90 || el == -90)
@@ -4729,7 +4955,8 @@
   if (cameraupvectormode_is ("auto"))
     {
       Matrix tview = get_view ().matrix_value ();
-      double az = tview(0), el = tview(1);
+      double az = tview(0);
+      double el = tview(1);
 
       if (el == 90 || el == -90)
         {
@@ -4791,7 +5018,8 @@
   translate (x_view, -0.5, -0.5, -0.5);
 
   Matrix x_cube = x_view * unit_cube ();
-  ColumnVector cmin = x_cube.row_min (), cmax = x_cube.row_max ();
+  ColumnVector cmin = x_cube.row_min ();
+  ColumnVector cmax = x_cube.row_max ();
   double xM = cmax(0)-cmin(0);
   double yM = cmax(1)-cmin(1);
 
@@ -4897,9 +5125,11 @@
   const Matrix xlims = xform.xscale (get_xlim ().matrix_value ());
   const Matrix ylims = xform.yscale (get_ylim ().matrix_value ());
   const Matrix zlims = xform.zscale (get_zlim ().matrix_value ());
-  double x_min = xlims(0), x_max = xlims(1);
-  double y_min = ylims(0), y_max = ylims(1);
-  double z_min = zlims(0), z_max = zlims(1);
+
+  double x_min, x_max, y_min, y_max, z_min, z_max;
+  x_min = xlims(0), x_max = xlims(1);
+  y_min = ylims(0), y_max = ylims(1);
+  z_min = zlims(0), z_max = zlims(1);
 
   ColumnVector p1, p2, dir (3);
 
@@ -5011,18 +5241,14 @@
     {
       if (xaxislocation_is ("top"))
         {
-          double tmp = yPlane;
-          yPlane = yPlaneN;
-          yPlaneN = tmp;
+          std::swap (yPlane, yPlaneN);
           x2Dtop = true;
         }
       ypTick = yPlaneN;
       ypTickN = yPlane;
       if (yaxislocation_is ("right"))
         {
-          double tmp = xPlane;
-          xPlane = xPlaneN;
-          xPlaneN = tmp;
+          std::swap (xPlane, xPlaneN);
           y2Dright = true;
         }
       xpTick = xPlaneN;
@@ -5038,6 +5264,7 @@
 
   Matrix viewmat = get_view ().matrix_value ();
   nearhoriz = std::abs (viewmat(1)) <= 5;
+  is2D = viewmat(1) == 90;
 
   update_ticklength ();
 }
@@ -5139,7 +5366,9 @@
                                    get_xticklabel ().all_strings (),
                                    get_xlim ().matrix_value ());
 
-      double wmax = ext(0), hmax = ext(1), angle = 0;
+      double wmax = ext(0);
+      double hmax = ext(1);
+      double angle = 0;
       ColumnVector p =
         graphics_xform::xform_vector ((xpTickN+xpTick)/2, ypTick, zpTick);
 
@@ -5240,7 +5469,9 @@
                                    get_yticklabel ().all_strings (),
                                    get_ylim ().matrix_value ());
 
-      double wmax = ext(0)+4, hmax = ext(1), angle = 0;
+      double wmax = ext(0)+4;
+      double hmax = ext(1);
+      double angle = 0;
       ColumnVector p =
         graphics_xform::xform_vector (xpTick, (ypTickN+ypTick)/2, zpTick);
 
@@ -5333,7 +5564,9 @@
                                    get_zticklabel ().all_strings (),
                                    get_zlim ().matrix_value ());
 
-      double wmax = ext(0), hmax = ext(1), angle = 0;
+      double wmax = ext(0);
+      double hmax = ext(1);
+      double angle = 0;
       ColumnVector p;
 
       if (xySym)
@@ -5494,12 +5727,13 @@
     s = xmax(s, (limits(1) - limits(0)) / (pbfactor * dafactor));
 }
 
-static bool updating_aspectratios = false;
+static std::set<double> updating_aspectratios;
 
 void
 axes::properties::update_aspectratios (void)
 {
-  if (updating_aspectratios)
+  if (updating_aspectratios.find (get___myhandle__ ().value ()) !=
+      updating_aspectratios.end ())
     return;
 
   Matrix xlimits = get_xlim ().matrix_value ();
@@ -5565,7 +5799,7 @@
           unwind_protect frame;
           frame.protect_var (updating_aspectratios);
 
-          updating_aspectratios = true;
+          updating_aspectratios.insert (get___myhandle__ ().value ());
 
           dx = pba(0) *da(0);
           dy = pba(1) *da(1);
@@ -6248,11 +6482,7 @@
   double tmp;
   // FIXME: should this be checked for somewhere else? (i.e. set{x,y,z}lim)
   if (hi < lo)
-    {
-      tmp = hi;
-      hi = lo;
-      lo = tmp;
-    }
+    std::swap (hi, lo);
 
   if (is_logscale)
     {
@@ -6269,15 +6499,17 @@
         }
     }
 
-  double tick_sep = calc_tick_sep (lo , hi);
-
-  if (is_logscale && ! (xisinf (hi) || xisinf (lo)))
-    {
-      // FIXME: what if (hi-lo) < tick_sep?
-      //         ex: loglog ([1 1.1])
-      tick_sep = std::max (tick_sep, 1.);
-      tick_sep = std::ceil (tick_sep);
-    }
+  double tick_sep;
+  
+  if (is_logscale)
+    {
+      if (! (xisinf (hi) || xisinf (lo)))
+        tick_sep = 1;  // Tick is every order of magnitude (bug #39449)
+      else
+        tick_sep = 0;
+    }
+  else
+    tick_sep = calc_tick_sep (lo , hi);
 
   int i1 = static_cast<int> (gnulib::floor (lo / tick_sep));
   int i2 = static_cast<int> (std::ceil (hi / tick_sep));
@@ -6402,7 +6634,8 @@
 #endif
 
   Matrix ext (1, 2, 0.0);
-  double wmax = 0., hmax = 0.;
+  double wmax, hmax;
+  wmax = hmax = 0.;
   int n = std::min (ticklabels.numel (), ticks.numel ());
   for (int i = 0; i < n; i++)
     {
@@ -6514,13 +6747,14 @@
     }
 }
 
-static bool updating_axis_limits = false;
+static std::set<double> updating_axis_limits;
 
 void
 axes::update_axis_limits (const std::string& axis_type,
                           const graphics_handle& h)
 {
-  if (updating_axis_limits)
+  if (updating_axis_limits.find (get_handle ().value ()) != 
+      updating_axis_limits.end ())
     return;
 
   Matrix kids = Matrix (1, 1, h.value ());
@@ -6679,7 +6913,7 @@
   unwind_protect frame;
   frame.protect_var (updating_axis_limits);
 
-  updating_axis_limits = true;
+  updating_axis_limits.insert (get_handle ().value ());
 
   switch (update_type)
     {
@@ -6722,7 +6956,10 @@
 void
 axes::update_axis_limits (const std::string& axis_type)
 {
-  if (updating_axis_limits || updating_aspectratios)
+  if ((updating_axis_limits.find (get_handle ().value ()) != 
+       updating_axis_limits.end ()) ||
+      (updating_aspectratios.find (get_handle ().value ()) !=
+       updating_aspectratios.end ()))
     return;
 
   Matrix kids = xproperties.get_children ();
@@ -6838,7 +7075,7 @@
   unwind_protect frame;
   frame.protect_var (updating_axis_limits);
 
-  updating_axis_limits = true;
+  updating_axis_limits.insert (get_handle ().value ());
 
   switch (update_type)
     {
@@ -6878,14 +7115,14 @@
 }
 
 inline
-double force_in_range (const double x, const double lower, const double upper)
+double force_in_range (double x, double lower, double upper)
 {
   if (x < lower)
-    { return lower; }
+    return lower;
   else if (x > upper)
-    { return upper; }
+    return upper;
   else
-    { return x; }
+    return x;
 }
 
 static Matrix
@@ -7225,7 +7462,8 @@
 {
 #ifdef HAVE_FREETYPE
 
-  int halign = 0, valign = 0;
+  int halign = 0;
+  int valign = 0;
 
   if (horizontalalignment_is ("center"))
     halign = 1;
@@ -7368,9 +7606,11 @@
       Matrix z = get_zdata ().matrix_value ();
 
 
-      int p = z.columns (), q = z.rows ();
-      int i1 = 0, i2 = 0, i3 = 0;
-      int j1 = 0, j2 = 0, j3 = 0;
+      int p = z.columns ();
+      int q = z.rows ();
+      int i1, i2, i3, j1, j2, j3;
+      i1 = i2 = i3 = 0;
+      j1 = j2 = j3 = 0;
 
       bool x_mat = (x.rows () == q);
       bool y_mat = (y.columns () == p);
@@ -8144,9 +8384,9 @@
 
   // No copying!
 
-  function_event (const function_event &);
-
-  function_event & operator = (const function_event &);
+  function_event (const function_event&);
+
+  function_event & operator = (const function_event&);
 };
 
 class
@@ -8348,7 +8588,7 @@
 }
 
 void
-gh_manager::do_post_callback (const graphics_handle& h, const std::string name,
+gh_manager::do_post_callback (const graphics_handle& h, const std::string& name,
                               const octave_value& data)
 {
   gh_manager::auto_lock guard;
@@ -8398,7 +8638,7 @@
 }
 
 void
-gh_manager::do_post_set (const graphics_handle& h, const std::string name,
+gh_manager::do_post_set (const graphics_handle& h, const std::string& name,
                          const octave_value& value, bool notify_toolkit)
 {
   gh_manager::auto_lock guard;
@@ -8628,9 +8868,11 @@
 @deftypefn  {Built-in Function} {} set (@var{h}, @var{property}, @var{value}, @dots{})\n\
 @deftypefnx {Built-in Function} {} set (@var{h}, @var{properties}, @var{values})\n\
 @deftypefnx {Built-in Function} {} set (@var{h}, @var{pv})\n\
+@deftypefnx {Built-in Function} {@var{value_list} =} set (@var{h}, @var{property})\n\
+@deftypefnx {Built-in Function} {@var{all_value_list} =} set (@var{h})\n\
 Set named property values for the graphics handle (or vector of graphics\n\
 handles) @var{h}.\n\
-There are three ways how to give the property names and values:\n\
+There are three ways to give the property names and values:\n\
 \n\
 @itemize\n\
 @item as a comma separated list of @var{property}, @var{value} pairs\n\
@@ -8656,6 +8898,32 @@
 elements of @var{pv} will be set in all handles in @var{h} independent of\n\
 the dimensions of @var{pv}.\n\
 @end itemize\n\
+\n\
+@code{set} is also used to query the list of values a named property will\n\
+take.  @code{@var{clist} = set (@var{h}, \"property\")} will return the list\n\
+of possible values for @qcode{\"property\"} in the cell list @var{clist}.\n\
+If no output variable is used then the list is formatted and printed to the\n\
+screen.\n\
+\n\
+If no property is specified (@code{@var{slist} = set (@var{h})}) then a\n\
+structure @var{slist} is returned where the fieldnames are the properties of\n\
+the object @var{h} and the fields are the list of possible values for each\n\
+property.  If no output variable is used then the list is formatted and\n\
+printed to the screen.\n\
+\n\
+For example,\n\
+\n\
+@example\n\
+@group\n\
+hf = figure ();\n\
+set (hf, \"paperorientation\")\n\
+@result{}  paperorientation:  [ landscape | @{portrait@} | rotated ]\n\
+@end group\n\
+@end example\n\
+\n\
+@noindent\n\
+shows the paperorientation property can take three values with the default\n\
+being @qcode{\"portrait\"}.\n\
 @seealso{get}\n\
 @end deftypefn")
 {
@@ -8706,6 +8974,35 @@
                     {
                       obj.set (args(1).map_value ());
                     }
+                  else if (nargin == 2 && args(1).is_string ())
+                    {
+                      std::string property = args(1).string_value ();
+                      
+                      octave_map pmap = obj.values_as_struct ();
+
+                      if (obj.has_readonly_property (property))
+                        if (nargout != 0)
+                          retval = Matrix ();
+                        else
+                          octave_stdout << "set: " << property
+                                        <<" is read-only" << std::endl;
+                      else if (pmap.isfield (property))
+                        {
+                          if (nargout != 0)
+                            retval = pmap.getfield (property)(0);
+                          else
+                            {
+                              std::string s = obj.value_as_string (property);
+                              if (! error_state)
+                                octave_stdout << s;
+                            }
+                        }
+                      else
+                        {
+                          error ("set: unknown property");
+                          break;
+                        }
+                    }
                   else if (nargin == 1)
                     {
                       if (nargout != 0)
@@ -8748,7 +9045,7 @@
 }
 
 static std::string
-get_graphics_object_type (const double val)
+get_graphics_object_type (double val)
 {
   std::string retval;
 
@@ -9379,7 +9676,7 @@
     {
       graphics_handle h = octave_NaN;
 
-      const NDArray vals = args (0).array_value ();
+      const NDArray vals = args(0).array_value ();
 
       if (! error_state)
         {
@@ -9656,12 +9953,13 @@
 
           while (pa != available_toolkits.end ())
             {
-              std::string name = *pa++;
-
-              if (name == "qt"
-                  || (name == "fltk"
-                      && available_toolkits.find ("qt") == available_toolkits.end ()))
-                dtk = name;
+              std::string tk_name = *pa++;
+
+              if (tk_name == "qt"
+                  || (tk_name == "fltk"
+                      && available_toolkits.find ("qt")
+                        == available_toolkits.end ()))
+                dtk = tk_name;
             }
         }
     }
@@ -10205,7 +10503,7 @@
 static bool
 compare_property_values (const octave_value& o1, const octave_value& o2)
 {
-  octave_value_list args (2);
+  octave_value_list args(2);
 
   args(0) = o1;
   args(1) = o2;
--- a/libinterp/corefcn/graphics.in.h
+++ b/libinterp/corefcn/graphics.in.h
@@ -296,7 +296,7 @@
 
   graphics_handle get_parent (void) const { return parent; }
 
-  void set_parent (const graphics_handle &h) { parent = h; }
+  void set_parent (const graphics_handle& h) { parent = h; }
 
   bool is_hidden (void) const { return hidden; }
 
@@ -1028,7 +1028,7 @@
     validate ();
   }
 
-  color_values (std::string str)
+  color_values (const std::string& str)
     : xrgb (1, 3)
   {
     if (! str2rgb (str))
@@ -1076,7 +1076,7 @@
 private:
   Matrix xrgb;
 
-  OCTINTERP_API bool str2rgb (std::string str);
+  OCTINTERP_API bool str2rgb (const std::string& str);
 };
 
 class color_property : public base_property
@@ -1631,7 +1631,7 @@
   }
 
   children_property (const std::string& nm, const graphics_handle& h,
-                     const Matrix &val)
+                     const Matrix& val)
     : base_property (nm, h), children_list ()
   {
     do_init_children (val);
@@ -1651,12 +1651,12 @@
 
   base_property* clone (void) const { return new children_property (*this); }
 
-  bool remove_child (const double &val)
+  bool remove_child (double val)
   {
     return do_remove_child (val);
   }
 
-  void adopt (const double &val)
+  void adopt (double val)
   {
     do_adopt_child (val);
   }
@@ -1759,14 +1759,14 @@
   }
 
 private:
-  void do_init_children (const Matrix &val)
+  void do_init_children (const Matrix& val)
   {
     children_list.clear ();
     for (octave_idx_type i = 0; i < val.numel (); i++)
       children_list.push_front (val.xelem (i));
   }
 
-  void do_init_children (const std::list<double> &val)
+  void do_init_children (const std::list<double>& val)
   {
     children_list.clear ();
     for (const_children_list_iterator p = val.begin (); p != val.end (); p++)
@@ -1800,7 +1800,7 @@
     return false;
   }
 
-  void do_adopt_child (const double &val)
+  void do_adopt_child (double val)
   {
     children_list.push_front (val);
   }
@@ -2594,7 +2594,7 @@
 protected:
   struct cmp_caseless_str
   {
-    bool operator () (const caseless_str &a, const caseless_str &b) const
+    bool operator () (const caseless_str& a, const caseless_str& b) const
     {
       std::string a1 = a;
       std::transform (a1.begin (), a1.end (), a1.begin (), tolower);
@@ -2698,8 +2698,15 @@
     return octave_value ();
   }
 
+  virtual bool has_readonly_property (const caseless_str& pname) const
+  {
+    return base_properties::has_readonly_property (pname);
+  }
+
   virtual std::string values_as_string (void);
 
+  virtual std::string value_as_string (const std::string& prop);
+
   virtual octave_scalar_map values_as_struct (void);
 
   virtual graphics_handle get_parent (void) const
@@ -2969,8 +2976,18 @@
     return rep->get_factory_defaults ();
   }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    return rep->has_readonly_property (pname);
+  }
+
   std::string values_as_string (void) { return rep->values_as_string (); }
 
+  std::string value_as_string (const std::string& prop) 
+  { 
+    return rep->value_as_string (prop); 
+  }
+
   octave_map values_as_struct (void) { return rep->values_as_struct (); }
 
   graphics_handle get_parent (void) const { return rep->get_parent (); }
@@ -3090,20 +3107,16 @@
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
-    // FIXME: it seems strange to me that the diary, diaryfile,
-    // echo, errormessage, format, formatspacing, language, and
-    // recursionlimit properties are here.
-    // WTF do they have to do with graphics?
-    // Also note that these properties (and the monitorpositions,
+    // FIXME: Matlab defines some root properties and uses them in
+    // the same way that Octave uses an internal static variable to
+    // keep track of state.  set (0, "echo", "on") is equivalent
+    // to Octave's echo ("on"). Properties that still dont have callbacks
+    // are : diary, diaryfileecho, errormessage, language, and recursionlimit.
+    // Note that these properties (and the monitorpositions,
     // pointerlocation, and pointerwindow properties) are not yet used
     // by Octave, so setting them will have no effect, and changes
     // made elswhere (say, the diary or format functions) will not
     // cause these properties to be updated.
-    // ANSWER: Matlab defines these properties and uses them in
-    // the same way that Octave uses an internal static variable to
-    // keep track of state.  set (0, "echo", "on") is equivalent
-    // to Octave's echo ("on").  Maybe someday we can connect callbacks
-    // that actually call Octave's own functions for this.
 
     // Programming note: Keep property list sorted if new ones are added.
 
@@ -3116,8 +3129,8 @@
       bool_property echo , "off"
       string_property errormessage , ""
       string_property fixedwidthfontname , "Courier"
-      radio_property format , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rational|{short}|shorte|shorteng|shortg"
-      radio_property formatspacing , "compact|{loose}"
+      radio_property format GS , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rat|{short}|shorte|shorteng|shortg"
+      radio_property formatspacing GS , "compact|{loose}"
       string_property language , "ascii"
       array_property monitorpositions , Matrix (1, 4, 0)
       array_property pointerlocation , Matrix (1, 2, 0)
@@ -3132,6 +3145,7 @@
 
   private:
     std::list<graphics_handle> cbo_stack;
+
   };
 
 private:
@@ -3224,6 +3238,14 @@
   bool valid_object (void) const { return true; }
 
   void reset_default_properties (void);
+  
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 
 private:
   property_list default_properties;
@@ -3448,6 +3470,14 @@
   bool valid_object (void) const { return true; }
 
   void reset_default_properties (void);
+  
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 
 private:
   property_list default_properties;
@@ -3633,6 +3663,7 @@
     bool get_x2Dtop (void) const { return x2Dtop; }
     bool get_y2Dright (void) const { return y2Dright; }
     bool get_layer2Dtop (void) const { return layer2Dtop; }
+    bool get_is2D (void) const { return is2D; }
     bool get_xySym (void) const { return xySym; }
     bool get_xyzSym (void) const { return xyzSym; }
     bool get_zSign (void) const { return zSign; }
@@ -3671,11 +3702,11 @@
     double fx, fy, fz;
     double xticklen, yticklen, zticklen;
     double xtickoffset, ytickoffset, ztickoffset;
-    bool x2Dtop, y2Dright, layer2Dtop;
+    bool x2Dtop, y2Dright, layer2Dtop, is2D;
     bool xySym, xyzSym, zSign, nearhoriz;
 
 #if HAVE_FREETYPE
-    // freetype renderer, used for calculation of text (tick labels) size
+    // FreeType renderer, used for calculation of text (tick labels) size
     ft_render text_renderer;
 #endif
 
@@ -3698,7 +3729,7 @@
       radio_property camerapositionmode , "{auto}|manual"
       array_property cameratarget m , Matrix (1, 3, 0.0)
       radio_property cameratargetmode , "{auto}|manual"
-      array_property cameraupvector m , Matrix ()
+      array_property cameraupvector m , Matrix (1, 3, 0.0)
       radio_property cameraupvectormode , "{auto}|manual"
       double_property cameraviewangle m , 10.0
       radio_property cameraviewanglemode , "{auto}|manual"
@@ -3737,7 +3768,7 @@
       handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
       // FIXME: uicontextmenu should be moved here.
       radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
-      array_property view u , Matrix ()
+      array_property view u , default_axes_view ()
       radio_property xaxislocation u , "{bottom}|top|zero"
       color_property xcolor , color_values (0, 0, 0)
       radio_property xdir u , "{normal}|reverse"
@@ -4170,6 +4201,14 @@
 
   void reset_default_properties (void);
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 protected:
   void initialize (const graphics_object& go);
 
@@ -4250,6 +4289,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4307,7 +4354,7 @@
       radio_property interpreter u , "{tex}|none|latex"
       radio_property linestyle , "{-}|--|:|-.|none"
       double_property linewidth , 0.5
-      double_property margin , 1
+      double_property margin , 2
       array_property position smu , Matrix (1, 3, 0.0)
       double_property rotation mu , 0
       text_label_property string u , ""
@@ -4333,7 +4380,7 @@
     Matrix get_extent_matrix (void) const;
     const uint8NDArray& get_pixels (void) const { return pixels; }
 #if HAVE_FREETYPE
-    // freetype renderer, used for calculation of text size
+    // FreeType renderer, used for calculation of text size
     ft_render renderer;
 #endif
 
@@ -4415,6 +4462,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4442,10 +4497,11 @@
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (image)
-      array_property alphadata u , Matrix ()
-      radio_property alphadatamapping al , "none|direct|{scaled}"
-      array_property cdata u , Matrix ()
+      array_property alphadata u , Matrix (1, 1, 1.0)
+      radio_property alphadatamapping al , "{none}|direct|scaled"
+      array_property cdata u , default_image_cdata ()
       radio_property cdatamapping al , "scaled|{direct}"
+      string_property displayname , ""
       radio_property erasemode , "{normal}|none|xor|background"
       row_vector_property xdata u , Matrix ()
       row_vector_property ydata u , Matrix ()
@@ -4562,6 +4618,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4603,7 +4667,7 @@
       double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp"))
       color_property facecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
       radio_property facelighting , "{none}|flat|gouraud|phong"
-      array_property faces , Matrix ()
+      array_property faces , default_patch_faces ()
       array_property facevertexalphadata , Matrix ()
       array_property facevertexcdata , Matrix ()
       // FIXME: interpreter is not a property of a Matlab patch.
@@ -4618,9 +4682,9 @@
       radio_property normalmode , "{auto}|manual"
       double_property specularcolorreflectance , 1.0
       double_property specularexponent , 10.0
-      double_property specularstrength , 0.6
+      double_property specularstrength , 0.9
       array_property vertexnormals , Matrix ()
-      array_property vertices , Matrix ()
+      array_property vertices , default_patch_vertices ()
       array_property xdata u , Matrix ()
       array_property ydata u , Matrix ()
       array_property zdata u , Matrix ()
@@ -4686,6 +4750,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4713,11 +4785,11 @@
     // Programming note: Keep property list sorted if new ones are added.
 
     BEGIN_PROPERTIES (surface)
-      array_property alphadata u , Matrix ()
+      array_property alphadata u , Matrix (1, 1, 1.0)
       radio_property alphadatamapping l , "none|direct|{scaled}"
       double_property ambientstrength , 0.3
       radio_property backfacelighting , "unlit|lit|{reverselit}"
-      array_property cdata u , Matrix ()
+      array_property cdata u , default_surface_cdata ()
       radio_property cdatamapping al , "{scaled}|direct"
       string_property cdatasource , ""
       double_property diffusestrength , 0.6
@@ -4744,11 +4816,11 @@
       double_property specularexponent , 10
       double_property specularstrength , 0.9
       array_property vertexnormals u , Matrix ()
-      array_property xdata u , Matrix ()
+      array_property xdata u , default_surface_xdata ()
       string_property xdatasource , ""
-      array_property ydata u , Matrix ()
+      array_property ydata u , default_surface_ydata ()
       string_property ydatasource , ""
-      array_property zdata u , Matrix ()
+      array_property zdata u , default_surface_zdata ()
       string_property zdatasource , ""
 
       // hidden properties for limit computation
@@ -4778,6 +4850,7 @@
       alphadata.add_constraint ("uint8");
       alphadata.add_constraint (dim_vector (-1, -1));
       vertexnormals.add_constraint (dim_vector (-1, -1, 3));
+      vertexnormals.add_constraint (dim_vector (0, 0));
     }
 
   private:
@@ -4841,6 +4914,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -4919,6 +5000,14 @@
   void update_axis_limits (const std::string& axis_type,
                            const graphics_handle& h);
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -4980,6 +5069,14 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -5027,6 +5124,14 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -5119,6 +5224,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -5186,6 +5299,14 @@
   const base_properties& get_properties (void) const { return xproperties; }
 
   bool valid_object (void) const { return true; }
+
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
 };
 
 // ---------------------------------------------------------------------
@@ -5273,6 +5394,14 @@
 
   void reset_default_properties (void);
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 private:
   property_list default_properties;
 };
@@ -5325,6 +5454,14 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
@@ -5378,16 +5515,24 @@
 
   bool valid_object (void) const { return true; }
 
+  bool has_readonly_property (const caseless_str& pname) const
+  {
+    bool retval = xproperties.has_readonly_property (pname);
+    if (! retval)
+      retval = base_properties::has_readonly_property (pname);
+    return retval;
+  }
+
 };
 
 // ---------------------------------------------------------------------
 
 octave_value
-get_property_from_handle (double handle, const std::string &property,
-                          const std::string &func);
+get_property_from_handle (double handle, const std::string& property,
+                          const std::string& func);
 bool
-set_property_in_handle (double handle, const std::string &property,
-                        const octave_value &arg, const std::string &func);
+set_property_in_handle (double handle, const std::string& property,
+                        const octave_value& arg, const std::string& func);
 
 // ---------------------------------------------------------------------
 
@@ -5858,12 +6003,12 @@
   void do_execute_callback (const graphics_handle& h, const octave_value& cb,
                             const octave_value& data);
 
-  void do_post_callback (const graphics_handle& h, const std::string name,
+  void do_post_callback (const graphics_handle& h, const std::string& name,
                          const octave_value& data);
 
   void do_post_function (graphics_event::event_fcn fcn, void* fcn_data);
 
-  void do_post_set (const graphics_handle& h, const std::string name,
+  void do_post_set (const graphics_handle& h, const std::string& name,
                     const octave_value& value, bool notify_toolkit = true);
 
   int do_process_events (bool force = false);
--- a/libinterp/corefcn/help.cc
+++ b/libinterp/corefcn/help.cc
@@ -230,7 +230,7 @@
 
   pair_type (")",
     "-*- texinfo -*-\n\
-@deftypefn {Operator} {} )\n\
+@deftypefn {Operator} {})\n\
 Array index or function argument delimiter.\n\
 @end deftypefn"),
 
@@ -1078,7 +1078,7 @@
 
   if (args.length () == 1)
     {
-      const std::string name = args (0).string_value ();
+      const std::string name = args(0).string_value ();
 
       if (! error_state)
         {
@@ -1367,7 +1367,7 @@
     retval = Cell (ffl.append (afl));
   else
     {
-      std::string dir = args (0).string_value ();
+      std::string dir = args(0).string_value ();
 
       if (! error_state)
         {
--- a/libinterp/corefcn/input.cc
+++ b/libinterp/corefcn/input.cc
@@ -750,10 +750,10 @@
 @noindent\n\
 and waits for the user to enter a value.  The string entered by the user\n\
 is evaluated as an expression, so it may be a literal constant, a\n\
-variable name, or any other valid expression.\n\
+variable name, or any other valid Octave code.\n\
 \n\
-Currently, @code{input} only returns one value, regardless of the number\n\
-of values produced by the evaluation of the expression.\n\
+The number of return arguments, their size, and their class depend on the\n\
+expression entered.\n\
 \n\
 If you are only interested in getting a literal string value, you can\n\
 call @code{input} with the character string @qcode{\"s\"} as the second\n\
@@ -772,7 +772,7 @@
   int nargin = args.length ();
 
   if (nargin == 1 || nargin == 2)
-    retval = get_user_input (args, nargout);
+    retval = get_user_input (args, std::max (nargout, 1));
   else
     print_usage ();
 
@@ -1410,11 +1410,12 @@
 DEFUN (filemarker, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} filemarker ()\n\
-@deftypefnx {Built-in Function} {} filemarker (@var{new_val})\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} filemarker (@var{new_val})\n\
 @deftypefnx {Built-in Function} {} filemarker (@var{new_val}, \"local\")\n\
-Query or set the character used to separate filename from the\n\
-the subfunction names contained within the file.  This can be used in\n\
-a generic manner to interact with subfunctions.  For example,\n\
+Query or set the character used to separate the filename from the subfunction\n\
+names contained within the file.  By default this is the character @samp{>}.\n\
+This can be used in a generic manner to interact with subfunctions.\n\
+For example,\n\
 \n\
 @example\n\
 help ([\"myfunc\", filemarker, \"mysubfunc\"])\n\
@@ -1422,8 +1423,10 @@
 \n\
 @noindent\n\
 returns the help string associated with the subfunction @code{mysubfunc}\n\
-of the function @code{myfunc}.  Another use of @code{filemarker} is when\n\
-debugging it allows easier placement of breakpoints within subfunctions.\n\
+located in the file @file{myfunc.m}.\n\
+\n\
+@code{filemarker} is also useful during debugging for placing breakpoints\n\
+within subfunctions or nested functions.\n\
 For example,\n\
 \n\
 @example\n\
@@ -1434,7 +1437,7 @@
 will set a breakpoint at the first line of the subfunction @code{mysubfunc}.\n\
 \n\
 When called from inside a function with the @qcode{\"local\"} option, the\n\
-variable is changed locally for the function and any subroutines it calls.  \n\
+variable is changed locally for the function and any subroutines it calls.\n\
 The original variable value is restored when exiting the function.\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/jit-typeinfo.cc
+++ b/libinterp/corefcn/jit-typeinfo.cc
@@ -1247,6 +1247,8 @@
   destroy_fn.add_overload (create_identity(index));
   destroy_fn.add_overload (create_identity(complex));
 
+  // -------------------- scalar related operations --------------------
+
   // now for binary scalar operations
   add_binary_op (scalar, octave_value::op_add, llvm::Instruction::FAdd);
   add_binary_op (scalar, octave_value::op_sub, llvm::Instruction::FSub);
@@ -1335,6 +1337,7 @@
     val = builder.CreateFMul (val, mone);
     fn.do_return (builder, val);
   }
+  unary_ops[octave_value::op_uminus].add_overload (fn);
 
   fn = create_identity (scalar);
   unary_ops[octave_value::op_uplus].add_overload (fn);
@@ -1842,7 +1845,7 @@
   register_generic ("cos", matrix, matrix);
 
   add_builtin ("exp");
-  register_intrinsic ("exp", llvm::Intrinsic::cos, scalar, scalar);
+  register_intrinsic ("exp", llvm::Intrinsic::exp, scalar, scalar);
   register_generic ("exp", matrix, matrix);
 
   add_builtin ("balance");
--- a/libinterp/corefcn/kron.cc
+++ b/libinterp/corefcn/kron.cc
@@ -55,8 +55,10 @@
   assert (a.ndims () == 2);
   assert (b.ndims () == 2);
 
-  octave_idx_type nra = a.rows (), nrb = b.rows ();
-  octave_idx_type nca = a.cols (), ncb = b.cols ();
+  octave_idx_type nra = a.rows ();
+  octave_idx_type nrb = b.rows ();
+  octave_idx_type nca = a.cols ();
+  octave_idx_type ncb = b.cols ();
 
   MArray<T> c (dim_vector (nra*nrb, nca*ncb));
   T *cv = c.fortran_vec ();
@@ -79,8 +81,11 @@
 {
   assert (b.ndims () == 2);
 
-  octave_idx_type nra = a.rows (), nrb = b.rows (), dla = a.diag_length ();
-  octave_idx_type nca = a.cols (), ncb = b.cols ();
+  octave_idx_type nra = a.rows ();
+  octave_idx_type nrb = b.rows ();
+  octave_idx_type dla = a.diag_length ();
+  octave_idx_type nca = a.cols ();
+  octave_idx_type ncb = b.cols ();
 
   MArray<T> c (dim_vector (nra*nrb, nca*ncb), T ());
 
@@ -129,12 +134,15 @@
 static PermMatrix
 kron (const PermMatrix& a, const PermMatrix& b)
 {
-  octave_idx_type na = a.rows (), nb = b.rows ();
-  const octave_idx_type *pa = a.data (), *pb = b.data ();
+  octave_idx_type na = a.rows ();
+  octave_idx_type nb = b.rows ();
+  const octave_idx_type *pa = a.data ();
+  const octave_idx_type *pb = b.data ();
   PermMatrix c(na*nb); // Row permutation.
   octave_idx_type *pc = c.fortran_vec ();
 
-  bool cola = a.is_col_perm (), colb = b.is_col_perm ();
+  bool cola = a.is_col_perm ();
+  bool colb = b.is_col_perm ();
   if (cola && colb)
     {
       for (octave_idx_type i = 0; i < na; i++)
@@ -282,7 +290,8 @@
 
   if (nargin >= 2)
     {
-      octave_value a = args(0), b = args(1);
+      octave_value a = args(0);
+      octave_value b = args(1);
       retval = dispatch_kron (a, b);
       for (octave_idx_type i = 2; i < nargin; i++)
         retval = dispatch_kron (retval, args(i));
--- a/libinterp/corefcn/load-path.cc
+++ b/libinterp/corefcn/load-path.cc
@@ -38,6 +38,7 @@
 #include "defun.h"
 #include "input.h"
 #include "load-path.h"
+#include "ov-usr-fcn.h"
 #include "pager.h"
 #include "parse.h"
 #include "toplev.h"
@@ -120,6 +121,7 @@
   if (fs)
     {
       method_file_map.clear ();
+      package_dir_map.clear ();
 
       dir_mtime = fs.mtime ();
       dir_time_last_checked = octave_time ();
@@ -181,6 +183,8 @@
                     get_private_file_map (full_name);
                   else if (fname[0] == '@')
                     get_method_file_map (full_name, fname.substr (1));
+                  else if (fname[0] == '+')
+                    get_package_dir (full_name, fname.substr (1));
                 }
               else
                 {
@@ -286,6 +290,13 @@
     method_file_map[class_name].private_file_map = get_fcn_files (pd);
 }
 
+void
+load_path::dir_info::get_package_dir (const std::string& d,
+                                      const std::string& package_name)
+{
+  package_dir_map[package_name] = dir_info (d);
+}
+
 bool
 load_path::instance_ok (void)
 {
@@ -373,8 +384,8 @@
 }
 
 void
-load_path::move_fcn_map (const std::string& dir_name,
-                         const string_vector& fcn_files, bool at_end)
+load_path::loader::move_fcn_map (const std::string& dir_name,
+                                 const string_vector& fcn_files, bool at_end)
 {
   octave_idx_type len = fcn_files.length ();
 
@@ -422,7 +433,7 @@
 }
 
 void
-load_path::move_method_map (const std::string& dir_name, bool at_end)
+load_path::loader::move_method_map (const std::string& dir_name, bool at_end)
 {
   for (method_map_iterator i = method_map.begin ();
        i != method_map.end ();
@@ -466,7 +477,7 @@
 }
 
 void
-load_path::move (dir_info_list_iterator i, bool at_end)
+load_path::do_move (dir_info_list_iterator i, bool at_end)
 {
   if (dir_info_list.size () > 1)
     {
@@ -479,16 +490,56 @@
       else
         dir_info_list.push_front (di);
 
-      std::string dir_name = di.dir_name;
-
-      move_fcn_map (dir_name, di.fcn_files, at_end);
-
-      // No need to move elements of private function map.
-
-      move_method_map (dir_name, at_end);
+      move (di, at_end);
+    }
+}
+
+void
+load_path::move (const dir_info& di, bool at_end, const std::string& pname)
+{
+  loader& l = get_loader (pname);
+
+  l.move (di, at_end);
+
+  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
+
+  for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin ();
+       p != package_dir_map.end (); ++p)
+    {
+      std::string full_name = p->first;
+
+      if (! pname.empty ())
+        full_name = pname + "." + full_name;
+
+      move (p->second, at_end, full_name);
     }
 }
 
+void
+load_path::loader::move (const dir_info& di, bool at_end)
+{
+  std::string dir_name = di.dir_name;
+
+  std::list<std::string>::iterator s = 
+    std::find (dir_list.begin (), dir_list.end (), dir_name);
+
+  if (s != dir_list.end ())
+    {
+      dir_list.erase (s);
+
+      if (at_end)
+        dir_list.push_back (dir_name);
+      else
+        dir_list.push_front (dir_name);
+    }
+
+  move_fcn_map (dir_name, di.fcn_files, at_end);
+
+  // No need to move elements of private function map.
+
+  move_method_map (dir_name, at_end);
+}
+
 static void
 maybe_add_path_elts (std::string& path, const std::string& dir)
 {
@@ -544,9 +595,10 @@
 load_path::do_clear (void)
 {
   dir_info_list.clear ();
-  fcn_map.clear ();
-  private_fcn_map.clear ();
-  method_map.clear ();
+
+  default_loader.clear ();
+
+  loader_map.clear ();
 }
 
 static std::list<std::string>
@@ -683,7 +735,7 @@
   dir_info_list_iterator i = find_dir_info (dir);
 
   if (i != dir_info_list.end ())
-    move (i, at_end);
+    do_move (i, at_end);
   else
     {
       file_stat fs (dir);
@@ -701,11 +753,7 @@
                   else
                     dir_info_list.push_front (di);
 
-                  add_to_fcn_map (di, at_end);
-
-                  add_to_private_fcn_map (di);
-
-                  add_to_method_map (di, at_end);
+                  add (di, at_end);
 
                   if (add_hook)
                     add_hook (dir);
@@ -726,12 +774,12 @@
   i = find_dir_info (".");
 
   if (i != dir_info_list.end ())
-    move (i, false);
+    do_move (i, false);
 }
 
 void
-load_path::remove_fcn_map (const std::string& dir,
-                           const string_vector& fcn_files)
+load_path::loader::remove_fcn_map (const std::string& dir,
+                                   const string_vector& fcn_files)
 {
   octave_idx_type len = fcn_files.length ();
 
@@ -770,7 +818,7 @@
 }
 
 void
-load_path::remove_private_fcn_map (const std::string& dir)
+load_path::loader::remove_private_fcn_map (const std::string& dir)
 {
   private_fcn_map_iterator p = private_fcn_map.find (dir);
 
@@ -779,7 +827,7 @@
 }
 
 void
-load_path::remove_method_map (const std::string& dir)
+load_path::loader::remove_method_map (const std::string& dir)
 {
   for (method_map_iterator i = method_map.begin ();
        i != method_map.end ();
@@ -847,15 +895,11 @@
               if (remove_hook)
                 remove_hook (dir);
 
-              string_vector fcn_files = i->fcn_files;
+              dir_info& di = *i;
+
+              remove (di);
 
               dir_info_list.erase (i);
-
-              remove_fcn_map (dir, fcn_files);
-
-              remove_private_fcn_map (dir);
-
-              remove_method_map (dir);
             }
         }
     }
@@ -864,17 +908,52 @@
 }
 
 void
+load_path::remove (const dir_info& di, const std::string& pname)
+{
+  loader& l = get_loader (pname);
+
+  l.remove (di);
+
+  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
+
+  for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin ();
+       p != package_dir_map.end (); ++p)
+    {
+      std::string full_name = p->first;
+
+      if (! pname.empty ())
+        full_name = pname + "." + full_name;
+
+      remove (p->second, full_name);
+    }
+}
+
+void
+load_path::loader::remove (const dir_info& di)
+{
+  std::string dir = di.dir_name;
+
+  string_vector fcn_files = di.fcn_files;
+
+  dir_list.remove (dir);
+
+  remove_fcn_map (dir, fcn_files);
+
+  remove_private_fcn_map (dir);
+
+  remove_method_map (dir);
+}
+
+void
 load_path::do_update (void) const
 {
   // I don't see a better way to do this because we need to
   // preserve the correct directory ordering for new files that
   // have appeared.
 
-  fcn_map.clear ();
-
-  private_fcn_map.clear ();
-
-  method_map.clear ();
+  default_loader.clear ();
+
+  loader_map.clear ();
 
   for (dir_info_list_iterator p = dir_info_list.begin ();
        p != dir_info_list.end ();
@@ -884,11 +963,7 @@
 
       di.update ();
 
-      add_to_fcn_map (di, true);
-
-      add_to_private_fcn_map (di);
-
-      add_to_method_map (di, true);
+      add (di, true);
     }
 }
 
@@ -987,8 +1062,8 @@
 }
 
 std::string
-load_path::do_find_fcn (const std::string& fcn, std::string& dir_name,
-                        int type) const
+load_path::loader::find_fcn (const std::string& fcn, std::string& dir_name,
+                             int type) const
 {
   std::string retval;
 
@@ -1003,7 +1078,7 @@
           std::string class_name = fcn.substr (1, pos-1);
           std::string meth = fcn.substr (pos+1);
 
-          retval = do_find_method (class_name, meth, dir_name);
+          retval = find_method (class_name, meth, dir_name);
         }
       else
         retval = std::string ();
@@ -1042,8 +1117,8 @@
 }
 
 std::string
-load_path::do_find_private_fcn (const std::string& dir,
-                                const std::string& fcn, int type) const
+load_path::loader::find_private_fcn (const std::string& dir,
+                                     const std::string& fcn, int type) const
 {
   std::string retval;
 
@@ -1072,9 +1147,9 @@
 }
 
 std::string
-load_path::do_find_method (const std::string& class_name,
-                           const std::string& meth,
-                           std::string& dir_name, int type) const
+load_path::loader::find_method (const std::string& class_name,
+                                const std::string& meth,
+                                std::string& dir_name, int type) const
 {
   std::string retval;
 
@@ -1120,7 +1195,7 @@
 }
 
 std::list<std::string>
-load_path::do_methods (const std::string& class_name) const
+load_path::loader::methods (const std::string& class_name) const
 {
   std::list<std::string> retval;
 
@@ -1149,13 +1224,63 @@
 
   //  update ();
 
+  default_loader.overloads (meth, retval);
+
+  for (const_loader_map_iterator l = loader_map.begin ();
+       l != loader_map.end (); ++l)
+    l->second.overloads (meth, retval);
+
+  return retval;
+}
+
+void
+load_path::loader::overloads (const std::string& meth,
+                              std::list<std::string>& l) const
+{
   for (const_method_map_iterator q = method_map.begin ();
        q != method_map.end (); q++)
     {
       const fcn_map_type& m = q->second;
 
       if (m.find (meth) != m.end ())
-        retval.push_back (q->first);
+        {
+          std::string class_name = q->first;
+
+          if (! prefix.empty ())
+            class_name = prefix + "." + class_name;
+
+          l.push_back (class_name);
+        }
+    }
+}
+
+// Should we cache all files in private directories, or is it OK to just
+// look them up each time as needed?
+
+std::string
+find_private_file (const std::string& fname)
+{
+  std::string retval;
+
+  // Look in private directory corresponding to current function (if
+  // any).
+
+  octave_user_function *curr_fcn = symbol_table::get_curr_fcn ();
+
+  if (curr_fcn && ! curr_fcn->is_private_function ())
+    {
+      std::string dir_name = curr_fcn->dir_name ();
+
+      if (! dir_name.empty ())
+        {
+          std::string pfname = dir_name + file_ops::dir_sep_str ()
+            + "private" + file_ops::dir_sep_str () + fname;
+
+          file_stat fs (pfname);
+
+          if (fs.exists () && fs.is_reg ())
+            retval = pfname;
+        }
     }
 
   return retval;
@@ -1166,33 +1291,43 @@
 {
   std::string retval;
 
+  if (octave_env::absolute_pathname (file)
+      || octave_env::rooted_relative_pathname (file))
+    {
+      file_stat fs (file);
+
+      if (fs.exists ())
+        return file;
+    }
+  else
+    {
+      std::string tfile = find_private_file (file);
+
+      if (! tfile.empty ())
+        return tfile;
+    }
+
   if (file.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos)
     {
-      if (octave_env::absolute_pathname (file)
-          || octave_env::rooted_relative_pathname (file))
+      // Given name has a directory separator, so append it to each
+      // element of the load path in turn.
+
+      for (const_dir_info_list_iterator p = dir_info_list.begin ();
+           p != dir_info_list.end ();
+           p++)
         {
-          file_stat fs (file);
+          std::string tfile = file_ops::concat (p->dir_name, file);
+
+          file_stat fs (tfile);
 
           if (fs.exists ())
-            return file;
-        }
-      else
-        {
-          for (const_dir_info_list_iterator p = dir_info_list.begin ();
-               p != dir_info_list.end ();
-               p++)
-            {
-              std::string tfile = file_ops::concat (p->dir_name, file);
-
-              file_stat fs (tfile);
-
-              if (fs.exists ())
-                return tfile;
-            }
+            return tfile;
         }
     }
   else
     {
+      // Look in cache.
+
       for (const_dir_info_list_iterator p = dir_info_list.begin ();
            p != dir_info_list.end ();
            p++)
@@ -1515,6 +1650,12 @@
 string_vector
 load_path::do_fcn_names (void) const
 {
+  return default_loader.fcn_names ();
+}
+
+string_vector
+load_path::loader::fcn_names (void) const
+{
   size_t len = fcn_map.size ();
 
   string_vector retval (len);
@@ -1657,69 +1798,11 @@
         }
     }
 
-  for (const_private_fcn_map_iterator i = private_fcn_map.begin ();
-       i != private_fcn_map.end (); i++)
-    {
-      os << "\n*** private functions in "
-         << file_ops::concat (i->first, "private") << ":\n\n";
-
-      print_fcn_list (os, i->second);
-    }
-
-#if defined (DEBUG_LOAD_PATH)
-
-  for (const_fcn_map_iterator i = fcn_map.begin ();
-       i != fcn_map.end ();
-       i++)
-    {
-      os << i->first << ":\n";
-
-      const file_info_list_type& file_info_list = i->second;
-
-      for (const_file_info_list_iterator p = file_info_list.begin ();
-           p != file_info_list.end ();
-           p++)
-        {
-          os << "  " << p->dir_name << " (";
-
-          print_types (os, p->types);
-
-          os << ")\n";
-        }
-    }
-
-  for (const_method_map_iterator i = method_map.begin ();
-       i != method_map.end ();
-       i++)
-    {
-      os << "CLASS " << i->first << ":\n";
-
-      const fcn_map_type& fm = i->second;
-
-      for (const_fcn_map_iterator q = fm.begin ();
-           q != fm.end ();
-           q++)
-        {
-          os << "  " << q->first << ":\n";
-
-          const file_info_list_type& file_info_list = q->second;
-
-          for (const_file_info_list_iterator p = file_info_list.begin ();
-               p != file_info_list.end ();
-               p++)
-            {
-              os << "  " << p->dir_name << " (";
-
-              print_types (os, p->types);
-
-              os << ")\n";
-            }
-        }
-    }
-
-  os << "\n";
-
-#endif
+  default_loader.display (os);
+
+  for (const_loader_map_iterator l = loader_map.begin ();
+       l != loader_map.end (); ++l)
+    l->second.display (os);
 }
 
 // True if a path is contained in a path list separated by path_sep_char
@@ -1743,7 +1826,29 @@
 }
 
 void
-load_path::add_to_fcn_map (const dir_info& di, bool at_end) const
+load_path::add (const dir_info& di, bool at_end,
+                const std::string& pname) const
+{
+  loader& l = get_loader (pname);
+
+  l.add (di, at_end);
+
+  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
+
+  for (dir_info::const_package_dir_map_iterator p = package_dir_map.begin ();
+       p != package_dir_map.end (); ++p)
+    {
+      std::string full_name = p->first;
+
+      if (! pname.empty ())
+        full_name = pname + "." + full_name;
+
+      add (p->second, at_end, full_name);
+    }
+}
+
+void
+load_path::loader::add_to_fcn_map (const dir_info& di, bool at_end)
 {
   std::string dir_name = di.dir_name;
 
@@ -1839,7 +1944,7 @@
 }
 
 void
-load_path::add_to_private_fcn_map (const dir_info& di) const
+load_path::loader::add_to_private_fcn_map (const dir_info& di)
 {
   dir_info::fcn_file_map_type private_file_map = di.private_file_map;
 
@@ -1848,7 +1953,7 @@
 }
 
 void
-load_path::add_to_method_map (const dir_info& di, bool at_end) const
+load_path::loader::add_to_method_map (const dir_info& di, bool at_end)
 {
   std::string dir_name = di.dir_name;
 
@@ -1918,6 +2023,81 @@
     }
 }
 
+void
+load_path::loader::display (std::ostream& os) const
+{
+  os << "*** loader: " << (prefix.empty () ? "<top-level>" : prefix) << "\n\n";
+
+  for (std::list<std::string>::const_iterator s = dir_list.begin ();
+       s != dir_list.end (); ++s)
+    os << *s << "\n";
+  os << "\n";
+
+  for (const_private_fcn_map_iterator i = private_fcn_map.begin ();
+       i != private_fcn_map.end (); i++)
+    {
+      os << "\n*** private functions in "
+         << file_ops::concat (i->first, "private") << ":\n\n";
+
+      print_fcn_list (os, i->second);
+    }
+
+#if defined (DEBUG_LOAD_PATH)
+
+  for (const_fcn_map_iterator i = fcn_map.begin ();
+       i != fcn_map.end ();
+       i++)
+    {
+      os << i->first << ":\n";
+
+      const file_info_list_type& file_info_list = i->second;
+
+      for (const_file_info_list_iterator p = file_info_list.begin ();
+           p != file_info_list.end ();
+           p++)
+        {
+          os << "  " << p->dir_name << " (";
+
+          print_types (os, p->types);
+
+          os << ")\n";
+        }
+    }
+
+  for (const_method_map_iterator i = method_map.begin ();
+       i != method_map.end ();
+       i++)
+    {
+      os << "CLASS " << i->first << ":\n";
+
+      const fcn_map_type& fm = i->second;
+
+      for (const_fcn_map_iterator q = fm.begin ();
+           q != fm.end ();
+           q++)
+        {
+          os << "  " << q->first << ":\n";
+
+          const file_info_list_type& file_info_list = q->second;
+
+          for (const_file_info_list_iterator p = file_info_list.begin ();
+               p != file_info_list.end ();
+               p++)
+            {
+              os << "  " << p->dir_name << " (";
+
+              print_types (os, p->types);
+
+              os << ")\n";
+            }
+        }
+    }
+
+  os << "\n";
+
+#endif
+}
+
 std::string
 genpath (const std::string& dirname, const string_vector& skip)
 {
@@ -1929,7 +2109,7 @@
     {
       retval = dirname;
 
-      string_vector dirlist = dir.read ();
+      string_vector dirlist = dir.read ().sort (false);
 
       octave_idx_type len = dirlist.length ();
 
@@ -1937,7 +2117,8 @@
         {
           std::string elt = dirlist[i];
 
-          bool skip_p = (elt == "." || elt == ".." || elt[0] == '@');
+          bool skip_p = (elt == "." || elt == ".." || elt[0] == '@'
+                         || elt[0] == '+');
 
           if (! skip_p)
             {
@@ -1964,6 +2145,21 @@
   return retval;
 }
 
+std::list<std::string>
+load_path::do_get_all_package_names (bool only_top_level) const
+{
+  std::list<std::string> retval;
+
+  for (const_loader_map_iterator l = loader_map.begin ();
+       l != loader_map.end (); ++l)
+    {
+      if (! only_top_level || l->first.find ('.') == std::string::npos)
+        retval.push_back (l->first);
+    }
+
+  return retval;
+}
+
 static void
 execute_pkg_add_or_del (const std::string& dir,
                         const std::string& script_file)
@@ -2339,3 +2535,10 @@
 
   return retval;
 }
+
+DEFUN (__dump_load_path__, , , "")
+{
+  load_path::display (octave_stdout);
+
+  return octave_value_list ();
+}
--- a/libinterp/corefcn/load-path.h
+++ b/libinterp/corefcn/load-path.h
@@ -39,8 +39,7 @@
 protected:
 
   load_path (void)
-    : dir_info_list (), fcn_map (), private_fcn_map (), method_map (),
-      init_dirs () { }
+    : loader_map (), default_loader (), dir_info_list (), init_dirs () { }
 
 public:
 
@@ -96,24 +95,29 @@
 
   static std::string find_method (const std::string& class_name,
                                   const std::string& meth,
-                                  std::string& dir_name)
+                                  std::string& dir_name,
+                                  const std::string& pack_name = std::string ())
   {
     return instance_ok ()
-           ? instance->do_find_method (class_name, meth, dir_name)
-           : std::string ();
+      ? instance->get_loader (pack_name).find_method (class_name, meth,
+                                                      dir_name)
+      : std::string ();
   }
 
   static std::string find_method (const std::string& class_name,
-                                  const std::string& meth)
+                                  const std::string& meth,
+                                  const std::string& pack_name = std::string ())
   {
     std::string dir_name;
-    return find_method (class_name, meth, dir_name);
+    return find_method (class_name, meth, dir_name, pack_name);
   }
 
-  static std::list<std::string> methods (const std::string& class_name)
+  static std::list<std::string> methods (const std::string& class_name,
+                                         const std::string& pack_name = std::string ())
   {
     return instance_ok ()
-           ? instance->do_methods (class_name) : std::list<std::string> ();
+      ? instance->get_loader(pack_name).methods (class_name)
+      : std::list<std::string> ();
   }
 
   static std::list<std::string> overloads (const std::string& meth)
@@ -122,47 +126,72 @@
            ? instance->do_overloads (meth) : std::list<std::string> ();
   }
 
-  static std::string find_fcn (const std::string& fcn, std::string& dir_name)
+  static bool find_package (const std::string& package_name)
+  {
+    return instance_ok ()
+      ? instance->do_find_package (package_name) : false;
+  }
+
+  static std::list<std::string>
+  get_all_package_names (bool only_top_level = true)
   {
     return instance_ok ()
-           ? instance->do_find_fcn (fcn, dir_name) : std::string ();
+      ? instance->do_get_all_package_names (only_top_level)
+      : std::list<std::string> ();
   }
 
-  static std::string find_fcn (const std::string& fcn)
+  static std::string find_fcn (const std::string& fcn, std::string& dir_name,
+                               const std::string& pack_name = std::string ())
+  {
+    return instance_ok ()
+      ? instance->get_loader (pack_name).find_fcn (fcn, dir_name)
+      : std::string ();
+  }
+
+  static std::string find_fcn (const std::string& fcn,
+                               const std::string& pack_name = std::string ())
   {
     std::string dir_name;
-    return find_fcn (fcn, dir_name);
+    return find_fcn (fcn, dir_name, pack_name);
   }
 
   static std::string find_private_fcn (const std::string& dir,
-                                       const std::string& fcn)
+                                       const std::string& fcn,
+                                       const std::string& pack_name = std::string ())
   {
     return instance_ok ()
-           ? instance->do_find_private_fcn (dir, fcn) : std::string ();
+      ? instance->get_loader (pack_name).find_private_fcn (dir, fcn)
+      : std::string ();
   }
 
-  static std::string find_fcn_file (const std::string& fcn)
+  static std::string find_fcn_file (const std::string& fcn,
+                                    const std::string& pack_name = std::string ())
   {
     std::string dir_name;
 
-    return instance_ok () ?
-           instance->do_find_fcn (fcn, dir_name, M_FILE) : std::string ();
+    return instance_ok ()
+      ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE)
+      : std::string ();
   }
 
-  static std::string find_oct_file (const std::string& fcn)
+  static std::string find_oct_file (const std::string& fcn,
+                                    const std::string& pack_name = std::string ())
   {
     std::string dir_name;
 
-    return instance_ok () ?
-           instance->do_find_fcn (fcn, dir_name, OCT_FILE) : std::string ();
+    return instance_ok ()
+      ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE)
+      : std::string ();
   }
 
-  static std::string find_mex_file (const std::string& fcn)
+  static std::string find_mex_file (const std::string& fcn,
+                                    const std::string& pack_name = std::string ())
   {
     std::string dir_name;
 
-    return instance_ok () ?
-           instance->do_find_fcn (fcn, dir_name, MEX_FILE) : std::string ();
+    return instance_ok ()
+      ? instance->get_loader (pack_name).find_fcn (fcn, dir_name, M_FILE)
+      : std::string ();
   }
 
   static std::string find_file (const std::string& file)
@@ -297,19 +326,27 @@
     typedef method_file_map_type::const_iterator const_method_file_map_iterator;
     typedef method_file_map_type::iterator method_file_map_iterator;
 
+    // <PACKAGE_NAME, DIR_INFO>
+    typedef std::map<std::string, dir_info> package_dir_map_type;
+
+    typedef package_dir_map_type::const_iterator const_package_dir_map_iterator;
+    typedef package_dir_map_type::iterator package_dir_map_iterator;
+
     // This default constructor is only provided so we can create a
     // std::map of dir_info objects.  You should not use this
     // constructor for any other purpose.
     dir_info (void)
       : dir_name (), abs_dir_name (), is_relative (false),
         dir_mtime (), dir_time_last_checked (),
-        all_files (), fcn_files (), private_file_map (), method_file_map ()
+        all_files (), fcn_files (), private_file_map (), method_file_map (),
+        package_dir_map ()
     { }
 
     dir_info (const std::string& d)
       : dir_name (d), abs_dir_name (), is_relative (false),
         dir_mtime (), dir_time_last_checked (),
-        all_files (), fcn_files (), private_file_map (), method_file_map ()
+        all_files (), fcn_files (), private_file_map (), method_file_map (),
+        package_dir_map ()
     {
       initialize ();
     }
@@ -321,7 +358,8 @@
         dir_time_last_checked (di.dir_time_last_checked),
         all_files (di.all_files), fcn_files (di.fcn_files),
         private_file_map (di.private_file_map),
-        method_file_map (di.method_file_map) { }
+        method_file_map (di.method_file_map),
+        package_dir_map (di.package_dir_map) { }
 
     ~dir_info (void) { }
 
@@ -338,6 +376,7 @@
           fcn_files = di.fcn_files;
           private_file_map = di.private_file_map;
           method_file_map = di.method_file_map;
+          package_dir_map = di.package_dir_map;
         }
 
       return *this;
@@ -354,6 +393,7 @@
     string_vector fcn_files;
     fcn_file_map_type private_file_map;
     method_file_map_type method_file_map;
+    package_dir_map_type package_dir_map;
 
   private:
 
@@ -366,6 +406,9 @@
     void get_method_file_map (const std::string& d,
                               const std::string& class_name);
 
+    void get_package_dir (const std::string& d,
+                          const std::string& package_name);
+
     friend fcn_file_map_type get_fcn_files (const std::string& d);
   };
 
@@ -442,13 +485,125 @@
   typedef method_map_type::const_iterator const_method_map_iterator;
   typedef method_map_type::iterator method_map_iterator;
 
-  mutable dir_info_list_type dir_info_list;
+  class loader
+  {
+  public:
+    loader (const std::string& pfx = std::string ())
+      : prefix (pfx), dir_list (), fcn_map (), private_fcn_map (),
+        method_map () { }
+
+    loader (const loader& l)
+      : prefix (l.prefix), dir_list (l.dir_list),
+        private_fcn_map (l.private_fcn_map), method_map (l.method_map) { }
+
+    ~loader (void) { }
+
+    loader& operator = (const loader& l)
+    {
+      if (&l != this)
+        {
+          prefix = l.prefix;
+          dir_list = l.dir_list;
+          fcn_map = l.fcn_map;
+          private_fcn_map = l.private_fcn_map;
+          method_map = l.method_map;
+        }
+
+      return *this;
+    }
 
-  mutable fcn_map_type fcn_map;
+    void add (const dir_info& di, bool at_end)
+    {
+      if (at_end)
+        dir_list.push_back (di.dir_name);
+      else
+        dir_list.push_front (di.dir_name);
+
+      add_to_fcn_map (di, at_end);
+
+      add_to_private_fcn_map (di);
+
+      add_to_method_map (di, at_end);
+    }
+
+    void move (const dir_info& di, bool at_end);
+
+    void remove (const dir_info& di);
+
+    void clear (void)
+      {
+        dir_list.clear ();
+
+        fcn_map.clear ();
+
+        private_fcn_map.clear ();
+
+        method_map.clear ();
+      }
+
+    void display (std::ostream& out) const;
 
-  mutable private_fcn_map_type private_fcn_map;
+    std::string find_fcn (const std::string& fcn,
+                          std::string& dir_name,
+                          int type = M_FILE | OCT_FILE | MEX_FILE) const;
+
+    std::string find_private_fcn (const std::string& dir,
+                                  const std::string& fcn,
+                                  int type = M_FILE | OCT_FILE | MEX_FILE) const;
+
+    std::string find_method (const std::string& class_name,
+                             const std::string& meth,
+                             std::string& dir_name,
+                             int type = M_FILE | OCT_FILE | MEX_FILE) const;
+
+    std::list<std::string> methods (const std::string& class_name) const;
+
+    void overloads (const std::string& meth, std::list<std::string>& l) const;
+
+    string_vector fcn_names (void) const;
+
+  private:
+    void add_to_fcn_map (const dir_info& di, bool at_end);
+
+    void add_to_private_fcn_map (const dir_info& di);
+
+    void add_to_method_map (const dir_info& di, bool at_end);
+
+    void move_fcn_map (const std::string& dir,
+                       const string_vector& fcn_files, bool at_end);
+
+    void move_method_map (const std::string& dir, bool at_end);
 
-  mutable method_map_type method_map;
+    void remove_fcn_map (const std::string& dir,
+                         const string_vector& fcn_files);
+
+    void remove_private_fcn_map (const std::string& dir);
+
+    void remove_method_map (const std::string& dir);
+
+  private:
+    std::string prefix;
+
+    std::list<std::string> dir_list;
+
+    fcn_map_type fcn_map;
+
+    private_fcn_map_type private_fcn_map;
+
+    method_map_type method_map;
+  };
+
+  // <PACKAGE_NAME, LOADER>
+  typedef std::map<std::string, loader> loader_map_type;
+
+  typedef loader_map_type::const_iterator const_loader_map_iterator;
+  typedef loader_map_type::iterator loader_map_iterator;
+
+  mutable loader_map_type loader_map;
+
+  mutable loader default_loader;
+
+  mutable dir_info_list_type dir_info_list;
 
   mutable std::set<std::string> init_dirs;
 
@@ -475,12 +630,13 @@
 
   bool do_contains_canonical (const std::string& dir) const;
 
-  void move_fcn_map (const std::string& dir,
-                     const string_vector& fcn_files, bool at_end);
+  void do_move (dir_info_list_iterator i, bool at_end);
 
-  void move_method_map (const std::string& dir, bool at_end);
+  void move (const dir_info& di, bool at_end,
+             const std::string& pname = std::string ());
 
-  void move (std::list<dir_info>::iterator i, bool at_end);
+  void remove (const dir_info& di,
+               const std::string& pname = std::string ());
 
   void do_initialize (bool set_initial_path);
 
@@ -494,12 +650,6 @@
 
   void do_add (const std::string& dir, bool at_end, bool warn);
 
-  void remove_fcn_map (const std::string& dir, const string_vector& fcn_files);
-
-  void remove_private_fcn_map (const std::string& dir);
-
-  void remove_method_map (const std::string& dir);
-
   bool do_remove (const std::string& dir);
 
   void do_update (void) const;
@@ -508,23 +658,31 @@
   check_file_type (std::string& fname, int type, int possible_types,
                    const std::string& fcn, const char *who);
 
-  std::string do_find_fcn (const std::string& fcn,
-                           std::string& dir_name,
-                           int type = M_FILE | OCT_FILE | MEX_FILE) const;
+  loader& get_loader (const std::string& name) const
+  {
+    if (! name.empty ())
+      {
+        loader_map_iterator l = loader_map.find (name);
 
-  std::string do_find_private_fcn (const std::string& dir,
-                                   const std::string& fcn,
-                                   int type = M_FILE | OCT_FILE | MEX_FILE) const;
+        if (l == loader_map.end ())
+          l = loader_map.insert (loader_map.end (),
+                                 loader_map_type::value_type (name, loader (name)));
 
-  std::string do_find_method (const std::string& class_name,
-                              const std::string& meth,
-                              std::string& dir_name,
-                              int type = M_FILE | OCT_FILE | MEX_FILE) const;
+        return l->second;
+      }
 
-  std::list<std::string> do_methods (const std::string& class_name) const;
+    return default_loader;
+  }
 
   std::list<std::string> do_overloads (const std::string& meth) const;
 
+  bool do_find_package (const std::string& package_name) const
+  {
+    return (loader_map.find (package_name) != loader_map.end ());
+  }
+
+  std::list<std::string> do_get_all_package_names (bool only_top_level) const;
+
   std::string do_find_file (const std::string& file) const;
 
   std::string do_find_dir (const std::string& dir) const;
@@ -559,11 +717,8 @@
   std::string do_get_command_line_path (void) const
   { return command_line_path; }
 
-  void add_to_fcn_map (const dir_info& di, bool at_end) const;
-
-  void add_to_private_fcn_map (const dir_info& di) const;
-
-  void add_to_method_map (const dir_info& di, bool at_end) const;
+  void add (const dir_info& di, bool at_end,
+            const std::string& pname = std::string ()) const;
 
   friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d);
 };
--- a/libinterp/corefcn/load-save.cc
+++ b/libinterp/corefcn/load-save.cc
@@ -502,17 +502,24 @@
   if (! (octave_env::absolute_pathname (fname)
          || octave_env::rooted_relative_pathname (fname)))
     {
+      // Load path will also search "." first, but we don't want to
+      // issue a warning if the file is found in the current directory,
+      // so do an explicit check for that.
+
       file_stat fs (fname);
 
       if (! (fs.exists () && fs.is_reg ()))
         {
+          // Not directly found; search load path.
+
           std::string tmp
             = octave_env::make_absolute (load_path::find_file (fname));
 
           if (! tmp.empty ())
             {
               warning_with_id ("Octave:load-file-in-path",
-                               "load: file found in load path");
+                               "load: file found in load path: %s",
+                               tmp.c_str ());
               fname = tmp;
             }
         }
@@ -1065,7 +1072,8 @@
   string_vector retval;
   int argc = argv.length ();
 
-  bool do_double = false, do_tabs = false;
+  bool do_double = false;
+  bool do_tabs = false;
 
   for (int i = 0; i < argc; i++)
     {
@@ -1615,8 +1623,6 @@
 {
   octave_value_list retval;
 
-  int argc = args.length ();
-
   string_vector argv = args.make_argv ();
 
   if (error_state)
@@ -1640,7 +1646,7 @@
   // override from command line
   argv = parse_save_options (argv, format, append, save_as_floats,
                              use_zlib);
-  argc = argv.length ();
+  int argc = argv.length ();
   int i = 0;
 
   if (error_state)
--- a/libinterp/corefcn/lookup.cc
+++ b/libinterp/corefcn/lookup.cc
@@ -115,7 +115,8 @@
   octave_value retval;
 
   Array<octave_idx_type> idx = array.lookup (values);
-  octave_idx_type n = array.numel (), nval = values.numel ();
+  octave_idx_type n = array.numel ();
+  octave_idx_type nval = values.numel ();
 
   // Post-process.
   if (match_bool)
@@ -246,7 +247,8 @@
       return retval;
     }
 
-  octave_value table = args(0), y = args(1);
+  octave_value table = args(0);
+  octave_value y = args(1);
   if (table.ndims () > 2 || (table.columns () > 1 && table.rows () > 1))
     warning ("lookup: table is not a vector");
 
--- a/libinterp/corefcn/ls-hdf5.cc
+++ b/libinterp/corefcn/ls-hdf5.cc
@@ -263,7 +263,7 @@
   // Allow identifiers as all digits so we can load lists saved by
   // earlier versions of Octave.
 
-  if (! ident_valid )
+  if (! ident_valid)
     {
       // fix the identifier, replacing invalid chars with underscores
       vname = make_valid_identifier (vname);
@@ -528,6 +528,7 @@
         {
           warning ("load: can't read '%s' (unknown datatype)", name);
           retval = 0; // unknown datatype; skip
+          return retval;
         }
 
       // check for OCTAVE_GLOBAL attribute:
@@ -615,7 +616,7 @@
 
       len = H5Gget_objname_by_idx (hs.file_id, hs.current_item, 0, 0);
       var_name.resize (len+1);
-      H5Gget_objname_by_idx( hs.file_id, hs.current_item, &var_name[0], len+1);
+      H5Gget_objname_by_idx (hs.file_id, hs.current_item, &var_name[0], len+1);
 
       for (int i = argv_idx; i < argc; i++)
         {
@@ -738,7 +739,8 @@
   hsize_t sz = d.length ();
   OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz);
   bool empty = false;
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid = -1;
+  hid_t data_hid = -1;
   int retval;
   for (hsize_t i = 0; i < sz; i++)
     {
@@ -865,7 +867,9 @@
                bool mark_as_global, bool save_as_floats)
 {
   hsize_t dims[3];
-  hid_t type_id = -1, space_id = -1, data_id = -1, data_type_id = -1;
+  hid_t type_id, space_id, data_id, data_type_id;
+  type_id = space_id = data_id = data_type_id = -1;
+
   bool retval = false;
   octave_value val = tc;
   // FIXME: diagonal & permutation matrices currently don't know how to save
--- a/libinterp/corefcn/ls-mat4.cc
+++ b/libinterp/corefcn/ls-mat4.cc
@@ -461,7 +461,6 @@
       len = nr * nc;
     }
 
-
   // LEN includes the terminating character, and the file is also
   // supposed to include it.
 
@@ -489,7 +488,10 @@
           for (octave_idx_type j = 0; j < ncol; j++)
             buf[j*nrow+i] = static_cast<double> (*s++ & 0x00FF);
         }
-      os.write (reinterpret_cast<char *> (buf), nrow*ncol*sizeof (double));
+      std::streamsize n_bytes = static_cast<std::streamsize> (nrow) *
+                                static_cast<std::streamsize> (ncol) *
+                                sizeof (double);
+      os.write (reinterpret_cast<char *> (buf), n_bytes);
     }
   else if (tc.is_range ())
     {
@@ -518,7 +520,8 @@
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = m.ridx (i) + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nr;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
@@ -526,19 +529,19 @@
           for (octave_idx_type j = 0; j < nc; j++)
             for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
               dtmp[ii++] = j + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nc;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = std::real (m.data (i));
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = 0.;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = std::imag (m.data (i));
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           os.write (reinterpret_cast<const char *> (&ds), 8);
         }
       else
@@ -547,7 +550,8 @@
 
           for (octave_idx_type i = 0; i < len; i++)
             dtmp[i] = m.ridx (i) + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nr;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
@@ -555,11 +559,11 @@
           for (octave_idx_type j = 0; j < nc; j++)
             for (octave_idx_type i = m.cidx (j); i < m.cidx (j+1); i++)
               dtmp[ii++] = j + 1;
-          os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
+          os.write (reinterpret_cast<const char *> (dtmp), n_bytes);
           ds = nc;
           os.write (reinterpret_cast<const char *> (&ds), 8);
 
-          os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+          os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
           ds = 0.;
           os.write (reinterpret_cast<const char *> (&ds), 8);
         }
@@ -567,7 +571,8 @@
   else if (tc.is_real_matrix ())
     {
       Matrix m = tc.matrix_value ();
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+      std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
     }
   else if (tc.is_complex_scalar ())
     {
@@ -578,9 +583,10 @@
     {
       ComplexMatrix m_cmplx = tc.complex_matrix_value ();
       Matrix m = ::real (m_cmplx);
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+      std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
+      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
       m = ::imag (m_cmplx);
-      os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
+      os.write (reinterpret_cast<const char *> (m.data ()), n_bytes);
     }
   else
     gripe_wrong_type_arg ("save", tc, false);
--- a/libinterp/corefcn/ls-mat5.cc
+++ b/libinterp/corefcn/ls-mat5.cc
@@ -264,7 +264,8 @@
       if (len > 0) \
         { \
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
-          stream.read (reinterpret_cast<char *> (ptr), size * len); \
+          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
+          stream.read (reinterpret_cast<char *> (ptr), n_bytes); \
           if (swap) \
             swap_bytes< size > (ptr, len); \
           for (octave_idx_type i = 0; i < len; i++) \
@@ -439,7 +440,7 @@
   unsigned int upper;
   int32_t temp;
 
-  if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
+  if (! is.read (reinterpret_cast<char *> (&temp), 4))
     goto data_read_error;
 
   if (swap)
@@ -456,7 +457,7 @@
     }
   else
     {
-      if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
+      if (! is.read (reinterpret_cast<char *> (&temp), 4))
         goto data_read_error;
       if (swap)
         swap_bytes<4> (&temp);
@@ -701,7 +702,7 @@
 
     if (len)
       {
-        if (! is.read (name, len ))
+        if (! is.read (name, len))
           goto data_read_error;
 
         is.seekg (tmp_pos + static_cast<std::streamoff>
@@ -929,7 +930,7 @@
                         std::string dir_name = str.substr (0, xpos);
 
                         octave_function *fcn
-                          = load_fcn_from_file (str, dir_name, "", fname);
+                          = load_fcn_from_file (str, dir_name, "", "", fname);
 
                         if (fcn)
                           {
@@ -958,7 +959,7 @@
                         std::string dir_name = str.substr (0, xpos);
 
                         octave_function *fcn
-                          = load_fcn_from_file (str, dir_name, "", fname);
+                          = load_fcn_from_file (str, dir_name, "", "", fname);
 
                         if (fcn)
                           {
@@ -983,7 +984,7 @@
                     std::string dir_name = fpath.substr (0, xpos);
 
                     octave_function *fcn
-                      = load_fcn_from_file (fpath, dir_name, "", fname);
+                      = load_fcn_from_file (fpath, dir_name, "", "", fname);
 
                     if (fcn)
                       {
@@ -1163,7 +1164,7 @@
 
           if (len)
             {
-              if (! is.read (name, len ))
+              if (! is.read (name, len))
                 goto data_read_error;
 
               is.seekg (tmp_pos + static_cast<std::streamoff>
@@ -1193,7 +1194,7 @@
             goto data_read_error;
           }
 
-        if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len ))
+        if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len))
           goto data_read_error;
 
         if (swap)
@@ -1560,7 +1561,8 @@
 read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet,
                               const std::string& filename)
 {
-  int16_t version=0, magic=0;
+  int16_t version = 0;
+  int16_t magic = 0;
   uint64_t subsys_offset;
 
   is.seekg (116, std::ios::beg);
@@ -1666,7 +1668,8 @@
       OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \
       for (octave_idx_type i = 0; i < count; i++) \
         ptr[i] = static_cast<TYPE> (data[i]); \
-      stream.write (reinterpret_cast<char *> (ptr), count * sizeof (TYPE)); \
+      std::streamsize n_bytes = sizeof (TYPE) * static_cast<std::streamsize> (count); \
+      stream.write (reinterpret_cast<char *> (ptr), n_bytes); \
     } \
   while (0)
 
--- a/libinterp/corefcn/lu.cc
+++ b/libinterp/corefcn/lu.cc
@@ -158,11 +158,11 @@
   int n = 1;
   while (n < nargin && ! error_state)
     {
-      if (args (n).is_string ())
+      if (args(n).is_string ())
         {
           std::string tmp = args(n++).string_value ();
 
-          if (! error_state )
+          if (! error_state)
             {
               if (tmp.compare ("vector") == 0)
                 vecout = true;
@@ -174,7 +174,7 @@
         {
           Matrix tmp = args(n++).matrix_value ();
 
-          if (! error_state )
+          if (! error_state)
             {
               if (!issparse)
                 error ("lu: can not define pivoting threshold THRES for full matrices");
@@ -211,7 +211,7 @@
 
           SparseMatrix m = arg.sparse_matrix_value ();
 
-          if ( nargout < 4 )
+          if (nargout < 4)
             {
 
               ColumnVector Qinit;
@@ -220,7 +220,7 @@
                 Qinit (i) = i;
               SparseLU fact (m, Qinit, thres, false, true);
 
-              if ( nargout < 2 )
+              if (nargout < 2)
                   retval(0) = fact.Y ();
               else
                 {
@@ -233,15 +233,15 @@
 
                   PermMatrix P = fact.Pr_mat ();
                   SparseMatrix L = fact.L ();
-                  if ( nargout < 3 )
+                  if (nargout < 3)
                       retval(0)
-                        = octave_value ( P.transpose () * L,
+                        = octave_value (P.transpose () * L,
                             MatrixType (MatrixType::Permuted_Lower,
                                         nr, fact.row_perm ()));
                   else
                     {
                       retval(0) = L;
-                      if ( vecout )
+                      if (vecout)
                         retval(2) = fact.Pr_vec();
                       else
                         retval(2) = P;
@@ -279,7 +279,7 @@
         {
           SparseComplexMatrix m = arg.sparse_complex_matrix_value ();
 
-          if ( nargout < 4 )
+          if (nargout < 4)
             {
 
               ColumnVector Qinit;
@@ -288,7 +288,7 @@
                 Qinit (i) = i;
               SparseComplexLU fact (m, Qinit, thres, false, true);
 
-              if ( nargout < 2 )
+              if (nargout < 2)
 
                   retval(0) = fact.Y ();
 
@@ -303,15 +303,15 @@
 
                   PermMatrix P = fact.Pr_mat ();
                   SparseComplexMatrix L = fact.L ();
-                  if ( nargout < 3 )
+                  if (nargout < 3)
                       retval(0)
-                        = octave_value ( P.transpose () * L,
+                        = octave_value (P.transpose () * L,
                             MatrixType (MatrixType::Permuted_Lower,
                                         nr, fact.row_perm ()));
                   else
                     {
                       retval(0) = L;
-                      if ( vecout )
+                      if (vecout)
                         retval(2) = fact.Pr_vec();
                       else
                         retval(2) = P;
@@ -592,7 +592,9 @@
 bool check_lu_dims (const octave_value& l, const octave_value& u,
                     const octave_value& p)
 {
-  octave_idx_type m = l.rows (), k = u.rows (), n = u.columns ();
+  octave_idx_type m = l.rows ();
+  octave_idx_type k = u.rows ();
+  octave_idx_type n = u.columns ();
   return ((l.ndims () == 2 && u.ndims () == 2 && k == l.columns ())
           && k == std::min (m, n) &&
           (p.is_undefined () || p.rows () == m));
--- a/libinterp/corefcn/luinc.cc
+++ b/libinterp/corefcn/luinc.cc
@@ -177,7 +177,7 @@
         {
           std::string tmp = args(2).string_value ();
 
-          if (! error_state )
+          if (! error_state)
             {
               if (tmp.compare ("vector") == 0)
                 vecout = true;
--- a/libinterp/corefcn/mappers.cc
+++ b/libinterp/corefcn/mappers.cc
@@ -2156,8 +2156,17 @@
 %!assert (tolower ({"ABC", "DEF", {"GHI", {"JKL"}}}), {"abc", "def", {"ghi", {"jkl"}}})
 %!assert (tolower (["ABC"; "DEF"]), ["abc"; "def"])
 %!assert (tolower ({["ABC"; "DEF"]}), {["abc";"def"]})
-%!assert (tolower (68), "d")
-%!assert (tolower ({[68, 68; 68, 68]}), {["dd";"dd"]})
+%!assert (tolower (68), 68)
+%!assert (tolower ({[68, 68; 68, 68]}), {[68, 68; 68, 68]})
+%!test
+%! classes = {@char, @double, @single, ...
+%!            @int8, @int16, @int32, @int64, ...
+%!            @uint8, @uint16, @uint32, @uint64};
+%! for i = 1:numel (classes)
+%!   cls = classes{i};
+%!   assert (class (tolower (cls (97))), class (cls (97)));
+%!   assert (class (tolower (cls ([98, 99]))), class (cls ([98, 99])));
+%! endfor
 %!test
 %! a(3,3,3,3) = "D";
 %! assert (tolower (a)(3,3,3,3), "d");
@@ -2207,8 +2216,17 @@
 %!assert (toupper ({"abc", "def", {"ghi", {"jkl"}}}), {"ABC", "DEF", {"GHI", {"JKL"}}})
 %!assert (toupper (["abc"; "def"]), ["ABC"; "DEF"])
 %!assert (toupper ({["abc"; "def"]}), {["ABC";"DEF"]})
-%!assert (toupper (100), "D")
-%!assert (toupper ({[100, 100; 100, 100]}), {["DD";"DD"]})
+%!assert (toupper (100), 100)
+%!assert (toupper ({[100, 100; 100, 100]}), {[100, 100; 100, 100]})
+%!test
+%! classes = {@char, @double, @single, ...
+%!            @int8, @int16, @int32, @int64, ...
+%!            @uint8, @uint16, @uint32, @uint64};
+%! for i = 1:numel (classes)
+%!   cls = classes{i};
+%!   assert (class (toupper (cls (97))), class (cls (97)));
+%!   assert (class (toupper (cls ([98, 99]))), class (cls ([98, 99])));
+%! endfor
 %!test
 %! a(3,3,3,3) = "d";
 %! assert (toupper (a)(3,3,3,3), "D");
--- a/libinterp/corefcn/matrix_type.cc
+++ b/libinterp/corefcn/matrix_type.cc
@@ -148,7 +148,7 @@
                 {
                   mattyp = args(0).matrix_type ();
 
-                  if (mattyp.is_unknown () && autocomp )
+                  if (mattyp.is_unknown () && autocomp)
                     {
                       SparseComplexMatrix m =
                         args(0).sparse_complex_matrix_value ();
@@ -281,7 +281,7 @@
                           && (str_typ == "upper" || str_typ == "lower"))
                         {
                           const ColumnVector perm =
-                            ColumnVector (args (2).vector_value ());
+                            ColumnVector (args(2).vector_value ());
 
                           if (error_state)
                             error ("matrix_type: Invalid permutation vector PERM");
@@ -454,7 +454,7 @@
                                           || str_typ == "lower"))
                         {
                           const ColumnVector perm =
-                            ColumnVector (args (2).vector_value ());
+                            ColumnVector (args(2).vector_value ());
 
                           if (error_state)
                             error ("matrix_type: Invalid permutation vector PERM");
--- a/libinterp/corefcn/max.cc
+++ b/libinterp/corefcn/max.cc
@@ -354,8 +354,10 @@
     }
   else if (nargin == 2)
     {
-      octave_value argx = args(0), argy = args(1);
-      builtin_type_t xtyp = argx.builtin_type (), ytyp = argy.builtin_type ();
+      octave_value argx = args(0);
+      octave_value argy = args(1);
+      builtin_type_t xtyp = argx.builtin_type ();
+      builtin_type_t ytyp = argy.builtin_type ();
       builtin_type_t rtyp;
       if (xtyp == btyp_char && ytyp == btyp_char)
         rtyp = btyp_char;
@@ -560,6 +562,10 @@
 %! assert (ndims(i), 2);
 %! assert (i, [1, 1; 1, 1]);
 
+## Test for bug #40743
+%!assert (max (zeros (1,0), ones (1,1)), zeros (1,0))
+%!assert (max (sparse (zeros (1,0)), sparse (ones (1,1))), sparse (zeros (1,0)))
+
 %!error max ()
 %!error max (1, 2, 3, 4)
 */
--- a/libinterp/corefcn/module.mk
+++ b/libinterp/corefcn/module.mk
@@ -91,6 +91,7 @@
   corefcn/oct-stream.h \
   corefcn/oct-strstrm.h \
   corefcn/oct.h \
+  corefcn/octave-default-image.h \
   corefcn/octave-link.h \
   corefcn/pager.h \
   corefcn/pr-output.h \
--- a/libinterp/corefcn/oct-map.cc
+++ b/libinterp/corefcn/oct-map.cc
@@ -117,7 +117,8 @@
 {
   bool retval = true;
 
-  iterator p = begin (), q = other.begin ();
+  iterator p = begin ();
+  iterator q = other.begin ();
   for (; p != end () && q != other.end (); p++, q++)
     {
       if (p->first == q->first)
@@ -251,15 +252,6 @@
     }
 }
 
-octave_map::octave_map (const Octave_map& m)
-  : xkeys (m.keys ()), xvals (m.nfields ()), dimensions (m.dims ())
-{
-  for (iterator p = begin (); p != end (); p++)
-    contents(p) = m.contents (key (p));
-
-  optimize_dimensions ();
-}
-
 Cell
 octave_map::getfield (const std::string& k) const
 {
@@ -819,9 +811,9 @@
 %! sr = [s,s];
 %! sc = [s;s];
 %! sm = [s,s;s,s];
-%! assert (nfields (sr), 0);
-%! assert (nfields (sc), 0);
-%! assert (nfields (sm), 0);
+%! assert (numfields (sr), 0);
+%! assert (numfields (sc), 0);
+%! assert (numfields (sm), 0);
 %! assert (size (sr), [1, 2]);
 %! assert (size (sc), [2, 1]);
 %! assert (size (sm), [2, 2]);
@@ -1314,470 +1306,3 @@
 
 }
 
-Octave_map::Octave_map (const dim_vector& dv, const Cell& key_vals)
-  : map (), key_list (), dimensions (dv)
-{
-  Cell c (dv);
-
-  if (key_vals.is_cellstr ())
-    {
-      for (octave_idx_type i = 0; i < key_vals.numel (); i++)
-        {
-          std::string k = key_vals(i).string_value ();
-          map[k] = c;
-          key_list.push_back (k);
-        }
-    }
-  else
-    error ("Octave_map: expecting keys to be cellstr");
-}
-
-Octave_map::Octave_map (const octave_map& m)
-  : map (), key_list (), dimensions (m.dims ())
-{
-  for (octave_map::const_iterator p = m.begin (); p != m.end (); p++)
-    map[m.key (p)] = m.contents (p);
-  const string_vector mkeys = m.fieldnames ();
-  for (octave_idx_type i = 0; i < mkeys.numel (); i++)
-    key_list.push_back (mkeys(i));
-}
-
-Octave_map
-Octave_map::squeeze (void) const
-{
-  Octave_map retval (dims ().squeeze ());
-
-  for (const_iterator pa = begin (); pa != end (); pa++)
-    {
-      Cell tmp = contents (pa).squeeze ();
-
-      if (error_state)
-        break;
-
-      retval.assign (key (pa), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::permute (const Array<int>& vec, bool inv) const
-{
-  Octave_map retval (dims ());
-
-  for (const_iterator pa = begin (); pa != end (); pa++)
-    {
-      Cell tmp = contents (pa).permute (vec, inv);
-
-      if (error_state)
-        break;
-
-      retval.assign (key (pa), tmp);
-    }
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Cell&
-Octave_map::contents (const std::string& k)
-{
-  maybe_add_to_key_list (k);
-
-  return map[k];
-}
-
-Cell
-Octave_map::contents (const std::string& k) const
-{
-  const_iterator p = seek (k);
-
-  return p != end () ? p->second : Cell ();
-}
-
-int
-Octave_map::intfield (const std::string& k, int def_val) const
-{
-  int retval = def_val;
-
-  Cell c = contents (k);
-
-  if (! c.is_empty ())
-    retval = c(0).int_value ();
-
-  return retval;
-}
-
-std::string
-Octave_map::stringfield (const std::string& k,
-                         const std::string& def_val) const
-{
-  std::string retval = def_val;
-
-  Cell c = contents (k);
-
-  if (! c.is_empty ())
-    retval = c(0).string_value ();
-
-  return retval;
-}
-
-string_vector
-Octave_map::keys (void) const
-{
-  assert (static_cast<size_t>(nfields ()) == key_list.size ());
-
-  return string_vector (key_list);
-}
-
-Octave_map
-Octave_map::transpose (void) const
-{
-  assert (ndims () == 2);
-
-  dim_vector dv = dims ();
-
-  octave_idx_type nr = dv(0);
-  octave_idx_type nc = dv(1);
-
-  dim_vector new_dims (nc, nr);
-
-  Octave_map retval (new_dims);
-
-  for (const_iterator p = begin (); p != end (); p++)
-    retval.assign (key(p), Cell (contents(p).transpose ()));
-
-  // Preserve order of keys.
-  retval.key_list = key_list;
-
-  return retval;
-}
-
-Octave_map
-Octave_map::reshape (const dim_vector& new_dims) const
-{
-  Octave_map retval;
-
-  if (new_dims != dims ())
-    {
-      for (const_iterator p = begin (); p != end (); p++)
-        retval.assign (key(p), contents(p).reshape (new_dims));
-
-      retval.dimensions = new_dims;
-
-      // Preserve order of keys.
-      retval.key_list = key_list;
-    }
-  else
-    retval = *this;
-
-  return retval;
-}
-
-void
-Octave_map::resize (const dim_vector& dv, bool fill)
-{
-  if (dv != dims ())
-    {
-      if (nfields () == 0)
-        dimensions = dv;
-      else
-        {
-          for (const_iterator p = begin (); p != end (); p++)
-            {
-              Cell tmp = contents(p);
-
-              if (fill)
-                tmp.resize (dv, Matrix ());
-              else
-                tmp.resize (dv);
-
-              dimensions = dv;
-
-              assign (key(p), tmp);
-            }
-        }
-    }
-}
-
-Octave_map
-Octave_map::concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx)
-{
-  Octave_map retval;
-
-  if (nfields () == rb.nfields ())
-    {
-      for (const_iterator pa = begin (); pa != end (); pa++)
-        {
-          const_iterator pb = rb.seek (key(pa));
-
-          if (pb == rb.end ())
-            {
-              error ("field name mismatch in structure concatenation");
-              break;
-            }
-
-          retval.assign (key(pa),
-                         contents(pa).insert (rb.contents(pb), ra_idx));
-        }
-
-      // Preserve order of keys.
-      retval.key_list = key_list;
-    }
-  else
-    {
-      dim_vector dv = dims ();
-
-      if (dv.all_zero ())
-        retval = rb;
-      else
-        {
-          dv = rb.dims ();
-
-          if (dv.all_zero ())
-            retval = *this;
-          else
-            error ("invalid structure concatenation");
-        }
-    }
-
-  return retval;
-}
-
-static bool
-keys_ok (const Octave_map& a, const Octave_map& b, string_vector& keys)
-{
-  bool retval = false;
-
-  keys = string_vector ();
-
-  if (a.nfields () == 0)
-    {
-      keys = b.keys ();
-      retval = true;
-    }
-  else
-    {
-      string_vector a_keys = a.keys ().sort ();
-      string_vector b_keys = b.keys ().sort ();
-
-      octave_idx_type a_len = a_keys.length ();
-      octave_idx_type b_len = b_keys.length ();
-
-      if (a_len == b_len)
-        {
-          for (octave_idx_type i = 0; i < a_len; i++)
-            {
-              if (a_keys[i] != b_keys[i])
-                goto done;
-            }
-
-          keys = a_keys;
-          retval = true;
-        }
-    }
-
-done:
-  return retval;
-}
-
-Octave_map&
-Octave_map::maybe_delete_elements (const octave_value_list& idx)
-{
-  string_vector t_keys = keys ();
-  octave_idx_type len = t_keys.length ();
-
-  if (len > 0)
-    {
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          std::string k = t_keys[i];
-
-          contents(k).delete_elements (idx);
-
-          if (error_state)
-            break;
-        }
-
-      if (!error_state)
-        dimensions = contents(t_keys[0]).dims ();
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs)
-{
-  string_vector t_keys;
-
-  if (keys_ok (*this, rhs, t_keys))
-    {
-      octave_idx_type len = t_keys.length ();
-
-      if (len == 0)
-        {
-          Cell tmp_lhs (dims ());
-          Cell tmp_rhs (rhs.dims ());
-
-          tmp_lhs.assign (idx, tmp_rhs, Matrix ());
-
-          if (! error_state)
-            resize (tmp_lhs.dims ());
-          else
-            error ("size mismatch in structure assignment");
-        }
-      else
-        {
-          for (octave_idx_type i = 0; i < len; i++)
-            {
-              std::string k = t_keys[i];
-
-              Cell t_rhs = rhs.contents (k);
-
-              assign (idx, k, t_rhs);
-
-              if (error_state)
-                break;
-            }
-        }
-    }
-  else
-    error ("field name mismatch in structure assignment");
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const octave_value_list& idx, const std::string& k,
-                    const Cell& rhs)
-{
-  Cell tmp;
-
-  if (contains (k))
-    tmp = map[k];
-  else
-    tmp = Cell (dimensions);
-
-  tmp.assign (idx, rhs);
-
-  if (! error_state)
-    {
-      dim_vector tmp_dims = tmp.dims ();
-
-      if (tmp_dims != dimensions)
-        {
-          for (iterator p = begin (); p != end (); p++)
-            contents(p).resize (tmp_dims, Matrix ());
-
-          dimensions = tmp_dims;
-        }
-
-      maybe_add_to_key_list (k);
-
-      map[k] = tmp;
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const std::string& k, const octave_value& rhs)
-{
-  if (nfields () == 0)
-    {
-      maybe_add_to_key_list (k);
-
-      map[k] = Cell (rhs);
-
-      dimensions = dim_vector (1, 1);
-    }
-  else
-    {
-      dim_vector dv = dims ();
-
-      if (dv.all_ones ())
-        {
-          maybe_add_to_key_list (k);
-
-          map[k] = Cell (rhs);
-        }
-      else
-        error ("invalid structure assignment");
-    }
-
-  return *this;
-}
-
-Octave_map&
-Octave_map::assign (const std::string& k, const Cell& rhs)
-{
-  if (nfields () == 0)
-    {
-      maybe_add_to_key_list (k);
-
-      map[k] = rhs;
-
-      dimensions = rhs.dims ();
-    }
-  else
-    {
-      if (dims () == rhs.dims ())
-        {
-          maybe_add_to_key_list (k);
-
-          map[k] = rhs;
-        }
-      else
-        error ("invalid structure assignment");
-    }
-
-  return *this;
-}
-
-Octave_map
-Octave_map::index (const octave_value_list& idx, bool resize_ok) const
-{
-  Octave_map retval;
-
-  octave_idx_type n_idx = idx.length ();
-
-  if (n_idx > 0)
-    {
-      Array<idx_vector> ra_idx (dim_vector (n_idx, 1));
-
-      for (octave_idx_type i = 0; i < n_idx; i++)
-        {
-          ra_idx(i) = idx(i).index_vector ();
-          if (error_state)
-            break;
-        }
-
-      if (! error_state)
-        {
-          for (const_iterator p = begin (); p != end (); p++)
-            {
-              Cell tmp = contents (p);
-
-              tmp = tmp.Array<octave_value>::index (ra_idx, resize_ok);
-
-              if (error_state)
-                break;
-
-              retval.assign (key(p), tmp);
-            }
-
-          // Preserve order of keys.
-          retval.key_list = key_list;
-        }
-    }
-  else
-    retval = *this;
-
-  return retval;
-}
--- a/libinterp/corefcn/oct-map.h
+++ b/libinterp/corefcn/oct-map.h
@@ -287,8 +287,6 @@
 
   octave_map (const octave_scalar_map& m);
 
-  octave_map (const Octave_map& m);
-
   octave_map& operator = (const octave_map& m)
   {
     xkeys = m.xkeys;
@@ -475,189 +473,4 @@
 inline octave_map octave_value_extract<octave_map> (const octave_value& v)
 { return v.map_value (); }
 
-// The original Octave_map object which is now deprecated.
-// It was fully deprecated in version 3.8 and should be removed in 3.12.
-// Octave_map and octave_map are convertible to each other.
-
-class
-OCTINTERP_API
-Octave_map
-{
-public:
-
-  typedef std::map<std::string, Cell>::iterator iterator;
-  typedef std::map<std::string, Cell>::const_iterator const_iterator;
-
-  typedef std::list<std::string>::iterator key_list_iterator;
-  typedef std::list<std::string>::const_iterator const_key_list_iterator;
-
-  // Warning!  You should always use at least two dimensions.
-
-  Octave_map (const dim_vector& dv = dim_vector (0, 0),
-              const Cell& key_vals = Cell ());
-
-  Octave_map (const std::string& k, const octave_value& value)
-    : map (), key_list (), dimensions (1, 1)
-  {
-    map[k] = value;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const string_vector& sv,
-              const dim_vector& dv = dim_vector (0, 0))
-    : map (), key_list (), dimensions (dv)
-  {
-    for (octave_idx_type i = 0; i < sv.length (); i++)
-      {
-        std::string k = sv[i];
-        map[k] = Cell (dv);
-        key_list.push_back (k);
-      }
-  }
-
-  Octave_map (const std::string& k, const Cell& vals)
-    : map (), key_list (), dimensions (vals.dims ())
-  {
-    map[k] = vals;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const std::string& k, const octave_value_list& val_list)
-    : map (), key_list (), dimensions (1, val_list.length ())
-  {
-    map[k] = val_list;
-    key_list.push_back (k);
-  }
-
-  Octave_map (const Octave_map& m)
-    : map (m.map), key_list (m.key_list), dimensions (m.dimensions) { }
-
-  Octave_map (const octave_map& m);
-
-  Octave_map& operator = (const Octave_map& m)
-  {
-    if (this != &m)
-      {
-        map = m.map;
-        key_list = m.key_list;
-        dimensions = m.dimensions;
-      }
-
-    return *this;
-  }
-
-  ~Octave_map (void) { }
-
-  Octave_map squeeze (void) const;
-
-  Octave_map permute (const Array<int>& vec, bool inv = false) const;
-
-  // This is the number of keys.
-  octave_idx_type nfields (void) const { return map.size (); }
-
-  void del (const std::string& k)
-  {
-    iterator p = map.find (k);
-
-    if (p != map.end ())
-      {
-        map.erase (p);
-
-        key_list_iterator q
-          = std::find (key_list.begin (), key_list.end (), k);
-
-        assert (q != key_list.end ());
-
-        key_list.erase (q);
-      }
-  }
-
-  iterator begin (void) { return iterator (map.begin ()); }
-  const_iterator begin (void) const { return const_iterator (map.begin ()); }
-
-  iterator end (void) { return iterator (map.end ()); }
-  const_iterator end (void) const { return const_iterator (map.end ()); }
-
-  std::string key (const_iterator p) const { return p->first; }
-
-  Cell& contents (const std::string& k);
-  Cell contents (const std::string& k) const;
-
-  Cell& contents (iterator p)
-  { return p->second; }
-
-  Cell contents (const_iterator p) const
-  { return p->second; }
-
-  int intfield (const std::string& k, int def_val = 0) const;
-
-  std::string stringfield (const std::string& k,
-                           const std::string& def_val = std::string ()) const;
-
-  iterator seek (const std::string& k) { return map.find (k); }
-  const_iterator seek (const std::string& k) const { return map.find (k); }
-
-  bool contains (const std::string& k) const
-  { return (seek (k) != map.end ()); }
-
-  void clear (void)
-  {
-    map.clear ();
-    key_list.clear ();
-  }
-
-  string_vector keys (void) const;
-
-  octave_idx_type rows (void) const { return dimensions(0); }
-
-  octave_idx_type columns (void) const { return dimensions(1); }
-
-  dim_vector dims (void) const { return dimensions; }
-
-  int ndims (void) const { return dimensions.length (); }
-
-  Octave_map transpose (void) const;
-
-  Octave_map reshape (const dim_vector& new_dims) const;
-
-  void resize (const dim_vector& dv, bool fill = false);
-
-  octave_idx_type numel (void) const { return dimensions.numel (); }
-
-  Octave_map concat (const Octave_map& rb,
-                     const Array<octave_idx_type>& ra_idx);
-
-  Octave_map& maybe_delete_elements (const octave_value_list& idx);
-
-  Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs);
-
-  Octave_map& assign (const octave_value_list& idx, const std::string& k,
-                      const Cell& rhs);
-
-  Octave_map& assign (const std::string& k, const octave_value& rhs);
-
-  Octave_map& assign (const std::string& k, const Cell& rhs);
-
-  Octave_map index (const octave_value_list& idx,
-                    bool resize_ok = false) const;
-
-private:
-
-  // The map of names to values.
-  std::map<std::string, Cell> map;
-
-  // An extra list of keys, so we can keep track of the order the keys
-  // are added for compatibility with you know what.
-  std::list<std::string> key_list;
-
-  // The current size.
-  mutable dim_vector dimensions;
-
-  void maybe_add_to_key_list (const std::string& k)
-  {
-    if (! contains (k))
-      key_list.push_back (k);
-  }
-} GCC_ATTR_DEPRECATED;
-
 #endif
--- a/libinterp/corefcn/oct-obj.cc
+++ b/libinterp/corefcn/oct-obj.cc
@@ -35,7 +35,8 @@
 
 octave_value_list::octave_value_list (const std::list<octave_value_list>& lst)
 {
-  octave_idx_type n = 0, nel = 0;
+  octave_idx_type n = 0;
+  octave_idx_type nel = 0;
 
   // Determine number.
   for (std::list<octave_value_list>::const_iterator p = lst.begin ();
--- a/libinterp/corefcn/oct-obj.h
+++ b/libinterp/corefcn/oct-obj.h
@@ -107,10 +107,16 @@
   octave_value_list
   slice (octave_idx_type offset, octave_idx_type len, bool tags = false) const
   {
-    octave_value_list retval (data.linear_slice (offset, offset + len));
+    // linear_slice uses begin/end indices instead of offset and
+    // length.  Avoid calling with upper bound out of range.
+    // linear_slice handles the case of len < 0.
+
+    octave_value_list retval
+      = data.linear_slice (offset, std::min (offset + len, length ()));
+
     if (tags && len > 0 && names.length () > 0)
-      retval.names = names.linear_slice (offset,
-                                         std::min (len, names.length ()));
+      retval.names = names.linear_slice (offset, std::min (offset + len,
+                                                           names.length ()));
 
     return retval;
   }
--- a/libinterp/corefcn/oct-stream.cc
+++ b/libinterp/corefcn/oct-stream.cc
@@ -785,11 +785,14 @@
 
   if (i < n)
     {
+      // Accept and record modifier, but don't place it in the format
+      // item text.  All integer conversions are handled as 64-bit
+      // integers.
+
       switch (s[i])
         {
         case 'h': case 'l': case 'L':
-          modifier = s[i];
-          *buf << s[i++];
+          modifier = s[i++];
           break;
 
         default:
@@ -1053,7 +1056,8 @@
     {
       std::istream& is = *isp;
 
-      int c = 0, lastc = -1;
+      int c = 0;
+      int lastc = -1;
       cnt = 0;
 
       while (is && (c = is.get ()) != EOF)
@@ -2159,7 +2163,7 @@
 
   printf_value_cache (const octave_value_list& args, const std::string& who)
     : values (args), val_idx (0), elt_idx (0),
-      n_vals (values.length ()), n_elts (0), data (0),
+      n_vals (values.length ()), n_elts (0), have_data (false),
       curr_state (ok)
   {
     for (octave_idx_type i = 0; i < values.length (); i++)
@@ -2177,7 +2181,7 @@
   ~printf_value_cache (void) { }
 
   // Get the current value as a double and advance the internal pointer.
-  double double_value (void);
+  octave_value get_next_value (void);
 
   // Get the current value as an int and advance the internal pointer.
   int int_value (void);
@@ -2196,8 +2200,8 @@
   int elt_idx;
   int n_vals;
   int n_elts;
-  const double *data;
-  NDArray curr_val;
+  bool have_data;
+  octave_value curr_val;
   state curr_state;
 
   // Must create value cache with values!
@@ -2211,29 +2215,27 @@
   printf_value_cache& operator = (const printf_value_cache&);
 };
 
-double
-printf_value_cache::double_value (void)
+octave_value
+printf_value_cache::get_next_value (void)
 {
-  double retval = 0.0;
+  octave_value retval;
 
   if (exhausted ())
     curr_state = conversion_error;
 
   while (! exhausted ())
     {
-      if (! data)
+      if (! have_data)
         {
-          octave_value tmp_val = values (val_idx);
+          curr_val = values (val_idx);
 
           // Force string conversion here for compatibility.
 
-          curr_val = tmp_val.array_value (true);
-
           if (! error_state)
             {
               elt_idx = 0;
-              n_elts = curr_val.length ();
-              data = curr_val.data ();
+              n_elts = curr_val.numel ();
+              have_data = true;
             }
           else
             {
@@ -2244,13 +2246,13 @@
 
       if (elt_idx < n_elts)
         {
-          retval = data[elt_idx++];
+          retval = curr_val.fast_elem_extract (elt_idx++);
 
           if (elt_idx >= n_elts)
             {
               elt_idx = 0;
               val_idx++;
-              data = 0;
+              have_data = false;
             }
 
           break;
@@ -2258,7 +2260,7 @@
       else
         {
           val_idx++;
-          data = 0;
+          have_data = false;
 
           if (n_elts == 0 && exhausted ())
             curr_state = conversion_error;
@@ -2275,14 +2277,19 @@
 {
   int retval = 0;
 
-  double dval = double_value ();
+  octave_value val = get_next_value ();
 
   if (! error_state)
     {
-      if (D_NINT (dval) == dval)
-        retval = NINT (dval);
-      else
-        curr_state = conversion_error;
+      double dval = val.double_value ();
+
+      if (! error_state)
+        {
+          if (D_NINT (dval) == dval)
+            retval = NINT (dval);
+          else
+            curr_state = conversion_error;
+        }
     }
 
   return retval;
@@ -2357,27 +2364,202 @@
   return retval;
 }
 
-#define DO_DOUBLE_CONV(TQUAL) \
-  do \
-    { \
-      if (val > std::numeric_limits<TQUAL long>::max () \
-          || val < std::numeric_limits<TQUAL long>::min ()) \
-        { \
-          std::string tfmt = fmt; \
- \
-          tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \
- \
-          if (elt->modifier == 'l') \
-            tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \
- \
-          retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \
-                                    val, who); \
-        } \
-      else \
-        retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \
-                                  static_cast<TQUAL long> (val), who); \
-    } \
-  while (0)
+static bool
+is_nan_or_inf (const octave_value& val)
+{
+  octave_value ov_isnan = val.isnan ();
+  octave_value ov_isinf = val.isinf ();
+
+  return (ov_isnan.is_true () || ov_isinf.is_true ());
+}
+
+static bool
+ok_for_signed_int_conv (const octave_value& val)
+{
+  uint64_t limit = std::numeric_limits<int64_t>::max ();
+
+  if (val.is_integer_type ())
+    {
+      if (val.is_uint64_type ())
+        {
+          octave_uint64 ival = val.uint64_scalar_value ();
+
+          if (ival.value () <= limit)
+            return true;
+        }
+      else
+        return true;
+    }
+  else
+    {
+      double dval = val.double_value ();
+
+      if (dval == xround (dval) && dval <= limit)
+        return true;
+    }
+
+  return false;
+}
+
+static bool
+ok_for_unsigned_int_conv (const octave_value& val)
+{
+  if (val.is_integer_type ())
+    {
+      // Easier than dispatching here...
+
+      octave_value ov_is_ge_zero
+        = do_binary_op (octave_value::op_ge, val, octave_value (0.0));
+
+      return ov_is_ge_zero.is_true ();
+    }
+  else
+    {
+      double dval = val.double_value ();
+
+      uint64_t limit = std::numeric_limits<uint64_t>::max ();
+
+      if (dval == xround (dval) && dval >= 0 && dval <= limit)
+        return true;
+    }
+
+  return false;
+}
+
+static std::string
+switch_to_g_format (const printf_format_elt *elt)
+{
+  std::string tfmt = elt->text;
+
+  tfmt.replace (tfmt.rfind (elt->type), 1, "g");
+
+  return tfmt;
+}
+
+int
+octave_base_stream::do_numeric_printf_conv (std::ostream& os,
+                                            const printf_format_elt *elt,
+                                            int nsa, int sa_1, int sa_2,
+                                            const octave_value& val,
+                                            const std::string& who)
+{
+  int retval = 0;
+
+  const char *fmt = elt->text;
+
+  if (is_nan_or_inf (val))
+    {
+      double dval = val.double_value ();
+
+      std::string tfmt = fmt;
+      std::string::size_type i1, i2;
+
+      tfmt.replace ((i1 = tfmt.rfind (elt->type)),
+                   1, 1, 's');
+
+      if ((i2 = tfmt.rfind ('.')) != std::string::npos
+          && i2 < i1)
+        {
+          tfmt.erase (i2, i1-i2);
+          if (elt->prec < 0)
+            nsa--;
+        }
+
+      const char *tval;
+      if (lo_ieee_isinf (dval))
+        {
+          if (elt->flags.find ('+') != std::string::npos)
+            tval = (dval < 0 ? "-Inf" : "+Inf");
+          else
+            tval = (dval < 0 ? "-Inf" : "Inf");
+        }
+      else
+        {
+          if (elt->flags.find ('+') != std::string::npos)
+            tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN");
+          else
+            tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN");
+        }
+
+      retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, who);
+    }
+  else
+    {
+      static std::string llmod
+        = sizeof (long) == sizeof (int64_t) ? "l" : "ll";
+
+      char type = elt->type;
+
+      switch (type)
+        {
+        case 'd': case 'i': case 'c':
+          if (ok_for_signed_int_conv (val))
+            {
+              octave_int64 tval = val.int64_scalar_value ();
+
+              // Insert "long" modifier.
+              std::string tfmt = fmt;
+              tfmt.replace (tfmt.rfind (type), 1, llmod + type);
+
+              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
+                                        tval.value (), who);
+            }
+          else
+            {
+              std::string tfmt = switch_to_g_format (elt);
+
+              double dval = val.double_value ();
+
+              if (! error_state)
+                retval += do_printf_conv (os, tfmt.c_str (), nsa,
+                                          sa_1, sa_2, dval, who);
+            }
+          break;
+
+        case 'o': case 'x': case 'X': case 'u':
+          if (ok_for_unsigned_int_conv (val))
+            {
+              octave_uint64 tval = val.uint64_scalar_value ();
+
+              // Insert "long" modifier.
+              std::string tfmt = fmt;
+              tfmt.replace (tfmt.rfind (type), 1, llmod + type);
+
+              retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
+                                        tval.value (), who);
+            }
+          else
+            {
+              std::string tfmt = switch_to_g_format (elt);
+
+              double dval = val.double_value ();
+
+              if (! error_state)
+                retval += do_printf_conv (os, tfmt.c_str (), nsa,
+                                          sa_1, sa_2, dval, who);
+            }
+          break;
+
+        case 'f': case 'e': case 'E':
+        case 'g': case 'G':
+          {
+            double dval = val.double_value ();
+
+            if (! error_state)
+              retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, dval, who);
+          }
+          break;
+
+        default:
+          error ("%s: invalid format specifier",
+                 who.c_str ());
+          return -1;
+          break;
+        }
+    }
+
+  return retval;
+}
 
 int
 octave_base_stream::do_printf (printf_format_list& fmt_list,
@@ -2432,8 +2614,6 @@
                     }
                 }
 
-              const char *fmt = elt->text;
-
               if (elt->type == '%')
                 {
                   os << "%";
@@ -2449,77 +2629,18 @@
                   std::string val = val_cache.string_value ();
 
                   if (val_cache)
-                    retval += do_printf_conv (os, fmt, nsa, sa_1,
+                    retval += do_printf_conv (os, elt->text, nsa, sa_1,
                                               sa_2, val.c_str (), who);
                   else
                     break;
                 }
               else
                 {
-                  double val = val_cache.double_value ();
+                  octave_value val = val_cache.get_next_value ();
 
                   if (val_cache)
-                    {
-                      if (lo_ieee_isnan (val) || xisinf (val))
-                        {
-                          std::string tfmt = fmt;
-                          std::string::size_type i1, i2;
-
-                          tfmt.replace ((i1 = tfmt.rfind (elt->type)),
-                                        1, 1, 's');
-
-                          if ((i2 = tfmt.rfind ('.')) != std::string::npos
-                              && i2 < i1)
-                            {
-                              tfmt.erase (i2, i1-i2);
-                              if (elt->prec < 0)
-                                nsa--;
-                            }
-
-                          const char *tval;
-                          if (xisinf (val))
-                            if (elt->flags.find ('+') != std::string::npos)
-                              tval = (val < 0 ? "-Inf" : "+Inf");
-                            else
-                              tval = (val < 0 ? "-Inf" : "Inf");
-                          else
-                            if (elt->flags.find ('+') != std::string::npos)
-                              tval = (lo_ieee_is_NA (val) ? "+NA" : "+NaN");
-                            else
-                              tval = (lo_ieee_is_NA (val) ? "NA" : "NaN");
-
-                          retval += do_printf_conv (os, tfmt.c_str (),
-                                                    nsa, sa_1, sa_2,
-                                                    tval, who);
-                        }
-                      else
-                        {
-                          char type = elt->type;
-
-                          switch (type)
-                            {
-                            case 'd': case 'i': case 'c':
-                              DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG);
-                              break;
-
-                            case 'o': case 'x': case 'X': case 'u':
-                              DO_DOUBLE_CONV (unsigned);
-                              break;
-
-                            case 'f': case 'e': case 'E':
-                            case 'g': case 'G':
-                              retval += do_printf_conv (os, fmt, nsa,
-                                                        sa_1, sa_2, val, who);
-                              break;
-
-                            default:
-                              error ("%s: invalid format specifier",
-                                     who.c_str ());
-                              return -1;
-                              break;
-                            }
-                        }
-                    }
+                    retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
+                                                      sa_2, val, who);
                   else
                     break;
                 }
@@ -3191,8 +3312,7 @@
       if (! error_state)
         {
 
-          octave_idx_type elts_to_read
-            = std::numeric_limits<octave_idx_type>::max ();
+          octave_idx_type elts_to_read;
 
           if (one_elt_size_spec)
             {
@@ -3221,7 +3341,9 @@
                 nr = nc = 0;
             }
 
-          // FIXME: ensure that this does not overflow.
+          // FIXME: Ensure that this does not overflow.
+          //        Maybe try comparing nr * nc computed in double with
+          //        std::numeric_limits<octave_idx_type>::max ();
 
           elts_to_read = nr * nc;
 
--- a/libinterp/corefcn/oct-stream.h
+++ b/libinterp/corefcn/oct-stream.h
@@ -479,6 +479,11 @@
 
   int flush (void);
 
+  int do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt,
+                              int nsa, int sa_1, int sa_2,
+                              const octave_value& val,
+                              const std::string& who);
+
   int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
                  const std::string& who /* = "printf" */);
 
new file mode 100644
--- /dev/null
+++ b/libinterp/corefcn/octave-default-image.h
@@ -0,0 +1,281 @@
+/*
+
+Copyright (C) 2014 Pantxo Diribarne
+
+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/>.
+
+*/
+
+static char default_im_data[] = {
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,20,20,20,20,20,20,21,21,21,21,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,20,20,20,20,20,20,20,20,20,20,20,21,21,
+  21,21,21,21,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,
+  21,21,21,21,21,21,21,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+  21,21,21,21,21,21,21,21,21,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+  20,21,21,21,21,21,21,21,21,21,21,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+  20,20,21,21,21,21,21,21,21,21,21,21,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,
+  20,20,20,20,20,20,20,20,20,20,20,20,31,31,31,31,
+  31,31,31,31,31,31,21,21,21,21,21,21,21,21,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,
+  20,20,20,20,20,20,20,20,20,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,21,21,21,21,21,21,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,20,
+  20,20,20,20,20,20,20,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,21,21,21,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,
+  20,20,20,20,20,20,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,21,
+  21,21,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,20,
+  20,20,20,20,20,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,63,
+  49,49,49,49,49,49,49,49,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,20,20,20,20,20,20,20,20,
+  20,20,20,20,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,48,48,48,48,48,48,49,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,20,20,20,20,20,20,20,20,20,
+  20,20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,19,20,20,20,20,20,20,20,20,
+  20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,20,19,20,20,20,20,20,20,20,
+  20,20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,20,20,20,20,20,20,
+  20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,19,20,20,20,20,20,
+  20,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,47,48,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,19,19,19,20,20,20,
+  19,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  48,47,47,47,47,47,48,48,63,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,19,19,19,19,19,19,20,19,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,49,
+  49,48,48,48,48,48,48,48,21,31,31,31,31,31,31,31,
+  31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,21,21,21,31,31,31,31,31,31,
+  31,31,31,31,31,20,20,20,20,20,20,20,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,21,21,31,31,31,31,31,31,
+  31,31,49,49,49,49,49,49,49,49,49,49,49,49,49,49,
+  49,49,49,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,21,21,31,31,31,31,31,
+  31,49,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
+  48,48,48,49,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,21,21,21,31,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,21,21,21,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,21,21,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,21,31,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,21,21,21,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,21,21,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,21,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  31,49,48,47,47,47,47,47,47,47,47,47,47,47,47,47,
+  47,47,48,49,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  31,49,49,48,48,48,48,48,48,48,48,48,48,48,48,48,
+  48,48,49,63,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,
+  31,31,31,49,49,49,49,49,49,47,63,63,63,63,63,63,
+  63,63,20,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,19,
+  19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,
+  19,19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,
+  19,19,19,19,19,19,19,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,
+  19,19,19,19,19,19,19,19,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,20,20,20,20,20,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,
+  19,19,19,19,19,19,19,19,19,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,49,49,49,49,49,47,63,63,63,21,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,49,48,48,48,48,48,48,48,48,48,48,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,48,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,48,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,19,20,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,20,20,49,47,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,18,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,20,49,47,47,47,47,47,47,47,47,47,47,48,48,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,20,20,49,48,47,47,47,47,47,47,47,47,47,48,49,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,19,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,20,63,48,48,48,48,48,48,48,48,48,48,49,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,19,19,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,20,21,63,63,63,48,49,49,49,49,49,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,19,19,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,20,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,19,19,
+  19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,19,19,19,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
+  19,19,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,
+  31,31,31,31,31,19,19,19,19,19,19,19,19,19,19,31,
+  31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31
+};
+
--- a/libinterp/corefcn/octave-link.cc
+++ b/libinterp/corefcn/octave-link.cc
@@ -225,7 +225,7 @@
       std::string multi_on = args(4).string_value (); // on, off, create
       std::string pathname = args(5).string_value ();
 
-      octave_idx_type nel = flist.numel ();
+      octave_idx_type nel;
       octave_link::filter_list filter_lst;
 
       for (octave_idx_type i = 0; i < flist.rows (); i++)
@@ -432,7 +432,7 @@
 
 DEFUN (__octave_link_show_doc__, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} __octave_link_show_doc__ ( @var{filename} )\n\
+@deftypefn {Built-in Function} {} __octave_link_show_doc__ (@var{filename})\n\
 Undocumented internal function.\n\
 @end deftypefn")
 {
--- a/libinterp/corefcn/pinv.cc
+++ b/libinterp/corefcn/pinv.cc
@@ -76,22 +76,45 @@
 
   if (arg.is_diag_matrix ())
     {
-      if (nargin == 2)
-        warning ("pinv: tol is ignored for diagonal matrices");
-
-      if (arg.is_complex_type ())
+      if (isfloat)
         {
-          if (isfloat)
-            retval = arg.float_complex_diag_matrix_value ().pseudo_inverse ();
+          float tol = 0.0;
+          if (nargin == 2)
+            tol = args(1).float_value ();
+
+          if (error_state)
+            return retval;
+
+          if (tol < 0.0)
+            {
+              error ("pinv: TOL must be greater than zero");
+              return retval;
+            }
+
+          if (arg.is_real_type ())
+            retval = arg.float_diag_matrix_value ().pseudo_inverse (tol);
           else
-            retval = arg.complex_diag_matrix_value ().pseudo_inverse ();
+            retval = arg.float_complex_diag_matrix_value ().pseudo_inverse (tol);
         }
       else
         {
-          if (isfloat)
-            retval = arg.float_diag_matrix_value ().pseudo_inverse ();
+          double tol = 0.0;
+          if (nargin == 2)
+            tol = args(1).double_value ();
+
+          if (error_state)
+            return retval;
+
+          if (tol < 0.0)
+            {
+              error ("pinv: TOL must be greater than zero");
+              return retval;
+            }
+
+          if (arg.is_real_type ())
+            retval = arg.diag_matrix_value ().pseudo_inverse (tol);
           else
-            retval = arg.diag_matrix_value ().pseudo_inverse ();
+            retval = arg.complex_diag_matrix_value ().pseudo_inverse (tol);
         }
     }
   else if (arg.is_perm_matrix ())
@@ -189,4 +212,20 @@
 %!assert (y*x*y, y, -hitol)
 %!assert ((x*y)', x*y, hitol)
 %!assert ((y*x)', y*x, hitol)
+
+## Clear shared variables
+%!shared
+
+## Test pinv for Diagonal matrices
+%!test
+%! x = diag ([3 2 1 0 -0.5]);
+%! y = pinv (x);
+%! assert (typeinfo (y)(1:8), "diagonal");
+%! assert (isa (y, "double"));
+%! assert (diag (y), [1/3, 1/2, 1, 0  1/-0.5]');
+%! y = pinv (x, 1);
+%! assert (diag (y), [1/3 1/2 1 0 0]');
+%! y = pinv (x, 2);
+%! assert (diag (y), [1/3 1/2 0 0 0]');
+
 */
--- a/libinterp/corefcn/pr-output.cc
+++ b/libinterp/corefcn/pr-output.cc
@@ -581,13 +581,11 @@
         {
           ld = digits;
           rd = prec > digits ? prec - digits : prec;
-          digits++;
         }
       else
         {
           ld = 1;
           rd = prec > digits ? prec - digits : prec;
-          digits = -digits + 1;
         }
 
       fw = 1 + ld + 1 + rd;
@@ -3387,8 +3385,7 @@
 }
 
 void
-octave_print_internal (std::ostream&, const octave_value&,
-                       bool pr_as_read_syntax)
+octave_print_internal (std::ostream&, const octave_value&, bool)
 {
   panic_impossible ();
 }
@@ -3439,7 +3436,7 @@
               rat_format = true;
 
               std::ostringstream buf;
-              args(0).print (buf);
+              arg.print (buf);
               std::string s = buf.str ();
 
               std::list<std::string> lst;
@@ -3501,11 +3498,12 @@
 
   if (nargin == 1 && nargout < 2)
     {
+      octave_value arg = args(0);
+
       if (nargout == 0)
-        args(0).print (octave_stdout);
+        arg.print (octave_stdout);
       else
         {
-          octave_value arg = args(0);
           std::ostringstream buf;
           arg.print (buf);
           retval = octave_value (buf.str (), arg.is_dq_string () ? '"' : '\'');
@@ -3542,7 +3540,7 @@
 
   if (nargin == 2)
     {
-      int fid = octave_stream_list::get_file_number (args (0));
+      int fid = octave_stream_list::get_file_number (args(0));
 
       octave_stream os = octave_stream_list::lookup (fid, "fdisp");
 
@@ -3550,8 +3548,10 @@
         {
           std::ostream *osp = os.output_stream ();
 
+          octave_value arg = args(1);
+
           if (osp)
-            args(1).print (*osp);
+            arg.print (*osp);
           else
             error ("fdisp: stream FID not open for writing");
         }
@@ -3612,20 +3612,25 @@
   Voutput_max_field_width = fw;
 }
 
+static std::string format_string ("short");
+
 static void
 set_format_style (int argc, const string_vector& argv)
 {
   int idx = 1;
+  std::string format;
 
   if (--argc > 0)
     {
       std::string arg = argv[idx++];
+      format = arg;
 
       if (arg == "short")
         {
           if (--argc > 0)
             {
               arg = argv[idx++];
+              format.append (arg);
 
               if (arg == "e")
                 {
@@ -3666,11 +3671,44 @@
 
           set_output_prec_and_fw (5, 10);
         }
+      else if (arg == "shorte")
+        {
+          init_format_state ();
+          print_e = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortE")
+        {
+          init_format_state ();
+          print_e = true;
+          print_big_e = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortg")
+        {
+          init_format_state ();
+          print_g = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortG")
+        {
+          init_format_state ();
+          print_g = true;
+          print_big_e = true;
+          set_output_prec_and_fw (5, 10);
+        }
+      else if (arg == "shortEng")
+        {
+          init_format_state ();
+          print_eng = true;
+          set_output_prec_and_fw (5, 10);
+        }
       else if (arg == "long")
         {
           if (--argc > 0)
             {
               arg = argv[idx++];
+              format.append (arg);
 
               if (arg == "e")
                 {
@@ -3711,6 +3749,38 @@
 
           set_output_prec_and_fw (15, 20);
         }
+      else if (arg == "longe")
+        {
+          init_format_state ();
+          print_e = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longE")
+        {
+          init_format_state ();
+          print_e = true;
+          print_big_e = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longg")
+        {
+          init_format_state ();
+          print_g = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longG")
+        {
+          init_format_state ();
+          print_g = true;
+          print_big_e = true;
+          set_output_prec_and_fw (15, 20);
+        }
+      else if (arg == "longEng")
+        {
+          init_format_state ();
+          print_eng = true;
+          set_output_prec_and_fw (15, 20);
+        }
       else if (arg == "hex")
         {
           init_format_state ();
@@ -3736,6 +3806,7 @@
           if (--argc > 0)
             {
               arg = argv[idx++];
+              format.append (arg);
 
               if (arg.length () == 3)
                 plus_format_chars = arg;
@@ -3774,21 +3845,30 @@
       else if (arg == "compact")
         {
           Vcompact_format = true;
+          return;
         }
       else if (arg == "loose")
         {
           Vcompact_format = false;
+          return;
         }
       else
-        error ("format: unrecognized format state '%s'", arg.c_str ());
+        {
+          error ("format: unrecognized format state '%s'", arg.c_str ());
+          return;
+        }  
     }
   else
     {
       init_format_state ();
       set_output_prec_and_fw (5, 10);
+      format = std::string ("short");
     }
+
+  format_string = format;
 }
 
+
 DEFUN (format, args, ,
        "-*- texinfo -*-\n\
 @deftypefn  {Command} {} format\n\
@@ -3973,6 +4053,25 @@
   return retval;
 }
 
+DEFUN (__compactformat__, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} __compactformat__ ()\n\
+@deftypefnx {Built-in Function} {} __compactformat__ (@var{TRUE|FALSE})\n\
+Undocumented internal function\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (compact_format);
+}
+
+DEFUN (__formatstring__, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} __formatstring__ ()\n\
+Undocumented internal function\n\
+@end deftypefn")
+{
+  return ovl (format_string);
+}
+
 DEFUN (fixed_point_format, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} fixed_point_format ()\n\
--- a/libinterp/corefcn/pt-jit.cc
+++ b/libinterp/corefcn/pt-jit.cc
@@ -46,6 +46,8 @@
 
 static int Vjit_startcnt = 1000;
 
+static int Vjit_failure_count = 0;
+
 #include <llvm/Analysis/CallGraph.h>
 #include <llvm/Analysis/Passes.h>
 #include <llvm/Analysis/Verifier.h>
@@ -164,7 +166,7 @@
       if (expr)
         {
           jit_variable *retvar = get_variable ("#return");
-          jit_value *retval;
+          jit_value *retval = 0;
           try
             {
               retval = visit (expr);
@@ -230,13 +232,13 @@
 void
 jit_convert::visit_anon_fcn_handle (tree_anon_fcn_handle&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_anon_fcn_handle implementation");
 }
 
 void
 jit_convert::visit_argument_list (tree_argument_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_argument_list implementation");
 }
 
 void
@@ -337,25 +339,25 @@
 void
 jit_convert::visit_global_command (tree_global_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_global_command implemenation");
 }
 
 void
 jit_convert::visit_persistent_command (tree_persistent_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_persistent_command implementation");
 }
 
 void
 jit_convert::visit_decl_elt (tree_decl_elt&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_decl_elt implementation");
 }
 
 void
 jit_convert::visit_decl_init_list (tree_decl_init_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_decl_init_list implementation");
 }
 
 void
@@ -464,37 +466,37 @@
 void
 jit_convert::visit_complex_for_command (tree_complex_for_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_complex_for_command implementation");
 }
 
 void
 jit_convert::visit_octave_user_script (octave_user_script&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_script implementation");
 }
 
 void
 jit_convert::visit_octave_user_function (octave_user_function&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_function implementation");
 }
 
 void
 jit_convert::visit_octave_user_function_header (octave_user_function&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_function_header implementation");
 }
 
 void
 jit_convert::visit_octave_user_function_trailer (octave_user_function&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_octave_user_function_trailer implementation");
 }
 
 void
 jit_convert::visit_function_def (tree_function_def&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_function_def implementation");
 }
 
 void
@@ -518,7 +520,7 @@
 void
 jit_convert::visit_if_clause (tree_if_clause&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_if_clause implementation");
 }
 
 void
@@ -539,7 +541,6 @@
   // the condition check for the ith clause. For the else, it is simple the
   // else body. If there is no else body, then it is padded with the tail
   std::vector<jit_block *> entry_blocks (lst.size () + 1 - last_else);
-  std::vector<jit_block *> branch_blocks (lst.size (), 0); // final blocks
   entry_blocks[0] = block;
 
   // we need to construct blocks first, because they have jumps to eachother
@@ -630,25 +631,25 @@
 void
 jit_convert::visit_matrix (tree_matrix&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_matrix implementation");
 }
 
 void
 jit_convert::visit_cell (tree_cell&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_cell implementation");
 }
 
 void
 jit_convert::visit_multi_assignment (tree_multi_assignment&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_multi_assignment implementation");
 }
 
 void
 jit_convert::visit_no_op_command (tree_no_op_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_no_op_command implementation");
 }
 
 void
@@ -679,13 +680,19 @@
 void
 jit_convert::visit_fcn_handle (tree_fcn_handle&)
 {
+  throw jit_fail_exception ("No visit_fcn_handle implementation");
+}
+
+void
+jit_convert::visit_funcall (tree_funcall&)
+{
   throw jit_fail_exception ();
 }
 
 void
 jit_convert::visit_parameter_list (tree_parameter_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_parameter_list implementation");
 }
 
 void
@@ -721,13 +728,13 @@
 void
 jit_convert::visit_return_command (tree_return_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_return_command implementation");
 }
 
 void
 jit_convert::visit_return_list (tree_return_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_return_list implementation");
 }
 
 void
@@ -805,31 +812,132 @@
 void
 jit_convert::visit_switch_case (tree_switch_case&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_switch_case implementation");
 }
 
 void
 jit_convert::visit_switch_case_list (tree_switch_case_list&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_switch_case_list implementation");
 }
 
 void
-jit_convert::visit_switch_command (tree_switch_command&)
+jit_convert::visit_switch_command (tree_switch_command& cmd)
 {
-  throw jit_fail_exception ();
+  tree_switch_case_list *lst = cmd.case_list ();
+
+  // always visit switch expression
+  tree_expression *expr = cmd.switch_value ();
+  assert (expr && "Switch value can not be null");
+  jit_value *value = visit (expr);
+  assert (value);
+
+  size_t case_blocks_num = lst->size ();
+
+  if (! case_blocks_num)  // there's nothing to do
+    return;
+
+  // check for otherwise, it's interpreted as last 'else' condition
+  size_t has_otherwise = 0;
+  tree_switch_case *last = lst->back ();
+  if (last->is_default_case ())
+    has_otherwise = 1;
+
+  std::vector<jit_block *> entry_blocks (case_blocks_num + 1 - has_otherwise);
+
+  // the first entry point is always the actual block. afterward new blocks
+  // are created for every case and the otherwise branch
+  entry_blocks[0] = block;
+  for (size_t i = 1; i < case_blocks_num; ++i)
+    entry_blocks[i] = factory.create<jit_block> ("case_cond");
+
+  jit_block *tail = factory.create<jit_block> ("switch_tail");
+
+  // if there's no otherwise branch, the the 'else' of the last branch
+  // has to point to the tail
+  if (! has_otherwise)
+    entry_blocks[entry_blocks.size()-1] = tail;
+
+  // each branch in the case statement will have different breaks/continues
+  block_list current_breaks = breaks;
+  block_list current_continues = continues;
+  breaks.clear ();
+  continues.clear ();
+
+  size_t num_incomming = 0; // number of incomming blocks to our tail
+
+  tree_switch_case_list::iterator iter = lst->begin ();
+  for (size_t i = 0; i < case_blocks_num; ++iter, ++i)
+    {
+      tree_switch_case *twc = *iter;
+      block = entry_blocks[i]; // case_cond
+      assert (block);
+
+      if (i)
+        blocks.push_back (entry_blocks[i]);  // first block already pushed
+
+      if (! twc->is_default_case ())
+        {
+          // compare result of switch expression with actual case label
+          tree_expression *te = twc->case_label ();
+          jit_value *label = visit (te);
+          assert(label);
+
+          const jit_operation& fn = jit_typeinfo::binary_op (octave_value::op_eq);
+          jit_value *cond = create_checked (fn, value, label);
+          assert(cond);
+
+          jit_call *check = create_checked (&jit_typeinfo::logically_true,
+                                            cond);
+
+          jit_block *body = factory.create<jit_block> ("case_body");
+          blocks.push_back (body);
+
+          block->append (factory.create<jit_cond_branch> (check, body,
+                                                          entry_blocks[i+1]));
+          block = body; // case_body
+        }
+
+      tree_statement_list *stmt_lst = twc->commands ();
+      assert(stmt_lst);
+
+      try
+        {
+          stmt_lst->accept (*this);
+          num_incomming++;
+          block->append (factory.create<jit_branch> (tail));
+        }
+      catch (const jit_break_exception&)
+        { }
+
+      // each branch in the case statement will have different breaks/continues
+      current_breaks.splice (current_breaks.end (), breaks);
+      current_continues.splice (current_continues.end (), continues);
+    }
+
+  // each branch in the case statement will have different breaks/continues
+  breaks.splice (breaks.end (), current_breaks);
+  continues.splice (continues.end (), current_continues);
+
+  if (num_incomming || ! has_otherwise)
+    {
+      blocks.push_back (tail);
+      block = tail; // switch_tail
+    }
+  else
+    throw jit_break_exception ();   // every branch broke
 }
 
 void
 jit_convert::visit_try_catch_command (tree_try_catch_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_try_catch_command implementation");
 }
 
 void
 jit_convert::visit_unwind_protect_command (tree_unwind_protect_command&)
 {
-  throw jit_fail_exception ();
+  throw jit_fail_exception ("No visit_unwind_protect_command implementation");
 }
 
 void
@@ -895,9 +1003,66 @@
 }
 
 void
-jit_convert::visit_do_until_command (tree_do_until_command&)
+jit_convert::visit_do_until_command (tree_do_until_command& duc)
 {
-  throw jit_fail_exception ();
+  unwind_protect prot;
+  prot.protect_var (breaks);
+  prot.protect_var (continues);
+  breaks.clear ();
+  continues.clear ();
+
+  jit_block *body = factory.create<jit_block> ("do_until_body");
+  jit_block *cond_check = factory.create<jit_block> ("do_until_cond_check");
+  jit_block *tail = factory.create<jit_block> ("do_until_tail");
+
+  block->append (factory.create<jit_branch> (body));
+  blocks.push_back (body);
+  block = body;
+
+  tree_statement_list *loop_body = duc.body ();
+  bool all_breaking = false;
+  if (loop_body)
+    {
+      try
+        {
+          loop_body->accept (*this);
+        }
+      catch (const jit_break_exception&)
+        {
+          all_breaking = true;
+        }
+    }
+
+  finish_breaks (tail, breaks);
+
+  if (! all_breaking || continues.size ())
+    {
+      jit_block *interrupt_check
+        = factory.create<jit_block> ("interrupt_check");
+      blocks.push_back (interrupt_check);
+      finish_breaks (interrupt_check, continues);
+      if (! all_breaking)
+        block->append (factory.create<jit_branch> (interrupt_check));
+
+      block = interrupt_check;
+      jit_error_check *ec
+        = factory.create<jit_error_check> (jit_error_check::var_interrupt,
+                                           cond_check, final_block);
+      block->append (ec);
+
+      blocks.push_back (cond_check);
+      block = cond_check;
+
+      tree_expression *expr = duc.condition ();
+      assert (expr && "Do-Until expression can not be null");
+      jit_value *check = visit (expr);
+      check = create_checked (&jit_typeinfo::logically_true, check);
+
+      block->append (factory.create<jit_cond_branch> (check, tail, body));
+    }
+
+  blocks.push_back (tail);
+  block = tail;
 }
 
 void
@@ -2123,6 +2288,8 @@
             std::cout << "jit fail: " << e.what () << std::endl;
         }
 
+      Vjit_failure_count++;
+
       wrapper.erase ();
       raw_fn.erase ();
     }
@@ -2279,6 +2446,9 @@
           if (e.known ())
             std::cout << "jit fail: " << e.what () << std::endl;
         }
+
+      Vjit_failure_count++;
+
     }
 
   if (llvm_function)
@@ -2314,6 +2484,29 @@
 
 #endif
 
+
+DEFUN (jit_failure_count, args, nargout,
+       "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} jit_failure_count ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} jit_failure_count (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} jit_failure_count (@var{new_val}, \"local\")\n\
+Query or set the internal variable that counts the number of\n\
+JIT fail exceptions for Octave's JIT compiler.\n\
+\n\
+When called from inside a function with the @qcode{\"local\"} option, the\n\
+variable is changed locally for the function and any subroutines it calls.  \n\
+The original variable value is restored when exiting the function.\n\
+@seealso{jit_enable, jit_startcnt, debug_jit}\n\
+@end deftypefn")
+{
+#if defined (HAVE_LLVM)
+  return SET_INTERNAL_VARIABLE (jit_failure_count);
+#else
+  warning ("jit_failure_count: JIT compiling not available in this version of Octave");
+  return octave_value ();
+#endif
+}
+
 DEFUN (debug_jit, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} debug_jit ()\n\
--- a/libinterp/corefcn/pt-jit.h
+++ b/libinterp/corefcn/pt-jit.h
@@ -129,6 +129,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/corefcn/qz.cc
+++ b/libinterp/corefcn/qz.cc
@@ -928,7 +928,7 @@
                   std::cout << "  single gen eig:" << std::endl;
                   std::cout << "  alphar(" << jj << ") = " << aa(jj,jj)
                             << std::endl;
-                  std::cout << "  betar( " << jj << ") = " << bb(jj,jj)
+                  std::cout << "  betar(" << jj << ") = " << bb(jj,jj)
                             << std::endl;
                   std::cout << "  alphai(" << jj << ") = 0" << std::endl;
 #endif
@@ -1277,9 +1277,9 @@
 %! [aa, bb, q, z, v, w, lambda] = qz (a, b);
 %! sz = length (lambda);
 %! observed = (b * v * diag ([lambda;0])) (:, 1:sz);
-%! assert ( (a*v) (:, 1:sz), observed, norm (observed) * 1e-14);
+%! assert ((a*v)(:, 1:sz), observed, norm (observed) * 1e-14);
 %! observed = (diag ([lambda;0]) * w' * b) (1:sz, :);
-%! assert ( (w'*a) (1:sz, :) , observed, norm (observed) * 1e-13);
+%! assert ((w'*a)(1:sz, :) , observed, norm (observed) * 1e-13);
 %! assert (q * a * z, aa, norm (aa) * 1e-14);
 %! assert (q * b * z, bb, norm (bb) * 1e-14);
 
--- a/libinterp/corefcn/rand.cc
+++ b/libinterp/corefcn/rand.cc
@@ -577,7 +577,7 @@
 Reference: G. Marsaglia and W.W. Tsang,\n\
 @cite{Ziggurat Method for Generating Random Variables},\n\
 J. Statistical Software, vol 5, 2000,\n\
-@url{http://www.jstatsoft.org/v05/i08/})\n\
+@url{http://www.jstatsoft.org/v05/i08/}\n\
 \n\
 @seealso{rand, rande, randg, randp}\n\
 @end deftypefn")
@@ -648,7 +648,7 @@
 Reference: G. Marsaglia and W.W. Tsang,\n\
 @cite{Ziggurat Method for Generating Random Variables},\n\
 J. Statistical Software, vol 5, 2000,\n\
-@url{http://www.jstatsoft.org/v05/i08/})\n\
+@url{http://www.jstatsoft.org/v05/i08/}\n\
 \n\
 @seealso{rand, randn, randg, randp}\n\
 @end deftypefn")
--- a/libinterp/corefcn/sparse-xdiv.cc
+++ b/libinterp/corefcn/sparse-xdiv.cc
@@ -302,7 +302,7 @@
   using std::min;
   const octave_idx_type nc = min (d_nr, a_nc);
 
-  if ( ! mx_div_conform (a, d))
+  if (! mx_div_conform (a, d))
     return RT ();
 
   const octave_idx_type nz = a.nnz ();
@@ -569,7 +569,7 @@
   using std::min;
   const octave_idx_type nr = min (d_nc, a_nr);
 
-  if ( ! mx_leftdiv_conform (d, a))
+  if (! mx_leftdiv_conform (d, a))
     return RT ();
 
   const octave_idx_type nz = a.nnz ();
--- a/libinterp/corefcn/sparse.cc
+++ b/libinterp/corefcn/sparse.cc
@@ -113,7 +113,7 @@
 
   if (nargin == 1)
     {
-      octave_value arg = args (0);
+      octave_value arg = args(0);
       if (arg.is_bool_type ())
         retval = arg.sparse_bool_matrix_value ();
       else if (arg.is_complex_type ())
@@ -156,7 +156,8 @@
 
       if (! error_state)
         {
-          octave_idx_type m = -1, n = -1, nzmax = -1;
+          octave_idx_type m, n, nzmax;
+          m = n = nzmax = -1;
           if (nargin == 6)
             {
               nzmax = args(5).idx_type_value ();
--- a/libinterp/corefcn/sqrtm.cc
+++ b/libinterp/corefcn/sqrtm.cc
@@ -101,7 +101,8 @@
 
   typedef typename Matrix::element_type real_type;
 
-  real_type cutoff = 0, one = 1;
+  real_type cutoff = 0;
+  real_type one = 1;
   real_type eps = std::numeric_limits<real_type>::epsilon ();
 
   if (! iscomplex)
--- a/libinterp/corefcn/str2double.cc
+++ b/libinterp/corefcn/str2double.cc
@@ -45,7 +45,7 @@
 static double
 single_num (std::istringstream& is)
 {
-  double num;
+  double num = 0.0;
 
   char c = is.peek ();
 
@@ -60,7 +60,8 @@
     {
       // It's infinity.
       is.get ();
-      char c1 = is.get (), c2 = is.get ();
+      char c1 = is.get ();
+      char c2 = is.get ();
       if (std::tolower (c1) == 'n' && std::tolower (c2) == 'f')
         {
           num = octave_Inf;
--- a/libinterp/corefcn/strfind.cc
+++ b/libinterp/corefcn/strfind.cc
@@ -209,7 +209,8 @@
 
   if (nargin == 2)
     {
-      octave_value argstr = args(0), argpat = args(1);
+      octave_value argstr = args(0);
+      octave_value argpat = args(1);
       if (argpat.is_string ())
         {
           Array<char> needle = argpat.char_array_value ();
@@ -279,7 +280,9 @@
 {
   Array<char> ret = str;
 
-  octave_idx_type siz = str.numel (), psiz = pat.numel (), rsiz = rep.numel ();
+  octave_idx_type siz = str.numel ();
+  octave_idx_type psiz = pat.numel ();
+  octave_idx_type rsiz = rep.numel ();
 
   if (psiz != 0)
     {
@@ -312,7 +315,8 @@
             retsiz = siz + nidx * (rsiz - psiz);
 
           ret.clear (dim_vector (1, retsiz));
-          const char *src = str.data (), *reps = rep.data ();
+          const char *src = str.data ();
+          const char *reps = rep.data ();
           char *dest = ret.fortran_vec ();
 
           octave_idx_type k = 0;
@@ -380,7 +384,9 @@
 
   if (nargin == 3)
     {
-      octave_value argstr = args(0), argpat = args(1), argrep = args(2);
+      octave_value argstr = args(0);
+      octave_value argpat = args(1);
+      octave_value argrep = args(2);
       if (argpat.is_string () && argrep.is_string ())
         {
           const Array<char> pat = argpat.char_array_value ();
--- a/libinterp/corefcn/strfns.cc
+++ b/libinterp/corefcn/strfns.cc
@@ -585,7 +585,7 @@
 
   if (args.length () == 2)
     {
-      retval = do_strcmp_fun (args (0), args (1), 0,
+      retval = do_strcmp_fun (args(0), args(1), 0,
                               "strcmp", strcmp_array_op, strcmp_str_op);
     }
   else
@@ -647,7 +647,8 @@
 strncmp_array_op (const charNDArray& s1, const charNDArray& s2,
                   octave_idx_type n)
 {
-  octave_idx_type l1 = s1.numel (), l2 = s2.numel ();
+  octave_idx_type l1 = s1.numel ();
+  octave_idx_type l2 = s2.numel ();
   return (n > 0 && n <= l1 && n <= l2
           && std::equal (s1.data (), s1.data () + n, s2.data ()));
 }
@@ -658,7 +659,8 @@
 static bool
 strncmp_str_op (const std::string& s1, const std::string& s2, octave_idx_type n)
 {
-  octave_idx_type l1 = s1.length (), l2 = s2.length ();
+  octave_idx_type l1 = s1.length ();
+  octave_idx_type l2 = s2.length ();
   return (n > 0 && n <= l1 && n <= l2
           && std::equal (s1.data (), s1.data () + n, s2.data ()));
 }
@@ -781,7 +783,7 @@
 
   if (args.length () == 2)
     {
-      retval = do_strcmp_fun (args (0), args (1), 0,
+      retval = do_strcmp_fun (args(0), args(1), 0,
                               "strcmpi", strcmpi_array_op, strcmpi_str_op);
     }
   else
@@ -799,7 +801,8 @@
 strncmpi_array_op (const charNDArray& s1, const charNDArray& s2,
                    octave_idx_type n)
 {
-  octave_idx_type l1 = s1.numel (), l2 = s2.numel ();
+  octave_idx_type l1 = s1.numel ();
+  octave_idx_type l2 = s2.numel ();
   return (n > 0 && n <= l1 && n <= l2
           && std::equal (s1.data (), s1.data () + n, s2.data (),
                          icmp_char_eq ()));
@@ -810,7 +813,8 @@
 strncmpi_str_op (const std::string& s1, const std::string& s2,
                  octave_idx_type n)
 {
-  octave_idx_type l1 = s1.length (), l2 = s2.length ();
+  octave_idx_type l1 = s1.length ();
+  octave_idx_type l2 = s2.length ();
   return (n > 0 && n <= l1 && n <= l2
           && std::equal (s1.data (), s1.data () + n, s2.data (),
                          icmp_char_eq ()));
--- a/libinterp/corefcn/symtab.cc
+++ b/libinterp/corefcn/symtab.cc
@@ -38,6 +38,7 @@
 #include "dirfns.h"
 #include "input.h"
 #include "load-path.h"
+#include "ov-classdef.h"
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
@@ -149,6 +150,24 @@
   return retval;
 }
 
+static void
+split_name_with_package (const std::string& name, std::string& fname,
+                         std::string& pname)
+{
+  size_t pos = name.rfind ('.');
+
+  fname.clear ();
+  pname.clear ();
+
+  if (pos != std::string::npos)
+    {
+      fname = name.substr (pos + 1);
+      pname = name.substr (0, pos);
+    }
+  else
+    fname = name;
+}
+
 // Check the load path to see if file that defined this is still
 // visible.  If the file is no longer visible, then erase the
 // definition and move on.  If the file is visible, then we also
@@ -165,11 +184,13 @@
 static inline bool
 load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
                       octave_value& function,
-                      const std::string& dispatch_type = std::string ())
+                      const std::string& dispatch_type = std::string (),
+                      const std::string& package_name = std::string ())
 {
   bool retval = false;
 
-  octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type);
+  octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type,
+                                             package_name);
 
   if (fcn)
     {
@@ -206,11 +227,13 @@
 
               bool relative = check_relative && fcn->is_relative ();
 
-              if (tc < Vlast_prompt_time
+              if (tc <= Vlast_prompt_time
                   || (relative && tc < Vlast_chdir_time))
                 {
                   bool clear_breakpoints = false;
                   std::string nm = fcn->name ();
+                  std::string pack = fcn->package_name ();
+                  std::string canonical_nm = fcn->canonical_name ();
 
                   bool is_same_file = false;
 
@@ -235,10 +258,13 @@
                           if (! dispatch_type.empty ())
                             {
                               file = load_path::find_method (dispatch_type, nm,
-                                                             dir_name);
+                                                             dir_name, pack);
 
                               if (file.empty ())
                                 {
+                                  std::string s_name;
+                                  std::string s_pack;
+
                                   const std::list<std::string>& plist
                                     = symbol_table::parent_classes (dispatch_type);
                                   std::list<std::string>::const_iterator it
@@ -246,10 +272,17 @@
 
                                   while (it != plist.end ())
                                     {
+                                      split_name_with_package (*it, s_name,
+                                                               s_pack);
+
                                       file = load_path::find_method (*it, nm,
-                                                                     dir_name);
+                                                                     dir_name,
+                                                                     s_pack);
                                       if (! file.empty ())
-                                        break;
+                                        {
+                                          pack = s_pack;
+                                          break;
+                                        }
 
                                       it++;
                                     }
@@ -261,7 +294,7 @@
                             file = lookup_autoload (nm);
 
                           if (file.empty ())
-                            file = load_path::find_fcn (nm, dir_name);
+                            file = load_path::find_fcn (nm, dir_name, pack);
                         }
 
                       if (! file.empty ())
@@ -303,7 +336,8 @@
                                 {
                                   retval = load_out_of_date_fcn (ff, dir_name,
                                                                  function,
-                                                                 dispatch_type);
+                                                                 dispatch_type,
+                                                                 pack);
 
                                   clear_breakpoints = true;
                                 }
@@ -322,7 +356,7 @@
                       // place of the old.
 
                       retval = load_out_of_date_fcn (file, dir_name, function,
-                                                     dispatch_type);
+                                                     dispatch_type, pack);
 
                       clear_breakpoints = true;
                     }
@@ -330,7 +364,8 @@
                   // If the function has been replaced then clear any
                   // breakpoints associated with it
                   if (clear_breakpoints)
-                    bp_table::remove_all_breakpoints_in_file (nm, true);
+                    bp_table::remove_all_breakpoints_in_file (canonical_nm,
+                                                              true);
                 }
             }
         }
@@ -383,11 +418,13 @@
 
   std::string dir_name;
 
-  std::string file_name = load_path::find_method (name, name, dir_name);
+  std::string file_name = load_path::find_method (name, name, dir_name,
+                                                  package_name);
 
   if (! file_name.empty ())
     {
-      octave_function *fcn = load_fcn_from_file (file_name, dir_name, name);
+      octave_function *fcn = load_fcn_from_file (file_name, dir_name, name,
+                                                 package_name);
 
       if (fcn)
         {
@@ -396,6 +433,31 @@
           class_constructors[name] = retval;
         }
     }
+  else
+    {
+      // Classdef constructors can be defined anywhere in the path, not
+      // necessarily in @-folders. Look for a normal function and load it.
+      // If the loaded function is a classdef constructor, store it as such
+      // and restore function_on_path to its previous value.
+
+      octave_value old_function_on_path = function_on_path;
+
+      octave_value maybe_cdef_ctor = find_user_function ();
+
+      if (maybe_cdef_ctor.is_defined ())
+        {
+          octave_function *fcn = maybe_cdef_ctor.function_value (true);
+
+          if (fcn && fcn->is_classdef_constructor ())
+            {
+              retval = maybe_cdef_ctor;
+
+              class_constructors[name] = retval;
+
+              function_on_path = old_function_on_path;
+            }
+        }
+    }
 
   return retval;
 }
@@ -406,47 +468,57 @@
 {
   octave_value retval;
 
-  if (name == dispatch_type)
+  if (full_name () == dispatch_type)
     retval = load_class_constructor ();
   else
     {
-      std::string dir_name;
+      octave_function *cm = cdef_manager::find_method_symbol (name,
+                                                              dispatch_type);
 
-      std::string file_name = load_path::find_method (dispatch_type, name,
-                                                      dir_name);
+      if (cm)
+        retval = octave_value (cm);
 
-      if (! file_name.empty ())
+      if (! retval.is_defined ())
         {
-          octave_function *fcn = load_fcn_from_file (file_name, dir_name,
-                                                     dispatch_type);
+          std::string dir_name;
 
-          if (fcn)
+          std::string file_name = load_path::find_method (dispatch_type, name,
+                                                          dir_name);
+
+          if (! file_name.empty ())
             {
-              retval = octave_value (fcn);
+              octave_function *fcn = load_fcn_from_file (file_name, dir_name,
+                                                         dispatch_type);
 
-              class_methods[dispatch_type] = retval;
-            }
-        }
+              if (fcn)
+                {
+                  retval = octave_value (fcn);
 
-      if (retval.is_undefined ())
-        {
-          // Search parent classes
+                  class_methods[dispatch_type] = retval;
+                }
+            }
 
-          const std::list<std::string>& plist = parent_classes (dispatch_type);
-
-          std::list<std::string>::const_iterator it = plist.begin ();
-
-          while (it != plist.end ())
+          if (retval.is_undefined ())
             {
-              retval = find_method (*it);
+              // Search parent classes
 
-              if (retval.is_defined ())
+              const std::list<std::string>& plist =
+                parent_classes (dispatch_type);
+
+              std::list<std::string>::const_iterator it = plist.begin ();
+
+              while (it != plist.end ())
                 {
-                  class_methods[dispatch_type] = retval;
-                  break;
+                  retval = find_method (*it);
+
+                  if (retval.is_defined ())
+                    {
+                      class_methods[dispatch_type] = retval;
+                      break;
+                    }
+
+                  it++;
                 }
-
-              it++;
             }
         }
     }
@@ -787,6 +859,13 @@
   if (fcn.is_defined ())
     return fcn;
 
+  // Package
+
+  fcn = find_package ();
+
+  if (fcn.is_defined ())
+    return fcn;
+
   // Built-in function (might be undefined).
 
   return built_in_function;
@@ -975,7 +1054,7 @@
 
           std::string dir_name = file_name.substr (0, pos);
 
-          octave_function *fcn = load_fcn_from_file (file_name, dir_name,
+          octave_function *fcn = load_fcn_from_file (file_name, dir_name, "",
                                                      "", name, true);
 
           if (fcn)
@@ -998,11 +1077,13 @@
     {
       std::string dir_name;
 
-      std::string file_name = load_path::find_fcn (name, dir_name);
+      std::string file_name = load_path::find_fcn (name, dir_name,
+                                                   package_name);
 
       if (! file_name.empty ())
         {
-          octave_function *fcn = load_fcn_from_file (file_name, dir_name);
+          octave_function *fcn = load_fcn_from_file (file_name, dir_name, "",
+                                                     package_name);
 
           if (fcn)
             function_on_path = octave_value (fcn);
@@ -1012,6 +1093,25 @@
   return function_on_path;
 }
 
+octave_value
+symbol_table::fcn_info::fcn_info_rep::find_package (void)
+{
+  // FIXME: implement correct way to check out of date package
+  //if (package.is_defined ())
+  //  out_of_date_check (package);
+
+  if (! (error_state || package.is_defined ()))
+    {
+      octave_function * fcn =
+        cdef_manager::find_package_symbol (full_name ());
+
+      if (fcn)
+        package = octave_value (fcn);
+    }
+
+  return package;
+}
+
 // Insert INF_CLASS in the set of class names that are considered
 // inferior to SUP_CLASS.  Return FALSE if INF_CLASS is currently
 // marked as superior to  SUP_CLASS.
@@ -1069,10 +1169,11 @@
 symbol_table::fcn_info::fcn_info_rep::dump (std::ostream& os,
                                             const std::string& prefix) const
 {
-  os << prefix << name
+  os << prefix << full_name ()
      << " ["
      << (cmdline_function.is_defined () ? "c" : "")
      << (built_in_function.is_defined () ? "b" : "")
+     << (package.is_defined () ? "p" : "")
      << "]\n";
 
   std::string tprefix = prefix + "  ";
--- a/libinterp/corefcn/symtab.h
+++ b/libinterp/corefcn/symtab.h
@@ -756,10 +756,19 @@
     public:
 
       fcn_info_rep (const std::string& nm)
-        : name (nm), subfunctions (), private_functions (),
+        : name (nm), package_name (), subfunctions (), private_functions (),
           class_constructors (), class_methods (), dispatch_map (),
           cmdline_function (), autoload_function (), function_on_path (),
-          built_in_function (), count (1) { }
+          built_in_function (), count (1)
+      {
+        size_t pos = name.rfind ('.');
+
+        if (pos != std::string::npos)
+          {
+            package_name = name.substr (0, pos);
+            name = name.substr (pos+1);
+          }
+      }
 
       octave_value load_private_function (const std::string& dir_name);
 
@@ -775,6 +784,8 @@
 
       octave_value find_autoload (void);
 
+      octave_value find_package (void);
+
       octave_value find_user_function (void);
 
       bool is_user_function_defined (void) const
@@ -883,6 +894,11 @@
           clear_user_function ();
       }
 
+      void clear_package (void)
+      {
+        package = octave_value ();
+      }
+
       void clear (bool force = false)
       {
         clear_map (subfunctions, force);
@@ -892,6 +908,7 @@
 
         clear_autoload_function (force);
         clear_user_function (force);
+        clear_package ();
       }
 
       void add_dispatch (const std::string& type, const std::string& fname)
@@ -915,8 +932,18 @@
 
       void dump (std::ostream& os, const std::string& prefix) const;
 
+      std::string full_name (void) const
+      {
+        if (package_name.empty ())
+          return name;
+        else
+          return package_name + "." + name;
+      }
+
       std::string name;
 
+      std::string package_name;
+
       // Scope id to function object.
       std::map<scope_id, octave_value> subfunctions;
 
@@ -938,6 +965,8 @@
 
       octave_value function_on_path;
 
+      octave_value package;
+
       octave_value built_in_function;
 
       octave_refcount<size_t> count;
--- a/libinterp/corefcn/syscalls.cc
+++ b/libinterp/corefcn/syscalls.cc
@@ -511,7 +511,7 @@
 
   if (nargin == 3)
     {
-      octave_stream strm = octave_stream_list::lookup (args (0), "fcntl");
+      octave_stream strm = octave_stream_list::lookup (args(0), "fcntl");
 
       if (! error_state)
         {
--- a/libinterp/corefcn/toplev.cc
+++ b/libinterp/corefcn/toplev.cc
@@ -301,7 +301,8 @@
 
 octave_map
 octave_call_stack::do_backtrace (size_t nskip,
-                                 octave_idx_type& curr_user_frame) const
+                                 octave_idx_type& curr_user_frame,
+                                 bool print_subfn) const
 {
   size_t user_code_frames = do_num_user_code_frames (curr_user_frame);
 
@@ -340,7 +341,7 @@
 
                   file(k) = f->fcn_file_name ();
                   std::string parent_fcn_name = f->parent_fcn_name ();
-                  if (parent_fcn_name == std::string ())
+                  if (! print_subfn || parent_fcn_name == std::string ())
                     name(k) = f->name ();
                   else
                     name(k) = f->parent_fcn_name () + Vfilemarker + f->name ();
@@ -445,6 +446,8 @@
               break;
             }
         }
+      else if (incr == 0)  // Break out of infinite loop by choosing an incr. 
+        incr = -1;
 
       // There is no need to set scope and context here.  That will
       // happen when the dbup/dbdown/keyboard frame is popped and we
@@ -651,6 +654,8 @@
     }
   while (retval == 0);
 
+  octave_stdout << "\n";
+
   if (retval == EOF)
     retval = 0;
 
@@ -1274,8 +1279,6 @@
     { false, "CAMD_LIBS", OCTAVE_CONF_CAMD_LIBS },
     { false, "CARBON_LIBS", OCTAVE_CONF_CARBON_LIBS },
     { false, "CC", OCTAVE_CONF_CC },
-    // FIXME: CC_VERSION is deprecated.  Remove in version 3.12
-    { false, "CC_VERSION", OCTAVE_CONF_CC_VERSION },
     { false, "CCOLAMD_CPPFLAGS", OCTAVE_CONF_CCOLAMD_CPPFLAGS },
     { false, "CCOLAMD_LDFLAGS", OCTAVE_CONF_CCOLAMD_LDFLAGS },
     { false, "CCOLAMD_LIBS", OCTAVE_CONF_CCOLAMD_LIBS },
@@ -1298,8 +1301,6 @@
     { false, "CXXCPP", OCTAVE_CONF_CXXCPP },
     { false, "CXXFLAGS", OCTAVE_CONF_CXXFLAGS },
     { false, "CXXPICFLAG", OCTAVE_CONF_CXXPICFLAG },
-    // FIXME: CXX_VERSION is deprecated.  Remove in version 3.12
-    { false, "CXX_VERSION", OCTAVE_CONF_CXX_VERSION },
     { false, "DEFAULT_PAGER", OCTAVE_DEFAULT_PAGER },
     { false, "DEFS", OCTAVE_CONF_DEFS },
     { false, "DL_LD", OCTAVE_CONF_DL_LD },
--- a/libinterp/corefcn/toplev.h
+++ b/libinterp/corefcn/toplev.h
@@ -278,7 +278,16 @@
   static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame)
   {
     return instance_ok ()
-           ? instance->do_backtrace (nskip, curr_user_frame) : octave_map ();
+           ? instance->do_backtrace (nskip, curr_user_frame, true)
+           : octave_map ();
+  }
+
+  static octave_map backtrace (size_t nskip, octave_idx_type& curr_user_frame,
+                               bool print_subfn)
+  {
+    return instance_ok ()
+           ? instance->do_backtrace (nskip, curr_user_frame, print_subfn)
+           : octave_map ();
   }
 
   static octave_map empty_backtrace (void);
@@ -414,7 +423,8 @@
   }
 
   octave_map do_backtrace (size_t nskip,
-                           octave_idx_type& curr_user_frame) const;
+                           octave_idx_type& curr_user_frame,
+                           bool print_subfn) const;
 
   bool do_goto_frame (size_t n, bool verbose);
 
--- a/libinterp/corefcn/tril.cc
+++ b/libinterp/corefcn/tril.cc
@@ -42,7 +42,8 @@
 static Array<T>
 do_tril (const Array<T>& a, octave_idx_type k, bool pack)
 {
-  octave_idx_type nr = a.rows (), nc = a.columns ();
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.columns ();
   const T *avec = a.fortran_vec ();
   octave_idx_type zero = 0;
 
@@ -83,7 +84,8 @@
 static Array<T>
 do_triu (const Array<T>& a, octave_idx_type k, bool pack)
 {
-  octave_idx_type nr = a.rows (), nc = a.columns ();
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.columns ();
   const T *avec = a.fortran_vec ();
   octave_idx_type zero = 0;
 
@@ -211,7 +213,7 @@
     print_usage ();
   else
     {
-      octave_value arg = args (0);
+      octave_value arg = args(0);
 
       dim_vector dims = arg.dims ();
       if (dims.length () != 2)
@@ -274,7 +276,8 @@
                 if (arg.numel () == 0)
                   return arg;
 
-                octave_idx_type nr = dims(0), nc = dims (1);
+                octave_idx_type nr = dims(0);
+                octave_idx_type nc = dims(1);
 
                 // The sole purpose of the below is to force the correct
                 // matrix size. This would not be necessary if the
--- a/libinterp/corefcn/txt-eng-ft.cc
+++ b/libinterp/corefcn/txt-eng-ft.cc
@@ -121,7 +121,7 @@
   typedef std::pair<std::string, double> ft_key;
   typedef std::map<ft_key, FT_Face> ft_cache;
 
-  // Cache the fonts loaded by freetype. This cache only contains
+  // Cache the fonts loaded by FreeType. This cache only contains
   // weak references to the fonts, strong references are only present
   // in class ft_render.
   ft_cache cache;
@@ -138,7 +138,7 @@
     : library (), freetype_initialized (false), fontconfig_initialized (false)
   {
     if (FT_Init_FreeType (&library))
-      ::error ("unable to initialize freetype library");
+      ::error ("unable to initialize FreeType library");
     else
       freetype_initialized = true;
 
@@ -635,7 +635,8 @@
       FT_UInt glyph_index, previous = 0;
 
       std::string str = e.string_value ();
-      size_t n = str.length (), curr = 0;
+      size_t n = str.length ();
+      size_t curr = 0;
       mbstate_t ps;
       memset (&ps, 0, sizeof (ps));  // Initialize state to 0.
       wchar_t wc;
--- a/libinterp/corefcn/txt-eng-ft.h
+++ b/libinterp/corefcn/txt-eng-ft.h
@@ -114,7 +114,7 @@
   ft_render& operator = (const ft_render&);
 
   // Class to hold information about fonts and a strong
-  // reference to the font objects loaded by freetype.
+  // reference to the font objects loaded by FreeType.
   class ft_font
   {
   public:
--- a/libinterp/corefcn/urlwrite.cc
+++ b/libinterp/corefcn/urlwrite.cc
@@ -391,7 +391,7 @@
         }
 
 
-      if (param.numel () % 2 == 1 )
+      if (param.numel () % 2 == 1)
         {
           error ("urlwrite: number of elements in PARAM must be even");
           return retval;
@@ -539,7 +539,7 @@
           return retval;
         }
 
-      if (param.numel () % 2 == 1 )
+      if (param.numel () % 2 == 1)
         {
           error ("urlread: number of elements in PARAM must be even");
           return retval;
--- a/libinterp/corefcn/utils.cc
+++ b/libinterp/corefcn/utils.cc
@@ -303,7 +303,7 @@
 If the second optional argument @qcode{\"all\"} is supplied, return\n\
 a cell array containing the list of all files that have the same\n\
 name in the path.  If no files are found, return an empty cell array.\n\
-@seealso{file_in_path, find_dir_in_path, path}\n\
+@seealso{file_in_path, dir_in_loadpath, path}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -380,7 +380,7 @@
 If the third optional argument @qcode{\"all\"} is supplied, return\n\
 a cell array containing the list of all files that have the same\n\
 name in the path.  If no files are found, return an empty cell array.\n\
-@seealso{file_in_loadpath, find_dir_in_path, path}\n\
+@seealso{file_in_loadpath, dir_in_loadpath, path}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -892,10 +892,10 @@
 %!error make_absolute_filename ("foo", "bar")
 */
 
-DEFUN (find_dir_in_path, args, ,
+DEFUN (dir_in_loadpath, args, ,
        "-*- texinfo -*-\n\
-@deftypefn  {Built-in Function} {} find_dir_in_path (@var{dir})\n\
-@deftypefnx {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\
+@deftypefn  {Built-in Function} {} dir_in_loadpath (@var{dir})\n\
+@deftypefnx {Built-in Function} {} dir_in_loadpath (@var{dir}, \"all\")\n\
 Return the full name of the path element matching @var{dir}.  The\n\
 match is performed at the end of each path element.  For example, if\n\
 @var{dir} is @qcode{\"foo/bar\"}, it matches the path element\n\
@@ -926,7 +926,7 @@
             retval = Cell (load_path::find_matching_dirs (dir));
         }
       else
-        error ("find_dir_in_path: DIR must be a directory name");
+        error ("dir_in_loadpath: DIR must be a directory name");
     }
   else
     print_usage ();
@@ -937,8 +937,8 @@
 /*
 ## FIXME: We need system-dependent tests here.
 
-%!error find_dir_in_path ()
-%!error find_dir_in_path ("foo", "bar", 1)
+%!error dir_in_loadpath ()
+%!error dir_in_loadpath ("foo", "bar", 1)
 */
 
 DEFUNX ("errno", Ferrno, args, ,
--- a/libinterp/corefcn/variables.cc
+++ b/libinterp/corefcn/variables.cc
@@ -548,7 +548,7 @@
 Check only for directories.\n\
 @end table\n\
 \n\
-@seealso{file_in_loadpath, file_in_path, find_dir_in_path, stat}\n\
+@seealso{file_in_loadpath, file_in_path, dir_in_loadpath, stat}\n\
 @end deftypefn")
 {
   octave_value retval = false;
@@ -1405,7 +1405,9 @@
             param.modifier = 'r';
             param.parameter_length = 0;
 
-            int a = 0, b = -1, balance = 1;
+            int a = 0;
+            int b = -1;
+            int balance = 1;
             unsigned int items;
             size_t pos;
             std::string cmd;
@@ -2255,6 +2257,7 @@
         {
           symbol_table::clear_objects ();
           octave_class::clear_exemplar_map ();
+          symbol_table::clear_all ();
         }
       else
         {
@@ -2464,6 +2467,7 @@
                     {
                       symbol_table::clear_objects ();
                       octave_class::clear_exemplar_map ();
+                      symbol_table::clear_all ();
                     }
                   else
                     {
--- a/libinterp/corefcn/xdiv.cc
+++ b/libinterp/corefcn/xdiv.cc
@@ -713,7 +713,9 @@
   if (! mx_div_conform (a, d))
     return MT ();
 
-  octave_idx_type m = a.rows (), n = d.rows (), l = d.length ();
+  octave_idx_type m = a.rows ();
+  octave_idx_type n = d.rows ();
+  octave_idx_type l = d.length ();
   MT x (m, n);
   typedef typename DMT::element_type S;
   typedef typename MT::element_type T;
@@ -794,7 +796,10 @@
   if (! mx_leftdiv_conform (d, a, blas_no_trans))
     return MT ();
 
-  octave_idx_type m = d.cols (), n = a.cols (), k = a.rows (), l = d.length ();
+  octave_idx_type m = d.cols ();
+  octave_idx_type n = a.cols ();
+  octave_idx_type k = a.rows ();
+  octave_idx_type l = d.length ();
   MT x (m, n);
   typedef typename DMT::element_type S;
   typedef typename MT::element_type T;
@@ -871,8 +876,11 @@
   if (! mx_div_conform (a, d))
     return MT ();
 
-  octave_idx_type m = a.rows (), n = d.rows (), k = d.cols ();
-  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
+  octave_idx_type m = a.rows ();
+  octave_idx_type n = d.rows ();
+  octave_idx_type k = d.cols ();
+  octave_idx_type l = std::min (m, n);
+  octave_idx_type lk = std::min (l, k);
   MT x (m, n);
   typedef typename DMT::element_type S;
   typedef typename MT::element_type T;
@@ -943,8 +951,11 @@
   if (! mx_leftdiv_conform (d, a, blas_no_trans))
     return MT ();
 
-  octave_idx_type m = d.cols (), n = a.cols (), k = d.rows ();
-  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
+  octave_idx_type m = d.cols ();
+  octave_idx_type n = a.cols ();
+  octave_idx_type k = d.rows ();
+  octave_idx_type l = std::min (m, n);
+  octave_idx_type lk = std::min (l, k);
   MT x (m, n);
   typedef typename DMT::element_type S;
   typedef typename MT::element_type T;
--- a/libinterp/dldfcn/__delaunayn__.cc
+++ b/libinterp/dldfcn/__delaunayn__.cc
@@ -175,7 +175,8 @@
 
           facetT *facet;
           vertexT *vertex, **vertexp;
-          octave_idx_type nf = 0, i = 0;
+          octave_idx_type nf = 0;
+          octave_idx_type i = 0;
 
           FORALLfacets
             {
--- a/libinterp/dldfcn/__init_fltk__.cc
+++ b/libinterp/dldfcn/__init_fltk__.cc
@@ -291,7 +291,7 @@
     //returns the number of visible menu items
     int len = menubar->size ();
     int n = 0;
-    for (int t = 0; t < len; t++ )
+    for (int t = 0; t < len; t++)
       {
         const Fl_Menu_Item *m = static_cast<const Fl_Menu_Item*> (&
                                 (menubar->menu ()[t]));
@@ -326,7 +326,7 @@
     // Kai Habel (14.10.2010)
 
     std::string menupath;
-    for (int t = 0; t < menubar->size (); t++ )
+    for (int t = 0; t < menubar->size (); t++)
       {
         Fl_Menu_Item *m = const_cast<Fl_Menu_Item*> (&(menubar->menu ()[t]));
         if (m->submenu ())
@@ -336,7 +336,7 @@
               menupath += "/";
             menupath += m->label ();
 
-            if (menupath.compare (findname) == 0 )
+            if (menupath.compare (findname) == 0)
               return (t);
           }
         else
@@ -1056,7 +1056,7 @@
   void pixel2pos (const graphics_handle& ax, int px, int py, double& xx,
                   double& yy) const
   {
-    pixel2pos ( gh_manager::get_object (ax), px, py, xx, yy);
+    pixel2pos (gh_manager::get_object (ax), px, py, xx, yy);
   }
 
   void pixel2pos (graphics_object ax, int px, int py, double& xx,
@@ -1072,7 +1072,7 @@
       }
   }
 
-  graphics_handle pixel2axes_or_ca (int px, int py )
+  graphics_handle pixel2axes_or_ca (int px, int py)
   {
     Matrix kids = fp.get_children ();
     int len = kids.length ();
@@ -1464,7 +1464,7 @@
 
             if (Fl::event_button () == 1)
               {
-                if ( Fl::event_clicks () == 1)
+                if (Fl::event_clicks () == 1)
                   {
                     if (ax_obj && ax_obj.isa ("axes"))
                       {
--- a/libinterp/dldfcn/amd.cc
+++ b/libinterp/dldfcn/amd.cc
@@ -67,8 +67,8 @@
 @table @asis\n\
 @item @var{opts}.dense\n\
 Determines what @code{amd} considers to be a dense row or column of the\n\
-input matrix.  Rows or columns with more than @code{max(16, (dense *\n\
-sqrt (@var{n})} entries, where @var{n} is the order of the matrix @var{S},\n\
+input matrix.  Rows or columns with more than @code{max (16, (dense *\n\
+sqrt (@var{n})))} entries, where @var{n} is the order of the matrix @var{S},\n\
 are ignored by @code{amd} during the calculation of the permutation\n\
 The value of dense must be a positive scalar and its default value is 10.0\n\
 \n\
--- a/libinterp/dldfcn/ccolamd.cc
+++ b/libinterp/dldfcn/ccolamd.cc
@@ -100,10 +100,9 @@
 @var{cmember} is an optional vector of length @math{n}.  It defines the\n\
 constraints on the column ordering.  If @code{@var{cmember}(j) = @var{c}},\n\
 then column @var{j} is in constraint set @var{c} (@var{c} must be in the\n\
-range 1 to\n\
-n).  In the output permutation @var{p}, all columns in set 1 appear\n\
-first, followed by all columns in set 2, and so on.  @code{@var{cmember} =\n\
-ones (1,n)} if not present or empty.\n\
+range 1 to n).  In the output permutation @var{p}, all columns in set 1\n\
+appear first, followed by all columns in set 2, and so on.\n\
+@code{@var{cmember} = ones (1,n)} if not present or empty.\n\
 @code{ccolamd (@var{S}, [], 1 : n)} returns @code{1 : n}\n\
 \n\
 @code{@var{p} = ccolamd (@var{S})} is about the same as\n\
--- a/libinterp/dldfcn/chol.cc
+++ b/libinterp/dldfcn/chol.cc
@@ -155,7 +155,7 @@
     {
       std::string tmp = args(n++).string_value ();
 
-      if (! error_state )
+      if (! error_state)
         {
           if (tmp.compare ("vector") == 0)
             vecout = true;
--- a/libinterp/dldfcn/fftw.cc
+++ b/libinterp/dldfcn/fftw.cc
@@ -303,7 +303,7 @@
                   if (args(1).is_real_scalar ())
                     {
                       int nthreads = args(1).int_value();
-                      if ( nthreads >= 1)
+                      if (nthreads >= 1)
                         {
 #if defined (HAVE_FFTW3_THREADS)
                           octave_fftw_planner::threads (nthreads);
--- a/libinterp/dldfcn/qr.cc
+++ b/libinterp/dldfcn/qr.cc
@@ -744,7 +744,9 @@
 bool check_qr_dims (const octave_value& q, const octave_value& r,
                     bool allow_ecf = false)
 {
-  octave_idx_type m = q.rows (), k = r.rows (), n = r.columns ();
+  octave_idx_type m = q.rows ();
+  octave_idx_type k = r.rows ();
+  octave_idx_type n = r.columns ();
   return ((q.ndims () == 2 && r.ndims () == 2 && k == q.columns ())
           && (m == k || (allow_ecf && k == n && k < m)));
 }
--- a/libinterp/dldfcn/symrcm.cc
+++ b/libinterp/dldfcn/symrcm.cc
@@ -487,7 +487,8 @@
   octave_idx_type s = 0;
 
   // head- and tail-indices for the queue
-  octave_idx_type qt = 0, qh = 0;
+  octave_idx_type qt = 0;
+  octave_idx_type qh = 0;
   CMK_Node v, w;
   // dimension of the matrix
   octave_idx_type N = nr;
--- a/libinterp/dldfcn/tsearch.cc
+++ b/libinterp/dldfcn/tsearch.cc
@@ -110,8 +110,10 @@
   const octave_idx_type np = xi.length ();
   ColumnVector values (np);
 
-  double x0 = 0.0, y0 = 0.0;
-  double a11 = 0.0, a12 = 0.0, a21 = 0.0, a22 = 0.0, det = 0.0;
+  double x0, y0, a11, a12, a21, a22, det;
+  x0 = y0 = 0.0;
+  a11 = a12 = a21 = a22 = 0.0;
+  det = 0.0;
 
   octave_idx_type k = nelem; // k is a counter of elements
   for (octave_idx_type kp = 0; kp < np; kp++)
--- a/libinterp/genprops.awk
+++ b/libinterp/genprops.awk
@@ -290,7 +290,7 @@
   if (class_name && ! base)
     emit_common_declarations();
 
-  printf ("public:\n\n\n  static std::set<std::string> core_property_names (void);\n\n  static bool has_core_property (const caseless_str& pname);\n\n  std::set<std::string> all_property_names (void) const;\n\n");
+  printf ("public:\n\n\n  static std::set<std::string> core_property_names (void);\n\n  static std::set<std::string> readonly_property_names (void);\n\n  static bool has_core_property (const caseless_str& pname);\n\n  static bool has_readonly_property (const caseless_str& pname);\n\n  std::set<std::string> all_property_names (void) const;\n\n");
 
   if (! base)
     printf ("  bool has_property (const caseless_str& pname) const;\n\n");
@@ -470,7 +470,7 @@
               class_name);
 
     if (! base)
-      printf ("  const std::set<std::string>& pnames = all_property_names ();\n\n  caseless_str pname = validate_property_name (\"get\", go_name, pnames, pname_arg);\n\n  if (error_state)\n    return;\n\n");
+        printf ("  const std::set<std::string>& pnames = all_property_names ();\n\n  caseless_str pname = validate_property_name (\"get\", go_name, pnames, pname_arg);\n\n  if (error_state)\n    return;\n  else if (has_readonly_property (pname))\n    {\n      error (\"set: \\\"%%s\\\" is read-only\", pname.c_str ());\n      return;\n    }\n\n");
 
     first = 1;
 
@@ -611,6 +611,7 @@
       printf ("std::string %s::properties::go_name (\"%s\");\n\n",
               class_name, object_name);
 
+    ## core_property_names
     printf ("std::set<std::string>\n");
     if (base)
       printf ("base_properties");
@@ -622,7 +623,7 @@
     if (! base)
       printf ("\n      std::set<std::string> base_pnames = base_properties::core_property_names ();\n      all_pnames.insert (base_pnames.begin (), base_pnames.end ());\n");
     printf ("\n      initialized = true;\n    }\n\n  return all_pnames;\n}\n\n");
-
+    ## has_core_property
     printf ("bool\n");
     if (base)
       printf ("base_properties");
@@ -630,6 +631,30 @@
       printf ("%s::properties", class_name);
     printf ("::has_core_property (const caseless_str& pname)\n{\n  std::set<std::string> pnames = core_property_names ();\n\n  return pnames.find (pname) != pnames.end ();\n}\n\n", class_name);
 
+    ## readonly_property_names
+    printf ("std::set<std::string>\n");
+    if (base)
+      printf ("base_properties");
+    else
+      printf ("%s::properties", class_name);
+    printf ("::readonly_property_names (void)\n{\n  static std::set<std::string> all_pnames;\n\n  static bool initialized = false;\n\n  if (! initialized)\n    {\n");
+    for (i = 1; i <= idx; i++)
+        if (readonly[i])
+        {
+            printf ("      all_pnames.insert (\"%s\");\n", name[i]);
+        }
+    if (! base)
+      printf ("\n      std::set<std::string> base_pnames = base_properties::readonly_property_names ();\n      all_pnames.insert (base_pnames.begin (), base_pnames.end ());\n");
+    printf ("\n      initialized = true;\n    }\n\n  return all_pnames;\n}\n\n");
+    ## has_readonly_property
+    printf ("bool\n");
+    if (base)
+      printf ("base_properties");
+    else
+      printf ("%s::properties", class_name);
+    printf ("::has_readonly_property (const caseless_str& pname)\n{\n  std::set<std::string> pnames = readonly_property_names ();\n\n  return pnames.find (pname) != pnames.end ();\n}\n\n", class_name);
+
+    ## all_property_names
     printf ("std::set<std::string>\n");
     if (base)
         printf ("base_properties");
--- a/libinterp/octave-value/module.mk
+++ b/libinterp/octave-value/module.mk
@@ -36,6 +36,7 @@
   octave-value/ov-cell.h \
   octave-value/ov-ch-mat.h \
   octave-value/ov-class.h \
+  octave-value/ov-classdef.h \
   octave-value/ov-colon.h \
   octave-value/ov-complex.h \
   octave-value/ov-cs-list.h \
@@ -94,6 +95,7 @@
   octave-value/ov-cell.cc \
   octave-value/ov-ch-mat.cc \
   octave-value/ov-class.cc \
+  octave-value/ov-classdef.cc \
   octave-value/ov-colon.cc \
   octave-value/ov-complex.cc \
   octave-value/ov-cs-list.cc \
--- a/libinterp/octave-value/ov-base-diag.cc
+++ b/libinterp/octave-value/ov-base-diag.cc
@@ -100,7 +100,6 @@
                                         bool resize_ok)
 {
   octave_value retval;
-  typedef typename DMT::element_type el_type;
 
   if (idx.length () == 2 && ! resize_ok)
     {
@@ -441,7 +440,8 @@
 bool
 octave_base_diag<DMT, MT>::load_ascii (std::istream& is)
 {
-  octave_idx_type r = 0, c = 0;
+  octave_idx_type r = 0;
+  octave_idx_type c = 0;
   bool success = true;
 
   if (extract_keyword (is, "rows", r, true)
@@ -505,8 +505,7 @@
 
 template <class DMT, class MT>
 void
-octave_base_diag<DMT, MT>::print (std::ostream& os,
-                                  bool pr_as_read_syntax) const
+octave_base_diag<DMT, MT>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -531,6 +530,23 @@
 
 template <class DMT, class MT>
 octave_value
+octave_base_diag<DMT, MT>::fast_elem_extract (octave_idx_type n) const
+{
+  if (n < matrix.numel ())
+    {
+      octave_idx_type nr = matrix.rows ();
+
+      octave_idx_type r = n % nr;
+      octave_idx_type c = n / nr;
+
+      return octave_value (matrix.elem (r, c));
+    }
+  else
+    return octave_value ();
+}
+
+template <class DMT, class MT>
+octave_value
 octave_base_diag<DMT, MT>::to_dense (void) const
 {
   if (! dense_cache.is_defined ())
--- a/libinterp/octave-value/ov-base-diag.h
+++ b/libinterp/octave-value/ov-base-diag.h
@@ -203,10 +203,12 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 protected:
 
   DMT matrix;
--- a/libinterp/octave-value/ov-base-int.cc
+++ b/libinterp/octave-value/ov-base-int.cc
@@ -266,7 +266,7 @@
 template <class T>
 bool
 octave_base_int_matrix<T>::load_binary (std::istream& is, bool swap,
-                                        oct_mach_info::float_format )
+                                        oct_mach_info::float_format)
 {
   int32_t mdims;
   if (! is.read (reinterpret_cast<char *> (&mdims), 4))
@@ -347,7 +347,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
 
   // Octave uses column-major, while HDF5 uses row-major ordering
@@ -550,7 +551,8 @@
   hid_t save_type_hid = HDF5_SAVE_TYPE;
   bool retval = true;
   hsize_t dimens[3];
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
 
   space_hid = H5Screate_simple (0, dimens, 0);
   if (space_hid < 0) return false;
--- a/libinterp/octave-value/ov-base-int.h
+++ b/libinterp/octave-value/ov-base-int.h
@@ -74,10 +74,10 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& );
+  bool save_binary (std::ostream& os, bool&);
 
   bool load_binary (std::istream& is, bool swap,
-                    oct_mach_info::float_format );
+                    oct_mach_info::float_format);
 
 #if defined (HAVE_HDF5)
   bool save_hdf5 (hid_t loc_id, const char *name, bool);
@@ -119,13 +119,13 @@
 
   bool load_ascii (std::istream& is);
 
-  bool save_binary (std::ostream& os, bool& );
+  bool save_binary (std::ostream& os, bool&);
 
   bool load_binary (std::istream& is, bool swap,
-                    oct_mach_info::float_format );
+                    oct_mach_info::float_format);
 
 #if defined (HAVE_HDF5)
-  bool save_hdf5 (hid_t loc_id, const char *name, bool );
+  bool save_hdf5 (hid_t loc_id, const char *name, bool);
 
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
--- a/libinterp/octave-value/ov-base-mat.cc
+++ b/libinterp/octave-value/ov-base-mat.cc
@@ -351,7 +351,8 @@
               {
                 // optimize all scalar indices. Don't construct an index array,
                 // but rather calc a scalar index directly.
-                octave_idx_type k = 1, j = 0;
+                octave_idx_type k = 1;
+                octave_idx_type j = 0;
                 for (octave_idx_type i = 0; i < n_idx; i++)
                   {
                     j += idx_vec(i)(0) * k;
@@ -435,7 +436,7 @@
 
 template <class MT>
 void
-octave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_matrix<MT>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
--- a/libinterp/octave-value/ov-base-mat.h
+++ b/libinterp/octave-value/ov-base-mat.h
@@ -153,7 +153,7 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
--- a/libinterp/octave-value/ov-base-scalar.cc
+++ b/libinterp/octave-value/ov-base-scalar.cc
@@ -143,7 +143,7 @@
 
 template <class ST>
 void
-octave_base_scalar<ST>::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_scalar<ST>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -180,6 +180,13 @@
 }
 
 template <class ST>
+octave_value
+octave_base_scalar<ST>::fast_elem_extract (octave_idx_type n) const
+{
+  return (n == 0) ? octave_value (scalar) : octave_value ();
+}
+
+template <class ST>
 bool
 octave_base_scalar<ST>::fast_elem_insert_self (void *where,
                                                builtin_type_t btyp) const
--- a/libinterp/octave-value/ov-base-scalar.h
+++ b/libinterp/octave-value/ov-base-scalar.h
@@ -132,7 +132,7 @@
 
   bool is_true (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -148,6 +148,8 @@
 
   ST& scalar_ref (void) { return scalar; }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
   bool fast_elem_insert_self (void *where, builtin_type_t btyp) const;
 
 protected:
--- a/libinterp/octave-value/ov-base-sparse.cc
+++ b/libinterp/octave-value/ov-base-sparse.cc
@@ -288,7 +288,7 @@
 
 template <class T>
 void
-octave_base_sparse<T>::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_base_sparse<T>::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -436,31 +436,73 @@
   return success;
 }
 
+
+template <class T>
+octave_value
+octave_base_sparse<T>::fast_elem_extract (octave_idx_type n) const
+{
+  octave_idx_type nr = matrix.rows ();
+  octave_idx_type nc = matrix.cols ();
+
+  octave_idx_type i = n % nr;
+  octave_idx_type j = n / nr;
+
+  return (i < nr && j < nc) ? octave_value (matrix(i,j)) : octave_value ();
+}
+
 template <class T>
 octave_value
 octave_base_sparse<T>::map (octave_base_value::unary_mapper_t umap) const
 {
+  if (umap == umap_xtolower || umap == umap_xtoupper)
+    return matrix;
+
   // Try the map on the dense value.
+  // FIXME: We should probably be smarter about this, especially for the
+  // cases that are expected to return sparse matrices.
   octave_value retval = this->full_value ().map (umap);
 
   // Sparsify the result if possible.
-  // FIXME: intentionally skip this step for string mappers. Is this wanted?
-  if (umap >= umap_xisalnum && umap <= umap_xtoupper)
-    return retval;
 
-  switch (retval.builtin_type ())
+  switch (umap)
     {
-    case btyp_double:
-      retval = retval.sparse_matrix_value ();
+    case umap_xisalnum:
+    case umap_xisalpha:
+    case umap_xisascii:
+    case umap_xiscntrl:
+    case umap_xisdigit:
+    case umap_xisgraph:
+    case umap_xislower:
+    case umap_xisprint:
+    case umap_xispunct:
+    case umap_xisspace:
+    case umap_xisupper:
+    case umap_xisxdigit:
+    case umap_xtoascii:
+      // FIXME: intentionally skip this step for string mappers.
+      // Is this wanted?
       break;
-    case btyp_complex:
-      retval = retval.sparse_complex_matrix_value ();
-      break;
-    case btyp_bool:
-      retval = retval.sparse_bool_matrix_value ();
-      break;
+
     default:
-      break;
+      {
+        switch (retval.builtin_type ())
+          {
+          case btyp_double:
+            retval = retval.sparse_matrix_value ();
+            break;
+
+          case btyp_complex:
+            retval = retval.sparse_complex_matrix_value ();
+            break;
+
+          case btyp_bool:
+            retval = retval.sparse_bool_matrix_value ();
+            break;
+
+          default:
+            break;
+          }
+      }
     }
 
   return retval;
--- a/libinterp/octave-value/ov-base-sparse.h
+++ b/libinterp/octave-value/ov-base-sparse.h
@@ -147,7 +147,7 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
@@ -165,6 +165,8 @@
 
   octave_idx_type *mex_get_jc (void) const { return matrix.mex_get_jc (); }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 protected:
 
   octave_value map (octave_base_value::unary_mapper_t umap) const;
--- a/libinterp/octave-value/ov-base.cc
+++ b/libinterp/octave-value/ov-base.cc
@@ -52,6 +52,7 @@
 #include "parse.h"
 #include "pr-output.h"
 #include "utils.h"
+#include "toplev.h"
 #include "variables.h"
 
 builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y)
@@ -396,7 +397,7 @@
 }
 
 void
-octave_base_value::print (std::ostream&, bool) const
+octave_base_value::print (std::ostream&, bool)
 {
   gripe_wrong_type_arg ("octave_base_value::print ()", type_name ());
 }
@@ -1536,6 +1537,111 @@
   return new octave_cell ();
 }
 
+static inline octave_value_list
+sanitize (const octave_value_list& ovl)
+{
+  octave_value_list retval = ovl;
+
+  for (octave_idx_type i = 0; i < ovl.length (); i++)
+    {
+      if (retval(i).is_magic_colon ())
+        retval(i) = ":";
+    }
+
+  return retval;
+}
+
+octave_value
+make_idx_args (const std::string& type,
+               const std::list<octave_value_list>& idx,
+               const std::string& who)
+{
+  octave_value retval;
+
+  size_t len = type.length ();
+
+  if (len == idx.size ())
+    {
+      Cell type_field (1, len);
+      Cell subs_field (1, len);
+
+      std::list<octave_value_list>::const_iterator p = idx.begin ();
+
+      for (size_t i = 0; i < len; i++)
+        {
+          char t = type[i];
+
+          switch (t)
+            {
+            case '(':
+              type_field(i) = "()";
+              subs_field(i) = Cell (sanitize (*p++));
+              break;
+
+            case '{':
+              type_field(i) = "{}";
+              subs_field(i) = Cell (sanitize (*p++));
+              break;
+
+            case '.':
+              {
+                type_field(i) = ".";
+
+                octave_value_list vlist = *p++;
+
+                if (vlist.length () == 1)
+                  {
+                    octave_value val = vlist(0);
+
+                    if (val.is_string ())
+                      subs_field(i) = val;
+                    else
+                      {
+                        error ("expecting character string argument for '.' index");
+                        return retval;
+                      }
+                  }
+                else
+                  {
+                    error ("expecting single argument for '.' index");
+                    return retval;
+                  }
+              }
+              break;
+
+            default:
+              panic_impossible ();
+              break;
+            }
+        }
+
+      octave_map m;
+
+      m.assign ("type", type_field);
+      m.assign ("subs", subs_field);
+
+      retval = m;
+    }
+  else
+    error ("invalid index for %s", who.c_str ());
+
+  return retval;
+}
+
+bool
+called_from_builtin (void)
+{
+  octave_function *fcn = octave_call_stack::caller ();
+
+  // FIXME: we probably need a better check here, or some other
+  // mechanism to avoid overloaded functions when builtin is used.
+  // For example, what if someone overloads the builtin function?
+  // Also, are there other places where using builtin is not properly
+  // avoiding dispatch?
+
+  return (fcn && fcn->name () == "builtin");
+}
+
 void
 install_base_type_conversions (void)
 {
--- a/libinterp/octave-value/ov-base.h
+++ b/libinterp/octave-value/ov-base.h
@@ -606,7 +606,7 @@
 
   virtual bool print_as_scalar (void) const { return false; }
 
-  virtual void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  virtual void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   virtual void
   print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
@@ -828,4 +828,16 @@
 // is memory to be saved
 extern OCTINTERP_API bool Vsparse_auto_mutate;
 
+// Utility function to convert C++ arguments used in subsref/subsasgn into an
+// octave_value_list object that can be used to call a function/method in the
+// interpreter.
+extern OCTINTERP_API octave_value
+make_idx_args (const std::string& type,
+               const std::list<octave_value_list>& idx,
+               const std::string& who);
+
+// Tells whether some regular octave_value_base methods are being called from
+// within the "builtin" function.
+extern OCTINTERP_API bool called_from_builtin (void);
+
 #endif
--- a/libinterp/octave-value/ov-bool-mat.cc
+++ b/libinterp/octave-value/ov-bool-mat.cc
@@ -421,7 +421,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   boolNDArray m = bool_array_value ();
 
--- a/libinterp/octave-value/ov-bool-mat.h
+++ b/libinterp/octave-value/ov-bool-mat.h
@@ -151,10 +151,10 @@
   FloatComplex float_complex_value (bool = false) const;
 
   ComplexMatrix complex_matrix_value (bool = false) const
-  { return ComplexMatrix (matrix.matrix_value ( )); }
+  { return ComplexMatrix (matrix.matrix_value ()); }
 
   FloatComplexMatrix float_complex_matrix_value (bool = false) const
-  { return FloatComplexMatrix (matrix.matrix_value ( )); }
+  { return FloatComplexMatrix (matrix.matrix_value ()); }
 
   ComplexNDArray complex_array_value (bool = false) const
   { return ComplexNDArray (matrix); }
--- a/libinterp/octave-value/ov-bool-sparse.cc
+++ b/libinterp/octave-value/ov-bool-sparse.cc
@@ -225,16 +225,16 @@
 
   int32_t itmp;
   // Use negative value for ndims to be consistent with other formats
-  itmp= -2;
+  itmp = -2;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nr;
+  itmp = nr;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nc;
+  itmp = nc;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nz;
+  itmp = nz;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
   // add one to the printed indices to go from
@@ -358,7 +358,8 @@
   if (group_hid < 0)
     return false;
 
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   SparseBoolMatrix m = sparse_bool_matrix_value ();
   octave_idx_type tmp;
@@ -567,7 +568,7 @@
 #else
   group_hid = H5Gopen (loc_id, name);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
 #if HAVE_HDF5_18
   data_hid = H5Dopen (group_hid, "nr", H5P_DEFAULT);
--- a/libinterp/octave-value/ov-bool.cc
+++ b/libinterp/octave-value/ov-bool.cc
@@ -165,7 +165,8 @@
                         bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
--- a/libinterp/octave-value/ov-cell.cc
+++ b/libinterp/octave-value/ov-cell.cc
@@ -687,7 +687,7 @@
 }
 
 void
-octave_cell::print (std::ostream& os, bool) const
+octave_cell::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -1077,7 +1077,8 @@
     return (empty > 0);
 
   hsize_t rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1, size_hid = -1;
+  hid_t space_hid, data_hid, size_hid;
+  space_hid = data_hid = size_hid = -1;
 
 #if HAVE_HDF5_18
   data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
--- a/libinterp/octave-value/ov-cell.h
+++ b/libinterp/octave-value/ov-cell.h
@@ -147,7 +147,7 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-class.cc
+++ b/libinterp/octave-value/ov-class.cc
@@ -268,97 +268,6 @@
   error ("assignment to class element failed");
 }
 
-static inline octave_value_list
-sanitize (const octave_value_list& ovl)
-{
-  octave_value_list retval = ovl;
-
-  for (octave_idx_type i = 0; i < ovl.length (); i++)
-    {
-      if (retval(i).is_magic_colon ())
-        retval(i) = ":";
-    }
-
-  return retval;
-}
-
-static inline octave_value
-make_idx_args (const std::string& type,
-               const std::list<octave_value_list>& idx,
-               const std::string& who)
-{
-  octave_value retval;
-
-  size_t len = type.length ();
-
-  if (len == idx.size ())
-    {
-      Cell type_field (1, len);
-      Cell subs_field (1, len);
-
-      std::list<octave_value_list>::const_iterator p = idx.begin ();
-
-      for (size_t i = 0; i < len; i++)
-        {
-          char t = type[i];
-
-          switch (t)
-            {
-            case '(':
-              type_field(i) = "()";
-              subs_field(i) = Cell (sanitize (*p++));
-              break;
-
-            case '{':
-              type_field(i) = "{}";
-              subs_field(i) = Cell (sanitize (*p++));
-              break;
-
-            case '.':
-              {
-                type_field(i) = ".";
-
-                octave_value_list vlist = *p++;
-
-                if (vlist.length () == 1)
-                  {
-                    octave_value val = vlist(0);
-
-                    if (val.is_string ())
-                      subs_field(i) = val;
-                    else
-                      {
-                        error ("expecting character string argument for '.' index");
-                        return retval;
-                      }
-                  }
-                else
-                  {
-                    error ("expecting single argument for '.' index");
-                    return retval;
-                  }
-              }
-              break;
-
-            default:
-              panic_impossible ();
-              break;
-            }
-        }
-
-      octave_map m;
-
-      m.assign ("type", type_field);
-      m.assign ("subs", subs_field);
-
-      retval = m;
-    }
-  else
-    error ("invalid index for %s", who.c_str ());
-
-  return retval;
-}
-
 Cell
 octave_class::dotref (const octave_value_list& idx)
 {
@@ -398,20 +307,6 @@
   return retval;
 }
 
-static bool
-called_from_builtin (void)
-{
-  octave_function *fcn = octave_call_stack::caller ();
-
-  // FIXME: we probably need a better check here, or some other
-  // mechanism to avoid overloaded functions when builtin is used.
-  // For example, what if someone overloads the builtin function?
-  // Also, are there other places where using builtin is not properly
-  // avoiding dispatch?
-
-  return (fcn && fcn->name () == "builtin");
-}
-
 Matrix
 octave_class::size (void)
 {
@@ -1150,7 +1045,7 @@
 
 
 void
-octave_class::print (std::ostream& os, bool) const
+octave_class::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -1279,7 +1174,8 @@
 bool
 octave_class::reconstruct_parents (void)
 {
-  bool retval = true, might_have_inheritance = false;
+  bool retval = true;
+  bool might_have_inheritance = false;
   std::string dbgstr = "dork";
 
   // First, check to see if there might be an issue with inheritance.
@@ -1287,10 +1183,10 @@
     {
       std::string  key = map.key (p);
       Cell         val = map.contents (p);
-      if ( val(0).is_object () )
+      if (val(0).is_object ())
         {
           dbgstr = "blork";
-          if ( key == val(0).class_name () )
+          if (key == val(0).class_name ())
             {
               might_have_inheritance = true;
               dbgstr = "cork";
@@ -1429,7 +1325,7 @@
                   success = false;
                 }
             }
-          else if (len == 0 )
+          else if (len == 0)
             {
               map = octave_map (dim_vector (1, 1));
               c_name = classname;
@@ -1573,7 +1469,7 @@
           success = false;
         }
     }
-  else if (len == 0 )
+  else if (len == 0)
     map = octave_map (dim_vector (1, 1));
   else
     panic_impossible ();
@@ -2148,7 +2044,7 @@
        "-*- texinfo -*-\n\
 @deftypefn {Built-in Function} {} isobject (@var{x})\n\
 Return true if @var{x} is a class object.\n\
-@seealso{class, typeinfo, isa, ismethod}\n\
+@seealso{class, typeinfo, isa, ismethod, isprop}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -2163,8 +2059,8 @@
 
 DEFUN (ismethod, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} ismethod (@var{x}, @var{method})\n\
-Return true if @var{x} is a class object and the string @var{method}\n\
+@deftypefn {Built-in Function} {} ismethod (@var{obj}, @var{method})\n\
+Return true if @var{obj} is a class object and the string @var{method}\n\
 is a method of this class.\n\
 @seealso{isprop, isobject}\n\
 @end deftypefn")
--- a/libinterp/octave-value/ov-class.h
+++ b/libinterp/octave-value/ov-class.h
@@ -169,7 +169,7 @@
 
   string_vector all_strings (bool pad) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
new file mode 100644
--- /dev/null
+++ b/libinterp/octave-value/ov-classdef.cc
@@ -0,0 +1,3910 @@
+/*
+
+Copyright (C) 2012-2013 Michael Goffioul
+
+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 <algorithm>
+
+#include "defun.h"
+#include "load-path.h"
+#include "ov-builtin.h"
+#include "ov-classdef.h"
+#include "ov-fcn-handle.h"
+#include "ov-typeinfo.h"
+#include "ov-usr-fcn.h"
+#include "pt-assign.h"
+#include "pt-classdef.h"
+#include "pt-funcall.h"
+#include "pt-misc.h"
+#include "pt-stmt.h"
+#include "pt-walk.h"
+#include "singleton-cleanup.h"
+#include "symtab.h"
+#include "toplev.h"
+
+#include "Array.cc"
+
+static void
+gripe_method_access (const std::string& from, const cdef_method& meth)
+{
+  octave_value acc = meth.get ("Access");
+  std::string acc_s;
+
+  if (acc.is_string ())
+    acc_s = acc.string_value ();
+  else
+    acc_s = "class-restricted";
+
+  error ("%s: method `%s' has %s access and cannot be run in this context",
+         from.c_str (), meth.get_name ().c_str (), acc_s.c_str ());
+}
+
+static void
+gripe_property_access (const std::string& from, const cdef_property& prop,
+                       bool is_set = false)
+{
+  octave_value acc = prop.get (is_set ? "SetAccess" : "GetAccess");
+  std::string acc_s;
+
+  if (acc.is_string ())
+    acc_s = acc.string_value ();
+  else
+    acc_s = "class-restricted";
+
+  if (is_set)
+    error ("%s: property `%s' has %s access and cannot be set in this context",
+           from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
+  else
+    error ("%s: property `%s' has %s access and cannot be obtained in this context",
+           from.c_str (), prop.get_name ().c_str (), acc_s.c_str ());
+}
+
+static std::string
+get_base_name (const std::string& nm)
+{
+  std::string::size_type pos = nm.find_last_of ('.');
+
+  if (pos != std::string::npos)
+    return nm.substr (pos + 1);
+
+  return nm;
+}
+
+static void
+make_function_of_class (const std::string& class_name,
+                        const octave_value& fcn)
+{
+  octave_function *of = fcn.function_value ();
+
+  if (! error_state)
+    {
+      of->stash_dispatch_class (class_name);
+
+      octave_user_function *uf = of->user_function_value (true);
+
+      if (! error_state && uf)
+        {
+          if (get_base_name (class_name) == uf->name ())
+            {
+              uf->mark_as_class_constructor ();
+              uf->mark_as_classdef_constructor ();
+            }
+          else
+            uf->mark_as_class_method ();
+        }
+    }
+}
+
+static void
+make_function_of_class (const cdef_class& cls, const octave_value& fcn)
+{
+  make_function_of_class (cls.get_name (), fcn);
+}
+
+static octave_value
+make_fcn_handle (octave_builtin::fcn ff, const std::string& nm)
+{
+  octave_value fcn (new octave_builtin (ff, nm));
+
+  octave_value fcn_handle (new octave_fcn_handle (fcn, nm));
+
+  return fcn_handle;
+}
+
+static octave_value
+make_fcn_handle (const octave_value& fcn, const std::string& nm)
+{
+  octave_value retval;
+
+  if (fcn.is_defined ())
+    retval = octave_value (new octave_fcn_handle (fcn, nm));
+
+  return retval;
+}
+
+inline octave_value_list
+execute_ov (octave_value val, const octave_value_list& args, int nargout)
+{
+  std::list<octave_value_list> idx (1, args);
+
+  std::string type ("(");
+
+  return val.subsref (type, idx, nargout);
+}
+
+static cdef_class
+lookup_class (const std::string& name, bool error_if_not_found = true,
+              bool load_if_not_found = true)
+{
+  return cdef_manager::find_class (name, error_if_not_found,
+                                   load_if_not_found);
+}
+
+static cdef_class
+lookup_class (const cdef_class& cls)
+{
+  // FIXME: placeholder for the time being, the purpose
+  //        is to centralized any class update activity here.
+
+  return cls;
+}
+
+static cdef_class
+lookup_class (const octave_value& ov)
+{
+  if (ov.is_string())
+    return lookup_class (ov.string_value ());
+  else
+    {
+      cdef_class cls (to_cdef (ov));
+
+      if (! error_state)
+        return lookup_class (cls);
+    }
+
+  return cdef_class ();
+}
+
+static std::list<cdef_class>
+lookup_classes (const Cell& cls_list)
+{
+  std::list<cdef_class> retval;
+
+  for (int i = 0; i < cls_list.numel (); i++)
+    {
+      cdef_class c = lookup_class (cls_list(i));
+
+      if (! error_state)
+        retval.push_back (c);
+      else
+        {
+          retval.clear ();
+          break;
+        }
+    }
+
+  return retval;
+}
+
+static octave_value
+to_ov (const std::list<cdef_class>& class_list)
+{
+  Cell cls (class_list.size (), 1);
+  int i = 0;
+
+  for (std::list<cdef_class>::const_iterator it = class_list.begin ();
+       it != class_list.end (); ++it, ++i)
+    cls(i) = to_ov (*it);
+
+  return octave_value (cls);
+}
+
+static bool
+is_superclass (const cdef_class& clsa, const cdef_class& clsb,
+               bool allow_equal = true, int max_depth = -1)
+{
+  bool retval = false;
+
+  if (allow_equal && clsa == clsb)
+    retval = true;
+  else if (max_depth != 0)
+    {
+      Cell c = clsb.get ("SuperClasses").cell_value ();
+
+      for (int i = 0; ! error_state && ! retval && i < c.numel (); i++)
+        {
+          cdef_class cls = lookup_class (c(i));
+
+          if (! error_state)
+            retval = is_superclass (clsa, cls, true,
+                                    max_depth < 0 ? max_depth : max_depth-1);
+        }
+    }
+
+  return retval;
+}
+
+inline bool
+is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb)
+{ return is_superclass (clsa, clsb, false); }
+
+inline bool
+is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb)
+{ return is_superclass (clsa, clsb, false, 1); }
+
+static octave_value_list
+class_get_properties (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      retval(0) = cls.get_properties ();
+    }
+
+  return retval;
+}
+
+static cdef_class
+get_class_context (std::string& name, bool& in_constructor)
+{
+  cdef_class cls;
+
+  octave_function* fcn = octave_call_stack::current ();
+
+  in_constructor = false;
+
+  if (fcn &&
+      (fcn->is_class_method ()
+       || fcn->is_classdef_constructor ()
+       || fcn->is_anonymous_function_of_class ()
+       || (fcn->is_private_function ()
+           && ! fcn->dispatch_class ().empty ())))
+    {
+      cls = lookup_class (fcn->dispatch_class ());
+      if (! error_state)
+        {
+          name = fcn->name ();
+          in_constructor = fcn->is_classdef_constructor ();
+        }
+    }
+
+  return cls;
+}
+
+inline cdef_class
+get_class_context (void)
+{
+  std::string dummy_string;
+  bool dummy_bool;
+
+  return get_class_context (dummy_string, dummy_bool);
+}
+
+static bool
+in_class_method (const cdef_class& cls)
+{
+  cdef_class ctx = get_class_context ();
+
+  return (ctx.ok () && is_superclass (ctx, cls));
+}
+
+static bool
+check_access (const cdef_class& cls, const octave_value& acc,
+              const std::string& meth_name = std::string (),
+              const std::string& prop_name = std::string (),
+              bool is_prop_set = false)
+{
+  if (acc.is_string ())
+    {
+      std::string acc_s = acc.string_value ();
+
+      if (acc_s == "public")
+        return true;
+
+      cdef_class ctx = get_class_context ();
+
+      // The access is private or protected, this requires a
+      // valid class context.
+
+      if (! error_state && ctx.ok ())
+        {
+          if (acc_s == "private")
+            return (ctx == cls);
+          else if (acc_s == "protected")
+            {
+              if (is_superclass (cls, ctx))
+                // Calling a protected method in a superclass.
+                return true;
+              else if (is_strict_superclass (ctx, cls))
+                {
+                  // Calling a protected method or property in a derived class.
+                  // This is only allowed if the context class knows about it
+                  // and has access to it.
+
+                  if (! meth_name.empty ())
+                    {
+                      cdef_method m = ctx.find_method (meth_name);
+
+                      if (m.ok ())
+                        return check_access (ctx, m.get ("Access"), meth_name);
+
+                      return false;
+                    }
+                  else if (! prop_name.empty ())
+                    {
+                      cdef_property p = ctx.find_property (prop_name);
+
+                      if (p.ok ())
+                        {
+                          octave_value p_access = p.get (is_prop_set ?
+                                                         "SetAccess" :
+                                                         "GetAccess");
+
+                          return check_access (ctx, p_access, meth_name,
+                                               prop_name, is_prop_set);
+                        }
+
+                      return false;
+                    }
+                  else
+                    panic_impossible ();
+                }
+
+              return false;
+            }
+          else
+            panic_impossible ();
+        }
+    }
+  else if (acc.is_cell ())
+    {
+      Cell acc_c = acc.cell_value ();
+
+      cdef_class ctx = get_class_context ();
+
+      // At this point, a class context is always required.
+
+      if (! error_state && ctx.ok ())
+        {
+          if (ctx == cls)
+            return true;
+
+          for (int i = 0; ! error_state && i < acc.numel (); i++)
+            {
+              cdef_class acc_cls (to_cdef (acc_c(i)));
+
+              if (! error_state)
+                {
+                  if (is_superclass (acc_cls, ctx))
+                    return true;
+                }
+            }
+        }
+    }
+  else
+    error ("invalid property/method access in class `%s'",
+           cls.get_name ().c_str ());
+  
+  return false;
+}
+
+static bool
+is_dummy_method (const octave_value& fcn)
+{
+  bool retval = false;
+
+  if (fcn.is_defined ())
+    {
+      if (fcn.is_user_function ())
+        {
+          octave_user_function *uf = fcn.user_function_value (true);
+
+          if (! uf || ! uf->body ())
+            retval = true;
+        }
+    }
+  else
+    retval = true;
+
+  return retval;
+}
+
+bool
+is_method_executing (const octave_value& ov, const cdef_object& obj)
+{
+  octave_function* stack_fcn = octave_call_stack::current ();
+
+  octave_function* method_fcn = ov.function_value (true);
+
+  // Does the top of the call stack match our target function?
+
+  if (stack_fcn && stack_fcn == method_fcn)
+    {
+      octave_user_function* uf = method_fcn->user_function_value (true);
+
+      // We can only check the context object for user-function (not builtin),
+      // where we have access to the parameters (arguments and return values).
+      // That's ok as there's no need to call this function for builtin
+      // methods.
+
+      if (uf)
+        {
+          // At this point, the method is executing, but we still need to
+          // check the context object for which the method is executing. For
+          // methods, it's the first argument of the function; for ctors, it
+          // is the first return value.
+
+          tree_parameter_list* pl = uf->is_classdef_constructor ()
+            ? uf->return_list () : uf->parameter_list ();
+
+          if (pl && pl->size () > 0)
+            {
+              octave_value arg0 = pl->front ()->lvalue ().value ();
+
+              if (arg0.is_defined () && arg0.type_name () == "object")
+                {
+                  cdef_object arg0_obj = to_cdef (arg0);
+
+                  return obj.is (arg0_obj);
+                }
+            }
+        }
+    }
+
+  return false;
+}
+
+static octave_value_list
+class_get_methods (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      retval(0) = cls.get_methods ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_get_superclasses (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      Cell classes = cls.get ("SuperClasses").cell_value ();
+
+      retval(0) = to_ov (lookup_classes (classes));
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_get_inferiorclasses (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      Cell classes = cls.get ("InferiorClasses").cell_value ();
+
+      retval(0) = to_ov (lookup_classes (classes));
+    }
+
+  return retval;
+}
+
+static octave_value_list
+class_fromName (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        retval(0) = to_ov (lookup_class (name));
+      else
+        error ("fromName: invalid class name, expected a string value");
+    }
+  else
+    error ("fromName: invalid number of parameters");
+
+  return retval;
+}
+
+static octave_value_list
+class_fevalStatic (const octave_value_list& args, int nargout)
+{
+  octave_value_list retval;
+
+  if (args.length () > 1 && args(0).type_name () == "object")
+    {
+      cdef_class cls (to_cdef (args(0)));
+
+      if (! error_state)
+        {
+          std::string meth_name = args(1).string_value ();
+
+          if (! error_state)
+            {
+              cdef_method meth = cls.find_method (meth_name);
+
+              if (meth.ok ())
+                {
+                    if (meth.is_static ())
+                      retval = meth.execute (args.splice (0, 2), nargout,
+                                             true, "fevalStatic");
+                    else
+                      error ("fevalStatic: method `%s' is not static",
+                             meth_name.c_str ());
+                }
+              else
+                error ("fevalStatic: method not found: %s",
+                       meth_name.c_str ());
+            }
+          else
+            error ("fevalStatic: invalid method name, expected a string value");
+        }
+      error ("fevalStatic: invalid object, expected a meta.class object");
+    }
+  else
+    error ("fevalStatic: invalid arguments");
+
+  return retval;
+}
+
+static octave_value_list
+class_getConstant (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 2 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.class")
+    {
+      cdef_class cls = to_cdef (args(0));
+
+      if (! error_state)
+        {
+          std::string prop_name = args(1).string_value ();
+
+          if (! error_state)
+            {
+              cdef_property prop = cls.find_property (prop_name);
+
+              if (prop.ok ())
+                {
+                  if (prop.is_constant ())
+                    retval(0) = prop.get_value (true, "getConstant");
+                  else
+                    error ("getConstant: property `%s' is not constant",
+                           prop_name.c_str ());
+                }
+              else
+                error ("getConstant: property not found: %s",
+                       prop_name.c_str ());
+            }
+          else
+            error ("getConstant: invalid property name, expected a string value");
+        }
+      else
+        error ("getConstant: invalid object, expected a meta.class object");
+    }
+  else
+    error ("getConstant: invalid arguments");
+
+  return retval;
+}
+
+#define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \
+static octave_value_list \
+class_ ## OP (const octave_value_list& args, int /* nargout */) \
+{ \
+  octave_value_list retval; \
+\
+  if (args.length () == 2 \
+      && args(0).type_name () == "object" && args(1).type_name () == "object" \
+      && args(0).class_name () == "meta.class" && args(1).class_name () == "meta.class") \
+    { \
+      cdef_class clsa = to_cdef (args(0)); \
+\
+      cdef_class clsb = to_cdef (args(1)); \
+\
+      if (! error_state) \
+        retval(0) = FUN (CLSA, CLSB); \
+      else \
+        error (#OP ": invalid objects, expected meta.class objects"); \
+    } \
+  else \
+    error (#OP ": invalid arguments"); \
+\
+  return retval; \
+}
+
+META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass)
+META_CLASS_CMP (le, clsb, clsa, is_superclass)
+META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass)
+META_CLASS_CMP (ge, clsa, clsb, is_superclass)
+META_CLASS_CMP (eq, clsa, clsb, operator==)
+META_CLASS_CMP (ne, clsa, clsb, operator!=)
+
+octave_value_list
+property_get_defaultvalue (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1 && args(0).type_name () == "object")
+    {
+      cdef_property prop (to_cdef (args(0)));
+
+      retval(0) = prop.get ("DefaultValue");
+
+      if (! retval(0).is_defined ())
+        error_with_id ("Octave:class:NotDefaultDefined",
+                       "no default value for property `%s'",
+                       prop.get_name ().c_str ());
+    }
+
+  return retval;
+}
+
+static octave_value_list
+handle_delete (const octave_value_list& /* args */, int /* nargout */)
+{
+  octave_value_list retval;
+
+  // FIXME: implement this
+
+  return retval;
+}
+
+static cdef_class
+make_class (const std::string& name,
+            const std::list<cdef_class>& super_list = std::list<cdef_class> ())
+{
+  cdef_class cls (name, super_list);
+
+  cls.set_class (cdef_class::meta_class ());
+  cls.put ("Abstract", false);
+  cls.put ("ConstructOnLoad", false);
+  cls.put ("ContainingPackage", Matrix ());
+  cls.put ("Description", std::string ());
+  cls.put ("DetailedDescription", std::string ());
+  cls.put ("Events", Cell ());
+  cls.put ("Hidden", false);
+  cls.put ("InferiorClasses", Cell ());
+  cls.put ("Methods", Cell ());
+  cls.put ("Properties", Cell ());
+  cls.put ("Sealed", false);
+
+  if (name == "handle")
+    {
+      cls.put ("HandleCompatible", true);
+      cls.mark_as_handle_class ();
+    }
+  else if (super_list.empty ())
+    {
+      cls.put ("HandleCompatible", false);
+    }
+  else
+    {
+      bool all_handle_compatible = true;
+      bool has_handle_class = false;
+
+      for (std::list<cdef_class>::const_iterator it = super_list.begin ();
+           it != super_list.end (); ++it)
+        {
+          all_handle_compatible = all_handle_compatible && it->get ("HandleCompatible").bool_value ();
+          has_handle_class = has_handle_class || it->is_handle_class ();
+        }
+
+      if (has_handle_class && ! all_handle_compatible)
+        ::error ("%s: cannot mix handle and non-HandleCompatible classes",
+                 name.c_str ());
+      else
+        {
+          cls.put ("HandleCompatible", all_handle_compatible);
+          if (has_handle_class)
+            cls.mark_as_handle_class ();
+        }
+    }
+
+  if (error_state)
+    return cdef_class ();
+
+  if (! name.empty ())
+    cdef_manager::register_class (cls);
+
+  return cls;
+}
+
+static cdef_class
+make_class (const std::string& name, const cdef_class& super)
+{
+  return make_class (name, std::list<cdef_class> (1, super));
+}
+
+static cdef_class
+make_meta_class (const std::string& name, const cdef_class& super)
+{
+  cdef_class cls = make_class (name, super);
+
+  cls.put ("Sealed", true);
+  cls.mark_as_meta_class ();
+
+  return cls;
+}
+
+static cdef_property
+make_property (const cdef_class& cls, const std::string& name,
+               const octave_value& get_method = Matrix (),
+               const std::string& get_access = "public",
+               const octave_value& set_method = Matrix (),
+               const std::string& set_access = "public")
+{
+  cdef_property prop (name);
+
+  prop.set_class (cdef_class::meta_property ());
+  prop.put ("Description", std::string ());
+  prop.put ("DetailedDescription", std::string ());
+  prop.put ("Abstract", false);
+  prop.put ("Constant", false);
+  prop.put ("GetAccess", get_access);
+  prop.put ("SetAccess", set_access);
+  prop.put ("Dependent", false);
+  prop.put ("Transient", false);
+  prop.put ("Hidden", false);
+  prop.put ("GetObservable", false);
+  prop.put ("SetObservable", false);
+  prop.put ("GetMethod", get_method);
+  prop.put ("SetMethod", set_method);
+  prop.put ("DefiningClass", to_ov (cls));
+  prop.put ("DefaultValue", octave_value ());
+  prop.put ("HasDefault", false);
+
+  std::string class_name = cls.get_name ();
+
+  if (! get_method.is_empty ())
+    make_function_of_class (class_name, get_method);
+  if (! set_method.is_empty ())
+    make_function_of_class (class_name, set_method);
+
+  return prop;
+}
+
+inline cdef_property
+make_attribute (const cdef_class& cls, const std::string& name)
+{
+  return make_property (cls, name, Matrix (), "public", Matrix (), "private");
+}
+
+static cdef_method
+make_method (const cdef_class& cls, const std::string& name,
+             const octave_value& fcn,const std::string& m_access = "public",
+             bool is_static = false)
+{
+  cdef_method meth (name);
+
+  meth.set_class (cdef_class::meta_method ());
+  meth.put ("Abstract", false);
+  meth.put ("Access", m_access);
+  meth.put ("DefiningClass", to_ov (cls));
+  meth.put ("Description", std::string ());
+  meth.put ("DetailedDescription", std::string ());
+  meth.put ("Hidden", false);
+  meth.put ("Sealed", true);
+  meth.put ("Static", is_static);
+
+  if (fcn.is_defined ())
+    make_function_of_class (cls, fcn);
+
+  meth.set_function (fcn);
+
+  if (is_dummy_method (fcn))
+    meth.mark_as_external (cls.get_name ());
+
+  return meth;
+}
+
+inline cdef_method
+make_method (const cdef_class& cls, const std::string& name,
+             octave_builtin::fcn ff, const std::string& m_access = "public",
+             bool is_static = false)
+{
+  octave_value fcn (new octave_builtin (ff, name));
+
+  return make_method (cls, name, fcn, m_access, is_static);
+}
+
+static cdef_package
+make_package (const std::string& nm,
+              const std::string& parent = std::string ())
+{
+  cdef_package pack (nm);
+
+  pack.set_class (cdef_class::meta_package ());
+  if (parent.empty ())
+    pack.put ("ContainingPackage", Matrix ());
+  else
+    pack.put ("ContainingPackage", to_ov (cdef_manager::find_package (parent)));
+
+  if (! nm.empty ())
+    cdef_manager::register_package (pack);
+
+  return pack;
+}
+
+//----------------------------------------------------------------------------
+
+DEFINE_OCTAVE_ALLOCATOR (octave_classdef);
+
+int octave_classdef::t_id (-1);
+
+const std::string octave_classdef::t_name ("object");
+
+void
+octave_classdef::register_type (void)
+{
+  t_id = octave_value_typeinfo::register_type
+    (octave_classdef::t_name, "<unknown>", octave_value (new octave_classdef ()));
+}
+
+octave_value_list
+octave_classdef::subsref (const std::string& type,
+                          const std::list<octave_value_list>& idx,
+                          int nargout)
+{
+  size_t skip = 0;
+  octave_value_list retval;
+
+  cdef_class cls = object.get_class ();
+
+  if (! in_class_method (cls) && ! called_from_builtin ())
+    {
+      cdef_method meth = cls.find_method ("subsref");
+
+      if (meth.ok ())
+        {
+          octave_value_list args;
+
+          args(1) = make_idx_args (type, idx, "subsref");
+
+          if (! error_state)
+            {
+              count++;
+              args(0) = octave_value (this);
+
+              retval = meth.execute (args, nargout, true, "subsref");
+            }
+
+          return retval;
+        }
+    }
+
+  // At this point, the default subsref mechanism must be used.
+
+  retval = object.subsref (type, idx, nargout, skip, cdef_class ());
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip)
+        retval = retval(0).next_subsref (nargout, type, idx, skip);
+    }
+
+  return retval;
+}
+
+octave_value
+octave_classdef::subsref (const std::string& type,
+                          const std::list<octave_value_list>& idx,
+                          bool auto_add)
+{
+  size_t skip = 0;
+  octave_value_list retval;
+
+  // This variant of subsref is used to create temporary values when doing
+  // assignment with multi-level indexing. AFAIK this is only used for internal
+  // purpose (not sure we should even implement this) and any overload subsref
+  // should not be called.
+
+  retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add);
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip)
+        retval = retval(0).next_subsref (1, type, idx, skip);
+    }
+
+  return retval.length () > 0 ? retval(0) : octave_value ();
+}
+
+octave_value
+octave_classdef::subsasgn (const std::string& type,
+                           const std::list<octave_value_list>& idx,
+                           const octave_value& rhs)
+{
+  octave_value retval;
+
+  cdef_class cls = object.get_class ();
+
+  if (! in_class_method (cls) && ! called_from_builtin ())
+    {
+      cdef_method meth = cls.find_method ("subsasgn");
+
+      if (meth.ok ())
+        {
+          octave_value_list args;
+
+          args(1) = make_idx_args (type, idx, "subsasgn");
+
+          if (! error_state)
+            {
+              count++;
+              args(0) = octave_value (this);
+              args(2) = rhs;
+
+              octave_value_list retlist;
+
+              retlist = meth.execute (args, 1, true, "subsasgn");
+
+              if (! error_state)
+                {
+                  if (retlist.length () > 0)
+                    retval = retlist(0);
+                  else
+                    ::error ("overloaded method `subsasgn' did not return any value");
+                }
+            }
+        }
+    }
+
+  if (! error_state && ! retval.is_defined ())
+    retval = object.subsasgn (type, idx, rhs);
+
+  return retval;
+}
+
+octave_value
+octave_classdef::undef_subsasgn (const std::string& type,
+                                 const std::list<octave_value_list>& idx,
+                                 const octave_value& rhs)
+{
+  if (type.length () == 1 && type[0] == '(')
+    {
+      object = object.make_array ();
+
+      if (! error_state)
+        return subsasgn (type, idx, rhs);
+    }
+  else
+    return octave_base_value::undef_subsasgn (type, idx, rhs);
+
+  return octave_value ();
+}
+
+void
+octave_classdef::print (std::ostream& os, bool)
+{
+  if (! called_from_builtin ())
+    {
+      cdef_method meth = object.get_class ().find_method ("disp");
+
+      if (meth.ok ())
+        {
+          octave_value_list args;
+
+          count++;
+          args(0) = octave_value (this);
+
+          indent (os);
+          meth.execute (args, 0, true, "disp");
+
+          return;
+        }
+    }
+
+  print_raw (os);
+}
+
+void
+octave_classdef::print_raw (std::ostream& os, bool) const
+{
+  indent (os);
+  os << "<object ";
+  if (object.is_array ())
+    os << "array ";
+  os << class_name () << ">";
+  newline (os);
+}
+
+bool
+octave_classdef::print_name_tag (std::ostream& os,
+                                 const std::string& name) const
+{
+  return octave_base_value::print_name_tag (os, name);
+}
+
+void
+octave_classdef::print_with_name (std::ostream& os, const std::string& name,
+                                  bool print_padding)
+{
+  cdef_method meth = object.get_class ().find_method ("display");
+
+  if (meth.ok ())
+    {
+      octave_value_list args;
+
+      count++;
+      args(0) = octave_value (this);
+
+      string_vector arg_names (1);
+
+      arg_names[0] = name;
+      args.stash_name_tags (arg_names);
+
+      indent (os);
+      meth.execute (args, 0, true, "display");
+    }
+  else
+    octave_base_value::print_with_name (os, name, print_padding);
+}
+
+//----------------------------------------------------------------------------
+
+class octave_classdef_meta : public octave_function
+{
+public:
+  octave_classdef_meta (const cdef_meta_object& obj)
+    : object (obj) { }
+
+  ~octave_classdef_meta (void)
+    { object.meta_release (); }
+
+  octave_function* function_value (bool = false) { return this; }
+
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
+    { return object.meta_subsref (type, idx, nargout); }
+
+  octave_value
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx)
+    {
+      octave_value_list retval;
+
+      retval = subsref (type, idx, 1);
+
+      return (retval.length () > 0 ? retval(0) : octave_value ());
+    }
+
+  octave_value_list
+  do_multi_index_op (int nargout, const octave_value_list& idx)
+    {
+      // Emulate ()-type meta subsref
+
+      std::list<octave_value_list> l (1, idx);
+      std::string type ("(");
+
+      return subsref (type, l, nargout);
+    }
+
+  bool is_postfix_index_handled (char type) const
+    { return object.meta_is_postfix_index_handled (type); }
+
+  bool
+  is_classdef_constructor (const std::string& cname = std::string ()) const
+    {
+      bool retval = false;
+
+      if (object.is_class ())
+        {
+          if (cname.empty ())
+            retval = true;
+          else
+            {
+              cdef_class cls (object);
+
+              if (cls.get_name () == cname)
+                retval = true;
+            }
+        }
+
+      return retval;
+    }
+
+private:
+  cdef_meta_object object;
+};
+
+//----------------------------------------------------------------------------
+
+class octave_classdef_superclass_ref : public octave_function
+{
+public:
+  octave_classdef_superclass_ref (const octave_value_list& a)
+    : octave_function (), args (a) { }
+
+  ~octave_classdef_superclass_ref (void) { }
+
+  octave_function* function_value (bool = false) { return this; }
+
+  octave_value_list
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx,
+           int nargout)
+    {
+      size_t skip = 0;
+      octave_value_list retval;
+
+      switch (type[0])
+        {
+        case '(':
+          skip = 1;
+          retval = do_multi_index_op (type.length () > 1 ? 1 : nargout,
+                                      idx.front ());
+          break;
+        default:
+          retval = do_multi_index_op (1, octave_value_list ());
+          break;
+        }
+
+      if (! error_state)
+        {
+          if (type.length () > skip && idx.size () > skip
+              && retval.length () > 0)
+            retval = retval(0).next_subsref (nargout, type, idx, skip);
+        }
+
+      return retval;
+    }
+
+  octave_value
+  subsref (const std::string& type,
+           const std::list<octave_value_list>& idx)
+    {
+      octave_value_list retval;
+
+      retval = subsref (type, idx, 1);
+
+      return (retval.length () > 0 ? retval(0) : octave_value ());
+    }
+
+  octave_value_list
+  do_multi_index_op (int nargout, const octave_value_list& idx)
+    {
+      octave_value_list retval;
+
+      std::string meth_name;
+      bool in_constructor;
+      cdef_class ctx;
+
+      ctx = get_class_context (meth_name, in_constructor);
+
+      if (! error_state && ctx.ok ())
+        {
+          std::string mname = args(0).string_value ();
+          std::string cname = args(1).string_value ();
+
+          cdef_class cls = lookup_class (cname);
+
+          if (! error_state)
+            {
+              if (in_constructor)
+                {
+                  if (is_direct_superclass (cls, ctx))
+                    {
+                      if (is_constructed_object (mname))
+                        {
+                          octave_value sym = symbol_table::varval (mname);
+
+                          cls.run_constructor (to_cdef_ref (sym), idx);
+
+                          retval(0) = sym;
+                        }
+                      else
+                        ::error ("cannot call superclass constructor with "
+                                 "variable `%s'", mname.c_str ());
+                    }
+                  else
+                    ::error ("`%s' is not a direct superclass of `%s'",
+                             cname.c_str (), ctx.get_name ().c_str ());
+                }
+              else
+                {
+                  if (mname == meth_name)
+                    {
+                      if (is_strict_superclass (cls, ctx))
+                        {
+                          // I see 2 possible implementations here:
+                          // 1) use cdef_object::subsref with a different class
+                          //    context; this avoids duplicating code, but
+                          //    assumes the object is always the first argument
+                          // 2) lookup the method manually and call
+                          //    cdef_method::execute; this duplicates part of
+                          //    logic in cdef_object::subsref, but avoid the
+                          //    assumption of 1)
+                          // Not being sure about the assumption of 1), I
+                          // go with option 2) for the time being.
+
+                          cdef_method meth = cls.find_method (meth_name, false);
+
+                          if (meth.ok ())
+                            retval = meth.execute (idx, nargout, true,
+                                                   meth_name);
+                          else
+                            ::error ("no method `%s' found in superclass `%s'",
+                                     meth_name.c_str (), cname.c_str ());
+                        }
+                      else
+                        ::error ("`%s' is not a superclass of `%s'",
+                                 cname.c_str (), ctx.get_name ().c_str ());
+                    }
+                  else
+                    ::error ("method name mismatch (`%s' != `%s')",
+                             mname.c_str (), meth_name.c_str ());
+                }
+            }
+        }
+      else if (! error_state)
+        ::error ("superclass calls can only occur in methods or constructors");
+
+      return retval;
+    }
+
+private:
+  bool is_constructed_object (const std::string nm)
+    {
+      octave_function *of = octave_call_stack::current ();
+
+      if (of->is_classdef_constructor ())
+        {
+          octave_user_function *uf = of->user_function_value (true);
+
+          if (uf)
+            {
+              tree_parameter_list *ret_list = uf->return_list ();
+
+              if (ret_list && ret_list->length () == 1)
+                return (ret_list->front ()->name () == nm);
+            }
+        }
+
+      return false;
+    }
+
+private:
+  octave_value_list args;
+};
+
+//----------------------------------------------------------------------------
+
+string_vector
+cdef_object_rep::map_keys (void) const
+{
+  cdef_class cls = get_class ();
+
+  if (cls.ok ())
+    return cls.get_names ();
+  
+  return string_vector ();
+}
+
+octave_value_list
+cdef_object_scalar::subsref (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             int nargout, size_t& skip,
+                             const cdef_class& context, bool auto_add)
+{
+  skip = 0;
+
+  cdef_class cls = (context.ok () ? context : get_class ());
+
+  octave_value_list retval;
+
+  if (! cls.ok ())
+    return retval;
+
+  switch (type[0])
+    {
+    case '.':
+        {
+          std::string name = (idx.front ())(0).string_value ();
+
+          cdef_method meth = cls.find_method (name);
+
+          if (meth.ok ())
+            {
+              int _nargout = (type.length () > 2 ? 1 : nargout);
+
+              octave_value_list args;
+
+              skip = 1;
+
+              if (type.length () > 1 && type[1] == '(')
+                {
+                  std::list<octave_value_list>::const_iterator it = idx.begin ();
+
+                  args = *++it;
+
+                  skip++;
+                }
+
+              if (meth.is_static ())
+                retval = meth.execute (args, _nargout, true, "subsref");
+              else
+                {
+                  refcount++;
+                  retval = meth.execute (cdef_object (this), args, _nargout,
+                                         true, "subsref");
+                }
+            }
+
+          if (skip == 0 && ! error_state)
+            {
+              cdef_property prop = cls.find_property (name);
+
+              if (prop.ok ())
+                {
+                  if (prop.is_constant ())
+                    retval(0) = prop.get_value (true, "subsref");
+                  else
+                    {
+                      refcount++;
+                      retval(0) = prop.get_value (cdef_object (this),
+                                                  true, "subsref");
+                    }
+
+                  skip = 1;
+                }
+              else
+                error ("subsref: unknown method or property: %s", name.c_str ());
+            }
+          break;
+        }
+
+    case '(':
+        {
+          refcount++;
+
+          cdef_object this_obj (this);
+
+          Array<cdef_object> arr (dim_vector (1, 1), this_obj);
+
+          cdef_object new_obj = cdef_object (new cdef_object_array (arr));
+
+          new_obj.set_class (get_class ());
+
+          retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add);
+        }
+      break;
+
+    default:
+      error ("object cannot be indexed with `%c'", type[0]);
+      break;
+    }
+
+  return retval;
+}
+
+octave_value
+cdef_object_scalar::subsasgn (const std::string& type,
+                              const std::list<octave_value_list>& idx,
+                              const octave_value& rhs)
+{
+  octave_value retval;
+
+  cdef_class cls = get_class ();
+
+  switch (type[0])
+    {
+    case '.':
+        {
+          std::string name = (idx.front ())(0).string_value ();
+
+          if (! error_state)
+            {
+              cdef_property prop = cls.find_property (name);
+
+              if (prop.ok ())
+                {
+                  if (prop.is_constant ())
+                    error ("subsasgn: cannot assign constant property: %s",
+                           name.c_str ());
+                  else
+                    {
+                      refcount++;
+
+                      cdef_object obj (this);
+
+                      if (type.length () == 1)
+                        {
+                          prop.set_value (obj, rhs, true, "subsasgn");
+
+                          if (! error_state)
+                            retval = to_ov (obj);
+                        }
+                      else
+                        {
+                          octave_value val = 
+                            prop.get_value (obj, true, "subsasgn");
+
+                          if (! error_state)
+                            {
+                              std::list<octave_value_list> args (idx);
+
+                              args.erase (args.begin ());
+
+                              val = val.assign (octave_value::op_asn_eq,
+                                                type.substr (1), args, rhs);
+
+                              if (! error_state)
+                                {
+                                  if (val.class_name () != "object"
+                                      || ! to_cdef (val).is_handle_object ())
+                                    prop.set_value (obj, val, true, "subsasgn");
+
+                                  if (! error_state)
+                                    retval = to_ov (obj);
+                                }
+                            }
+                        }
+                    }
+                }
+              else
+                error ("subsasgn: unknown property: %s", name.c_str ());
+            }
+        }
+      break;
+
+    case '(':
+        {
+          refcount++;
+
+          cdef_object this_obj (this);
+
+          Array<cdef_object> arr (dim_vector (1, 1), this_obj);
+
+          cdef_object new_obj = cdef_object (new cdef_object_array (arr));
+
+          new_obj.set_class (get_class ());
+
+          octave_value tmp = new_obj.subsasgn (type, idx, rhs);
+
+          if (! error_state)
+            retval = tmp;
+        }
+      break;
+
+    default:
+      error ("subsasgn: object cannot be index with `%c'", type[0]);
+      break;
+    }
+
+  return retval;
+}
+
+void
+cdef_object_scalar::mark_for_construction (const cdef_class& cls)
+{
+  std::string cls_name = cls.get_name ();
+
+  Cell supcls = cls.get ("SuperClasses").cell_value ();
+
+  if (! error_state)
+    {
+      std::list<cdef_class> supcls_list = lookup_classes (supcls);
+
+      if (! error_state)
+        ctor_list[cls] = supcls_list;
+    }
+}
+
+octave_value_list
+cdef_object_array::subsref (const std::string& type,
+                            const std::list<octave_value_list>& idx,
+                            int /* nargout */, size_t& skip,
+                            const cdef_class& /* context */, bool auto_add)
+{
+  octave_value_list retval;
+
+  skip = 1;
+
+  switch (type[0])
+    {
+    case '(':
+        {
+          const octave_value_list& ival = idx.front ();
+          bool is_scalar = true;
+          Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+          for (int i = 0; ! error_state && i < ival.length (); i++)
+            {
+              iv(i) = ival(i).index_vector ();
+              if (! error_state)
+                is_scalar = is_scalar && iv(i).is_scalar ();
+            }
+
+          if (! error_state)
+            {
+              Array<cdef_object> ires = array.index (iv, auto_add);
+
+              if (! error_state)
+                {
+                  // If resizing is enabled (auto_add = true), it's possible
+                  // indexing was out-of-bound and the result array contains
+                  // invalid cdef_objects.
+
+                  if (auto_add)
+                    fill_empty_values (ires);
+
+                  if (is_scalar)
+                    retval(0) = to_ov (ires(0));
+                  else
+                    {
+                      cdef_object array_obj (new cdef_object_array (ires));
+
+                      array_obj.set_class (get_class ());
+
+                      retval(0) = to_ov (array_obj);
+                    }
+                }
+            }
+        }
+      break;
+
+    case '.':
+      if (type.size () == 1 && idx.size () == 1)
+        {
+          Cell c (dims ());
+
+          octave_idx_type n = array.numel ();
+
+          // dummy variables
+          size_t dummy_skip;
+          cdef_class dummy_cls;
+
+          for (octave_idx_type i = 0; i < n; i++)
+            {
+              octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip,
+                                                      dummy_cls);
+
+              if (! error_state)
+                {
+                  if (r.length () > 0)
+                    c(i) = r(0);
+                }
+              else
+                break;
+            }
+
+          if (! error_state)
+            retval(0) = octave_value (c, true);
+
+          break;
+        }
+      // fall through "default"
+
+    default:
+      ::error ("can't perform indexing operation on array of %s objects",
+               class_name ().c_str ());
+      break;
+    }
+
+  return retval;
+}
+
+octave_value
+cdef_object_array::subsasgn (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             const octave_value& rhs)
+{
+  octave_value retval;
+
+  switch (type[0])
+    {
+    case '(':
+      if (type.length () == 1)
+        {
+          cdef_object rhs_obj = to_cdef (rhs);
+
+          if (! error_state)
+            {
+              if (rhs_obj.get_class () == get_class ())
+                {
+                  const octave_value_list& ival = idx.front ();
+                  bool is_scalar = true;
+                  Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+                  for (int i = 0; ! error_state && i < ival.length (); i++)
+                    {
+                      iv(i) = ival(i).index_vector ();
+                      if (! error_state)
+                        is_scalar = is_scalar && iv(i).is_scalar ();
+                    }
+
+                  if (! error_state)
+                    {
+                      Array<cdef_object> rhs_mat;
+
+                      if (! rhs_obj.is_array ())
+                        {
+                          rhs_mat = Array<cdef_object> (dim_vector (1, 1));
+                          rhs_mat(0) = rhs_obj;
+                        }
+                      else
+                        rhs_mat = rhs_obj.array_value ();
+
+                      if (! error_state)
+                        {
+                          octave_idx_type n = array.numel ();
+
+                          array.assign (iv, rhs_mat, cdef_object ());
+
+                          if (! error_state)
+                            {
+                              if (array.numel () > n)
+                                fill_empty_values ();
+
+                              if (! error_state)
+                                {
+                                  refcount++;
+                                  retval = to_ov (cdef_object (this));
+                                }
+                            }
+                        }
+                    }
+                }
+              else
+                ::error ("can't assign %s object into array of %s objects.",
+                         rhs_obj.class_name ().c_str (),
+                         class_name ().c_str ());
+            }
+        }
+      else
+        {
+          const octave_value_list& ival = idx.front ();
+
+          bool is_scalar = true;
+
+          Array<idx_vector> iv (dim_vector (1, ival.length ()));
+
+          for (int i = 0; ! error_state && i < ival.length (); i++)
+            {
+              iv(i) = ival(i).index_vector ();
+
+              if (! error_state)
+                {
+                  is_scalar = is_scalar && iv(i).is_scalar ();
+
+                  if (! is_scalar)
+                    error ("subsasgn: invalid indexing for object array "
+                           "assignment, the index must reference a single "
+                           "object in the array.");
+                }
+            }
+
+          if (! error_state)
+            {
+              Array<cdef_object> a = array.index (iv, true);
+
+              if (a.numel () != 1)
+                error ("subsasgn: invalid indexing for object array "
+                       "assignment");
+
+              if (! error_state)
+                {
+                  cdef_object obj = a(0);
+
+                  int ignore_copies = 0;
+
+                  // If the object in 'a' is not valid, this means the index
+                  // was out-of-bound and we need to create a new object.
+
+                  if (! obj.ok ())
+                    obj = get_class ().construct_object (octave_value_list ());
+                  else
+                    // Optimize the subsasgn call to come. There are 2 copies
+                    // that we can safely ignore:
+                    // - 1 in "array"
+                    // - 1 in "a"
+                    ignore_copies = 2;
+
+                  std::list<octave_value_list> next_idx (idx);
+
+                  next_idx.erase (next_idx.begin ());
+
+                  octave_value tmp = obj.subsasgn (type.substr (1), next_idx,
+                                                   rhs, ignore_copies);
+
+                  if (! error_state)
+                    {
+                      cdef_object robj = to_cdef (tmp);
+
+                      if (robj.ok ()
+                          && ! robj.is_array ()
+                          && robj.get_class () == get_class ())
+                        {
+                          // Small optimization, when dealing with handle
+                          // objects, we don't need to re-assign the result
+                          // of subsasgn back into the array.
+
+                          if (! robj.is (a(0)))
+                            {
+                              Array<cdef_object> rhs_a (dim_vector (1, 1),
+                                                        robj);
+
+                              octave_idx_type n = array.numel ();
+
+                              array.assign (iv, rhs_a);
+
+                              if (array.numel () > n)
+                                fill_empty_values ();
+                            }
+
+                          refcount++;
+
+                          retval = to_ov (cdef_object (this));
+                        }
+                      else
+                        error ("subasgn: invalid assignment into array of %s "
+                               "objects", class_name ().c_str ());
+                    }
+                }
+            }
+        }
+      break;
+
+    default:
+      ::error ("can't perform indexing operation on array of %s objects",
+               class_name ().c_str ());
+      break;
+    }
+
+  return retval;
+}
+
+void
+cdef_object_array::fill_empty_values (Array<cdef_object>& arr)
+{
+  cdef_class cls = get_class ();
+
+  if (! error_state)
+    {
+      cdef_object obj;
+
+      int n = arr.numel ();
+
+      for (int i = 0; ! error_state && i < n; i++)
+        {
+          if (! arr.xelem (i).ok ())
+            {
+              if (! obj.ok ())
+                {
+                  obj = cls.construct_object (octave_value_list ());
+
+                  if (! error_state)
+                    arr.xelem (i) = obj;
+                }
+              else
+                arr.xelem (i) = obj.copy ();
+            }
+        }
+    }
+}
+  
+bool cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
+{
+  return (is_constructed ()
+          || ctor_list.find (cls) == ctor_list.end ());
+}
+
+bool cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const
+{
+  std::map< cdef_class, std::list<cdef_class> >::const_iterator it;
+
+  if (is_constructed ())
+    return true;
+  else if ((it = ctor_list.find (cls)) == ctor_list.end ()
+           || it->second.empty ())
+    return true;
+
+  for (std::list<cdef_class>::const_iterator lit = it->second.begin ();
+       lit != it->second.end (); ++lit)
+    if (! is_constructed_for (*lit))
+      return false;
+
+  return true;
+}
+
+handle_cdef_object::~handle_cdef_object (void)
+{
+  gnulib::printf ("deleting %s object (handle)\n",
+                  get_class ().get_name ().c_str ());
+}
+
+value_cdef_object::~value_cdef_object (void)
+{
+  gnulib::printf ("deleting %s object (value)\n",
+                  get_class ().get_name ().c_str ());
+}
+
+cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)
+     : cdef_meta_object_rep (), member_count (0), handle_class (false),
+       object_count (0), meta (false)
+{
+  put ("SuperClasses", to_ov (superclasses));
+  implicit_ctor_list = superclasses;
+}
+
+cdef_method
+cdef_class::cdef_class_rep::find_method (const std::string& nm, bool local)
+{
+  method_iterator it = method_map.find (nm);
+
+  if (it == method_map.end ())
+    {
+      // FIXME: look into class directory
+    }
+  else
+    {
+      cdef_method& meth = it->second;
+
+      // FIXME: check if method reload needed
+
+      if (meth.ok ())
+        return meth;
+    }
+
+  if (! local)
+    {
+      // Look into superclasses
+
+      Cell super_classes = get ("SuperClasses").cell_value ();
+
+      for (int i = 0; i < super_classes.numel (); i++)
+        {
+          cdef_class cls = lookup_class (super_classes(i));
+
+          if (! error_state)
+            {
+              cdef_method meth = cls.find_method (nm);
+
+              if (meth.ok ())
+                return meth;
+            }
+        }
+    }
+
+  return cdef_method ();
+}
+
+class ctor_analyzer : public tree_walker
+{
+public:
+  ctor_analyzer (const std::string& ctor, const std::string& obj)
+    : tree_walker (), who (ctor), obj_name (obj) { }
+
+  void visit_statement_list (tree_statement_list& t)
+    {
+      for (tree_statement_list::const_iterator it = t.begin ();
+           ! error_state && it != t.end (); ++it)
+        (*it)->accept (*this);
+    }
+
+  void visit_statement (tree_statement& t)
+    {
+      if (t.is_expression ())
+        t.expression ()->accept (*this);
+    }
+
+  void visit_simple_assignment (tree_simple_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+  void visit_multi_assignment (tree_multi_assignment& t)
+    {
+      t.right_hand_side ()->accept (*this);
+    }
+
+  void visit_index_expression (tree_index_expression& t)
+    {
+      t.expression ()->accept (*this);
+    }
+
+  void visit_funcall (tree_funcall& t)
+    {
+      octave_value fcn = t.function ();
+
+      if (fcn.is_function ())
+        {
+          octave_function *of = fcn.function_value (true);
+
+          if (of)
+            {
+              if (of->name () == "__superclass_reference__")
+                {
+                  octave_value_list args = t.arguments ();
+
+                  if (args(0).string_value () == obj_name)
+                    {
+                      std::string class_name = args(1).string_value ();
+
+                      cdef_class cls = lookup_class (class_name, false);
+
+                      if (cls.ok ())
+                        ctor_list.push_back (cls);
+                    }
+                }
+            }
+        }
+    }
+
+  std::list<cdef_class> get_constructor_list (void) const
+    { return ctor_list; }
+
+  // NO-OP
+  void visit_anon_fcn_handle (tree_anon_fcn_handle&) { }
+  void visit_argument_list (tree_argument_list&) { }
+  void visit_binary_expression (tree_binary_expression&) { }
+  void visit_break_command (tree_break_command&) { }
+  void visit_colon_expression (tree_colon_expression&) { }
+  void visit_continue_command (tree_continue_command&) { }
+  void visit_global_command (tree_global_command&) { }
+  void visit_persistent_command (tree_persistent_command&) { }
+  void visit_decl_elt (tree_decl_elt&) { }
+  void visit_decl_init_list (tree_decl_init_list&) { }
+  void visit_simple_for_command (tree_simple_for_command&) { }
+  void visit_complex_for_command (tree_complex_for_command&) { }
+  void visit_octave_user_script (octave_user_script&) { }
+  void visit_octave_user_function (octave_user_function&) { }
+  void visit_function_def (tree_function_def&) { }
+  void visit_identifier (tree_identifier&) { }
+  void visit_if_clause (tree_if_clause&) { }
+  void visit_if_command (tree_if_command&) { }
+  void visit_if_command_list (tree_if_command_list&) { }
+  void visit_switch_case (tree_switch_case&) { }
+  void visit_switch_case_list (tree_switch_case_list&) { }
+  void visit_switch_command (tree_switch_command&) { }
+  void visit_matrix (tree_matrix&) { }
+  void visit_cell (tree_cell&) { }
+  void visit_no_op_command (tree_no_op_command&) { }
+  void visit_constant (tree_constant&) { }
+  void visit_fcn_handle (tree_fcn_handle&) { }
+  void visit_parameter_list (tree_parameter_list&) { }
+  void visit_postfix_expression (tree_postfix_expression&) { }
+  void visit_prefix_expression (tree_prefix_expression&) { }
+  void visit_return_command (tree_return_command&) { }
+  void visit_return_list (tree_return_list&) { }
+  void visit_try_catch_command (tree_try_catch_command&) { }
+  void visit_unwind_protect_command (tree_unwind_protect_command&) { }
+  void visit_while_command (tree_while_command&) { }
+  void visit_do_until_command (tree_do_until_command&) { }
+
+private:
+  /* The name of the constructor being analyzed */
+  std::string who;
+
+  /* The name of the first output argument of the constructor */
+  std::string obj_name;
+
+  /* The list of superclass constructors that are explicitly called */
+  std::list<cdef_class> ctor_list;
+};
+
+void
+cdef_class::cdef_class_rep::install_method (const cdef_method& meth)
+{
+  method_map[meth.get_name ()] = meth;
+
+  member_count++;
+
+  if (meth.is_constructor ())
+    {
+      // Analyze the constructor code to determine what superclass
+      // constructors are called explicitly.
+
+      octave_function *of = meth.get_function ().function_value (true);
+
+      if (of)
+        {
+          octave_user_function *uf = of->user_function_value (true);
+
+          if (uf)
+            {
+              tree_parameter_list *ret_list = uf->return_list ();
+              tree_statement_list *body = uf->body ();
+
+              if (ret_list && ret_list->size () == 1)
+                {
+                  std::string obj_name = ret_list->front ()->name ();
+                  ctor_analyzer a (meth.get_name (), obj_name);
+
+                  body->accept (a);
+                  if (! error_state)
+                    {
+                      std::list<cdef_class> explicit_ctor_list
+                        = a.get_constructor_list ();
+
+                      for (std::list<cdef_class>::const_iterator it = explicit_ctor_list.begin ();
+                           ! error_state && it != explicit_ctor_list.end (); ++it)
+                        {
+                          gnulib::printf ("explicit superclass constructor: %s\n",
+                                          it->get_name ().c_str ());
+                          implicit_ctor_list.remove (*it);
+                        }
+                    }
+                }
+              else
+                ::error ("%s: invalid constructor output arguments",
+                         meth.get_name ().c_str ());
+            }
+        }
+    }
+}
+
+void
+cdef_class::cdef_class_rep::load_all_methods (void)
+{
+  // FIXME: re-scan class directory
+}
+
+Cell
+cdef_class::cdef_class_rep::get_methods (void)
+{
+  std::map<std::string,cdef_method> meths;
+
+  find_methods (meths, false);
+
+  if (! error_state)
+    {
+      Cell c (meths.size (), 1);
+
+      int idx = 0;
+
+      for (std::map<std::string,cdef_method>::const_iterator it = meths.begin ();
+           it != meths.end (); ++it, ++idx)
+        c (idx, 0) = to_ov (it->second);
+
+      return c;
+    }
+
+  return Cell ();
+}
+
+void
+cdef_class::cdef_class_rep::find_methods (std::map<std::string, cdef_method>& meths,
+                                          bool only_inherited)
+{
+  load_all_methods ();
+
+  method_const_iterator it;
+
+  for (it = method_map.begin (); it != method_map.end (); ++it)
+    {
+      if (! it->second.is_constructor ())
+        {
+          std::string nm = it->second.get_name ();
+
+          if (meths.find (nm) == meths.end ())
+            {
+              if (only_inherited)
+                {
+                  octave_value acc = it->second.get ("Access");
+
+                  if (! acc.is_string ()
+                      || acc.string_value () == "private")
+                    continue;
+                }
+
+              meths[nm] = it->second;
+            }
+        }
+    }
+
+  // Look into superclasses
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+        cls.get_rep ()->find_methods (meths, true);
+      else
+        break;
+    }
+}
+
+cdef_property
+cdef_class::cdef_class_rep::find_property (const std::string& nm)
+{
+  property_iterator it = property_map.find (nm);
+
+  if (it != property_map.end ())
+    {
+      cdef_property& prop = it->second;
+
+      if (prop.ok ())
+        return prop;
+    }
+
+  // Look into superclasses
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+        {
+          cdef_property prop = cls.find_property (nm);
+
+          if (prop.ok ())
+            return prop;
+        }
+    }
+
+  return cdef_property ();
+}
+
+void
+cdef_class::cdef_class_rep::install_property (const cdef_property& prop)
+{
+  property_map[prop.get_name ()] = prop;
+
+  member_count++;
+}
+
+Cell
+cdef_class::cdef_class_rep::get_properties (void)
+{
+  std::map<std::string,cdef_property> props;
+
+  find_properties (props, false);
+
+  if (! error_state)
+    {
+      Cell c (props.size (), 1);
+
+      int idx = 0;
+
+      for (std::map<std::string,cdef_property>::const_iterator it = props.begin ();
+           it != props.end (); ++it, ++idx)
+        c (idx, 0) = to_ov (it->second);
+
+      return c;
+    }
+
+  return Cell ();
+}
+
+void
+cdef_class::cdef_class_rep::find_properties (std::map<std::string,cdef_property>& props,
+                                             bool only_inherited)
+{
+  property_const_iterator it;
+
+  for (it = property_map.begin (); ! error_state && it != property_map.end ();
+       ++it)
+    {
+      std::string nm = it->second.get_name ();
+
+      if (props.find (nm) == props.end ())
+        {
+          if (only_inherited)
+            {
+              octave_value acc = it->second.get ("GetAccess");
+
+              if (! acc.is_string ()
+                  || acc.string_value () == "private")
+                continue;
+            }
+
+          props[nm] = it->second;
+        }
+    }
+
+  // Look into superclasses
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; ! error_state && i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+        cls.get_rep ()->find_properties (props, true);
+      else
+        break;
+    }
+}
+
+void
+cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
+                                        bool all)
+{
+  load_all_methods ();
+
+  for (method_const_iterator it = method_map.begin ();
+       ! error_state && it != method_map.end(); ++it)
+    {
+      if (! it->second.is_constructor ())
+        {
+          std::string nm = it->second.get_name ();
+
+          if (! all)
+            {
+              octave_value acc = it->second.get ("Access");
+
+              if (! acc.is_string()
+                  || acc.string_value () != "public")
+                continue;
+            }
+
+          names.insert (nm);
+        }
+    }
+
+  for (property_const_iterator it = property_map.begin ();
+       ! error_state && it != property_map.end (); ++it)
+    {
+      std::string nm = it->second.get_name ();
+
+      if (! all)
+        {
+          octave_value acc = it->second.get ("GetAccess");
+
+          if (! acc.is_string()
+              || acc.string_value () != "public")
+            continue;
+        }
+
+      names.insert (nm);
+    }
+
+  // Look into superclasses
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; ! error_state && i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (! error_state)
+        cls.get_rep ()->find_names (names, all);
+      else
+        break;
+    }
+}
+
+string_vector
+cdef_class::cdef_class_rep::get_names (void)
+{
+  std::set<std::string> names;
+
+  find_names (names, false);
+
+  if (! error_state)
+    {
+      string_vector v (names.size ());
+
+      int idx = 0;
+      for (std::set<std::string>::const_iterator it = names.begin ();
+           it != names.end (); ++it, ++idx)
+        v[idx] = *it;
+
+      return v.sort (true);
+    }
+
+  return string_vector ();
+}
+
+void
+cdef_class::cdef_class_rep::delete_object (cdef_object obj)
+{
+  method_iterator it = method_map.find ("delete");
+
+  if (it != method_map.end ())
+    {
+      cdef_class cls = obj.get_class ();
+
+      obj.set_class (wrap ());
+
+      it->second.execute (obj, octave_value_list (), 0, false);
+
+      obj.set_class (cls);
+    }
+
+  // FIXME: should we destroy corresponding properties here?
+
+  // Call "delete" in super classes
+
+  Cell super_classes = get ("SuperClasses").cell_value ();
+
+  for (int i = 0; i < super_classes.numel (); i++)
+    {
+      cdef_class cls = lookup_class (super_classes(i));
+
+      if (!error_state)
+        cls.delete_object (obj);
+    }
+}
+
+octave_value_list
+cdef_class::cdef_class_rep::meta_subsref (const std::string& type,
+                                          const std::list<octave_value_list>& idx,
+                                          int nargout)
+{
+  size_t skip = 1;
+
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      // Constructor call
+      gnulib::printf ("constructor\n");
+      retval(0) = construct (idx.front ());
+      break;
+
+    case '.':
+      // Static method, constant (or property?)
+      gnulib::printf ("static method/property\n");
+      if (idx.front ().length () == 1)
+        {
+          std::string nm = idx.front ()(0).string_value ();
+
+          if (! error_state)
+            {
+              cdef_method meth = find_method (nm);
+
+              if (meth.ok ())
+                {
+                  if (meth.is_static ())
+                    {
+                      octave_value_list args;
+
+                      if (type.length () > 1 && idx.size () > 1
+                          && type[1] == '(')
+                        {
+                          args = *(++(idx.begin ()));
+                          skip++;
+                        }
+
+                      retval = meth.execute (args, (type.length () > skip
+                                                    ? 1 : nargout), true,
+                                             "meta.class");
+                    }
+                  else
+                    ::error ("method `%s' is not static", nm.c_str ());
+                }
+              else
+                {
+                  cdef_property prop = find_property (nm);
+
+                  if (prop.ok ())
+                    {
+                      if (prop.is_constant ())
+                        retval(0) = prop.get_value (true, "meta.class");
+                      else
+                        ::error ("property `%s' is not constant",
+                                 nm.c_str ());
+                    }
+                  else
+                    ::error ("no such method or property `%s'", nm.c_str ());
+                }
+            }
+          else
+            ::error ("invalid meta.class indexing, expected a method or property name");
+        }
+      else
+        ::error ("invalid meta.class indexing");
+      break;
+
+    default:
+      ::error ("invalid meta.class indexing");
+      break;
+    }
+
+  if (! error_state)
+    {
+      if (type.length () > skip && idx.size () > skip && ! retval.empty ())
+        retval = retval(0).next_subsref (nargout, type, idx, skip);
+    }
+
+  return retval;
+}
+
+void
+cdef_class::cdef_class_rep::meta_release (void)
+{
+  cdef_manager::unregister_class (wrap ());
+}
+
+void
+cdef_class::cdef_class_rep::initialize_object (cdef_object& obj)
+{
+  // Populate the object with default property values
+
+  std::list<cdef_class> super_classes = lookup_classes (get ("SuperClasses").cell_value ());
+
+  if (! error_state)
+    {
+      for (std::list<cdef_class>::iterator it = super_classes.begin ();
+           ! error_state && it != super_classes.end (); ++it)
+        it->initialize_object (obj);
+
+      if (! error_state)
+        {
+          for (property_const_iterator it = property_map.begin ();
+               ! error_state && it != property_map.end (); ++it)
+            {
+              if (! it->second.get ("Dependent").bool_value ())
+                {
+                  octave_value pvalue = it->second.get ("DefaultValue");
+
+                  if (pvalue.is_defined ())
+                    obj.put (it->first, pvalue);
+                  else
+                    obj.put (it->first, octave_value (Matrix ()));
+                }
+            }
+
+          if (! error_state)
+            {
+              refcount++;
+              obj.mark_for_construction (cdef_class (this));
+            }
+        }
+    }
+}
+
+void
+cdef_class::cdef_class_rep::run_constructor (cdef_object& obj,
+                                             const octave_value_list& args)
+{
+  octave_value_list empty_args;
+
+  for (std::list<cdef_class>::const_iterator it = implicit_ctor_list.begin ();
+       ! error_state && it != implicit_ctor_list.end (); ++it)
+    {
+      cdef_class supcls = lookup_class (*it);
+
+      if (! error_state)
+        supcls.run_constructor (obj, empty_args);
+    }
+
+  if (error_state)
+    return;
+
+  std::string cls_name = get_name ();
+  std::string ctor_name = get_base_name (cls_name);
+
+  cdef_method ctor = find_method (ctor_name);
+
+  if (ctor.ok ())
+    {
+      octave_value_list ctor_args (args);
+      octave_value_list ctor_retval;
+
+      ctor_args.prepend (to_ov (obj));
+      ctor_retval = ctor.execute (ctor_args, 1, true, "constructor");
+
+      if (! error_state)
+        {
+          if (ctor_retval.length () == 1)
+            obj = to_cdef (ctor_retval(0));
+          else
+            {
+              ::error ("%s: invalid number of output arguments for classdef constructor",
+                       ctor_name.c_str ());
+              return;
+            }
+        }
+    }
+
+  obj.mark_as_constructed (wrap ());
+}
+
+octave_value
+cdef_class::cdef_class_rep::construct (const octave_value_list& args)
+{
+  cdef_object obj = construct_object (args);
+
+  if (! error_state && obj.ok ())
+    return to_ov (obj);
+
+  return octave_value ();
+}
+
+cdef_object
+cdef_class::cdef_class_rep::construct_object (const octave_value_list& args)
+{
+  if (! is_abstract ())
+    {
+      cdef_object obj;
+
+      if (is_meta_class ())
+        {
+          // This code path is only used to create empty meta objects
+          // as filler for the empty values within a meta object array.
+
+          cdef_class this_cls = wrap ();
+
+          static cdef_object empty_class;
+
+          if (this_cls == cdef_class::meta_class ())
+            {
+              if (! empty_class.ok ())
+                empty_class = make_class ("", std::list<cdef_class> ());
+              obj = empty_class;
+            }
+          else if (this_cls == cdef_class::meta_property ())
+            {
+              static cdef_property empty_property;
+
+              if (! empty_class.ok ())
+                empty_class = make_class ("", std::list<cdef_class> ());
+              if (! empty_property.ok ())
+                empty_property = make_property (empty_class, "");
+              obj = empty_property;
+            }
+          else if (this_cls == cdef_class::meta_method ())
+            {
+              static cdef_method empty_method;
+
+              if (! empty_class.ok ())
+                empty_class = make_class ("", std::list<cdef_class> ());
+              if (! empty_method.ok ())
+                empty_method = make_method (empty_class, "", octave_value ());
+              obj = empty_method;
+            }
+          else if (this_cls == cdef_class::meta_package ())
+            {
+              static cdef_package empty_package;
+
+              if (! empty_package.ok ())
+                empty_package = make_package ("");
+              obj = empty_package;
+            }
+          else
+            panic_impossible ();
+
+          return obj;
+        }
+      else
+        {
+          if (is_handle_class ())
+            obj = cdef_object (new handle_cdef_object ());
+          else
+            obj = cdef_object (new value_cdef_object ());
+          obj.set_class (wrap ());
+
+          initialize_object (obj);
+
+          if (! error_state)
+            {
+              run_constructor (obj, args);
+
+              if (! error_state)
+                return obj;
+            }
+        }
+    }
+  else
+    error ("cannot instantiate object for abstract class `%s'",
+           get_name ().c_str ());
+
+  return cdef_object ();
+}
+
+static octave_value
+compute_attribute_value (tree_classdef_attribute* t)
+{
+  if (t->expression ())
+    {
+      if (t->expression ()->is_identifier ())
+        {
+          std::string s = t->expression ()->name ();
+
+          if (s == "public")
+            return std::string ("public");
+          else if (s == "protected")
+            return std::string ("protected");
+          else if (s == "private")
+            return std::string ("private");
+        }
+
+      return t->expression ()->rvalue1 ();
+    }
+  else
+    return octave_value (true);
+}
+
+template<class T>
+static std::string
+attribute_value_to_string (T* t, octave_value v)
+{
+  if (v.is_string ())
+    return v.string_value ();
+  else if (t->expression ())
+    return t->expression ()->original_text ();
+  else
+    return std::string ("true");
+}
+
+cdef_class
+cdef_class::make_meta_class (tree_classdef* t, bool is_at_folder)
+{
+  cdef_class retval;
+  std::string class_name, full_class_name;
+
+  // Class creation
+
+  class_name = full_class_name = t->ident ()->name ();
+  if (! t->package_name ().empty ())
+    full_class_name = t->package_name () + "." + full_class_name;
+  gnulib::printf ("class: %s\n", full_class_name.c_str ());
+
+  std::list<cdef_class> slist;
+
+  if (t->superclass_list ())
+    {
+      for (tree_classdef_superclass_list::iterator it = t->superclass_list ()->begin ();
+           ! error_state && it != t->superclass_list ()->end (); ++it)
+        {
+          std::string sclass_name = (*it)->class_name ();
+
+          gnulib::printf ("superclass: %s\n", sclass_name.c_str ());
+
+          cdef_class sclass = lookup_class (sclass_name);
+
+          if (! error_state)
+            {
+              if (! sclass.get ("Sealed").bool_value ())
+                slist.push_back (sclass);
+              else
+                {
+                  ::error ("`%s' cannot inherit from `%s', because it is sealed",
+                           full_class_name.c_str (), sclass_name.c_str ());
+                  return retval;
+                }
+            }
+          else
+            return retval;
+
+        }
+    }
+
+  retval = ::make_class (full_class_name, slist);
+
+  if (error_state)
+    return cdef_class ();
+
+  // Package owning this class
+
+  if (! t->package_name ().empty ())
+    {
+      cdef_package pack = cdef_manager::find_package (t->package_name ());
+
+      if (! error_state && pack.ok ())
+        retval.put ("ContainingPackage", to_ov (pack));
+    }
+
+  // Class attributes
+
+  if (t->attribute_list ())
+    {
+      for (tree_classdef_attribute_list::iterator it = t->attribute_list ()->begin ();
+           it != t->attribute_list ()->end (); ++it)
+        {
+          std::string aname = (*it)->ident ()->name ();
+          octave_value avalue = compute_attribute_value (*it);
+
+          gnulib::printf ("class attribute: %s = %s\n", aname.c_str (),
+                  attribute_value_to_string (*it, avalue).c_str ());
+          retval.put (aname, avalue);
+        }
+    }
+
+  tree_classdef_body* b = t->body ();
+
+  if (b)
+    {
+      // Keep track of the get/set accessor methods. They will be used
+      // later on when creating properties.
+
+      std::map<std::string, octave_value> get_methods;
+      std::map<std::string, octave_value> set_methods;
+
+      // Method blocks
+
+      std::list<tree_classdef_methods_block *> mb_list = b->methods_list ();
+
+      for (tree_classdef_body::methods_list_iterator it = mb_list.begin ();
+           it != mb_list.end (); ++it)
+        {
+          std::map<std::string, octave_value> amap;
+          gnulib::printf ("method block\n");
+
+          // Method attributes
+
+          if ((*it)->attribute_list ())
+            {
+              for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin ();
+                   ait != (*it)->attribute_list ()->end (); ++ait)
+                {
+                  std::string aname = (*ait)->ident ()->name ();
+                  octave_value avalue = compute_attribute_value (*ait);
+
+                  gnulib::printf ("method attribute: %s = %s\n", aname.c_str (),
+                                  attribute_value_to_string (*ait, avalue).c_str ());
+                  amap[aname] = avalue;
+                }
+            }
+
+          // Methods
+
+          if ((*it)->element_list ())
+            {
+              for (tree_classdef_methods_list::iterator mit = (*it)->element_list ()->begin ();
+                   mit != (*it)->element_list ()->end (); ++mit)
+                {
+                  std::string mname = mit->function_value ()->name ();
+                  std::string mprefix = mname.substr (0, 4);
+
+                  if (mprefix == "get.")
+                    get_methods[mname.substr (4)] =
+                      make_fcn_handle (*mit, full_class_name + ">" + mname);
+                  else if (mprefix == "set.")
+                    set_methods[mname.substr (4)] =
+                      make_fcn_handle (*mit, full_class_name + ">" + mname);
+                  else
+                    {
+                      cdef_method meth = make_method (retval, mname, *mit);
+
+                      gnulib::printf ("%s: %s\n", (mname == class_name ? "constructor" : "method"),
+                                      mname.c_str ());
+                      for (std::map<std::string, octave_value>::iterator ait = amap.begin ();
+                           ait != amap.end (); ++ait)
+                        meth.put (ait->first, ait->second);
+
+                      retval.install_method (meth);
+                    }
+                }
+            }
+        }
+
+      if (is_at_folder)
+        {
+          // Look for all external methods visible on octave path at the
+          // time of loading of the class.
+          //
+          // TODO: This is an "extension" to Matlab behavior, which only
+          // looks in the @-folder containing the original classdef
+          // file. However, this is easier to implement it that way at
+          // the moment.
+
+          std::list<std::string> external_methods =
+            load_path::methods (full_class_name);
+
+          for (std::list<std::string>::const_iterator it = external_methods.begin ();
+               it != external_methods.end (); ++it)
+            {
+              // TODO: should we issue a warning if the method is already
+              // defined in the classdef file?
+
+              if (*it != class_name
+                  && ! retval.find_method (*it, true).ok ())
+                {
+                  // Create a dummy method that is used until the actual
+                  // method is loaded.
+
+                  octave_user_function *fcn = new octave_user_function ();
+
+                  fcn->stash_function_name (*it);
+
+                  cdef_method meth = make_method (retval, *it,
+                                                  octave_value (fcn));
+
+                  retval.install_method (meth);
+                }
+            }
+        }
+
+      // Property blocks
+
+      // FIXME: default property expression should be able to call static
+      //        methods of the class being constructed. A restricted CLASSNAME
+      //        symbol should be added to the scope before evaluating default
+      //        value expressions.
+
+      std::list<tree_classdef_properties_block *> pb_list = b->properties_list ();
+
+      for (tree_classdef_body::properties_list_iterator it = pb_list.begin ();
+           it != pb_list.end (); ++it)
+        {
+          std::map<std::string, octave_value> amap;
+          gnulib::printf ("property block\n");
+
+          // Property attributes
+
+          if ((*it)->attribute_list ())
+            {
+              for (tree_classdef_attribute_list::iterator ait = (*it)->attribute_list ()->begin ();
+                   ait != (*it)->attribute_list ()->end (); ++ait)
+                {
+                  std::string aname = (*ait)->ident ()->name ();
+                  octave_value avalue = compute_attribute_value (*ait);
+
+                  gnulib::printf ("property attribute: %s = %s\n", aname.c_str (),
+                          attribute_value_to_string (*ait, avalue).c_str ());
+                  if (aname == "Access")
+                    {
+                      amap["GetAccess"] = avalue;
+                      amap["SetAccess"] = avalue;
+                    }
+                  else
+                    amap[aname] = avalue;
+                }
+            }
+
+          // Properties
+
+          if ((*it)->element_list ())
+            {
+              for (tree_classdef_property_list::iterator pit = (*it)->element_list ()->begin ();
+                   pit != (*it)->element_list ()->end (); ++pit)
+                {
+                  std::string prop_name = (*pit)->ident ()->name ();
+
+                  cdef_property prop = ::make_property (retval, prop_name);
+
+                  gnulib::printf ("property: %s\n", (*pit)->ident ()->name ().c_str ());
+                  if ((*pit)->expression ())
+                    {
+                      octave_value pvalue = (*pit)->expression ()->rvalue1 ();
+
+                      gnulib::printf ("property default: %s\n",
+                              attribute_value_to_string (*pit, pvalue).c_str ());
+                      prop.put ("DefaultValue", pvalue);
+                    }
+
+                  // Install property attributes. This is done before assigning the
+                  // property accessors so we can do validationby using cdef_property
+                  // methods.
+
+                  for (std::map<std::string, octave_value>::iterator ait = amap.begin ();
+                       ait != amap.end (); ++ait)
+                    prop.put (ait->first, ait->second);
+
+                  // Install property access methods, if any. Remove the accessor
+                  // methods from the temporary storage map, so we can detect which
+                  // ones are invalid and do not correspond to a defined property.
+
+                  std::map<std::string, octave_value>::iterator git =
+                    get_methods.find (prop_name);
+
+                  if (git != get_methods.end ())
+                    {
+                      make_function_of_class (retval, git->second);
+                      prop.put ("GetMethod", git->second);
+                      get_methods.erase (git);
+                    }
+
+                  std::map<std::string, octave_value>::iterator sit =
+                    set_methods.find (prop_name);
+
+                  if (sit != set_methods.end ())
+                    {
+                      make_function_of_class (retval, sit->second);
+                      prop.put ("SetMethod", sit->second);
+                      set_methods.erase (sit);
+                    }
+
+                  retval.install_property (prop);
+                }
+            }
+        }
+    }
+
+  return retval;
+}
+
+octave_function*
+cdef_class::get_method_function (const std::string& /* nm */)
+{
+  octave_classdef_meta* p = new octave_classdef_meta (*this);
+
+  return p;
+}
+
+octave_value
+cdef_property::cdef_property_rep::get_value (const cdef_object& obj,
+                                             bool do_check_access,
+                                             const std::string& who)
+{
+  octave_value retval;
+
+  if (do_check_access && ! check_get_access ())
+    {
+      gripe_property_access (who, wrap (), false);
+
+      return retval;
+    }
+
+  if (! obj.is_constructed ())
+    {
+      cdef_class cls (to_cdef (get ("DefiningClass")));
+
+      if (! obj.is_partially_constructed_for (cls))
+        {
+          ::error ("cannot reference properties of class `%s' for non-constructed object",
+                   cls.get_name ().c_str ());
+          return retval;
+        }
+    }
+ 
+  octave_value get_fcn = get ("GetMethod");
+
+  // FIXME: should check whether we're already in get accessor method
+
+  if (get_fcn.is_empty () || is_method_executing (get_fcn, obj))
+    retval = obj.get (get ("Name").string_value ());
+  else
+    {
+      octave_value_list args;
+
+      args(0) = to_ov (obj);
+      
+      args = execute_ov (get_fcn, args, 1);
+
+      if (! error_state)
+        retval = args(0);
+    }
+
+  return retval;
+}
+
+octave_value
+cdef_property::cdef_property_rep::get_value (bool do_check_access,
+                                             const std::string& who)
+{
+  if (do_check_access && ! check_get_access ())
+    {
+      gripe_property_access (who, wrap (), false);
+
+      return octave_value ();
+    }
+
+  return get ("DefaultValue");
+}
+
+bool
+cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const
+{
+  // FIXME: implement
+  return false;
+}
+
+void
+cdef_property::cdef_property_rep::set_value (cdef_object& obj,
+                                             const octave_value& val,
+                                             bool do_check_access,
+                                             const std::string& who)
+{
+  if (do_check_access && ! check_set_access ())
+    {
+      gripe_property_access (who, wrap (), true);
+
+      return;
+    }
+
+  if (! obj.is_constructed ())
+    {
+      cdef_class cls (to_cdef (get ("DefiningClass")));
+
+      if (! obj.is_partially_constructed_for (cls))
+        {
+          ::error ("cannot reference properties of class `%s' for non-constructed object",
+                   cls.get_name ().c_str ());
+          return;
+        }
+    }
+ 
+  octave_value set_fcn = get ("SetMethod");
+
+  if (set_fcn.is_empty () || is_method_executing (set_fcn, obj))
+    obj.put (get ("Name").string_value (), val);
+  else
+    {
+      octave_value_list args;
+
+      args(0) = to_ov (obj);
+      args(1) = val;
+
+      args = execute_ov (set_fcn, args, 1);
+
+      if (! error_state)
+        {
+          if (args.length() > 0)
+            {
+              cdef_object new_obj = to_cdef (args(0));
+
+              if (! error_state)
+                obj = new_obj;
+            }
+        }
+    }
+}
+
+bool
+cdef_property::cdef_property_rep::check_get_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("GetAccess"), std::string (),
+                           get_name (), false);
+
+  return false;
+}
+
+bool
+cdef_property::cdef_property_rep::check_set_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("SetAccess"), std::string (),
+                           get_name (), true);
+
+  return false;
+}
+
+void
+cdef_method::cdef_method_rep::check_method (void)
+{
+  if (is_external ())
+    {
+      if (is_dummy_method (function))
+        {
+          std::string name = get_name ();
+          std::string cls_name = dispatch_type;
+          std::string pack_name;
+
+          size_t pos = cls_name.rfind ('.');
+
+          if (pos != std::string::npos)
+            {
+              pack_name = cls_name.substr (0, pos);
+              cls_name = cls_name.substr (pos + 1);
+            }
+
+          std::string dir_name;
+          std::string file_name = load_path::find_method (cls_name, name,
+                                                          dir_name, pack_name);
+
+          if (! file_name.empty ())
+            {
+              octave_function *fcn = load_fcn_from_file (file_name, dir_name,
+                                                         dispatch_type,
+                                                         pack_name);
+
+              if (fcn)
+                {
+                  function = octave_value (fcn);
+
+                  make_function_of_class (dispatch_type, function);
+                }
+            }
+        }
+      else
+        {
+          // FIXME: check out-of-date status
+        }
+
+      if (is_dummy_method (function))
+        ::error ("no definition found for method `%s' of class `%s'",
+                 get_name ().c_str (), dispatch_type.c_str ());
+    }
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::execute (const octave_value_list& args,
+                                       int nargout, bool do_check_access,
+                                       const std::string& who)
+{
+  octave_value_list retval;
+
+  if (do_check_access && ! check_access ())
+    {
+      gripe_method_access (who, wrap ());
+
+      return retval;
+    }
+
+  if (! get ("Abstract").bool_value ())
+    {
+      check_method ();
+
+      if (! error_state && function.is_defined ())
+        {
+          retval = execute_ov (function, args, nargout);
+        }
+    }
+  else
+    error ("%s: cannot execute abstract method",
+           get ("Name").string_value ().c_str ());
+
+  return retval;
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::execute (const cdef_object& obj,
+                                       const octave_value_list& args,
+                                       int nargout, bool do_check_access,
+                                       const std::string& who)
+{
+  octave_value_list retval;
+
+  if (do_check_access && ! check_access ())
+    {
+      gripe_method_access (who, wrap ());
+
+      return retval;
+    }
+
+  if (! get ("Abstract").bool_value ())
+    {
+      check_method ();
+
+      if (! error_state && function.is_defined ())
+        {
+          octave_value_list new_args;
+
+          new_args.resize (args.length () + 1);
+
+          new_args(0) = to_ov (obj);
+          for (int i = 0; i < args.length (); i++)
+            new_args(i+1) = args(i);
+
+          retval = execute_ov (function, new_args, nargout);
+        }
+    }
+  else
+    error ("%s: cannot execute abstract method",
+           get ("Name").string_value ().c_str ());
+
+  return retval;
+}
+
+bool
+cdef_method::cdef_method_rep::is_constructor (void) const
+{
+  if (function.is_function())
+    return function.function_value ()->is_classdef_constructor ();
+
+  return false;
+}
+
+bool
+cdef_method::cdef_method_rep::check_access (void) const
+{
+  cdef_class cls (to_cdef (get ("DefiningClass")));
+
+  if (! error_state)
+    return ::check_access (cls, get ("Access"), get_name ());
+
+  return false;
+}
+
+octave_value_list
+cdef_method::cdef_method_rep::meta_subsref
+  (const std::string& type, const std::list<octave_value_list>& idx,
+   int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '(':
+      retval = execute (idx.front (), type.length () > 1 ? 1 : nargout, true);
+      break;
+
+    default:
+      error ("invalid meta.method indexing");
+      break;
+    }
+
+  if (! error_state)
+    {
+      if (type.length () > 1 && idx.size () > 1 && ! retval.empty ())
+        retval = retval(0).next_subsref (nargout, type, idx, 1);
+    }
+
+  return retval;
+}
+
+static cdef_package
+lookup_package (const std::string& name)
+{
+  return cdef_manager::find_package (name);
+}
+
+static octave_value_list
+package_fromName (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      std::string name = args(0).string_value ();
+
+      if (! error_state)
+        retval(0) = to_ov (lookup_package (name));
+      else
+        error ("fromName: invalid package name, expected a string value");
+    }
+  else
+    error ("fromName: invalid number of parameters");
+
+  return retval;
+}
+
+static octave_value_list
+package_get_classes (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 1 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_classes ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_get_functions (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 0 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_functions ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_get_packages (const octave_value_list& args, int /* nargout */)
+{
+  octave_value_list retval (1, Matrix ());
+
+  if (args.length () == 0 && args(0).type_name () == "object"
+      && args(0).class_name () == "meta.package")
+    {
+      cdef_package pack (to_cdef (args(0)));
+
+      retval(0) = pack.get_packages ();
+    }
+
+  return retval;
+}
+
+static octave_value_list
+package_getAllPackages (const octave_value_list& /* args */,
+                        int /* nargout */)
+{
+  std::map<std::string, cdef_package> toplevel_packages;
+
+  std::list<std::string> names = load_path::get_all_package_names ();
+
+  toplevel_packages["meta"] = cdef_manager::find_package ("meta", false,
+                                                          false);
+
+  for (std::list<std::string>::const_iterator it = names.begin ();
+       it != names.end (); ++it)
+    toplevel_packages[*it] = cdef_manager::find_package (*it, false, true);
+
+  Cell c (toplevel_packages.size (), 1);
+
+  int i = 0;
+
+  for (std::map<std::string, cdef_package>::const_iterator it = toplevel_packages.begin ();
+       it != toplevel_packages.end (); ++it)
+    c(i++,0) = to_ov (it->second);
+
+  return octave_value_list (octave_value (c));
+}
+
+void
+cdef_package::cdef_package_rep::install_class (const cdef_class& cls,
+                                               const std::string& nm)
+{
+  class_map[nm] = cls;
+
+  member_count++;
+}
+
+void
+cdef_package::cdef_package_rep::install_function (const octave_value& fcn,
+                                                  const std::string& nm)
+{
+  function_map[nm] = fcn;
+}
+
+void
+cdef_package::cdef_package_rep::install_package (const cdef_package& pack,
+                                                 const std::string& nm)
+{
+  package_map[nm] = pack;
+
+  member_count++;
+}
+
+template<class T1, class T2>
+Cell
+map2Cell (const std::map<T1, T2>& m)
+{
+  Cell retval (1, m.size ());
+  int i = 0;
+
+  for (typename std::map<T1, T2>::const_iterator it = m.begin ();
+       it != m.end (); ++it, ++i)
+    {
+      retval(i) = to_ov (it->second);
+    }
+
+  return retval;
+}
+
+Cell
+cdef_package::cdef_package_rep::get_classes (void) const
+{ return map2Cell (class_map); }
+
+Cell
+cdef_package::cdef_package_rep::get_functions (void) const
+{ return map2Cell (function_map); }
+
+Cell
+cdef_package::cdef_package_rep::get_packages (void) const
+{ return map2Cell (package_map); }
+
+octave_value
+cdef_package::cdef_package_rep::find (const std::string& nm)
+{
+  std::string symbol_name = get_name () + "." + nm;
+
+  return symbol_table::find (symbol_name, octave_value_list (), true, false);
+}
+
+octave_value_list
+cdef_package::cdef_package_rep::meta_subsref
+  (const std::string& type, const std::list<octave_value_list>& idx,
+   int nargout)
+{
+  octave_value_list retval;
+
+  switch (type[0])
+    {
+    case '.':
+      if (idx.front ().length () == 1)
+        {
+          std::string nm = idx.front ()(0).string_value ();
+
+          if (! error_state)
+            {
+              gnulib::printf ("meta.package query: %s\n", nm.c_str ());
+
+              octave_value o = find (nm);
+
+              if (o.is_defined ())
+                {
+                  if (o.is_function ())
+                    {
+                      octave_function* fcn = o.function_value ();
+
+                      if (! error_state)
+                        {
+                          // NOTE: the case where the package query is the last
+                          // part of this subsref index is handled in the parse
+                          // tree, because there is some logic to handle magic
+                          // "end" that makes it impossible to execute the
+                          // function call at this stage.
+
+                          if (type.size () > 1 &&
+                              ! fcn->is_postfix_index_handled (type[1]))
+                            {
+                              octave_value_list tmp_args;
+
+                              retval = o.do_multi_index_op (nargout,
+                                                            tmp_args);
+                            }
+                          else
+                            retval(0) = o;
+
+                          if (type.size () > 1 && idx.size () > 1)
+                            retval = retval(0).next_subsref (nargout, type,
+                                                             idx, 1);
+                        }
+                    }
+                  else if (type.size () > 1 && idx.size () > 1)
+                    retval = o.next_subsref (nargout, type, idx, 1);
+                  else
+                    retval(0) = o;
+                }
+              else if (! error_state)
+                error ("member `%s' in package `%s' does not exist",
+                       nm.c_str (), get_name ().c_str ());
+            }
+          else
+            error ("invalid meta.package indexing, expected a symbol name");
+        }
+      else
+        error ("invalid meta.package indexing");
+      break;
+
+    default:
+      error ("invalid meta.package indexing");
+      break;
+    }
+
+  return retval;
+}
+
+void
+cdef_package::cdef_package_rep::meta_release (void)
+{
+  // FIXME: Do we really want to unregister the package, as it
+  //        could still be referenced by classes or sub-packages?
+  //        If the package object is recreated later on, it won't
+  //        match the one already referenced by those classes or
+  //        sub-packages.
+
+  //cdef_manager::unregister_package (wrap ());
+}
+
+cdef_class cdef_class::_meta_class = cdef_class ();
+cdef_class cdef_class::_meta_property = cdef_class ();
+cdef_class cdef_class::_meta_method = cdef_class ();
+cdef_class cdef_class::_meta_package = cdef_class ();
+
+cdef_package cdef_package::_meta = cdef_package ();
+
+void
+install_classdef (void)
+{
+  octave_classdef::register_type ();
+
+  /* bootstrap */
+  cdef_class handle = make_class ("handle");
+  cdef_class meta_class = cdef_class::_meta_class = make_meta_class ("meta.class", handle);
+  handle.set_class (meta_class);
+  meta_class.set_class (meta_class);
+
+  /* meta classes */
+  cdef_class meta_property = cdef_class::_meta_property = make_meta_class ("meta.property", handle);
+  cdef_class meta_method = cdef_class::_meta_method = make_meta_class ("meta.method", handle);
+  cdef_class meta_package = cdef_class::_meta_package = make_meta_class ("meta.package", handle);
+
+  cdef_class meta_event = make_meta_class ("meta.event", handle);
+  cdef_class meta_dynproperty = make_meta_class ("meta.dynamicproperty", handle);
+
+  /* meta.class properties */
+  meta_class.install_property (make_attribute (meta_class, "Abstract"));
+  meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad"));
+  meta_class.install_property (make_property  (meta_class, "ContainingPackage"));
+  meta_class.install_property (make_property  (meta_class, "Description"));
+  meta_class.install_property (make_property  (meta_class, "DetailedDescription"));
+  meta_class.install_property (make_property  (meta_class, "Events"));
+  meta_class.install_property (make_attribute (meta_class, "HandleCompatible"));
+  meta_class.install_property (make_attribute (meta_class, "Hidden"));
+  meta_class.install_property
+      (make_property (meta_class, "InferiorClasses",
+                      make_fcn_handle (class_get_inferiorclasses, "meta.class>get.InferiorClasses"),
+                      "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "Methods",
+                       make_fcn_handle (class_get_methods, "meta.class>get.Methods"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "MethodList",
+                       make_fcn_handle (class_get_methods, "meta.class>get.MethodList"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property (make_attribute (meta_class, "Name"));
+  meta_class.install_property
+      (make_property  (meta_class, "Properties",
+                       make_fcn_handle (class_get_properties, "meta.class>get.Properties"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property  (meta_class, "PropertyList",
+                       make_fcn_handle (class_get_properties, "meta.class>get.PropertyList"),
+                       "public", Matrix (), "private"));
+  meta_class.install_property (make_attribute (meta_class, "Sealed"));
+  meta_class.install_property
+      (make_property (meta_class, "SuperClasses",
+                      make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClasses"),
+                      "public", Matrix (), "private"));
+  meta_class.install_property
+      (make_property (meta_class, "SuperClassList",
+                      make_fcn_handle (class_get_superclasses, "meta.class>get.SuperClassList"),
+                      "public", Matrix (), "private"));
+  /* meta.class methods */
+  meta_class.install_method (make_method (meta_class, "fromName", class_fromName,
+                                          "public", true));
+  meta_class.install_method (make_method (meta_class, "fevalStatic", class_fevalStatic,
+                                          "public", false));
+  meta_class.install_method (make_method (meta_class, "getConstant", class_getConstant,
+                                          "public", false));
+  meta_class.install_method (make_method (meta_class, "eq", class_eq));
+  meta_class.install_method (make_method (meta_class, "ne", class_ne));
+  meta_class.install_method (make_method (meta_class, "lt", class_lt));
+  meta_class.install_method (make_method (meta_class, "le", class_le));
+  meta_class.install_method (make_method (meta_class, "gt", class_gt));
+  meta_class.install_method (make_method (meta_class, "ge", class_ge));
+
+  /* meta.method properties */
+  meta_method.install_property (make_attribute (meta_method, "Abstract"));
+  meta_method.install_property (make_attribute (meta_method, "Access"));
+  meta_method.install_property (make_attribute (meta_method, "DefiningClass"));
+  meta_method.install_property (make_attribute (meta_method, "Description"));
+  meta_method.install_property (make_attribute (meta_method, "DetailedDescription"));
+  meta_method.install_property (make_attribute (meta_method, "Hidden"));
+  meta_method.install_property (make_attribute (meta_method, "Name"));
+  meta_method.install_property (make_attribute (meta_method, "Sealed"));
+  meta_method.install_property (make_attribute (meta_method, "Static"));
+
+  /* meta.property properties */
+  meta_property.install_property (make_attribute (meta_property, "Name"));
+  meta_property.install_property (make_attribute (meta_property, "Description"));
+  meta_property.install_property (make_attribute (meta_property, "DetailedDescription"));
+  meta_property.install_property (make_attribute (meta_property, "Abstract"));
+  meta_property.install_property (make_attribute (meta_property, "Constant"));
+  meta_property.install_property (make_attribute (meta_property, "GetAccess"));
+  meta_property.install_property (make_attribute (meta_property, "SetAccess"));
+  meta_property.install_property (make_attribute (meta_property, "Dependent"));
+  meta_property.install_property (make_attribute (meta_property, "Transient"));
+  meta_property.install_property (make_attribute (meta_property, "Hidden"));
+  meta_property.install_property (make_attribute (meta_property, "GetObservable"));
+  meta_property.install_property (make_attribute (meta_property, "SetObservable"));
+  meta_property.install_property (make_attribute (meta_property, "GetMethod"));
+  meta_property.install_property (make_attribute (meta_property, "SetMethod"));
+  meta_property.install_property (make_attribute (meta_property, "DefiningClass"));
+  meta_property.install_property
+      (make_property (meta_property, "DefaultValue",
+                      make_fcn_handle (property_get_defaultvalue, "meta.property>get.DefaultValue"),
+                      "public", Matrix (), "private"));
+  meta_property.install_property (make_attribute (meta_property, "HasDefault"));
+  /* meta.property events */
+  // FIXME: add events
+
+  /* handle methods */
+  handle.install_method (make_method (handle, "delete", handle_delete));
+
+  /* meta.package properties */
+  meta_package.install_property (make_attribute (meta_package, "Name"));
+  meta_package.install_property (make_property  (meta_package, "ContainingPackage"));
+  meta_package.install_property
+      (make_property (meta_package, "ClassList",
+                      make_fcn_handle (package_get_classes, "meta.package>get.ClassList"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Classes",
+                      make_fcn_handle (package_get_classes, "meta.package>get.Classes"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "FunctionList",
+                      make_fcn_handle (package_get_functions, "meta.package>get.FunctionList"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Functions",
+                      make_fcn_handle (package_get_functions, "meta.package>get.Functions"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "PackageList",
+                      make_fcn_handle (package_get_packages, "meta.package>get.PackageList"),
+                      "public", Matrix (), "private"));
+  meta_package.install_property
+      (make_property (meta_package, "Packages",
+                      make_fcn_handle (package_get_packages, "meta.package>get.Packages"),
+                      "public", Matrix (), "private"));
+  meta_package.install_method (make_method (meta_package, "fromName", package_fromName,
+                                            "public", true));
+  meta_package.install_method (make_method (meta_package, "getAllPackages", package_getAllPackages,
+                                            "public", true));
+
+  /* create "meta" package */
+  cdef_package package_meta = cdef_package::_meta = make_package ("meta");
+  package_meta.install_class (meta_class,       "class");
+  package_meta.install_class (meta_property,    "property");
+  package_meta.install_class (meta_method,      "method");
+  package_meta.install_class (meta_package,     "package");
+  package_meta.install_class (meta_event,       "event");
+  package_meta.install_class (meta_dynproperty, "dynproperty");
+
+  /* install built-in classes into the symbol table */
+  symbol_table::install_built_in_function
+    ("meta.class", octave_value (meta_class.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.method", octave_value (meta_method.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.property", octave_value (meta_property.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.package", octave_value (meta_package.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.event", octave_value (meta_event.get_constructor_function ()));
+  symbol_table::install_built_in_function
+    ("meta.dynproperty", octave_value (meta_dynproperty.get_constructor_function ()));
+}
+
+//----------------------------------------------------------------------------
+
+cdef_manager* cdef_manager::instance = 0;
+
+void
+cdef_manager::create_instance (void)
+{
+  instance = new cdef_manager ();
+
+  if (instance)
+    singleton_cleanup_list::add (cleanup_instance);
+}
+
+cdef_class
+cdef_manager::do_find_class (const std::string& name,
+                             bool error_if_not_found, bool load_if_not_found)
+{
+  std::map<std::string, cdef_class>::iterator it = all_classes.find (name);
+
+  if (it == all_classes.end ())
+    {
+      if (load_if_not_found)
+        {
+          octave_value ov_cls;
+
+          size_t pos = name.rfind ('.');
+
+          if (pos == std::string::npos)
+            ov_cls = symbol_table::find (name);
+          else
+            {
+              std::string pack_name = name.substr (0, pos);
+
+              cdef_package pack = do_find_package (pack_name, false, true);
+
+              if (pack.ok ())
+                ov_cls = pack.find (name.substr (pos+1));
+            }
+
+          if (ov_cls.is_defined ())
+            it = all_classes.find (name);
+        }
+    }
+
+  if (it == all_classes.end ())
+    {
+      if (error_if_not_found)
+        error ("class not found: %s", name.c_str ());
+    }
+  else
+    {
+      cdef_class cls = it->second;
+
+      if (! cls.is_builtin ())
+        cls = lookup_class (cls);
+
+      if (cls.ok ())
+        return cls;
+      else
+        all_classes.erase (it);
+    }
+
+  return cdef_class ();
+}
+
+octave_function*
+cdef_manager::do_find_method_symbol (const std::string& method_name,
+                                     const std::string& class_name)
+{
+  octave_function *retval = 0;
+
+  cdef_class cls = find_class (class_name, false, false);
+
+  if (cls.ok ())
+    {
+      cdef_method meth = cls.find_method (method_name);
+
+      if (meth.ok ())
+        retval = new octave_classdef_meta (meth);
+    }
+
+  return retval;
+}
+
+cdef_package
+cdef_manager::do_find_package (const std::string& name,
+                               bool error_if_not_found,
+                               bool load_if_not_found)
+{
+  cdef_package retval;
+
+  std::map<std::string, cdef_package>::const_iterator it
+    = all_packages.find (name);
+
+  if (it != all_packages.end ())
+    {
+      retval = it->second;
+
+      if (! retval.ok ())
+        error ("invalid package `%s'", name.c_str ());
+    }
+  else
+    {
+      if (load_if_not_found && load_path::find_package (name))
+        {
+          size_t pos = name.find ('.');
+
+          if (pos == std::string::npos)
+            retval = make_package (name, std::string ());
+          else
+            {
+              std::string parent_name = name.substr (0, pos);
+
+              retval = make_package (name, parent_name);
+            }
+        }
+      else if (error_if_not_found)
+        error ("unknown package `%s'", name.c_str ());
+    }
+
+  return retval;
+}
+
+octave_function*
+cdef_manager::do_find_package_symbol (const std::string& pack_name)
+{
+  octave_function* retval = 0;
+
+  cdef_package pack = find_package (pack_name, false);
+
+  if (pack.ok ())
+    retval = new octave_classdef_meta (pack);
+
+  return retval;
+}
+
+//----------------------------------------------------------------------------
+
+DEFUN (__meta_get_package__, args, , "")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      std::string cname = args(0).string_value ();
+
+      if (! error_state)
+        retval = to_ov (lookup_package (cname));
+      else
+        error ("invalid package name, expected a string value");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (__superclass_reference__, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __superclass_reference__ ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  return octave_value (new octave_classdef_superclass_ref (args));
+}
+
+DEFUN (__meta_class_query__, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} __meta_class_query__ ()\n\
+Undocumented internal function.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  std::cerr << "__meta_class_query__ ("
+            << args(0).string_value () << ")"
+            << std::endl;
+
+  if (args.length () == 1)
+    {
+      std::string cls = args(0).string_value ();
+
+      if (! error_state)
+        retval = to_ov (lookup_class (cls));
+      else
+        error ("invalid class name, expected a string value");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+DEFUN (metaclass, args, /* nargout */,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} metaclass (obj)\n\
+Returns the meta.class object corresponding to the class of @var{obj}.\n\
+@end deftypefn")
+{
+  octave_value retval;
+
+  if (args.length () == 1)
+    {
+      cdef_object obj = to_cdef (args(0));
+
+      if (! error_state)
+        retval = to_ov (obj.get_class ());
+      else
+        print_usage ();
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
new file mode 100644
--- /dev/null
+++ b/libinterp/octave-value/ov-classdef.h
@@ -0,0 +1,1666 @@
+/*
+
+Copyright (C) 2012-2013 Michael Goffioul
+
+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/>.
+
+*/
+
+#if !defined (octave_classdef_h)
+#define octave_classdef_h 1
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "oct-map.h"
+#include "oct-refcount.h"
+#include "ov-base.h"
+#include "symtab.h"
+
+class cdef_object;
+class cdef_class;
+class cdef_property;
+class cdef_method;
+class cdef_package;
+
+class tree_classdef;
+
+// This is mainly a boostrap class to declare the expected interface.
+// The actual base class is cdef_class_base, which is declared after
+// cdef_object, such that it can contain cdef_object objects.
+class
+cdef_object_rep
+{
+public:
+  friend class cdef_object;
+
+public:
+  cdef_object_rep (void) : refcount (1) { }
+
+  virtual ~cdef_object_rep (void) { }
+
+  virtual cdef_class get_class (void) const;
+
+  virtual void set_class (const cdef_class&)
+    { gripe_invalid_object ("set_class"); }
+
+  virtual cdef_object_rep* clone (void) const
+    {
+      gripe_invalid_object ("clone");
+      return new cdef_object_rep ();
+    }
+
+  virtual cdef_object_rep* empty_clone (void) const
+    {
+      gripe_invalid_object ("empty_clone");
+      return new cdef_object_rep ();
+    }
+
+  virtual cdef_object_rep* copy (void) const
+    {
+      gripe_invalid_object ("copy");
+      return new cdef_object_rep ();
+    }
+
+  virtual cdef_object_rep* make_array (void) const
+    {
+      gripe_invalid_object ("make_array");
+      return new cdef_object_rep ();
+    }
+
+  virtual bool is_array (void) const { return false; }
+
+  virtual bool is_value_object (void) const { return false; }
+
+  virtual bool is_handle_object (void) const { return false; }
+
+  virtual bool is_meta_object (void) const { return false; }
+
+  virtual Array<cdef_object> array_value (void) const
+    {
+      gripe_invalid_object ("array_value");
+      return Array<cdef_object> ();
+    }
+
+  virtual void put (const std::string&, const octave_value&)
+    { gripe_invalid_object ("put"); }
+
+  virtual octave_value get (const std::string&) const
+    {
+      gripe_invalid_object ("get");
+      return octave_value ();
+    }
+
+  virtual octave_value_list
+  subsref (const std::string&, const std::list<octave_value_list>&,
+           int, size_t&, const cdef_class&, bool)
+    {
+      gripe_invalid_object ("subsref");
+      return octave_value_list ();
+    }
+
+  virtual octave_value
+  subsasgn (const std::string&, const std::list<octave_value_list>&,
+            const octave_value&)
+    {
+      gripe_invalid_object ("subsasgn");
+      return octave_value ();
+    }
+
+  virtual string_vector map_keys(void) const;
+
+  virtual bool is_valid (void) const { return false; }
+
+  std::string class_name (void) const;
+
+  virtual void mark_for_construction (const cdef_class&)
+    { gripe_invalid_object ("mark_for_construction"); }
+
+  virtual bool is_constructed_for (const cdef_class&) const
+    {
+      gripe_invalid_object ("is_constructed_for");
+      return false;
+    }
+
+  virtual bool is_partially_constructed_for (const cdef_class&) const
+    {
+      gripe_invalid_object ("is_partially_constructed_for");
+      return false;
+    }
+
+  virtual void mark_as_constructed (void)
+    { gripe_invalid_object ("mark_as_constructed"); }
+
+  virtual void mark_as_constructed (const cdef_class&)
+    { gripe_invalid_object ("mark_as_constructed"); }
+
+  virtual bool is_constructed (void) const
+    {
+      gripe_invalid_object ("is_constructed");
+      return false;
+    }
+
+  virtual octave_idx_type static_count (void) const { return 0; }
+
+  virtual void destroy (void) { delete this; }
+
+  void release (void)
+    {
+      if (--refcount == static_count ())
+        destroy ();
+    }
+
+  virtual dim_vector dims (void) const { return dim_vector (); }
+
+protected:
+  /* reference count */
+  octave_refcount<octave_idx_type> refcount;
+
+protected:
+  /* Restricted copying */
+  cdef_object_rep (const cdef_object_rep&)
+    : refcount (1) { }
+
+private:
+  /* No assignment */
+  cdef_object_rep& operator = (const cdef_object_rep& );
+
+  void gripe_invalid_object (const char *who) const
+    { error ("%s: invalid object", who); }
+};
+
+class
+cdef_object
+{
+public:
+  /* FIXME: use a null object */
+  cdef_object (void)
+      : rep (new cdef_object_rep ()) { }
+
+  cdef_object (const cdef_object& obj)
+    : rep (obj.rep)
+    {
+      rep->refcount++;
+    }
+
+  cdef_object (cdef_object_rep *r)
+      : rep (r) { }
+
+  virtual ~cdef_object (void)
+    { rep->release (); }
+
+  cdef_object& operator = (const cdef_object& obj)
+    {
+      if (rep != obj.rep)
+        {
+          rep->release ();
+
+          rep = obj.rep;
+          rep->refcount++;
+        }
+
+      return *this;
+    }
+
+  cdef_class get_class (void) const;
+
+  void set_class (const cdef_class& cls) { rep->set_class (cls); }
+
+  std::string class_name (void) const
+    { return rep->class_name (); }
+
+  cdef_object clone (void) const
+    { return cdef_object (rep->clone ()); }
+
+  cdef_object empty_clone (void) const
+    { return cdef_object (rep->empty_clone ()); }
+
+  dim_vector dims (void) const { return rep->dims (); }
+
+  cdef_object make_array (void) const
+    { return cdef_object (rep->make_array ()); }
+
+  cdef_object copy (void) const
+    { return cdef_object (rep->copy ()); }
+
+  bool is_array (void) const { return rep->is_array (); }
+
+  bool is_value_object (void) const { return rep->is_value_object (); }
+
+  bool is_handle_object (void) const { return rep->is_handle_object (); }
+
+  bool is_meta_object (void) const { return rep->is_meta_object (); }
+
+  Array<cdef_object> array_value (void) const { return rep->array_value (); }
+
+  void put (const std::string& pname, const octave_value& val)
+    { rep->put (pname, val); }
+
+  octave_value get (const std::string& pname) const
+    { return rep->get (pname); }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx,
+           int nargout, size_t& skip, const cdef_class& context,
+           bool auto_add = false)
+    { return rep->subsref (type, idx, nargout, skip, context, auto_add); }
+
+  octave_value
+  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+            const octave_value& rhs, int ignore_copies = 0)
+    {
+      make_unique (ignore_copies);
+      return rep->subsasgn (type, idx, rhs);
+    }
+
+  string_vector map_keys (void) const { return rep->map_keys (); }
+
+  const cdef_object_rep* get_rep (void) const { return rep; }
+
+  bool ok (void) const { return rep->is_valid (); }
+
+  void mark_for_construction (const cdef_class& cls)
+    { rep->mark_for_construction (cls); }
+
+  bool is_constructed (void) const { return rep->is_constructed (); }
+
+  bool is_constructed_for (const cdef_class& cls) const
+    { return rep->is_constructed_for (cls); }
+
+  bool is_partially_constructed_for (const cdef_class& cls) const
+    { return rep->is_partially_constructed_for (cls); }
+
+  void mark_as_constructed (void) { rep->mark_as_constructed (); }
+
+  void mark_as_constructed (const cdef_class& cls)
+    { rep->mark_as_constructed (cls); }
+
+  bool is (const cdef_object& obj) const { return rep == obj.rep; }
+
+protected:
+  cdef_object_rep* get_rep (void) { return rep; }
+
+  void make_unique (int ignore_copies)
+    {
+      if (rep->refcount > ignore_copies + 1)
+        *this = clone ();
+    }
+
+private:
+  cdef_object_rep *rep;
+};
+
+class
+cdef_object_base : public cdef_object_rep
+{
+public:
+  cdef_object_base (void)
+    : cdef_object_rep (), klass ()
+    {
+      register_object ();
+    }
+
+  ~cdef_object_base (void) { unregister_object (); }
+
+  cdef_class get_class (void) const;
+
+  void set_class (const cdef_class& cls);
+
+  cdef_object_rep* empty_clone (void) const
+    { return new cdef_object_base (*this); }
+
+  cdef_object_rep* make_array (void) const;
+
+protected:
+  // Restricted copying!
+  cdef_object_base (const cdef_object_base& obj)
+    : cdef_object_rep (obj), klass (obj.klass)
+    {
+      register_object ();
+    }
+
+private:
+  void register_object (void);
+
+  void unregister_object (void);
+
+private:
+  // The class of the object
+  cdef_object klass;
+
+private:
+  // No assignment!
+  cdef_object_base& operator = (const cdef_object_base&);
+};
+
+class
+cdef_object_array : public cdef_object_base
+{
+public:
+  cdef_object_array (void) : cdef_object_base () { }
+
+  cdef_object_array (const Array<cdef_object>& a)
+    : cdef_object_base (), array (a) { }
+
+  cdef_object_rep* clone (void) const
+    { return new cdef_object_array (*this); }
+
+  dim_vector dims (void) const { return array.dims (); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_array (void) const { return true; }
+
+  Array<cdef_object> array_value (void) const { return array; }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx,
+           int nargout, size_t& skip, const cdef_class& context,
+           bool auto_add);
+
+  octave_value
+  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+            const octave_value& rhs);
+
+private:
+  Array<cdef_object> array;
+
+private:
+  void fill_empty_values (void) { fill_empty_values (array); }
+
+  void fill_empty_values (Array<cdef_object>& arr);
+
+  // Private copying!
+  cdef_object_array (const cdef_object_array& obj)
+    : cdef_object_base (obj), array (obj.array) { }
+
+  // No assignment!
+  cdef_object_array& operator = (const cdef_object_array&);
+};
+
+class
+cdef_object_scalar : public cdef_object_base
+{
+public:
+  cdef_object_scalar (void) : cdef_object_base () { }
+
+  ~cdef_object_scalar (void) { }
+
+  dim_vector dims (void) const { return dim_vector (1, 1); }
+
+  void put (const std::string& pname, const octave_value& val)
+    { map.assign (pname, val); }
+
+  octave_value get (const std::string& pname) const
+    {
+      Cell val = map.contents (pname);
+
+      if (val.numel () > 0)
+        return val(0, 0);
+      else
+        {
+          error ("get: unknown slot: %s", pname.c_str ());
+          return octave_value ();
+        }
+    }
+
+  octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx,
+           int nargout, size_t& skip, const cdef_class& context,
+           bool auto_add);
+
+  octave_value
+  subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
+            const octave_value& rhs);
+
+  void mark_for_construction (const cdef_class&);
+
+  bool is_constructed_for (const cdef_class& cls) const;
+
+  bool is_partially_constructed_for (const cdef_class& cls) const;
+
+  void mark_as_constructed (void) { ctor_list.clear (); }
+
+  void mark_as_constructed (const cdef_class& cls) { ctor_list.erase (cls); }
+
+  bool is_constructed (void) const { return ctor_list.empty (); }
+
+protected:
+  // Object property values
+  octave_scalar_map map;
+
+  // Internal/temporary structure used during object construction
+  std::map< cdef_class, std::list<cdef_class> > ctor_list;
+
+protected:
+  // Restricted object copying!
+  cdef_object_scalar (const cdef_object_scalar& obj)
+    : cdef_object_base (obj), map (obj.map), ctor_list (obj.ctor_list) { }
+
+private:
+  // No assignment!
+  cdef_object_scalar& operator = (const cdef_object_scalar&);
+};
+
+class
+handle_cdef_object : public cdef_object_scalar
+{
+public:
+  handle_cdef_object (void)
+      : cdef_object_scalar () { }
+
+  ~handle_cdef_object (void);
+
+  cdef_object_rep* clone (void) const
+    {
+      handle_cdef_object *obj = const_cast<handle_cdef_object *> (this);
+      obj->refcount++;
+      return obj;
+    }
+
+  cdef_object_rep* copy (void) const
+    { return new handle_cdef_object (*this); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_handle_object (void) const { return true; }
+
+protected:
+  // Restricted copying!
+  handle_cdef_object (const handle_cdef_object& obj)
+    : cdef_object_scalar (obj) { }
+
+private:
+  // No assignment
+  handle_cdef_object& operator = (const handle_cdef_object&);
+};
+
+class
+value_cdef_object : public cdef_object_scalar
+{
+public:
+  value_cdef_object (void)
+      : cdef_object_scalar () { }
+
+  ~value_cdef_object (void);
+
+  cdef_object_rep* clone (void) const
+    { return new value_cdef_object (*this); }
+
+  cdef_object_rep* copy (void) const { return clone (); }
+
+  bool is_valid (void) const { return true; }
+
+  bool is_value_object (void) const { return true; }
+
+private:
+  // Private copying!
+  value_cdef_object (const value_cdef_object& obj)
+    : cdef_object_scalar (obj) { }
+
+  // No assignment!
+  value_cdef_object& operator = (const value_cdef_object&);
+};
+
+class
+cdef_meta_object_rep : public handle_cdef_object
+{
+public:
+  cdef_meta_object_rep (void)
+    : handle_cdef_object () { }
+
+  ~cdef_meta_object_rep (void) { }
+
+  cdef_object_rep* copy (void) const
+    { return new cdef_meta_object_rep (*this); }
+
+  bool is_meta_object (void) const { return true; }
+
+  virtual bool is_class (void) const { return false; }
+
+  virtual bool is_property (void) const { return false; }
+
+  virtual bool is_method (void) const { return false; }
+
+  virtual bool is_package (void) const { return false; }
+  
+  virtual octave_value_list
+  meta_subsref (const std::string& /* type */,
+                const std::list<octave_value_list>& /* idx */,
+                int /* nargout */)
+    {
+      ::error ("subsref: invalid meta object");
+      return octave_value_list ();
+    }
+
+  virtual void meta_release (void) { }
+
+  virtual bool meta_is_postfix_index_handled (char /* type */) const
+    { return false; }
+
+protected:
+  // Restricted copying!
+  cdef_meta_object_rep (const cdef_meta_object_rep& obj)
+    : handle_cdef_object (obj) { }
+
+private:
+  // No assignment!
+  cdef_meta_object_rep& operator = (const cdef_meta_object_rep&);
+};
+
+class
+cdef_meta_object : public cdef_object
+{
+public:
+  cdef_meta_object (void)
+    : cdef_object () { }
+
+  cdef_meta_object (const cdef_meta_object& obj)
+    : cdef_object (obj) { }
+
+  cdef_meta_object (cdef_meta_object_rep *r)
+    : cdef_object (r) { }
+
+  // Object consistency is checked in sub-classes.
+  cdef_meta_object (const cdef_object& obj)
+    : cdef_object (obj) { }
+
+  ~cdef_meta_object (void) { }
+
+  bool is_class (void) const { return get_rep ()->is_class (); }
+
+  bool is_property (void) const { return get_rep ()->is_property (); }
+
+  bool is_method (void) const { return get_rep ()->is_method (); }
+
+  bool is_package (void) const { return get_rep ()->is_package (); }
+
+  octave_value_list
+  meta_subsref (const std::string& type,
+                const std::list<octave_value_list>& idx, int nargout)
+    { return get_rep ()->meta_subsref (type, idx, nargout); }
+
+  void meta_release (void) { get_rep ()->meta_release (); }
+
+  bool meta_is_postfix_index_handled (char type) const
+    { return get_rep ()->meta_is_postfix_index_handled (type); }
+
+private:
+  cdef_meta_object_rep* get_rep (void)
+    { return dynamic_cast<cdef_meta_object_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_meta_object_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_meta_object_rep *> (cdef_object::get_rep ()); }
+};
+
+class
+cdef_class : public cdef_meta_object
+{
+private:
+
+  class
+  cdef_class_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_class_rep (void)
+        : cdef_meta_object_rep (), member_count (0), handle_class (false),
+          object_count (0), meta (false) { }
+
+    cdef_class_rep (const std::list<cdef_class>& superclasses);
+
+    cdef_object_rep* copy (void) const { return new cdef_class_rep (*this); }
+
+    bool is_class (void) const { return true; }
+
+    std::string get_name (void) const
+      { return get ("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_abstract (void) const { return get ("Abstract").bool_value (); }
+
+    bool is_sealed (void) const { return get ("Sealed").bool_value (); }
+
+    cdef_method find_method (const std::string& nm, bool local = false);
+
+    void install_method (const cdef_method& meth);
+
+    Cell get_methods (void);
+
+    cdef_property find_property (const std::string& nm);
+
+    void install_property (const cdef_property& prop);
+
+    Cell get_properties (void);
+
+    string_vector get_names (void);
+
+    void set_directory (const std::string& dir) { directory = dir; }
+
+    std::string get_directory (void) const { return directory; }
+
+    void delete_object (cdef_object obj);
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout);
+
+    void meta_release (void);
+
+    bool meta_is_postfix_index_handled (char type) const
+      { return (type == '(' || type == '.'); }
+
+    octave_value construct (const octave_value_list& args);
+
+    cdef_object construct_object (const octave_value_list& args);
+
+    void initialize_object (cdef_object& obj);
+
+    void run_constructor (cdef_object& obj, const octave_value_list& args);
+
+    void mark_as_handle_class (void) { handle_class = true; }
+
+    bool is_handle_class (void) const { return handle_class; }
+
+    void register_object (void) { object_count++; }
+
+    void unregister_object (void) { object_count--; }
+
+    octave_idx_type static_count (void) const { return member_count; }
+
+    void destroy (void)
+      {
+        if (member_count)
+          {
+            refcount++;
+            cdef_class lock (this);
+
+            member_count = 0;
+            method_map.clear ();
+            property_map.clear ();
+          }
+        else
+          delete this;
+      }
+
+    void mark_as_meta_class (void) { meta = true; }
+
+    bool is_meta_class (void) const { return meta; }
+
+  private:
+    void load_all_methods (void);
+
+    void find_names (std::set<std::string>& names, bool all);
+    
+    void find_properties (std::map<std::string,cdef_property>& props,
+                          bool only_inherited);
+
+    void find_methods (std::map<std::string, cdef_method>& meths,
+                       bool only_inherited);
+
+    cdef_class wrap (void)
+      {
+        refcount++;
+        return cdef_class (this);
+      }
+
+  private:
+    // The @-directory were this class is loaded from.
+    // (not used yet)
+    std::string directory;
+
+    // The methods defined by this class.
+    std::map<std::string,cdef_method> method_map;
+
+    // The properties defined by this class.
+    std::map<std::string,cdef_property> property_map;
+
+    // The number of members in this class (methods, properties...)
+    octave_idx_type member_count;
+
+    // TRUE if this class is a handle class. A class is a handle
+    // class when the abstract "handle" class is one of its superclasses.
+    bool handle_class;
+
+    // The list of super-class constructors that are called implicitly by the
+    // the classdef engine when creating an object. These constructors are not
+    // called explicitly by the class constructor.
+    std::list<cdef_class> implicit_ctor_list;
+
+    // The number of objects of this class.
+    octave_refcount<octave_idx_type> object_count;
+
+    // TRUE if this class is a built-in meta class.
+    bool meta;
+
+    // Utility iterator typedef's.
+    typedef std::map<std::string,cdef_method>::iterator method_iterator;
+    typedef std::map<std::string,cdef_method>::const_iterator method_const_iterator;
+    typedef std::map<std::string,cdef_property>::iterator property_iterator;
+    typedef std::map<std::string,cdef_property>::const_iterator property_const_iterator;
+
+  private:
+    cdef_class_rep (const cdef_class_rep& c)
+      : cdef_meta_object_rep (c), directory (c.directory),
+        method_map (c.method_map), property_map (c.property_map),
+        member_count (c.member_count), handle_class (c.handle_class),
+        implicit_ctor_list (c.implicit_ctor_list),
+        object_count (c.object_count), meta (c.meta) { }
+  };
+
+public:
+  // Create and invalid class object
+  cdef_class (void)
+      : cdef_meta_object () { }
+
+  cdef_class (const std::string& nm,
+              const std::list<cdef_class>& superclasses)
+      : cdef_meta_object (new cdef_class_rep (superclasses))
+    { get_rep ()->set_name (nm); }
+
+  cdef_class (const cdef_class& cls)
+      : cdef_meta_object (cls) { }
+
+  cdef_class (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_class ())
+        error ("internal error: invalid assignment from %s to meta.class object",
+               class_name ().c_str ());
+    }
+
+  cdef_class& operator = (const cdef_class& cls)
+    {
+      cdef_object::operator= (cls);
+
+      return *this;
+    }
+
+  cdef_method find_method (const std::string& nm, bool local = false);
+
+  void install_method (const cdef_method& meth)
+    { get_rep ()->install_method (meth); }
+
+  Cell get_methods (void) { return get_rep ()->get_methods (); }
+
+  cdef_property find_property (const std::string& nm);
+  
+  void install_property (const cdef_property& prop)
+    { get_rep ()->install_property (prop); }
+
+  Cell get_properties (void) { return get_rep ()->get_properties (); }
+
+  string_vector get_names (void) { return get_rep ()->get_names (); }
+
+  bool is_abstract (void) const { return get_rep ()->is_abstract (); }
+
+  bool is_sealed (void) const { return get_rep ()->is_sealed (); }
+
+  void set_directory (const std::string& dir)
+    { get_rep ()->set_directory (dir); }
+
+  std::string get_directory (void) const
+    { return get_rep ()->get_directory (); }
+
+  std::string get_name (void) const
+    { return get_rep ()->get_name (); }
+
+  bool is_builtin (void) const
+    { return get_directory ().empty (); }
+
+  void delete_object (cdef_object obj)
+    { get_rep ()->delete_object (obj); }
+
+  static cdef_class make_meta_class (tree_classdef* t,
+                                     bool is_at_folder = false);
+
+  octave_function* get_method_function (const std::string& nm);
+
+  octave_function* get_constructor_function (void)
+    { return get_method_function (get_name ()); }
+
+  octave_value construct (const octave_value_list& args)
+    { return get_rep ()->construct (args); }
+
+  cdef_object construct_object (const octave_value_list& args)
+    { return get_rep ()->construct_object (args); }
+
+  void initialize_object (cdef_object& obj)
+    { get_rep ()->initialize_object (obj); }
+
+  void run_constructor (cdef_object& obj, const octave_value_list& args)
+    { get_rep ()->run_constructor (obj, args); }
+
+  void mark_as_handle_class (void)
+    { get_rep ()->mark_as_handle_class (); }
+
+  bool is_handle_class (void) const
+    { return get_rep ()->is_handle_class (); }
+
+  void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); }
+
+  bool is_meta_class (void) const { return get_rep ()->is_meta_class (); }
+
+  static const cdef_class& meta_class (void) { return _meta_class; }
+  static const cdef_class& meta_property (void) { return _meta_property; }
+  static const cdef_class& meta_method (void) { return _meta_method; }
+  static const cdef_class& meta_package (void) { return _meta_package; }
+
+  void register_object (void) { get_rep ()->register_object (); }
+
+  void unregister_object (void) { get_rep ()->unregister_object (); }
+
+private:
+  cdef_class_rep* get_rep (void)
+    { return dynamic_cast<cdef_class_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_class_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_class_rep *> (cdef_object::get_rep ()); }
+
+  friend bool operator == (const cdef_class&, const cdef_class&);
+  friend bool operator != (const cdef_class&, const cdef_class&);
+  friend bool operator < (const cdef_class&, const cdef_class&);
+
+private:
+  static cdef_class _meta_class;
+  static cdef_class _meta_property;
+  static cdef_class _meta_method;
+  static cdef_class _meta_package;
+
+  friend void install_classdef (void);
+};
+
+inline bool
+operator == (const cdef_class& clsa, const cdef_class& clsb)
+// FIXME: is this really the right way to check class equality?
+{ return (clsa.get_rep () == clsb.get_rep ()); }
+
+inline bool
+operator != (const cdef_class& clsa, const cdef_class& clsb)
+{ return ! (clsa == clsb); }
+
+// This is only to be able to use cdef_class as map keys.
+inline bool
+operator < (const cdef_class& clsa, const cdef_class& clsb)
+{ return clsa.get_rep () < clsb.get_rep (); }
+
+class
+cdef_property : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_property_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_property_rep (void)
+        : cdef_meta_object_rep () { }
+
+    cdef_object_rep* copy (void) const { return new cdef_property_rep (*this); }
+
+    bool is_property (void) const { return true; }
+
+    std::string get_name (void) const { return get("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_constant (void) const { return get("Constant").bool_value (); }
+
+    octave_value get_value (bool do_check_access = true,
+                            const std::string& who = std::string ());
+
+    octave_value get_value (const cdef_object& obj,
+                            bool do_check_access = true,
+                            const std::string& who = std::string ());
+
+    void set_value (cdef_object& obj, const octave_value& val,
+                    bool do_check_access = true,
+                    const std::string& who = std::string ());
+
+    bool check_get_access (void) const;
+
+    bool check_set_access (void) const;
+
+  private:
+    cdef_property_rep (const cdef_property_rep& p)
+      : cdef_meta_object_rep (p) { }
+
+    bool is_recursive_set (const cdef_object& obj) const;
+    
+    cdef_property wrap (void)
+      {
+        refcount++;
+        return cdef_property (this);
+      }
+  };
+
+public:
+  cdef_property (void) : cdef_meta_object () { }
+
+  cdef_property (const std::string& nm)
+      : cdef_meta_object (new cdef_property_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_property (const cdef_property& prop)
+      : cdef_meta_object (prop) { }
+
+  cdef_property (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_property ())
+        error ("internal error: invalid assignment from %s to meta.property object",
+               class_name ().c_str ());
+    }
+
+  cdef_property& operator = (const cdef_property& prop)
+    {
+      cdef_object::operator= (prop);
+
+      return *this;
+    }
+
+  octave_value get_value (const cdef_object& obj, bool do_check_access = true,
+                          const std::string& who = std::string ())
+    { return get_rep ()->get_value (obj, do_check_access, who); }
+
+  octave_value get_value (bool do_check_access = true,
+                          const std::string& who = std::string ())
+    { return get_rep ()->get_value (do_check_access, who); }
+
+  void set_value (cdef_object& obj, const octave_value& val,
+                  bool do_check_access = true,
+                  const std::string& who = std::string ())
+    { get_rep ()->set_value (obj, val, do_check_access, who); }
+
+  bool check_get_access (void) const
+    { return get_rep ()->check_get_access (); }
+  
+  bool check_set_access (void) const
+    { return get_rep ()->check_set_access (); }
+
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  bool is_constant (void) const { return get_rep ()->is_constant (); }
+
+private:
+  cdef_property_rep* get_rep (void)
+    { return dynamic_cast<cdef_property_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_property_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_property_rep *> (cdef_object::get_rep ()); }
+};
+
+class
+cdef_method : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_method_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_method_rep (void)
+      : cdef_meta_object_rep (), function (), dispatch_type ()
+      { }
+
+    cdef_object_rep* copy (void) const { return new cdef_method_rep(*this); }
+
+    bool is_method (void) const { return true; }
+
+    std::string get_name (void) const { return get("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    bool is_static (void) const { return get("Static").bool_value (); }
+
+    octave_value get_function (void) const { return function; }
+
+    void set_function (const octave_value& fcn) { function = fcn; }
+
+    bool check_access (void) const;
+
+    bool is_external (void) const { return ! dispatch_type.empty (); }
+
+    void mark_as_external (const std::string& dtype)
+      { dispatch_type = dtype; }
+
+    octave_value_list execute (const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = std::string ());
+
+    octave_value_list execute (const cdef_object& obj,
+                               const octave_value_list& args, int nargout,
+                               bool do_check_access = true,
+                               const std::string& who = std::string ());
+
+    bool is_constructor (void) const;
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout);
+
+    bool meta_is_postfix_index_handled (char type) const
+      { return (type == '(' || type == '.'); }
+
+  private:
+    cdef_method_rep (const cdef_method_rep& m)
+      : cdef_meta_object_rep (m), function (m.function),
+        dispatch_type (m.dispatch_type)
+      { }
+
+    void check_method (void);
+
+    cdef_method wrap (void)
+      {
+        refcount++;
+        return cdef_method (this);
+      }
+
+  private:
+    octave_value function;
+
+    // When non-empty, the method is externally defined and this member
+    // is used to cache the dispatch type to look for the method.
+    std::string dispatch_type;
+  };
+
+public:
+  cdef_method (void) : cdef_meta_object () { }
+
+  cdef_method (const std::string& nm)
+      : cdef_meta_object (new cdef_method_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_method (const cdef_method& meth)
+      : cdef_meta_object (meth) { }
+
+  cdef_method (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_method ())
+        error ("internal error: invalid assignment from %s to meta.method object",
+               class_name ().c_str ());
+    }
+
+  cdef_method& operator = (const cdef_method& meth)
+    {
+      cdef_object::operator= (meth);
+
+      return *this;
+    }
+
+  /* normal invokation */
+  octave_value_list execute (const octave_value_list& args, int nargout,
+                             bool do_check_access = true,
+                             const std::string& who = std::string ())
+    { return get_rep ()->execute (args, nargout, do_check_access, who); }
+
+  /* dot-invokation: object is pushed as 1st argument */
+  octave_value_list execute (const cdef_object& obj,
+                             const octave_value_list& args, int nargout,
+                             bool do_check_access = true,
+                             const std::string& who = std::string ())
+    { return get_rep ()->execute (obj, args, nargout, do_check_access, who); }
+
+  bool check_access (void) const { return get_rep ()->check_access (); }
+  
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  bool is_static (void) const { return get_rep ()->is_static (); }
+
+  void set_function (const octave_value& fcn)
+    { get_rep ()->set_function (fcn); }
+
+  octave_value get_function (void) const
+    { return get_rep ()->get_function (); }
+
+  bool is_constructor (void) const
+    { return get_rep ()->is_constructor (); }
+
+  bool is_external (void) const { return get_rep ()->is_external (); }
+
+  void mark_as_external (const std::string& dtype)
+    { get_rep ()->mark_as_external (dtype); }
+
+private:
+  cdef_method_rep* get_rep (void)
+    { return dynamic_cast<cdef_method_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_method_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_method_rep *> (cdef_object::get_rep ()); }
+};
+
+inline cdef_class
+cdef_object_rep::get_class (void) const
+{
+  gripe_invalid_object ("get_class");
+  return cdef_class ();
+}
+
+inline std::string
+cdef_object_rep::class_name (void) const
+{ return get_class ().get_name (); }
+
+inline cdef_class
+cdef_object::get_class (void) const
+{ return rep->get_class (); }
+
+inline cdef_class
+cdef_object_base::get_class (void) const
+{ return cdef_class (klass); }
+
+inline void
+cdef_object_base::set_class (const cdef_class& cls)
+{
+  if ((klass.ok () && cls.ok () && cls != get_class ())
+      || (klass.ok () && ! cls.ok ())
+      || (! klass.ok () && cls.ok ()))
+    {
+      unregister_object ();
+      klass = cls;
+      register_object ();
+    }
+}
+
+inline void
+cdef_object_base::register_object (void)
+{
+  if (klass.ok ())
+    {
+      cdef_class cls (get_class ());
+
+      if (! error_state && cls.ok ())
+        cls.register_object ();
+    }
+}
+
+inline void
+cdef_object_base::unregister_object (void)
+{
+  if (klass.ok ())
+    {
+      cdef_class cls (get_class ());
+
+      if (! error_state && cls.ok ())
+        cls.unregister_object ();
+    }
+}
+
+inline cdef_object_rep*
+cdef_object_base::make_array (void) const
+{
+  cdef_object_rep* r = new cdef_object_array ();
+
+  r->set_class (get_class ());
+
+  return r;
+}
+
+inline cdef_method
+cdef_class::find_method (const std::string& nm, bool local)
+{ return get_rep ()->find_method (nm, local); }
+
+inline cdef_property
+cdef_class::find_property (const std::string& nm)
+{ return get_rep ()->find_property (nm); }
+
+class
+cdef_package : public cdef_meta_object
+{
+  friend class cdef_class;
+
+private:
+
+  class
+  cdef_package_rep : public cdef_meta_object_rep
+  {
+  public:
+    cdef_package_rep (void)
+      : cdef_meta_object_rep (), member_count (0) { }
+
+    ~cdef_package_rep (void) { }
+
+    cdef_object_rep* copy (void) const { return new cdef_package_rep (*this); }
+
+    bool is_package (void) const { return true; }
+
+    std::string get_name (void) const { return get("Name").string_value (); }
+
+    void set_name (const std::string& nm) { put ("Name", nm); }
+
+    void install_class (const cdef_class& cls, const std::string& nm);
+
+    void install_function (const octave_value& fcn, const std::string& nm);
+
+    void install_package (const cdef_package& pack, const std::string& nm);
+
+    Cell get_classes (void) const;
+
+    Cell get_functions (void) const;
+
+    Cell get_packages (void) const;
+
+    octave_idx_type static_count (void) const { return member_count; }
+
+    void destroy (void)
+      {
+        if (member_count)
+          {
+            refcount++;
+            cdef_package lock (this);
+
+            member_count = 0;
+            class_map.clear ();
+            package_map.clear ();
+          }
+        else
+          delete this;
+      }
+
+    octave_value_list
+    meta_subsref (const std::string& type,
+                  const std::list<octave_value_list>& idx, int nargout);
+
+    void meta_release (void);
+
+    bool meta_is_postfix_index_handled (char type) const
+      { return (type == '.'); }
+
+    octave_value find (const std::string& nm);
+
+  private:
+    std::string full_name;
+    std::map<std::string, cdef_class> class_map;
+    std::map<std::string, octave_value> function_map;
+    std::map<std::string, cdef_package> package_map;
+
+    // The number of registered members in this package (classes, packages).
+    // This only accounts for the members that back-reference to this package.
+    octave_idx_type member_count;
+
+    typedef std::map<std::string, cdef_class>::iterator class_iterator;
+    typedef std::map<std::string, cdef_class>::const_iterator class_const_iterator;
+    typedef std::map<std::string, octave_value>::iterator function_iterator;
+    typedef std::map<std::string, octave_value>::const_iterator function_const_iterator;
+    typedef std::map<std::string, cdef_package>::iterator package_iterator;
+    typedef std::map<std::string, cdef_package>::const_iterator package_const_iterator;
+
+  private:
+    cdef_package_rep (const cdef_package_rep& p)
+      : cdef_meta_object_rep (p), full_name (p.full_name),
+        class_map (p.class_map), function_map (p.function_map),
+        package_map (p.package_map), member_count (p.member_count)
+      { }
+
+    cdef_package wrap (void)
+      {
+        refcount++;
+        return cdef_package (this);
+      }
+  };
+
+public:
+  cdef_package (void) : cdef_meta_object () { }
+
+  cdef_package (const std::string& nm)
+      : cdef_meta_object (new cdef_package_rep ())
+    { get_rep ()->set_name (nm); }
+
+  cdef_package (const cdef_package& pack)
+    : cdef_meta_object (pack) { }
+
+  cdef_package (const cdef_object& obj)
+      : cdef_meta_object (obj)
+    {
+      // This should never happen...
+      if (! is_package ())
+        error ("internal error: invalid assignment from %s to meta.package object",
+               class_name ().c_str ());
+    }
+
+  cdef_package& operator = (const cdef_package& pack)
+    {
+      cdef_object::operator= (pack);
+
+      return *this;
+    }
+
+  void install_class (const cdef_class& cls, const std::string& nm)
+    { get_rep ()->install_class (cls, nm); }
+
+  void install_function (const octave_value& fcn, const std::string& nm)
+    { get_rep ()->install_function (fcn, nm); }
+
+  void install_package (const cdef_package& pack, const std::string& nm)
+    { get_rep ()->install_package (pack, nm); }
+
+  Cell get_classes (void) const
+    { return get_rep ()->get_classes (); }
+
+  Cell get_functions (void) const
+    { return get_rep ()->get_functions (); }
+
+  Cell get_packages (void) const
+    { return get_rep ()->get_packages (); }
+
+  std::string get_name (void) const { return get_rep ()->get_name (); }
+
+  octave_value find (const std::string& nm) { return get_rep ()->find (nm); }
+
+  static const cdef_package& meta (void) { return _meta; }
+
+private:
+  cdef_package_rep* get_rep (void)
+    { return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ()); }
+  
+  const cdef_package_rep* get_rep (void) const
+    { return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ()); }
+
+private:
+  static cdef_package _meta;
+
+  friend void install_classdef (void);
+};
+
+class
+octave_classdef : public octave_base_value
+{
+public:
+  octave_classdef (void)
+      : octave_base_value (), object () { }
+
+  octave_classdef (const cdef_object& obj)
+      : octave_base_value (), object (obj) { }
+
+  octave_classdef (const octave_classdef& obj)
+      : octave_base_value (obj), object (obj.object) { }
+
+  octave_base_value* clone (void) const
+    { return new octave_classdef (object.clone ()); }
+
+  octave_base_value* empty_clone (void) const
+    { return new octave_classdef (object.empty_clone ()); }
+
+  cdef_object get_object (void) const { return object; }
+
+  cdef_object& get_object_ref (void) { return object; }
+
+  bool is_defined (void) const { return true; }
+
+  bool is_map (void) const { return true; }
+
+  bool is_object (void) const { return true; }
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
+
+  bool print_name_tag (std::ostream& os, const std::string& name) const;
+
+  void print_with_name (std::ostream& os, const std::string& name,
+                        bool print_padding = true);
+
+  octave_value_list subsref (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             int nargout);
+
+  octave_value subsref (const std::string& type,
+                        const std::list<octave_value_list>& idx)
+    {
+      octave_value_list retval = subsref (type, idx, 1);
+      return (retval.length () > 0 ? retval(0) : octave_value ());
+    }
+
+  octave_value subsref (const std::string& type,
+                        const std::list<octave_value_list>& idx,
+                        bool auto_add);
+
+  octave_value subsasgn (const std::string& type,
+                         const std::list<octave_value_list>& idx,
+                         const octave_value& rhs);
+
+  octave_value
+  undef_subsasgn (const std::string& type,
+                  const std::list<octave_value_list>& idx,
+                  const octave_value& rhs);
+
+  string_vector map_keys (void) const { return object.map_keys (); }
+
+  dim_vector dims (void) const { return object.dims (); }
+
+private:
+  cdef_object object;
+
+private:
+  DECLARE_OCTAVE_ALLOCATOR
+
+public:
+  int type_id (void) const { return t_id; }
+  std::string type_name (void) const { return t_name; }
+  std::string class_name (void) const { return object.class_name (); }
+
+  static int static_type_id (void) { return t_id; }
+  static std::string static_type_name (void) { return t_name; }
+  static std::string static_class_name (void) { return "<unknown>"; }
+  static void register_type (void);
+
+private:
+  static int t_id;
+
+  static const std::string t_name;
+};
+
+inline octave_value
+to_ov (const cdef_object& obj)
+{
+  if (obj.ok ())
+    return octave_value (new octave_classdef (obj));
+  else
+    return octave_value (Matrix ());
+}
+
+inline octave_value
+to_ov (const octave_value& ov)
+{ return ov; }
+
+inline cdef_object
+to_cdef (const octave_value& val)
+{
+  if (val.type_name () == "object")
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object ();
+  else
+    {
+      error ("cannot convert `%s' into `object'", val.type_name().c_str ());
+      return cdef_object ();
+    }
+}
+
+inline cdef_object&
+to_cdef_ref (const octave_value& val)
+{
+  static cdef_object empty;
+
+  if (val.type_name () == "object")
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object_ref ();
+  else
+    {
+      error ("cannot convert `%s' into `object'", val.type_name().c_str ());
+      return empty;
+    }
+}
+
+inline cdef_object
+to_cdef (const cdef_object& obj)
+{ return obj; }
+
+OCTINTERP_API void install_classdef (void);
+
+class
+cdef_manager
+{
+public:
+
+  static cdef_class find_class (const std::string& name,
+                                bool error_if_not_found = true,
+                                bool load_if_not_found = true)
+    {
+      if (instance_ok ())
+        return instance->do_find_class (name, error_if_not_found,
+                                        load_if_not_found);
+
+      return cdef_class ();
+    }
+
+  static octave_function* find_method_symbol (const std::string& method_name,
+                                              const std::string& class_name)
+    {
+      if (instance_ok ())
+        return instance->do_find_method_symbol (method_name, class_name);
+
+      return 0;
+    }
+
+  static cdef_package find_package (const std::string& name,
+                                    bool error_if_not_found = true,
+                                    bool load_if_not_found = true)
+    {
+      if (instance_ok ())
+        return instance->do_find_package (name, error_if_not_found,
+                                          load_if_not_found);
+
+      return cdef_package ();
+    }
+
+  static octave_function* find_package_symbol (const std::string& pack_name)
+    {
+      if (instance_ok ())
+        return instance->do_find_package_symbol (pack_name);
+
+      return 0;
+    }
+
+  static void register_class (const cdef_class& cls)
+    {
+      if (instance_ok ())
+        instance->do_register_class (cls);
+    }
+
+  static void unregister_class (const cdef_class& cls)
+    {
+      if (instance_ok ())
+        instance->do_unregister_class (cls);
+    }
+
+  static void register_package (const cdef_package& pkg)
+    {
+      if (instance_ok ())
+        instance->do_register_package (pkg);
+    }
+
+  static void unregister_package (const cdef_package& pkg)
+    {
+      if (instance_ok ())
+        instance->do_unregister_package (pkg);
+    }
+
+private:
+
+  cdef_manager (void) { }
+
+  cdef_manager (const cdef_manager&);
+
+  cdef_manager& operator = (const cdef_manager&);
+
+  ~cdef_manager (void) { }
+
+  static void create_instance (void);
+
+  static bool instance_ok (void)
+    {
+      bool retval = true;
+
+      if (! instance)
+        create_instance ();
+
+      if (! instance)
+        {
+          ::error ("unable to create cdef_manager!");
+
+          retval = false;
+        }
+
+      return retval;
+    }
+
+  static void cleanup_instance (void)
+    {
+      delete instance;
+
+      instance = 0;
+    }
+
+  cdef_class do_find_class (const std::string& name, bool error_if_not_found,
+                            bool load_if_not_found);
+
+  octave_function* do_find_method_symbol (const std::string& method_name,
+                                          const std::string& class_name);
+
+  cdef_package do_find_package (const std::string& name,
+                                bool error_if_not_found,
+                                bool load_if_not_found);
+
+  octave_function* do_find_package_symbol (const std::string& pack_name);
+
+  void do_register_class (const cdef_class& cls)
+    { all_classes[cls.get_name ()] = cls; }
+
+  void do_unregister_class (const cdef_class& cls)
+    { all_classes.erase(cls.get_name ()); }
+
+  void do_register_package (const cdef_package& pkg)
+    { all_packages[pkg.get_name ()] = pkg; }
+
+  void do_unregister_package (const cdef_package& pkg)
+    { all_packages.erase(pkg.get_name ()); }
+
+private:
+
+  // The single cdef_manager instance
+  static cdef_manager *instance;
+
+  // All registered/loaded classes
+  std::map<std::string, cdef_class> all_classes;
+
+  // All registered/loaded packages
+  std::map<std::string, cdef_package> all_packages;
+};
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/
--- a/libinterp/octave-value/ov-colon.cc
+++ b/libinterp/octave-value/ov-colon.cc
@@ -35,7 +35,7 @@
                                      "magic-colon", "magic-colon");
 
 void
-octave_magic_colon::print (std::ostream& os, bool) const
+octave_magic_colon::print (std::ostream& os, bool)
 {
   indent (os);
   print_raw (os);
--- a/libinterp/octave-value/ov-colon.h
+++ b/libinterp/octave-value/ov-colon.h
@@ -67,7 +67,7 @@
 
   bool is_magic_colon (void) const { return true; }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-complex.cc
+++ b/libinterp/octave-value/ov-complex.cc
@@ -105,7 +105,7 @@
 double
 octave_complex::double_value (bool force_conversion) const
 {
-  double retval = lo_ieee_nan_value ();
+  double retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -119,7 +119,7 @@
 float
 octave_complex::float_value (bool force_conversion) const
 {
-  float retval = lo_ieee_float_nan_value ();
+  float retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -315,7 +315,8 @@
                            bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, type_hid = -1, data_hid = -1;
+  hid_t space_hid, type_hid, data_hid;
+  space_hid = type_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
--- a/libinterp/octave-value/ov-cx-diag.cc
+++ b/libinterp/octave-value/ov-cx-diag.cc
@@ -167,7 +167,8 @@
 octave_complex_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats)
 {
 
-  int32_t r = matrix.rows (), c = matrix.cols ();
+  int32_t r = matrix.rows ();
+  int32_t c = matrix.cols ();
   os.write (reinterpret_cast<char *> (&r), 4);
   os.write (reinterpret_cast<char *> (&c), 4);
 
--- a/libinterp/octave-value/ov-cx-mat.cc
+++ b/libinterp/octave-value/ov-cx-mat.cc
@@ -561,7 +561,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1, type_hid = -1;
+  hid_t space_hid, data_hid, type_hid;
+  space_hid = data_hid = type_hid = -1;
   bool retval = true;
   ComplexNDArray m = complex_array_value ();
 
--- a/libinterp/octave-value/ov-cx-sparse.cc
+++ b/libinterp/octave-value/ov-cx-sparse.cc
@@ -241,16 +241,16 @@
 
   int32_t itmp;
   // Use negative value for ndims to be consistent with other formats
-  itmp= -2;
+  itmp = -2;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nr;
+  itmp = nr;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nc;
+  itmp = nc;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nz;
+  itmp = nz;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
   save_type st = LS_DOUBLE;
@@ -390,7 +390,8 @@
   if (group_hid < 0)
     return false;
 
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   SparseComplexMatrix m = sparse_complex_matrix_value ();
   octave_idx_type tmp;
@@ -636,7 +637,7 @@
 #else
   group_hid = H5Gopen (loc_id, name);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
 #if HAVE_HDF5_18
   data_hid = H5Dopen (group_hid, "nr", H5P_DEFAULT);
--- a/libinterp/octave-value/ov-fcn-handle.cc
+++ b/libinterp/octave-value/ov-fcn-handle.cc
@@ -270,7 +270,7 @@
           std::string dir_name = str.substr (0, xpos);
 
           octave_function *xfcn
-            = load_fcn_from_file (str, dir_name, "", nm);
+            = load_fcn_from_file (str, dir_name, "", "", nm);
 
           if (xfcn)
             {
@@ -300,7 +300,7 @@
 
           std::string dir_name = str.substr (0, xpos);
 
-          octave_function *xfcn = load_fcn_from_file (str, dir_name, "", nm);
+          octave_function *xfcn = load_fcn_from_file (str, dir_name, "", "", nm);
 
           if (xfcn)
             {
@@ -323,7 +323,7 @@
 
           std::string dir_name = fpath.substr (0, xpos);
 
-          octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", nm);
+          octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", "", nm);
 
           if (xfcn)
             {
@@ -721,7 +721,8 @@
   if (group_hid < 0)
     return false;
 
-  hid_t space_hid = -1, data_hid = -1, type_hid = -1;;
+  hid_t space_hid, data_hid, type_hid;
+  space_hid = data_hid = type_hid = -1;
 
   // attach the type of the variable
   type_hid = H5Tcopy (H5T_C_S1);
@@ -1386,7 +1387,7 @@
 */
 
 void
-octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -1572,7 +1573,8 @@
   // for any class.
   if (local_funcs && fptr
       && (fptr->is_subfunction () || fptr->is_private_function ()
-          || fptr->is_class_constructor ()))
+          || fptr->is_class_constructor ()
+          || fptr->is_classdef_constructor ()))
     {
       // Locally visible function.
       retval = octave_value (new octave_fcn_handle (f, tnm));
--- a/libinterp/octave-value/ov-fcn-handle.h
+++ b/libinterp/octave-value/ov-fcn-handle.h
@@ -153,7 +153,7 @@
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-fcn-inline.cc
+++ b/libinterp/octave-value/ov-fcn-inline.cc
@@ -284,14 +284,15 @@
 #else
   group_hid = H5Gcreate (loc_id, name, 0);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
   size_t len = 0;
   for (int i = 0; i < ifargs.length (); i++)
     if (len < ifargs(i).length ())
       len = ifargs(i).length ();
 
-  hid_t space_hid = -1, data_hid = -1, type_hid = -1;;
+  hid_t space_hid, data_hid, type_hid;
+  space_hid = data_hid = type_hid = -1;
   bool retval = true;
 
   // FIXME: Is there a better way of saving string vectors,
@@ -423,7 +424,7 @@
 #else
   group_hid = H5Gopen (loc_id, name);
 #endif
-  if (group_hid < 0 ) return false;
+  if (group_hid < 0) return false;
 
 #if HAVE_HDF5_18
   data_hid = H5Dopen (group_hid, "args", H5P_DEFAULT);
@@ -597,7 +598,7 @@
 #endif
 
 void
-octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
--- a/libinterp/octave-value/ov-fcn-inline.h
+++ b/libinterp/octave-value/ov-fcn-inline.h
@@ -86,7 +86,7 @@
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-fcn.h
+++ b/libinterp/octave-value/ov-fcn.h
@@ -46,7 +46,8 @@
 
   octave_function (void)
     : relative (false), locked (false), private_function (false),
-      xdispatch_class (), my_name (), my_dir_name (), doc () { }
+      xdispatch_class (), xpackage_name (), my_name (), my_dir_name (),
+      doc () { }
 
   ~octave_function (void) { }
 
@@ -85,6 +86,10 @@
   virtual bool is_class_constructor (const std::string& = std::string ()) const
   { return false; }
 
+  virtual bool
+  is_classdef_constructor (const std::string& = std::string ()) const
+    { return false; }
+
   virtual bool is_class_method (const std::string& = std::string ()) const
   { return false; }
 
@@ -96,6 +101,10 @@
 
   std::string dispatch_class (void) const { return xdispatch_class; }
 
+  void stash_package_name (const std::string& pack) { xpackage_name = pack; }
+
+  std::string package_name (void) const { return xpackage_name; }
+
   virtual void
   mark_as_private_function (const std::string& cname = std::string ())
   {
@@ -152,6 +161,14 @@
 
   std::string name (void) const { return my_name; }
 
+  std::string canonical_name (void) const
+    {
+      if (xpackage_name.empty ())
+        return my_name;
+      else
+        return xpackage_name + "." + my_name;
+    }
+
   void document (const std::string& ds) { doc = ds; }
 
   std::string doc_string (void) const { return doc; }
@@ -160,6 +177,9 @@
 
   virtual void accept (tree_walker&) { }
 
+  virtual bool is_postfix_index_handled (char type) const
+    { return (type == '(' || type == '{'); }
+
 protected:
 
   octave_function (const std::string& nm,
@@ -181,6 +201,10 @@
   // to which the method belongs.
   std::string xdispatch_class;
 
+  // If this function is part of a package, this is the full name
+  // of the package to which the function belongs.
+  std::string xpackage_name;
+
   // The name of this function.
   std::string my_name;
 
--- a/libinterp/octave-value/ov-float.cc
+++ b/libinterp/octave-value/ov-float.cc
@@ -191,7 +191,8 @@
                                 bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
@@ -326,8 +327,31 @@
       SCALAR_MAPPER (isnan, xisnan);
       SCALAR_MAPPER (xsignbit, xsignbit);
 
+    // Special cases for Matlab compatibility.
+    case umap_xtolower:
+    case umap_xtoupper:
+      return scalar;
+
+    case umap_xisalnum:
+    case umap_xisalpha:
+    case umap_xisascii:
+    case umap_xiscntrl:
+    case umap_xisdigit:
+    case umap_xisgraph:
+    case umap_xislower:
+    case umap_xisprint:
+    case umap_xispunct:
+    case umap_xisspace:
+    case umap_xisupper:
+    case umap_xisxdigit:
+    case umap_xtoascii:
+      {
+        octave_value str_conv = convert_to_str (true, true);
+        return error_state ? octave_value () : str_conv.map (umap);
+      }
+
     default:
-      return octave_base_value::map (umap);
+        return octave_base_value::map (umap);
     }
 }
 
--- a/libinterp/octave-value/ov-flt-complex.cc
+++ b/libinterp/octave-value/ov-flt-complex.cc
@@ -89,7 +89,7 @@
 double
 octave_float_complex::double_value (bool force_conversion) const
 {
-  double retval = lo_ieee_nan_value ();
+  double retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -103,7 +103,7 @@
 float
 octave_float_complex::float_value (bool force_conversion) const
 {
-  float retval = lo_ieee_float_nan_value ();
+  float retval;
 
   if (! force_conversion)
     gripe_implicit_conversion ("Octave:imag-to-real",
@@ -300,7 +300,8 @@
                                  bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, type_hid = -1, data_hid = -1;
+  hid_t space_hid, type_hid, data_hid;
+  space_hid = type_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
--- a/libinterp/octave-value/ov-flt-cx-diag.cc
+++ b/libinterp/octave-value/ov-flt-cx-diag.cc
@@ -150,7 +150,8 @@
                                                bool& /* save_as_floats */)
 {
 
-  int32_t r = matrix.rows (), c = matrix.cols ();
+  int32_t r = matrix.rows ();
+  int32_t c = matrix.cols ();
   os.write (reinterpret_cast<char *> (&r), 4);
   os.write (reinterpret_cast<char *> (&c), 4);
 
--- a/libinterp/octave-value/ov-flt-cx-mat.cc
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc
@@ -536,7 +536,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1, type_hid = -1;
+  hid_t space_hid, data_hid, type_hid;
+  space_hid = data_hid = type_hid = -1;
   bool retval = true;
   FloatComplexNDArray m = complex_array_value ();
 
--- a/libinterp/octave-value/ov-flt-re-diag.cc
+++ b/libinterp/octave-value/ov-flt-re-diag.cc
@@ -119,7 +119,8 @@
                                        bool& /* save_as_floats*/)
 {
 
-  int32_t r = matrix.rows (), c = matrix.cols ();
+  int32_t r = matrix.rows ();
+  int32_t c = matrix.cols ();
   os.write (reinterpret_cast<char *> (&r), 4);
   os.write (reinterpret_cast<char *> (&c), 4);
 
--- a/libinterp/octave-value/ov-flt-re-mat.cc
+++ b/libinterp/octave-value/ov-flt-re-mat.cc
@@ -563,7 +563,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   FloatNDArray m = array_value ();
 
@@ -811,6 +812,29 @@
       ARRAY_MAPPER (isna, bool, octave_is_NA);
       ARRAY_MAPPER (xsignbit, float, xsignbit);
 
+    // Special cases for Matlab compatibility.
+    case umap_xtolower:
+    case umap_xtoupper:
+      return matrix;
+
+    case umap_xisalnum:
+    case umap_xisalpha:
+    case umap_xisascii:
+    case umap_xiscntrl:
+    case umap_xisdigit:
+    case umap_xisgraph:
+    case umap_xislower:
+    case umap_xisprint:
+    case umap_xispunct:
+    case umap_xisspace:
+    case umap_xisupper:
+    case umap_xisxdigit:
+    case umap_xtoascii:
+      {
+        octave_value str_conv = convert_to_str (true, true);
+        return error_state ? octave_value () : str_conv.map (umap);
+      }
+
     default:
       return octave_base_value::map (umap);
     }
--- a/libinterp/octave-value/ov-intx.h
+++ b/libinterp/octave-value/ov-intx.h
@@ -358,8 +358,15 @@
       case umap_finite:
         return boolNDArray (matrix.dims (), true);
 
+      // Special cases for Matlab compatibility.
+      case umap_xtolower:
+      case umap_xtoupper:
+        return matrix;
+
       default:
         {
+          // FIXME: we should be able to do better than converting to
+          // double here.
           octave_matrix m (array_value ());
           return m.map (umap);
         }
@@ -658,6 +665,11 @@
       case umap_finite:
         return true;
 
+      // Special cases for Matlab compatibility.
+      case umap_xtolower:
+      case umap_xtoupper:
+        return scalar;
+
       default:
         {
           octave_scalar m (scalar_value ());
--- a/libinterp/octave-value/ov-java.cc
+++ b/libinterp/octave-value/ov-java.cc
@@ -1150,7 +1150,8 @@
           if (jni_env->IsInstanceOf (jobj, cls))
             {
               jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);
-              int rows = jni_env->GetArrayLength (jarr), cols = 0;
+              int rows = jni_env->GetArrayLength (jarr);
+              int cols = 0;
 
               if (rows > 0)
                 {
@@ -1761,7 +1762,7 @@
 }
 
 void
-octave_java::print (std::ostream& os, bool) const
+octave_java::print (std::ostream& os, bool)
 {
   print_raw (os);
   newline (os);
--- a/libinterp/octave-value/ov-java.h
+++ b/libinterp/octave-value/ov-java.h
@@ -149,7 +149,7 @@
 
   dim_vector dims (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-lazy-idx.h
+++ b/libinterp/octave-value/ov-lazy-idx.h
@@ -128,7 +128,7 @@
   bool print_as_scalar (void) const
   { return make_value ().print_as_scalar (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const
+  void print (std::ostream& os, bool pr_as_read_syntax = false)
   { make_value ().print (os, pr_as_read_syntax); }
 
   void print_info (std::ostream& os, const std::string& prefix) const
--- a/libinterp/octave-value/ov-oncleanup.cc
+++ b/libinterp/octave-value/ov-oncleanup.cc
@@ -170,7 +170,7 @@
 #endif
 
 void
-octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_oncleanup::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
--- a/libinterp/octave-value/ov-oncleanup.h
+++ b/libinterp/octave-value/ov-oncleanup.h
@@ -87,7 +87,7 @@
   bool load_hdf5 (hid_t loc_id, const char *name);
 #endif
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-perm.cc
+++ b/libinterp/octave-value/ov-perm.cc
@@ -260,8 +260,6 @@
 bool
 octave_perm_matrix::save_ascii (std::ostream& os)
 {
-  typedef octave_int<octave_idx_type> idx_int_type;
-
   os << "# size: " << matrix.rows () << "\n";
   os << "# orient: " << (matrix.is_col_perm () ? 'c' : 'r') << '\n';
 
@@ -277,7 +275,6 @@
 bool
 octave_perm_matrix::load_ascii (std::istream& is)
 {
-  typedef octave_int<octave_idx_type> idx_int_type;
   octave_idx_type n;
   bool success = true;
   char orient;
@@ -328,7 +325,7 @@
 
 bool
 octave_perm_matrix::load_binary (std::istream& is, bool swap,
-                                 oct_mach_info::float_format )
+                                 oct_mach_info::float_format)
 {
   int32_t sz;
   bool colp;
@@ -389,7 +386,7 @@
 }
 
 void
-octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_perm_matrix::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -451,3 +448,18 @@
   return retval;
 }
 
+octave_value
+octave_perm_matrix::fast_elem_extract (octave_idx_type n) const
+{
+  if (n < matrix.numel ())
+    {
+      octave_idx_type nr = matrix.rows ();
+
+      octave_idx_type r = n % nr;
+      octave_idx_type c = n / nr;
+
+      return octave_value (matrix.elem (r, c));
+    }
+  else
+    return octave_value ();
+}
--- a/libinterp/octave-value/ov-perm.h
+++ b/libinterp/octave-value/ov-perm.h
@@ -211,13 +211,15 @@
 
   bool print_as_scalar (void) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_info (std::ostream& os, const std::string& prefix) const;
 
   octave_value map (unary_mapper_t umap) const
   { return to_dense ().map (umap); }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 protected:
 
   PermMatrix matrix;
--- a/libinterp/octave-value/ov-range.cc
+++ b/libinterp/octave-value/ov-range.cc
@@ -352,7 +352,7 @@
 }
 
 void
-octave_range::print (std::ostream& os, bool pr_as_read_syntax) const
+octave_range::print (std::ostream& os, bool pr_as_read_syntax)
 {
   print_raw (os, pr_as_read_syntax);
   newline (os);
@@ -549,7 +549,8 @@
                          bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, type_hid = -1, data_hid = -1;
+  hid_t space_hid, type_hid, data_hid;
+  space_hid = type_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
@@ -676,6 +677,13 @@
   return retval;
 }
 
+octave_value
+octave_range::fast_elem_extract (octave_idx_type n) const
+{
+  return (n < range.nelem ())
+    ? octave_value (range.elem (n)) : octave_value ();
+}
+
 DEFUN (allow_noninteger_range_as_index, args, nargout,
        "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {@var{val} =} allow_noninteger_range_as_index ()\n\
--- a/libinterp/octave-value/ov-range.h
+++ b/libinterp/octave-value/ov-range.h
@@ -249,7 +249,7 @@
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -290,6 +290,8 @@
     return m.map (umap);
   }
 
+  octave_value fast_elem_extract (octave_idx_type n) const;
+
 private:
 
   Range range;
--- a/libinterp/octave-value/ov-re-diag.cc
+++ b/libinterp/octave-value/ov-re-diag.cc
@@ -179,7 +179,8 @@
 octave_diag_matrix::save_binary (std::ostream& os, bool& save_as_floats)
 {
 
-  int32_t r = matrix.rows (), c = matrix.cols ();
+  int32_t r = matrix.rows ();
+  int32_t c = matrix.cols ();
   os.write (reinterpret_cast<char *> (&r), 4);
   os.write (reinterpret_cast<char *> (&c), 4);
 
--- a/libinterp/octave-value/ov-re-mat.cc
+++ b/libinterp/octave-value/ov-re-mat.cc
@@ -675,7 +675,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   NDArray m = array_value ();
 
@@ -934,13 +935,30 @@
       ARRAY_MAPPER (isna, bool, octave_is_NA);
       ARRAY_MAPPER (xsignbit, double, xsignbit);
 
+    // Special cases for Matlab compatibility.
+    case umap_xtolower:
+    case umap_xtoupper:
+      return matrix;
+
+    case umap_xisalnum:
+    case umap_xisalpha:
+    case umap_xisascii:
+    case umap_xiscntrl:
+    case umap_xisdigit:
+    case umap_xisgraph:
+    case umap_xislower:
+    case umap_xisprint:
+    case umap_xispunct:
+    case umap_xisspace:
+    case umap_xisupper:
+    case umap_xisxdigit:
+    case umap_xtoascii:
+      {
+        octave_value str_conv = convert_to_str (true, true);
+        return error_state ? octave_value () : str_conv.map (umap);
+      }
+
     default:
-      if (umap >= umap_xisalnum && umap <= umap_xtoupper)
-        {
-          octave_value str_conv = convert_to_str (true, true);
-          return error_state ? octave_value () : str_conv.map (umap);
-        }
-      else
         return octave_base_value::map (umap);
     }
 }
--- a/libinterp/octave-value/ov-re-sparse.cc
+++ b/libinterp/octave-value/ov-re-sparse.cc
@@ -274,16 +274,16 @@
 
   int32_t itmp;
   // Use negative value for ndims to be consistent with other formats
-  itmp= -2;
+  itmp = -2;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nr;
+  itmp = nr;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nc;
+  itmp = nc;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
-  itmp= nz;
+  itmp = nz;
   os.write (reinterpret_cast<char *> (&itmp), 4);
 
   save_type st = LS_DOUBLE;
@@ -421,7 +421,8 @@
   if (group_hid < 0)
     return false;
 
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   SparseMatrix m = sparse_matrix_value ();
   octave_idx_type tmp;
--- a/libinterp/octave-value/ov-scalar.cc
+++ b/libinterp/octave-value/ov-scalar.cc
@@ -206,7 +206,8 @@
                           bool /* save_as_floats */)
 {
   hsize_t dimens[3];
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
 
   space_hid = H5Screate_simple (0, dimens, 0);
@@ -342,14 +343,31 @@
       SCALAR_MAPPER (isnan, xisnan);
       SCALAR_MAPPER (xsignbit, xsignbit);
 
+    // Special cases for Matlab compatibility.
+    case umap_xtolower:
+    case umap_xtoupper:
+      return scalar;
+
+    case umap_xisalnum:
+    case umap_xisalpha:
+    case umap_xisascii:
+    case umap_xiscntrl:
+    case umap_xisdigit:
+    case umap_xisgraph:
+    case umap_xislower:
+    case umap_xisprint:
+    case umap_xispunct:
+    case umap_xisspace:
+    case umap_xisupper:
+    case umap_xisxdigit:
+    case umap_xtoascii:
+      {
+        octave_value str_conv = convert_to_str (true, true);
+        return error_state ? octave_value () : str_conv.map (umap);
+      }
+
     default:
-      if (umap >= umap_xisalnum && umap <= umap_xtoupper)
-        {
-          octave_value str_conv = convert_to_str (true, true);
-          return error_state ? octave_value () : str_conv.map (umap);
-        }
-      else
-        return octave_base_value::map (umap);
+      return octave_base_value::map (umap);
     }
 }
 
--- a/libinterp/octave-value/ov-str-mat.cc
+++ b/libinterp/octave-value/ov-str-mat.cc
@@ -583,7 +583,8 @@
     return (empty > 0);
 
   int rank = dv.length ();
-  hid_t space_hid = -1, data_hid = -1;
+  hid_t space_hid, data_hid;
+  space_hid = data_hid = -1;
   bool retval = true;
   charNDArray m = char_array_value ();
 
--- a/libinterp/octave-value/ov-struct.cc
+++ b/libinterp/octave-value/ov-struct.cc
@@ -648,7 +648,7 @@
 }
 
 void
-octave_struct::print (std::ostream& os, bool) const
+octave_struct::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -844,7 +844,7 @@
               success = false;
             }
         }
-      else if (len == 0 )
+      else if (len == 0)
         map = octave_map (dv);
       else
         panic_impossible ();
@@ -1359,7 +1359,7 @@
 }
 
 void
-octave_scalar_struct::print (std::ostream& os, bool) const
+octave_scalar_struct::print (std::ostream& os, bool)
 {
   print_raw (os);
 }
@@ -2066,9 +2066,9 @@
   return retval;
 }
 
-DEFUN (nfields, args, ,
+DEFUN (numfields, args, ,
        "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} nfields (@var{s})\n\
+@deftypefn {Built-in Function} {} numfields (@var{s})\n\
 Return the number of fields of the structure @var{s}.\n\
 @seealso{fieldnames}\n\
 @end deftypefn")
--- a/libinterp/octave-value/ov-struct.h
+++ b/libinterp/octave-value/ov-struct.h
@@ -126,7 +126,7 @@
 
   string_vector map_keys (void) const { return map.fieldnames (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
@@ -249,7 +249,7 @@
 
   string_vector map_keys (void) const { return map.fieldnames (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const;
+  void print (std::ostream& os, bool pr_as_read_syntax = false);
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
--- a/libinterp/octave-value/ov-usr-fcn.cc
+++ b/libinterp/octave-value/ov-usr-fcn.cc
@@ -203,7 +203,7 @@
     num_named_args (param_list ? param_list->length () : 0),
     subfunction (false), inline_function (false),
     anonymous_function (false), nested_function (false),
-    class_constructor (false), class_method (false),
+    class_constructor (none), class_method (false),
     parent_scope (-1), local_scope (sid),
     curr_unwind_protect_frame (0)
 #ifdef HAVE_LLVM
@@ -319,14 +319,18 @@
 {
   std::ostringstream result;
 
-  if (is_inline_function ())
-    result << "inline@" << fcn_file_name ()
-           << ":" << location_line << ":" << location_column;
-  else if (is_anonymous_function ())
+  if (is_anonymous_function ())
     result << "anonymous@" << fcn_file_name ()
            << ":" << location_line << ":" << location_column;
   else if (is_subfunction ())
     result << parent_fcn_name () << ">" << name ();
+  else if (is_class_method ())
+    result << "@" << dispatch_class () << "/" << name ();
+  else if (is_class_constructor () || is_classdef_constructor ())
+    result << "@" << name ();
+  else if (is_inline_function ())
+    result << "inline@" << fcn_file_name ()
+           << ":" << location_line << ":" << location_column;
   else
     result << name ();
 
@@ -470,7 +474,7 @@
 
 octave_value_list
 octave_user_function::do_multi_index_op (int nargout,
-                                         const octave_value_list& args,
+                                         const octave_value_list& _args,
                                          const std::list<octave_lvalue>* lvalue_list)
 {
   octave_value_list retval;
@@ -481,6 +485,23 @@
   if (! cmd_list)
     return retval;
 
+  // If this function is a classdef constructor, extract the first input
+  // argument, which must be the partially constructed object instance.
+
+  octave_value_list args (_args);
+  octave_value_list ret_args;
+
+  if (is_classdef_constructor ())
+    {
+      if (args.length () > 0)
+        {
+          ret_args = args.slice (0, 1, true);
+          args = args.slice (1, args.length () - 1, true);
+        }
+      else
+        panic_impossible ();
+    }
+
 #ifdef HAVE_LLVM
   if (is_special_expr ()
       && tree_jit::execute (*this, args, retval))
@@ -524,6 +545,25 @@
         return retval;
     }
 
+  // For classdef constructor, pre-populate the output arguments
+  // with the pre-initialized object instance, extracted above.
+
+  if (is_classdef_constructor ())
+    {
+      if (ret_list)
+        {
+          ret_list->define_from_arg_vector (ret_args);
+          if (error_state)
+            return retval;
+        }
+      else
+        {
+          ::error ("%s: invalid classdef constructor, no output argument defined",
+                   dispatch_class ().c_str ());
+          return retval;
+        }
+    }
+
   // Force parameter list to be undefined when this function exits.
   // Doing so decrements the reference counts on the values of local
   // variables that are also named function parameters.
@@ -744,7 +784,8 @@
         {
           // Only assign the hidden variable if black holes actually present.
           Matrix bh (1, nbh);
-          octave_idx_type k = 0, l = 0;
+          octave_idx_type k = 0;
+          octave_idx_type l = 0;
           for (std::list<octave_lvalue>::const_iterator
                p = lvalue_list->begin (); p != lvalue_list->end (); p++)
             {
--- a/libinterp/octave-value/ov-usr-fcn.h
+++ b/libinterp/octave-value/ov-usr-fcn.h
@@ -327,12 +327,20 @@
 
   void mark_as_nested_function (void) { nested_function = true; }
 
-  void mark_as_class_constructor (void) { class_constructor = true; }
+  void mark_as_class_constructor (void) { class_constructor = legacy; }
+
+  void mark_as_classdef_constructor (void) { class_constructor = classdef; }
 
   bool is_class_constructor (const std::string& cname = std::string ()) const
   {
-    return class_constructor
-           ? (cname.empty () ? true : cname == dispatch_class ()) : false;
+    return class_constructor == legacy
+      ? (cname.empty () ? true : cname == dispatch_class ()) : false;
+  }
+
+  bool is_classdef_constructor (const std::string& cname = std::string ()) const
+  {
+    return class_constructor == classdef
+      ? (cname.empty () ? true : cname == dispatch_class ()) : false;
   }
 
   void mark_as_class_method (void) { class_method = true; }
@@ -408,6 +416,13 @@
 
 private:
 
+  enum class_ctor_type
+    {
+      none,
+      legacy,
+      classdef
+    };
+
   // List of arguments for this function.  These are local variables.
   tree_parameter_list *param_list;
 
@@ -470,8 +485,8 @@
   // TRUE means this is a nested function. (either a child or parent)
   bool nested_function;
 
-  // TRUE means this function is the constructor for class object.
-  bool class_constructor;
+  // Enum describing whether this function is the constructor for class object.
+  class_ctor_type class_constructor;
 
   // TRUE means this function is a method for a class.
   bool class_method;
--- a/libinterp/octave-value/ov.cc
+++ b/libinterp/octave-value/ov.cc
@@ -65,6 +65,7 @@
 #include "ov-range.h"
 #include "ov-struct.h"
 #include "ov-class.h"
+#include "ov-classdef.h"
 #include "ov-oncleanup.h"
 #include "ov-cs-list.h"
 #include "ov-colon.h"
@@ -1193,13 +1194,14 @@
 {
 }
 
-octave_value::octave_value (const Octave_map& m)
-  : rep (new octave_struct (m))
+octave_value::octave_value (const octave_map& m, const std::string& id,
+                            const std::list<std::string>& plist)
+  : rep (new octave_class (m, id, plist))
 {
   maybe_mutate ();
 }
 
-octave_value::octave_value (const Octave_map& m, const std::string& id,
+octave_value::octave_value (const octave_scalar_map& m, const std::string& id,
                             const std::list<std::string>& plist)
   : rep (new octave_class (m, id, plist))
 {
@@ -1951,7 +1953,9 @@
   int t2 = v2.type_id ();
 
   if (t1 == octave_class::static_type_id ()
-      || t2 == octave_class::static_type_id ())
+      || t2 == octave_class::static_type_id ()
+      || t1 == octave_classdef::static_type_id ()
+      || t2 == octave_classdef::static_type_id ())
     {
       octave_value_typeinfo::binary_class_op_fcn f
         = octave_value_typeinfo::lookup_binary_class_op (op);
@@ -2207,7 +2211,9 @@
   int t2 = v2.type_id ();
 
   if (t1 == octave_class::static_type_id ()
-      || t2 == octave_class::static_type_id ())
+      || t2 == octave_class::static_type_id ()
+      || t1 == octave_classdef::static_type_id ()
+      || t2 == octave_classdef::static_type_id ())
     {
       octave_value_typeinfo::binary_class_op_fcn f
         = octave_value_typeinfo::lookup_binary_class_op (op);
@@ -2381,7 +2387,8 @@
 
   int t = v.type_id ();
 
-  if (t == octave_class::static_type_id ())
+  if (t == octave_class::static_type_id ()
+      || t == octave_classdef::static_type_id ())
     {
       octave_value_typeinfo::unary_class_op_fcn f
         = octave_value_typeinfo::lookup_unary_class_op (op);
--- a/libinterp/octave-value/ov.h
+++ b/libinterp/octave-value/ov.h
@@ -46,7 +46,6 @@
 class mxArray;
 class octave_map;
 class octave_scalar_map;
-class Octave_map;
 class octave_stream;
 class octave_function;
 class octave_user_function;
@@ -285,8 +284,9 @@
   octave_value (const Range& r);
   octave_value (const octave_map& m);
   octave_value (const octave_scalar_map& m);
-  octave_value (const Octave_map& m);
-  octave_value (const Octave_map& m, const std::string& id,
+  octave_value (const octave_map& m, const std::string& id,
+                const std::list<std::string>& plist);
+  octave_value (const octave_scalar_map& m, const std::string& id,
                 const std::list<std::string>& plist);
   octave_value (const octave_value_list& m, bool = false);
   octave_value (octave_value::magic_colon);
@@ -1017,7 +1017,7 @@
   bool print_as_scalar (void) const
   { return rep->print_as_scalar (); }
 
-  void print (std::ostream& os, bool pr_as_read_syntax = false) const
+  void print (std::ostream& os, bool pr_as_read_syntax = false)
   { rep->print (os, pr_as_read_syntax); }
 
   void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const
--- a/libinterp/octave.cc
+++ b/libinterp/octave.cc
@@ -68,6 +68,7 @@
 #include "ops.h"
 #include "options-usage.h"
 #include "ov.h"
+#include "ov-classdef.h"
 #include "ov-range.h"
 #include "toplev.h"
 #include "parse.h"
@@ -754,6 +755,8 @@
 
   install_builtins ();
 
+  install_classdef ();
+
   for (std::list<std::string>::const_iterator it = command_line_path.begin ();
        it != command_line_path.end (); it++)
     load_path::set_command_line_path (*it);
--- a/libinterp/operators/op-b-b.cc
+++ b/libinterp/operators/op-b-b.cc
@@ -33,6 +33,7 @@
 #include "ov-float.h"
 #include "ov-re-mat.h"
 #include "ov-typeinfo.h"
+#include "ov-null-mat.h"
 #include "ops.h"
 #include "xdiv.h"
 #include "xpow.h"
@@ -92,4 +93,8 @@
   INSTALL_CATOP (octave_float_scalar, octave_bool, f_b);
 
   INSTALL_ASSIGNCONV (octave_bool, octave_bool, octave_bool_matrix);
+
+  INSTALL_ASSIGNCONV (octave_bool, octave_null_matrix, octave_bool_matrix);
+  INSTALL_ASSIGNCONV (octave_bool, octave_null_str, octave_bool_matrix);
+  INSTALL_ASSIGNCONV (octave_bool, octave_null_sq_str, octave_bool_matrix);
 }
--- a/libinterp/operators/op-cm-sm.cc
+++ b/libinterp/operators/op-cm-sm.cc
@@ -106,8 +106,8 @@
                    const octave_sparse_matrix&);
 
   return octave_value
-         (elem_xpow ( SparseComplexMatrix (v1.complex_matrix_value ()),
-                      v2.sparse_matrix_value ()));
+         (elem_xpow (SparseComplexMatrix (v1.complex_matrix_value ()),
+                     v2.sparse_matrix_value ()));
 }
 
 DEFBINOP (el_ldiv, complex_matrix, sparse_matrix)
--- a/libinterp/operators/op-int.h
+++ b/libinterp/operators/op-int.h
@@ -1160,7 +1160,10 @@
 #define OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS(TYPE) \
   INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_matrix, TYPE ## null_assign) \
   INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_str, TYPE ## null_assign) \
-  INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign)
+  INSTALL_ASSIGNOP (op_asn_eq, octave_ ## TYPE ## _matrix, octave_null_sq_str, TYPE ## null_assign) \
+  INSTALL_ASSIGNCONV (octave_ ## TYPE ## _scalar, octave_null_matrix, octave_ ## TYPE ## _matrix) \
+  INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_str, octave_ ## TYPE ## _matrix) \
+  INSTALL_ASSIGNCONV (octave_## TYPE ## _scalar, octave_null_sq_str, octave_ ## TYPE ## _matrix)
 
 #define OCTAVE_INSTALL_INT_OPS(TYPE) \
   OCTAVE_INSTALL_SS_INT_OPS (TYPE) \
--- a/libinterp/operators/op-pm-sm.cc
+++ b/libinterp/operators/op-pm-sm.cc
@@ -44,12 +44,12 @@
 DEFUNOP (not, perm_matrix)
 {
   // Obviously negation of a permutation matrix destroys sparsity
-  return octave_value ( ! a.bool_array_value ());
+  return octave_value (! a.bool_array_value ());
 }
 
 DEFUNOP (uminus, perm_matrix)
 {
-  return octave_value ( - a.sparse_matrix_value ());
+  return octave_value (- a.sparse_matrix_value ());
 }
 
 // Most other logical operations cast to SparseBoolMatrix
--- a/libinterp/operators/op-sbm-sbm.cc
+++ b/libinterp/operators/op-sbm-sbm.cc
@@ -49,7 +49,7 @@
 DEFUNOP (uminus, sparse_bool_matrix)
 {
   CAST_UNOP_ARG (const octave_sparse_bool_matrix&);
-  return octave_value ( - v.sparse_matrix_value ());
+  return octave_value (- v.sparse_matrix_value ());
 }
 
 DEFUNOP (transpose, sparse_bool_matrix)
--- a/libinterp/parse-tree/lex.h
+++ b/libinterp/parse-tree/lex.h
@@ -261,7 +261,9 @@
       looking_at_matrix_or_assign_lhs (false),
       looking_for_object_index (false),
       looking_at_indirect_ref (false), parsing_class_method (false),
-      maybe_classdef_get_set_method (false), parsing_classdef (false),
+      parsing_classdef (false), maybe_classdef_get_set_method (false),
+      parsing_classdef_get_method (false),
+      parsing_classdef_set_method (false), 
       quote_is_transpose (false), force_script (false),
       reading_fcn_file (false), reading_script_file (false),
       reading_classdef_file (false),
@@ -341,13 +343,19 @@
   // true means we are parsing a class method in function or classdef file.
   bool parsing_class_method;
 
+  // true means we are parsing a classdef file
+  bool parsing_classdef;
+
   // true means we are parsing a class method declaration line in a
   // classdef file and can accept a property get or set method name.
   // for example, "get.propertyname" is recognized as a function name.
   bool maybe_classdef_get_set_method;
 
-  // true means we are parsing a classdef file
-  bool parsing_classdef;
+  // TRUE means we are parsing a classdef get.method.
+  bool parsing_classdef_get_method;
+
+  // TRUE means we are parsing a classdef set.method.
+  bool parsing_classdef_set_method;
 
   // return transpose or start a string?
   bool quote_is_transpose;
@@ -572,6 +580,8 @@
 
   int is_keyword_token (const std::string& s);
 
+  bool fq_identifier_contains_keyword (const std::string& s);
+
   bool whitespace_is_significant (void);
 
   void handle_number (void);
@@ -590,6 +600,8 @@
 
   int handle_meta_identifier (void);
 
+  int handle_fq_identifier (void);
+
   int handle_identifier (void);
 
   void maybe_warn_separator_insert (char sep);
@@ -675,6 +687,8 @@
 
   int show_token (int tok);
 
+  void enable_fq_identifier (void);
+
 protected:
 
   std::stack<int> start_state_stack;
--- a/libinterp/parse-tree/lex.ll
+++ b/libinterp/parse-tree/lex.ll
@@ -54,6 +54,8 @@
 %x DQ_STRING_START
 %x SQ_STRING_START
 
+%x FQ_IDENT_START
+
 %{
 
 #include <cctype>
@@ -254,6 +256,43 @@
     } \
   while (0)
 
+#define HANDLE_IDENTIFIER(pattern, get_set) \
+  do \
+    { \
+      curr_lexer->lexer_debug (pattern); \
+ \
+      int tok = curr_lexer->previous_token_value (); \
+ \
+      if (curr_lexer->whitespace_is_significant () \
+          && curr_lexer->space_follows_previous_token () \
+          && ! (tok == '[' || tok == '{' \
+                || curr_lexer->previous_token_is_binop ())) \
+        { \
+          yyless (0); \
+          unput (','); \
+        } \
+      else \
+        { \
+          if (! curr_lexer->looking_at_decl_list \
+              && curr_lexer->previous_token_may_be_command ()) \
+            { \
+              yyless (0); \
+              curr_lexer->push_start_state (COMMAND_START); \
+            } \
+          else \
+            { \
+              if (get_set) \
+                curr_lexer->maybe_classdef_get_set_method = false; \
+ \
+              int id_tok = curr_lexer->handle_identifier (); \
+ \
+              if (id_tok >= 0) \
+                return curr_lexer->count_token_internal (id_tok); \
+            } \
+        } \
+    } \
+  while (0)
+
 static bool Vdisplay_tokens = false;
 
 static unsigned int Vtoken_count = 0;
@@ -274,6 +313,7 @@
 Im      [iIjJ]
 CCHAR   [#%]
 IDENT   ([_$a-zA-Z][_$a-zA-Z0-9]*)
+FQIDENT ({IDENT}(\.{IDENT})*)
 EXPON   ([DdEe][+-]?{D}+)
 NUMBER  (({D}+\.?{D}*{EXPON}?)|(\.{D}+{EXPON}?)|(0[xX][0-9a-fA-F]+))
 
@@ -994,6 +1034,35 @@
   }
 
 %{
+// Fully-qualified identifiers (used for classdef).
+%}
+
+<FQ_IDENT_START>{FQIDENT} {
+    curr_lexer->lexer_debug ("<FQ_IDENT_START>{FQIDENT}");
+    curr_lexer->pop_start_state ();
+
+    int id_tok = curr_lexer->handle_fq_identifier ();
+
+    if (id_tok >= 0)
+      {
+        curr_lexer->looking_for_object_index = true;
+
+        return curr_lexer->count_token_internal (id_tok);
+      }
+  }
+
+<FQ_IDENT_START>{S}+ {
+    curr_lexer->current_input_column += yyleng;
+
+    curr_lexer->mark_previous_token_trailing_space ();
+  }
+
+<FQ_IDENT_START>. {
+    yyless (0);
+    curr_lexer->pop_start_state ();
+  }
+
+%{
 // Imaginary numbers.
 %}
 
@@ -1114,46 +1183,25 @@
 
 %{
 // Identifiers.
+
+// Don't allow get and set to be recognized as keywords if they are
+// followed by "(".
 %}
 
+(set|get)/{S}*\( {
+    HANDLE_IDENTIFIER ("(set|get)/{S}*\\(", true);
+  }
+
 {IDENT} {
-    curr_lexer->lexer_debug ("{IDENT}");
-
-    int tok = curr_lexer->previous_token_value ();
-
-    if (curr_lexer->whitespace_is_significant ()
-        && curr_lexer->space_follows_previous_token ()
-        && ! (tok == '[' || tok == '{'
-              || curr_lexer->previous_token_is_binop ()))
-      {
-        yyless (0);
-        unput (',');
-      }
-    else
-      {
-        if (! curr_lexer->looking_at_decl_list
-            && curr_lexer->previous_token_may_be_command ())
-          {
-            yyless (0);
-            curr_lexer->push_start_state (COMMAND_START);
-          }
-        else
-          {
-            int id_tok = curr_lexer->handle_identifier ();
-
-            if (id_tok >= 0)
-              return curr_lexer->count_token_internal (id_tok);
-          }
-      }
+    HANDLE_IDENTIFIER ("{IDENT}", false);
   }
 
 %{
 // Superclass method identifiers.
 %}
 
-{IDENT}@{IDENT} |
-{IDENT}@{IDENT}.{IDENT} {
-    curr_lexer->lexer_debug ("{IDENT}@{IDENT}|{IDENT}@{IDENT}.{IDENT}");
+{IDENT}@{FQIDENT} {
+    curr_lexer->lexer_debug ("{IDENT}@{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ())
       {
@@ -1168,7 +1216,7 @@
           {
             curr_lexer->looking_for_object_index = true;
 
-            return curr_lexer->count_token_internal (SUPERCLASSREF);
+            return curr_lexer->count_token_internal (id_tok);
           }
       }
   }
@@ -1177,9 +1225,8 @@
 // Metaclass query
 %}
 
-\?{IDENT} |
-\?{IDENT}\.{IDENT} {
-    curr_lexer->lexer_debug ("\\?{IDENT}|\\?{IDENT}\\.{IDENT}");
+\?{FQIDENT} {
+    curr_lexer->lexer_debug ("\\?{FQIDENT}");
 
     if (curr_lexer->previous_token_may_be_command ()
         &&  curr_lexer->space_follows_previous_token ())
@@ -1195,7 +1242,7 @@
           {
             curr_lexer->looking_for_object_index = true;
 
-            return curr_lexer->count_token_internal (METAQUERY);
+            return curr_lexer->count_token_internal (id_tok);
           }
       }
   }
@@ -1943,8 +1990,10 @@
   looking_for_object_index = false; 
   looking_at_indirect_ref = false;
   parsing_class_method = false;
+  parsing_classdef = false;
   maybe_classdef_get_set_method = false;
-  parsing_classdef = false;
+  parsing_classdef_get_method = false;
+  parsing_classdef_set_method = false;
   force_script = false;
   reading_fcn_file = false;
   reading_script_file = false;
@@ -2346,20 +2395,6 @@
           at_beginning_of_statement = true;
           break;
 
-        case static_kw:
-          if ((reading_fcn_file || reading_script_file
-               || reading_classdef_file)
-              && ! fcn_file_full_name.empty ())
-            warning_with_id ("Octave:deprecated-keyword",
-                             "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d of file '%s'",
-                             input_line_number,
-                             fcn_file_full_name.c_str ());
-          else
-            warning_with_id ("Octave:deprecated-keyword",
-                             "the 'static' keyword is obsolete and will be removed from a future version of Octave; please use 'persistent' instead; near line %d",
-                             input_line_number);
-          // fall through ...
-
         case persistent_kw:
         case global_kw:
           looking_at_decl_list = true;
@@ -2372,10 +2407,9 @@
 
         case end_kw:
           if (inside_any_object_index ()
-              || (! reading_classdef_file
-                  && (defining_func
-                      && ! (looking_at_return_list
-                            || parsed_function_name.top ()))))
+              || (defining_func
+                  && ! (looking_at_return_list
+                        || parsed_function_name.top ())))
             {
               at_beginning_of_statement = previous_at_bos;
               return 0;
@@ -2561,6 +2595,34 @@
 }
 
 bool
+octave_base_lexer::fq_identifier_contains_keyword (const std::string& s)
+{
+  size_t p1 = 0;
+  size_t p2;
+
+  std::string s_part;
+
+  do
+    {
+      p2 = s.find ('.', p1);
+
+      if (p2 != std::string::npos)
+        {
+          s_part = s.substr (p1, p2 - p1);
+          p1 = p2 + 1;
+        }
+      else
+        s_part = s.substr (p1);
+
+      if (is_keyword_token (s_part))
+        return true;
+    }
+  while (p2 != std::string::npos);
+
+  return false;
+}
+
+bool
 octave_base_lexer::whitespace_is_significant (void)
 {
   return (nesting_level.is_bracket ()
@@ -2732,36 +2794,23 @@
 int
 octave_base_lexer::handle_superclass_identifier (void)
 {
-  std::string pkg;
-  char *yytxt = flex_yytext ();
-  std::string meth = strip_trailing_whitespace (yytxt);
+  std::string meth = flex_yytext ();
+
   size_t pos = meth.find ("@");
-  std::string cls = meth.substr (pos).substr (1);
-  meth = meth.substr (0, pos - 1);
-
-  pos = cls.find (".");
-  if (pos != std::string::npos)
-    {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
-    }
-
-  int kw_token = (is_keyword_token (meth) || is_keyword_token (cls)
-                  || is_keyword_token (pkg));
+  std::string cls = meth.substr (pos + 1);
+  meth = meth.substr (0, pos);
+
+  bool kw_token = (is_keyword_token (meth)
+                   || fq_identifier_contains_keyword (cls));
+
   if (kw_token)
     {
-      error ("method, class and package names may not be keywords");
+      error ("method, class, and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  symbol_table::scope_id sid = symtab_context.curr_scope ();
-
-  push_token (new token
-              (SUPERCLASSREF,
-               meth.empty () ? 0 : &(symbol_table::insert (meth, sid)),
-               cls.empty () ? 0 : &(symbol_table::insert (cls, sid)),
-               pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)),
-               input_line_number, current_input_column));
+  push_token (new token (SUPERCLASSREF, meth, cls,
+                         input_line_number, current_input_column));
 
   current_input_column += flex_yyleng ();
 
@@ -2771,37 +2820,41 @@
 int
 octave_base_lexer::handle_meta_identifier (void)
 {
-  std::string pkg;
-  char *yytxt = flex_yytext ();
-  std::string cls = strip_trailing_whitespace (yytxt).substr (1);
-  size_t pos = cls.find (".");
-
-  if (pos != std::string::npos)
+  std::string cls = std::string(flex_yytext ()).substr (1);
+
+  if (fq_identifier_contains_keyword (cls))
     {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
-    }
-
-  int kw_token = is_keyword_token (cls) || is_keyword_token (pkg);
-  if (kw_token)
-    {
-       error ("class and package names may not be keywords");
+      error ("class and package names may not be keywords");
       return LEXICAL_ERROR;
     }
 
-  symbol_table::scope_id sid = symtab_context.curr_scope ();
-
-  push_token (new token
-              (METAQUERY,
-               cls.empty () ? 0 : &(symbol_table::insert (cls, sid)),
-               pkg.empty () ? 0 : &(symbol_table::insert (pkg, sid)),
-               input_line_number, current_input_column));
+  push_token (new token (METAQUERY, cls, input_line_number,
+                         current_input_column));
 
   current_input_column += flex_yyleng ();
 
   return METAQUERY;
 }
 
+int
+octave_base_lexer::handle_fq_identifier (void)
+{
+  std::string tok = flex_yytext ();
+
+  if (fq_identifier_contains_keyword (tok))
+    {
+      error ("function, method, class, and package names may not be keywords");
+      return LEXICAL_ERROR;
+    }
+
+  push_token (new token (FQ_IDENT, tok, input_line_number,
+                         current_input_column));
+
+  current_input_column += flex_yyleng ();
+
+  return FQ_IDENT;
+}
+
 // Figure out exactly what kind of token to return when we have seen
 // an identifier.  Handles keywords.  Return -1 if the identifier
 // should be ignored.
@@ -3359,6 +3412,12 @@
   return tok;
 }
 
+void
+octave_base_lexer::enable_fq_identifier (void)
+{
+  push_start_state (FQ_IDENT_START);
+}
+
 int
 octave_lexer::fill_flex_buffer (char *buf, unsigned max_size)
 {
--- a/libinterp/parse-tree/module.mk
+++ b/libinterp/parse-tree/module.mk
@@ -21,6 +21,7 @@
   parse-tree/pt-cbinop.h \
   parse-tree/pt-cell.h \
   parse-tree/pt-check.h \
+  parse-tree/pt-classdef.h \
   parse-tree/pt-cmd.h \
   parse-tree/pt-colon.h \
   parse-tree/pt-const.h \
@@ -29,6 +30,7 @@
   parse-tree/pt-except.h \
   parse-tree/pt-exp.h \
   parse-tree/pt-fcn-handle.h \
+  parse-tree/pt-funcall.h \
   parse-tree/pt-id.h \
   parse-tree/pt-idx.h \
   parse-tree/pt-jump.h \
@@ -52,6 +54,7 @@
   parse-tree/pt-cbinop.cc \
   parse-tree/pt-cell.cc \
   parse-tree/pt-check.cc \
+  parse-tree/pt-classdef.cc \
   parse-tree/pt-cmd.cc \
   parse-tree/pt-colon.cc \
   parse-tree/pt-const.cc \
@@ -60,6 +63,7 @@
   parse-tree/pt-except.cc \
   parse-tree/pt-exp.cc \
   parse-tree/pt-fcn-handle.cc \
+  parse-tree/pt-funcall.cc \
   parse-tree/pt-id.cc \
   parse-tree/pt-idx.cc \
   parse-tree/pt-jump.cc \
--- a/libinterp/parse-tree/oct-parse.in.yy
+++ b/libinterp/parse-tree/oct-parse.in.yy
@@ -62,6 +62,7 @@
 #include "load-path.h"
 #include "oct-hist.h"
 #include "oct-map.h"
+#include "ov-classdef.h"
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
 #include "ov-null-mat.h"
@@ -70,6 +71,7 @@
 #include "parse.h"
 #include "pt-all.h"
 #include "pt-eval.h"
+#include "pt-funcall.h"
 #include "symtab.h"
 #include "token.h"
 #include "unwind-prot.h"
@@ -164,6 +166,8 @@
   tree_expression *tree_expression_type;
   tree_constant *tree_constant_type;
   tree_fcn_handle *tree_fcn_handle_type;
+  tree_funcall *tree_funcall_type;
+  tree_function_def *tree_function_def_type;
   tree_anon_fcn_handle *tree_anon_fcn_handle_type;
   tree_identifier *tree_identifier_type;
   tree_index_expression *tree_index_expression_type;
@@ -183,7 +187,24 @@
   tree_statement *tree_statement_type;
   tree_statement_list *tree_statement_list_type;
   octave_user_function *octave_user_function_type;
-  void *dummy_type;
+
+  tree_classdef *tree_classdef_type;
+  tree_classdef_attribute* tree_classdef_attribute_type;
+  tree_classdef_attribute_list* tree_classdef_attribute_list_type;
+  tree_classdef_superclass* tree_classdef_superclass_type;
+  tree_classdef_superclass_list* tree_classdef_superclass_list_type;
+  tree_classdef_body* tree_classdef_body_type;
+  tree_classdef_property* tree_classdef_property_type;
+  tree_classdef_property_list* tree_classdef_property_list_type;
+  tree_classdef_properties_block* tree_classdef_properties_block_type;
+  tree_classdef_methods_list* tree_classdef_methods_list_type;
+  tree_classdef_methods_block* tree_classdef_methods_block_type;
+  tree_classdef_event* tree_classdef_event_type;
+  tree_classdef_events_list* tree_classdef_events_list_type;
+  tree_classdef_events_block* tree_classdef_events_block_type;
+  tree_classdef_enum* tree_classdef_enum_type;
+  tree_classdef_enum_list* tree_classdef_enum_list_type;
+  tree_classdef_enum_block* tree_classdef_enum_block_type;
 }
 
 // Tokens with line and column information.
@@ -210,21 +231,22 @@
 %token <tok_val> TRY CATCH
 %token <tok_val> GLOBAL PERSISTENT
 %token <tok_val> FCN_HANDLE
+%token <tok_val> CLASSDEF
 %token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
 %token <tok_val> METAQUERY
 %token <tok_val> SUPERCLASSREF
+%token <tok_val> FQ_IDENT
 %token <tok_val> GET SET
 %token <tok_val> FCN
 
 // Other tokens.
 %token END_OF_INPUT LEXICAL_ERROR
-%token INPUT_FILE CLASSDEF
+%token INPUT_FILE
 // %token VARARGIN VARARGOUT
 
 // Nonterminals we construct.
-%type <tok_val> function_beg
-%type <comment_type> stash_comment classdef_beg
-%type <comment_type> properties_beg methods_beg events_beg enum_beg
+%type <comment_type> stash_comment
+%type <tok_val> function_beg classdef_beg
 %type <sep_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep
 %type <tree_type> input
 %type <tree_constant_type> string constant magic_colon
@@ -236,18 +258,19 @@
 %type <tree_expression_type> primary_expr oper_expr power_expr
 %type <tree_expression_type> simple_expr colon_expr assign_expr expression
 %type <tree_identifier_type> identifier fcn_name magic_tilde
-%type <tree_identifier_type> superclass_identifier meta_identifier
-%type <octave_user_function_type> function1 function2 classdef1
+%type <tree_funcall_type> superclass_identifier meta_identifier
+%type <octave_user_function_type> function1 function2
 %type <tree_index_expression_type> word_list_cmd
 %type <tree_colon_expression_type> colon_expr1
 %type <tree_argument_list_type> arg_list word_list assign_lhs
 %type <tree_argument_list_type> cell_or_matrix_row
 %type <tree_parameter_list_type> param_list param_list1 param_list2
 %type <tree_parameter_list_type> return_list return_list1
-%type <tree_parameter_list_type> superclasses opt_superclasses
 %type <tree_command_type> command select_command loop_command
-%type <tree_command_type> jump_command except_command function
-%type <tree_command_type> file classdef
+%type <tree_command_type> jump_command except_command
+%type <tree_function_def_type> function
+%type <tree_classdef_type> classdef
+%type <tree_command_type> file
 %type <tree_if_command_type> if_command
 %type <tree_if_clause_type> elseif_clause else_clause
 %type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
@@ -257,25 +280,27 @@
 %type <tree_decl_elt_type> decl2 param_list_elt
 %type <tree_decl_init_list_type> decl1
 %type <tree_decl_command_type> declaration
-%type <tree_statement_type> statement function_end classdef_end
+%type <tree_statement_type> statement function_end
 %type <tree_statement_list_type> simple_list simple_list1 list list1
 %type <tree_statement_list_type> opt_list
-// These types need to be specified.
-%type <dummy_type> attr
-%type <dummy_type> class_event
-%type <dummy_type> class_enum
-%type <dummy_type> class_property
-%type <dummy_type> properties_list
-%type <dummy_type> properties_block
-%type <dummy_type> methods_list
-%type <dummy_type> methods_block
-%type <dummy_type> opt_attr_list
-%type <dummy_type> attr_list
-%type <dummy_type> events_list
-%type <dummy_type> events_block
-%type <dummy_type> enum_list
-%type <dummy_type> enum_block
-%type <dummy_type> class_body
+%type <tree_classdef_attribute_type> attr
+%type <tree_classdef_attribute_list_type> attr_list opt_attr_list
+%type <tree_classdef_superclass_type> superclass
+%type <tree_classdef_superclass_list_type> superclass_list opt_superclass_list
+%type <tree_classdef_body_type> class_body
+%type <tree_classdef_property_type> class_property
+%type <tree_classdef_property_list_type> property_list
+%type <tree_classdef_properties_block_type> properties_block
+%type <tree_classdef_methods_list_type> methods_list
+%type <tree_classdef_methods_block_type> methods_block
+%type <tree_classdef_event_type> class_event
+%type <tree_classdef_events_list_type> events_list
+%type <tree_classdef_events_block_type> events_block
+%type <tree_classdef_enum_type> class_enum
+%type <tree_classdef_enum_list_type> enum_list
+%type <tree_classdef_enum_block_type> enum_block
+%type <tree_function_def_type> method_decl method
+%type <octave_user_function_type> method_decl1
 
 // Precedence and associativity.
 %right '=' ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ OR_EQ AND_EQ LSHIFT_EQ RSHIFT_EQ
@@ -312,6 +337,8 @@
 %destructor { delete $$; } <tree_expression_type> 
 %destructor { delete $$; } <tree_constant_type> 
 %destructor { delete $$; } <tree_fcn_handle_type> 
+%destructor { delete $$; } <tree_funcall>
+%destructor { delete $$; } <tree_function_def>
 %destructor { delete $$; } <tree_anon_fcn_handle_type> 
 %destructor { delete $$; } <tree_identifier_type> 
 %destructor { delete $$; } <tree_index_expression_type> 
@@ -332,6 +359,24 @@
 %destructor { delete $$; } <tree_statement_list_type> 
 %destructor { delete $$; } <octave_user_function_type> 
 
+%destructor { delete $$; } <tree_classdef_type>
+%destructor { delete $$; } <tree_classdef_attribute_type>
+%destructor { delete $$; } <tree_classdef_attribute_list_type>
+%destructor { delete $$; } <tree_classdef_superclass_type>
+%destructor { delete $$; } <tree_classdef_superclass_list_type>
+%destructor { delete $$; } <tree_classdef_body_type>
+%destructor { delete $$; } <tree_classdef_property_type>
+%destructor { delete $$; } <tree_classdef_property_list_type>
+%destructor { delete $$; } <tree_classdef_properties_block_type>
+%destructor { delete $$; } <tree_classdef_methods_list_type>
+%destructor { delete $$; } <tree_classdef_methods_block_type>
+%destructor { delete $$; } <tree_classdef_event_type>
+%destructor { delete $$; } <tree_classdef_events_list_type>
+%destructor { delete $$; } <tree_classdef_events_block_type>
+%destructor { delete $$; } <tree_classdef_enum_type>
+%destructor { delete $$; } <tree_classdef_enum_list_type>
+%destructor { delete $$; } <tree_classdef_enum_block_type>
+
 %destructor {
     warning_with_id
       ("Octave:parser-destructor",
@@ -439,11 +484,23 @@
 
 superclass_identifier
                 : SUPERCLASSREF
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string method_nm = $1->superclass_method_name ();
+                    std::string class_nm = $1->superclass_class_name ();
+
+                    $$ = parser.make_superclass_ref
+                                       (method_nm, class_nm,
+                                        $1->line (), $1->column ());
+                  }
                 ;
 
 meta_identifier : METAQUERY
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string class_nm = $1->text ();
+
+                    $$ = parser.make_meta_class_query (class_nm, $1->line (),
+                                                       $1->column ());
+                  }
                 ;
 
 string          : DQ_STRING
@@ -867,8 +924,6 @@
                   { $$ = $1; }
                 | file
                   { $$ = $1; }
-                | classdef
-                  { $$ = $1; }
                 ;
 
 // =====================
@@ -1294,6 +1349,13 @@
 
                     $$ = 0;
                   }
+                | INPUT_FILE opt_nl classdef opt_sep END_OF_INPUT
+                  {
+                    if (lexer.reading_classdef_file)
+                      parser.classdef_object = $3;
+
+                    $$ = 0;
+                  }
                 ;
 
 // ===================
@@ -1336,12 +1398,14 @@
                   {
                     lexer.parsed_function_name.top () = true;
                     lexer.maybe_classdef_get_set_method = false;
+                    lexer.parsing_classdef_get_method = true;
                     $$ = $3;
                   }
                 | SET '.' identifier
                   {
                     lexer.parsed_function_name.top () = true;
                     lexer.maybe_classdef_get_set_method = false;
+                    lexer.parsing_classdef_set_method = true;
                     $$ = $3;
                   }
                 ;
@@ -1352,6 +1416,14 @@
 
                     delete $1;
 
+                    if (lexer.parsing_classdef_get_method)
+                      fname.insert (0, "get.");
+                    else if (lexer.parsing_classdef_set_method)
+                      fname.insert (0, "set.");
+
+                    lexer.parsing_classdef_get_method = false;
+                    lexer.parsing_classdef_set_method = false;
+
                     $$ = parser.frob_function (fname, $2);
                   }
                 ;
@@ -1411,158 +1483,299 @@
 // Classdef
 // ========
 
-classdef_beg    : CLASSDEF stash_comment
+classdef_beg    : CLASSDEF
                   {
-                    $$ = 0;
+                    if (! lexer.reading_classdef_file)
+                      {
+                        parser.bison_error ("classdef must appear inside a file containing only a class definition");
+                        YYABORT;
+                      }
+
                     lexer.parsing_classdef = true;
+                    $$ = $1;
                   }
                 ;
 
-classdef_end    : END
+classdef        : classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep class_body opt_sep END
                   {
                     lexer.parsing_classdef = false;
 
-                    if (parser.end_token_ok ($1, token::classdef_end))
-                      $$ = parser.make_end ("endclassdef", false,
-                                            $1->line (), $1->column ());
-                    else
-                      ABORT_PARSE;
+                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, $7, $9, $2)))
+                      {
+                        // make_classdef deleted $3, $4, $5, and $7.
+                        ABORT_PARSE;
+                      }
                   }
-                ;
-
-classdef1       : classdef_beg opt_attr_list identifier opt_superclasses
-                  { $$ = 0; }
-                ;
-
-classdef        : classdef1 opt_sep class_body opt_sep stash_comment classdef_end
-                  { $$ = 0; }
+                | classdef_beg stash_comment opt_attr_list identifier opt_superclass_list opt_sep END
+                  {
+                    lexer.parsing_classdef = false;
+
+                    if (! ($$ = parser.make_classdef ($1, $3, $4, $5, 0, $7, $2)))
+                      {
+                        // make_classdef deleted $3, $4, and $5.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
 opt_attr_list   : // empty
                   { $$ = 0; }
                 | '(' attr_list ')'
-                  { $$ = 0; }
+                  { $$ = $2; }
                 ;
 
 attr_list       : attr
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute_list ($1); }
                 | attr_list ',' attr
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 attr            : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($1); }
                 | identifier '=' decl_param_init expression
-                  { $$ = 0; }
+                  {
+                    lexer.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_attribute ($1, $4);
+                  }
                 | EXPR_NOT identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_attribute ($2, false); }
                 ;
 
-opt_superclasses
+opt_superclass_list
                 : // empty
                   { $$ = 0; }
-                | superclasses
-                  { $$ = 0; }
+                | superclass_list
+                  { $$ = $1; }
                 ;
 
-superclasses    : EXPR_LT identifier '.' identifier
-                  { $$ = 0; }
-                | EXPR_LT identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier '.' identifier
-                  { $$ = 0; }
-                | superclasses EXPR_AND identifier
-                  { $$ = 0; }
+superclass_list : EXPR_LT
+                  { lexer.enable_fq_identifier (); }
+                  superclass
+                  { $$ = new tree_classdef_superclass_list ($3); }
+                | superclass_list EXPR_AND
+                  { lexer.enable_fq_identifier (); }
+                  superclass
+                  {
+                    $1->append ($4);
+                    $$ = $1;
+                  }
+                ;
+
+superclass      : FQ_IDENT
+                  { $$ = new tree_classdef_superclass ($1->text ()); }
                 ;
 
 class_body      : properties_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | methods_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | events_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | enum_block
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_body ($1); }
                 | class_body opt_sep properties_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep methods_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep events_block
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 | class_body opt_sep enum_block
-                  { $$ = 0; }
-                ;
-
-properties_beg  : PROPERTIES stash_comment
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 properties_block
-                : properties_beg opt_attr_list opt_sep properties_list opt_sep END
-                  { $$ = 0; }
+                : PROPERTIES stash_comment opt_attr_list opt_sep property_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_properties_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_properties_block delete $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | PROPERTIES stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_properties_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_properties_block delete $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
-properties_list
+property_list
                 : class_property
-                  { $$ = 0; }
-                | properties_list opt_sep class_property
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property_list ($1); }
+                | property_list opt_sep class_property
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_property  : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_property ($1); }
                 | identifier '=' decl_param_init expression ';'
-                  { $$ = 0; }
+                  {
+                    lexer.looking_at_initializer_expression = false;
+                    $$ = new tree_classdef_property ($1, $4);
+                  }
                 ;
 
-methods_beg     : METHODS stash_comment
-                  { $$ = 0; }
+methods_block   : METHODS stash_comment opt_attr_list opt_sep methods_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_methods_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_methods_block deleted $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | METHODS stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_methods_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_methods_block deleted $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
-
-methods_block   : methods_beg opt_attr_list opt_sep methods_list opt_sep END
-                  { $$ = 0; }
+                ;
+
+method_decl1    : identifier
+                  {
+                    if (! ($$ = parser.start_classdef_external_method ($1, 0)))
+                      ABORT_PARSE;
+                  }
+                | identifier param_list
+                  {
+                    if (! ($$ = parser.start_classdef_external_method ($1, $2)))
+                      ABORT_PARSE;
+                  }
                 ;
 
-methods_list    : function
-                  { $$ = 0; }
-                | methods_list opt_sep function
-                  { $$ = 0; }
+method_decl     : stash_comment method_decl1
+                  { $$ = parser.finish_classdef_external_method ($2, 0, $1); }
+                | stash_comment return_list '='
+                  {
+                    lexer.defining_func++;
+                    lexer.parsed_function_name.push (false);
+                  }
+                  method_decl1
+                  {
+                    lexer.defining_func--;
+                    lexer.parsed_function_name.pop ();
+                    $$ = parser.finish_classdef_external_method ($5, $2, $1);
+                  }
+                ;
+
+method          : method_decl
+                  { $$ = $1; }
+                | function
+                  { $$ = $1; }
                 ;
 
-events_beg      : EVENTS stash_comment
-                  { $$ = 0; }
+methods_list    : method
+                  {
+                    octave_value fcn;
+                    if ($1)
+                      fcn = $1->function ();
+                    delete $1;
+                    $$ = new tree_classdef_methods_list (fcn);
+                  }
+                | methods_list opt_sep method
+                  {
+                    octave_value fcn;
+                    if ($3)
+                      fcn = $3->function ();
+                    delete $3;
+
+                    $1->append (fcn);
+                    $$ = $1;
+                  }
                 ;
 
-events_block    : events_beg opt_attr_list opt_sep events_list opt_sep END
-                  { $$ = 0; }
+events_block    : EVENTS stash_comment opt_attr_list opt_sep events_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_events_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_events_block deleted $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | EVENTS stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_events_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_events_block deleted $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
 events_list     : class_event
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_events_list ($1); }
                 | events_list opt_sep class_event
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_event     : identifier
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_event ($1); }
                 ;
 
-enum_beg        : ENUMERATION stash_comment
-                  { $$ = 0; }
-                ;
-
-enum_block      : enum_beg opt_attr_list opt_sep enum_list opt_sep END
-                  { $$ = 0; }
+enum_block      : ENUMERATION stash_comment opt_attr_list opt_sep enum_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_enum_block
+                           ($1, $3, $5, $7, $2)))
+                      {
+                        // make_classdef_enum_block deleted $3 and $5.
+                        ABORT_PARSE;
+                      }
+                  }
+                | ENUMERATION stash_comment opt_attr_list opt_sep END
+                  {
+                    if (! ($$ = parser.make_classdef_enum_block
+                           ($1, $3, 0, $5, $2)))
+                      {
+                        // make_classdef_enum_block deleted $3.
+                        ABORT_PARSE;
+                      }
+                  }
                 ;
 
 enum_list       : class_enum
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum_list ($1); }
                 | enum_list opt_sep class_enum
-                  { $$ = 0; }
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
                 ;
 
 class_enum      : identifier '(' expression ')'
-                  { $$ = 0; }
+                  { $$ = new tree_classdef_enum ($1, $3); }
                 ;
 
 // =============
@@ -1660,6 +1873,7 @@
   curr_fcn_depth = 0;
   primary_fcn_scope = -1;
   curr_class_name = "";
+  curr_package_name = "";
   function_scopes.clear ();
   primary_fcn_ptr  = 0;
   subfunction_names.clear ();
@@ -1831,95 +2045,6 @@
     }
 }
 
-static tree_expression *
-fold (tree_binary_expression *e)
-{
-  tree_expression *retval = e;
-
-  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;
-
-  tree_expression *op1 = e->lhs ();
-  tree_expression *op2 = e->rhs ();
-
-  if (op1->is_constant () && op2->is_constant ())
-    {
-      octave_value tmp = e->rvalue1 ();
-
-      if (! (error_state || warning_state))
-        {
-          tree_constant *tc_retval
-            = new tree_constant (tmp, op1->line (), op1->column ());
-
-          std::ostringstream buf;
-
-          tree_print_code tpc (buf);
-
-          e->accept (tpc);
-
-          tc_retval->stash_original_text (buf.str ());
-
-          delete e;
-
-          retval = tc_retval;
-        }
-    }
-
-  return retval;
-}
-
-static tree_expression *
-fold (tree_unary_expression *e)
-{
-  tree_expression *retval = e;
-
-  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;
-
-  tree_expression *op = e->operand ();
-
-  if (op->is_constant ())
-    {
-      octave_value tmp = e->rvalue1 ();
-
-      if (! (error_state || warning_state))
-        {
-          tree_constant *tc_retval
-            = new tree_constant (tmp, op->line (), op->column ());
-
-          std::ostringstream buf;
-
-          tree_print_code tpc (buf);
-
-          e->accept (tpc);
-
-          tc_retval->stash_original_text (buf.str ());
-
-          delete e;
-
-          retval = tc_retval;
-        }
-    }
-
-  return retval;
-}
-
 // Finish building a range.
 
 tree_expression *
@@ -1975,8 +2100,6 @@
           e->preserve_base ();
           delete e;
 
-          // FIXME -- need to attempt constant folding here
-          // too (we need a generic way to do that).
           retval = base;
         }
     }
@@ -2189,10 +2312,7 @@
   int l = tok_val->line ();
   int c = tok_val->column ();
 
-  tree_binary_expression *e
-    = maybe_compound_binary_expression (op1, op2, l, c, t);
-
-  return fold (e);
+  return maybe_compound_binary_expression (op1, op2, l, c, t);
 }
 
 // Build a boolean expression.
@@ -2221,10 +2341,7 @@
   int l = tok_val->line ();
   int c = tok_val->column ();
 
-  tree_boolean_expression *e
-    = new tree_boolean_expression (op1, op2, l, c, t);
-
-  return fold (e);
+  return new tree_boolean_expression (op1, op2, l, c, t);
 }
 
 // Build a prefix expression.
@@ -2265,10 +2382,7 @@
   int l = tok_val->line ();
   int c = tok_val->column ();
 
-  tree_prefix_expression *e
-    = new tree_prefix_expression (op1, l, c, t);
-
-  return fold (e);
+  return new tree_prefix_expression (op1, l, c, t);
 }
 
 // Build a postfix expression.
@@ -2305,10 +2419,7 @@
   int l = tok_val->line ();
   int c = tok_val->column ();
 
-  tree_postfix_expression *e
-    = new tree_postfix_expression (op1, l, c, t);
-
-  return fold (e);
+  return new tree_postfix_expression (op1, l, c, t);
 }
 
 // Build an unwind-protect command.
@@ -3002,6 +3113,274 @@
   lexer.looking_at_parameter_list = false;
 }
 
+tree_funcall *
+octave_base_parser::make_superclass_ref (const std::string& method_nm,
+                                         const std::string& class_nm,
+                                         int l, int c)
+{
+  octave_value_list args;
+
+  args(1) = class_nm;
+  args(0) = method_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__superclass_reference__");
+
+  return new tree_funcall (fcn, args);
+}
+
+tree_funcall *
+octave_base_parser::make_meta_class_query (const std::string& class_nm,
+                                           int l, int c)
+{
+  octave_value_list args;
+
+  args(0) = class_nm;
+
+  octave_value fcn
+    = symbol_table::find_built_in_function ("__meta_class_query__");
+
+  return new tree_funcall (fcn, args);
+}
+
+// A CLASSDEF block defines a class that has a constructor and other
+// methods, but it is not an executable command.  Parsing the block
+// makes some changes in the symbol table (inserting the constructor
+// and methods, and adding to the list of known objects) and creates
+// a parse tree containing meta information about the class.
+
+tree_classdef *
+octave_base_parser::make_classdef (token *tok_val,
+                                   tree_classdef_attribute_list *a,
+                                   tree_identifier *id,
+                                   tree_classdef_superclass_list *sc,
+                                   tree_classdef_body *body, token *end_tok,
+                                   octave_comment_list *lc)
+{
+  tree_classdef *retval = 0;
+
+  std::string cls_name = id->name ();
+
+  std::string nm = lexer.fcn_file_name;
+
+  size_t pos = nm.find_last_of (file_ops::dir_sep_chars ());
+
+  if (pos != std::string::npos)
+    nm = lexer.fcn_file_name.substr (pos+1);
+
+  if (nm != cls_name)
+    bison_error ("invalid classdef definition, the class name must match the file name");
+  else if (end_token_ok (end_tok, token::classdef_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! body)
+        body = new tree_classdef_body ();
+
+      retval = new tree_classdef (a, id, sc, body, lc, tc,
+                                  curr_package_name, l, c);
+    }
+
+  if (! retval)
+    {
+      delete a;
+      delete id;
+      delete sc;
+      delete body;
+    }
+
+  return retval;
+}
+
+tree_classdef_properties_block *
+octave_base_parser::make_classdef_properties_block (token *tok_val,
+                                                    tree_classdef_attribute_list *a,
+                                                    tree_classdef_property_list *plist,
+                                                    token *end_tok,
+                                                    octave_comment_list *lc)
+{
+  tree_classdef_properties_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::properties_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! plist)
+        plist = new tree_classdef_property_list ();
+
+      retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete plist;
+    }
+
+  return retval;
+}
+
+tree_classdef_methods_block *
+octave_base_parser::make_classdef_methods_block (token *tok_val,
+                                                 tree_classdef_attribute_list *a,
+                                                 tree_classdef_methods_list *mlist,
+                                                 token *end_tok,
+                                                 octave_comment_list *lc)
+{
+  tree_classdef_methods_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::methods_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! mlist)
+        mlist = new tree_classdef_methods_list ();
+
+      retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete mlist;
+    }
+
+  return retval;
+}
+
+tree_classdef_events_block *
+octave_base_parser::make_classdef_events_block (token *tok_val,
+                                                tree_classdef_attribute_list *a,
+                                                tree_classdef_events_list *elist,
+                                                token *end_tok,
+                                                octave_comment_list *lc)
+{
+  tree_classdef_events_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::events_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! elist)
+        elist = new tree_classdef_events_list ();
+
+      retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete elist;
+    }
+
+  return retval;
+}
+
+tree_classdef_enum_block *
+octave_base_parser::make_classdef_enum_block (token *tok_val,
+                                              tree_classdef_attribute_list *a,
+                                              tree_classdef_enum_list *elist,
+                                              token *end_tok,
+                                              octave_comment_list *lc)
+{
+  tree_classdef_enum_block *retval = 0;
+
+  if (end_token_ok (end_tok, token::enumeration_end))
+    {
+      octave_comment_list *tc = lexer.comment_buf.get_comment ();
+
+      int l = tok_val->line ();
+      int c = tok_val->column ();
+
+      if (! elist)
+        elist = new tree_classdef_enum_list ();
+
+      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete elist;
+    }
+
+  return retval;
+}
+
+octave_user_function*
+octave_base_parser::start_classdef_external_method (tree_identifier *id,
+                                                    tree_parameter_list *pl)
+{
+  octave_user_function* retval = 0;
+
+  // External methods are only allowed within @-folders. In this case,
+  // curr_class_name will be non-empty.
+
+  if (! curr_class_name.empty ())
+    {
+
+      std::string mname = id->name ();
+
+      // Methods that cannot be declared outside the classdef file:
+      // - methods with '.' character (e.g. property accessors)
+      // - class constructor
+      // - `delete'
+
+      if (mname.find_first_of (".") == std::string::npos
+          && mname != "delete"
+          && mname != curr_class_name)
+        {
+          // Create a dummy function that is used until the real method
+          // is loaded.
+
+          retval = new octave_user_function (-1, pl);
+
+          retval->stash_function_name (mname);
+
+          int l = id->line ();
+          int c = id->column ();
+
+          retval->stash_fcn_location (l, c);
+        }
+      else
+        bison_error ("invalid external method declaration, an external "
+                     "method cannot be the class constructor, `delete' "
+                     "or have a dot (.) character in its name");
+    }
+  else
+    bison_error ("external methods are only allowed in @-folders");
+
+  if (! retval)
+    delete id;
+
+  return retval;
+}
+
+tree_function_def *
+octave_base_parser::finish_classdef_external_method (octave_user_function *fcn,
+                                                     tree_parameter_list *ret_list,
+                                                     octave_comment_list *cl)
+{
+  if (ret_list)
+    fcn->define_ret_list (ret_list);
+
+  if (cl)
+    fcn->stash_leading_comment (cl);
+
+  int l = fcn->beginning_line ();
+  int c = fcn->beginning_column ();
+
+  return new tree_function_def (fcn, l, c);
+}
+
 // Make an index expression.
 
 tree_index_expression *
@@ -3024,7 +3403,8 @@
   int l = expr->line ();
   int c = expr->column ();
 
-  expr->mark_postfix_indexed ();
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index (type);
 
   if (expr->is_index_expression ())
     {
@@ -3051,6 +3431,9 @@
   int l = expr->line ();
   int c = expr->column ();
 
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index ('.');
+
   if (expr->is_index_expression ())
     {
       tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
@@ -3070,13 +3453,17 @@
 // Make an indirect reference expression with dynamic field name.
 
 tree_index_expression *
-octave_base_parser::make_indirect_ref (tree_expression *expr, tree_expression *elt)
+octave_base_parser::make_indirect_ref (tree_expression *expr,
+                                       tree_expression *elt)
 {
   tree_index_expression *retval = 0;
 
   int l = expr->line ();
   int c = expr->column ();
 
+  if (! expr->is_postfix_indexed ()) 
+    expr->set_postfix_index ('.');
+
   if (expr->is_index_expression ())
     {
       tree_index_expression *tmp = static_cast<tree_index_expression *> (expr);
@@ -3464,6 +3851,7 @@
 static octave_function *
 parse_fcn_file (const std::string& full_file, const std::string& file,
                 const std::string& dispatch_type,
+                const std::string& package_name,
                 bool require_file, bool force_script, bool autoload,    
                 bool relative_lookup, const std::string& warn_for)
 {
@@ -3497,6 +3885,7 @@
       octave_parser parser (ffile);
 
       parser.curr_class_name = dispatch_type;
+      parser.curr_package_name = package_name;
       parser.autoloading = autoload;
       parser.fcn_file_from_relative_lookup = relative_lookup;
 
@@ -3511,20 +3900,37 @@
 
       fcn_ptr = parser.primary_fcn_ptr;
 
-      if (fcn_ptr)
+      if (status == 0)
         {
-          fcn_ptr->maybe_relocate_end ();
-
-          if (parser.parsing_subfunctions)
+          if (parser.lexer.reading_classdef_file
+              && parser.classdef_object)
             {
-              if (! parser.endfunction_found)
-                parser.subfunction_names.reverse ();
-
-              fcn_ptr->stash_subfunction_names (parser.subfunction_names);
+              // Convert parse tree for classdef object to
+              // meta.class info (and stash it in the symbol
+              // table?).  Return pointer to constructor?
+
+              if (fcn_ptr)
+                panic_impossible ();
+
+              bool is_at_folder = ! dispatch_type.empty ();
+
+              fcn_ptr =
+                parser.classdef_object->make_meta_class (is_at_folder);
+            }
+          else if (fcn_ptr)
+            {
+              fcn_ptr->maybe_relocate_end ();
+
+              if (parser.parsing_subfunctions)
+                {
+                  if (! parser.endfunction_found)
+                    parser.subfunction_names.reverse ();
+
+                  fcn_ptr->stash_subfunction_names (parser.subfunction_names);
+                }
             }
         }
-
-      if (status != 0)
+      else
         error ("parse error while reading file %s", full_file.c_str ());
     }
   else if (require_file)
@@ -3565,7 +3971,8 @@
       symbol_found = true;
 
       octave_function *fcn
-        = parse_fcn_file (full_file, file, "", true, false, false, false, "");
+        = parse_fcn_file (full_file, file, "", "", true, false, false, false,
+                          "");
 
       if (fcn)
         {
@@ -3629,6 +4036,7 @@
 octave_function *
 load_fcn_from_file (const std::string& file_name, const std::string& dir_name,
                     const std::string& dispatch_type,
+                    const std::string& package_name,
                     const std::string& fcn_name, bool autoload)
 {
   octave_function *retval = 0;
@@ -3676,7 +4084,8 @@
       // to get the help-string to use.
 
       octave_function *tmpfcn = parse_fcn_file (file.substr (0, len - 2),
-                                                nm, dispatch_type, false,
+                                                nm, dispatch_type,
+                                                package_name, false,
                                                 autoload, autoload,
                                                 relative_lookup, "");
 
@@ -3688,13 +4097,14 @@
     }
   else if (len > 2)
     {
-      retval = parse_fcn_file (file, nm, dispatch_type, true, autoload,
-                               autoload, relative_lookup, "");
+      retval = parse_fcn_file (file, nm, dispatch_type, package_name, true,
+                               autoload, autoload, relative_lookup, "");
     }
 
   if (retval)
     {
       retval->stash_dir_name (dir_name);
+      retval->stash_package_name (package_name);
 
       if (retval->is_user_function ())
         {
@@ -3904,7 +4314,7 @@
   if (! error_state)
     {
       octave_function *fcn = parse_fcn_file (file_full_name, file_name,
-                                             "", require_file, true,
+                                             "", "", require_file, true,
                                              false, false, warn_for);
 
       if (! error_state)
@@ -4635,7 +5045,7 @@
           if (nargin == 2)
             octave_stdout << "parsing " << full_file << std::endl;
 
-          octave_function *fcn = parse_fcn_file (full_file, file, "",
+          octave_function *fcn = parse_fcn_file (full_file, file, "", "",
                                                  true, false, false,
                                                  false, "__parse_file__");
 
--- a/libinterp/parse-tree/octave.gperf
+++ b/libinterp/parse-tree/octave.gperf
@@ -64,7 +64,6 @@
   properties_kw,
   return_kw,
   set_kw,
-  static_kw,
   switch_kw,
   try_kw,
   until_kw,
@@ -111,7 +110,6 @@
 properties, PROPERTIES, properties_kw
 return, FUNC_RET, return_kw
 set, SET, set_kw
-static, PERSISTENT, static_kw
 switch, SWITCH, switch_kw
 try, TRY, try_kw
 until, UNTIL, until_kw
--- a/libinterp/parse-tree/parse.h
+++ b/libinterp/parse-tree/parse.h
@@ -43,6 +43,18 @@
 class tree_argument_list;
 class tree_array_list;
 class tree_cell;
+class tree_classdef;
+class tree_classdef_attribute_list;
+class tree_classdef_body;
+class tree_classdef_enum_block;
+class tree_classdef_enum_list;
+class tree_classdef_events_block;
+class tree_classdef_events_list;
+class tree_classdef_methods_block;
+class tree_classdef_methods_list;
+class tree_classdef_properties_block;
+class tree_classdef_property_list;
+class tree_classdef_superclass_list;
 class tree_colon_expression;
 class tree_command;
 class tree_constant;
@@ -50,6 +62,7 @@
 class tree_decl_init_list;
 class tree_expression;
 class tree_fcn_handle;
+class tree_funcall;
 class tree_function_def;
 class tree_identifier;
 class tree_if_clause;
@@ -92,6 +105,7 @@
 load_fcn_from_file (const std::string& file_name,
                     const std::string& dir_name = std::string (),
                     const std::string& dispatch_type = std::string (),
+                    const std::string& package_name = std::string (),
                     const std::string& fcn_name = std::string (),
                     bool autoload = false);
 
@@ -136,9 +150,9 @@
       autoloading (false), fcn_file_from_relative_lookup (false),
       parsing_subfunctions (false), max_fcn_depth (0),
       curr_fcn_depth (0), primary_fcn_scope (-1),
-      curr_class_name (), function_scopes (), primary_fcn_ptr (0),
-      subfunction_names (), stmt_list (0),
-      lexer (lxr)
+      curr_class_name (), curr_package_name (), function_scopes (),
+      primary_fcn_ptr (0), subfunction_names (), classdef_object (0),
+      stmt_list (0), lexer (lxr)
   { }
 
   ~octave_base_parser (void);
@@ -284,6 +298,54 @@
   void
   recover_from_parsing_function (void);
 
+  tree_funcall *
+  make_superclass_ref (const std::string& method_nm,
+                       const std::string& class_nm,
+                       int l, int c);
+
+  tree_funcall *
+  make_meta_class_query (const std::string& class_nm,
+                         int l, int c);
+
+  tree_classdef *
+  make_classdef (token *tok_val, tree_classdef_attribute_list *a,
+                 tree_identifier *id, tree_classdef_superclass_list *sc,
+                 tree_classdef_body *body, token *end_tok,
+                 octave_comment_list *lc);
+
+  tree_classdef_properties_block *
+  make_classdef_properties_block (token *tok_val,
+                                  tree_classdef_attribute_list *a,
+                                  tree_classdef_property_list *plist,
+                                  token *end_tok, octave_comment_list *lc);
+
+  tree_classdef_methods_block *
+  make_classdef_methods_block (token *tok_val,
+                               tree_classdef_attribute_list *a,
+                               tree_classdef_methods_list *mlist,
+                               token *end_tok, octave_comment_list *lc);
+
+  tree_classdef_events_block *
+  make_classdef_events_block (token *tok_val,
+                              tree_classdef_attribute_list *a,
+                              tree_classdef_events_list *elist,
+                              token *end_tok, octave_comment_list *lc);
+
+  tree_classdef_enum_block *
+  make_classdef_enum_block (token *tok_val,
+                            tree_classdef_attribute_list *a,
+                            tree_classdef_enum_list *elist,
+                            token *end_tok, octave_comment_list *lc);
+
+  octave_user_function *
+  start_classdef_external_method (tree_identifier *id,
+                                  tree_parameter_list *pl);
+
+  tree_function_def *
+  finish_classdef_external_method (octave_user_function *fcn,
+                                   tree_parameter_list *ret_list,
+                                   octave_comment_list *cl);
+
   // Make an index expression.
   tree_index_expression *
   make_index_expression (tree_expression *expr,
@@ -372,6 +434,10 @@
   // constructors.
   std::string curr_class_name;
 
+  // Name of the current package when we are parsing an element contained
+  // in a package directory (+-directory).
+  std::string curr_package_name;
+
   // A stack holding the nested function scopes being parsed.
   // We don't use std::stack, because we want the clear method. Also, we
   // must access one from the top
@@ -385,6 +451,9 @@
   // file.  Eventually stashed in the primary function object.
   std::list<std::string> subfunction_names;
 
+  // Pointer to the classdef object we just parsed, if any.
+  tree_classdef *classdef_object;
+
   // Result of parsing input.
   tree_statement_list *stmt_list;
 
--- a/libinterp/parse-tree/pt-all.h
+++ b/libinterp/parse-tree/pt-all.h
@@ -30,6 +30,7 @@
 #include "pt-binop.h"
 #include "pt-cbinop.h"
 #include "pt-check.h"
+#include "pt-classdef.h"
 #include "pt-cmd.h"
 #include "pt-colon.h"
 #include "pt-const.h"
@@ -37,6 +38,7 @@
 #include "pt-except.h"
 #include "pt-exp.h"
 #include "pt-fcn-handle.h"
+#include "pt-funcall.h"
 #include "pt-id.h"
 #include "pt-idx.h"
 #include "pt-jump.h"
--- a/libinterp/parse-tree/pt-bp.cc
+++ b/libinterp/parse-tree/pt-bp.cc
@@ -293,6 +293,12 @@
 }
 
 void
+tree_breakpoint::visit_funcall (tree_funcall&)
+{
+  panic_impossible ();
+}
+
+void
 tree_breakpoint::visit_parameter_list (tree_parameter_list&)
 {
   panic_impossible ();
--- a/libinterp/parse-tree/pt-bp.h
+++ b/libinterp/parse-tree/pt-bp.h
@@ -106,6 +106,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-cbinop.cc
+++ b/libinterp/parse-tree/pt-cbinop.cc
@@ -162,7 +162,8 @@
 maybe_compound_binary_expression (tree_expression *a, tree_expression *b,
                                   int l, int c, octave_value::binary_op t)
 {
-  tree_expression *ca = a, *cb = b;
+  tree_expression *ca = a;
+  tree_expression *cb = b;
   octave_value::compound_binary_op ct;
 
   switch (t)
--- a/libinterp/parse-tree/pt-check.cc
+++ b/libinterp/parse-tree/pt-check.cc
@@ -357,6 +357,11 @@
 }
 
 void
+tree_checker::visit_funcall (tree_funcall& /* fc */)
+{
+}
+
+void
 tree_checker::visit_parameter_list (tree_parameter_list& lst)
 {
   tree_parameter_list::iterator p = lst.begin ();
--- a/libinterp/parse-tree/pt-check.h
+++ b/libinterp/parse-tree/pt-check.h
@@ -91,6 +91,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
new file mode 100644
--- /dev/null
+++ b/libinterp/parse-tree/pt-classdef.cc
@@ -0,0 +1,259 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-classdef.h"
+#include "pt-classdef.h"
+
+// Classdef attribute
+
+void
+tree_classdef_attribute::accept (tree_walker& tw)
+{
+  tw.visit_classdef_attribute (*this);
+}
+
+// Classdef attribute_list
+
+tree_classdef_attribute_list::~tree_classdef_attribute_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_attribute_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_attribute_list (*this);
+}
+
+// Classdef superclass
+
+void
+tree_classdef_superclass::accept (tree_walker& tw)
+{
+  tw.visit_classdef_superclass (*this);
+}
+
+// Classdef superclass_list
+
+tree_classdef_superclass_list::~tree_classdef_superclass_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_superclass_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_superclass_list (*this);
+}
+
+// Classdef property
+
+void
+tree_classdef_property::accept (tree_walker& tw)
+{
+  tw.visit_classdef_property (*this);
+}
+
+// Classdef property_list
+
+tree_classdef_property_list::~tree_classdef_property_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_property_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_property_list (*this);
+}
+
+// Classdef properties_block
+
+void
+tree_classdef_properties_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_properties_block (*this);
+}
+
+// Classdef methods_list
+
+void
+tree_classdef_methods_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_methods_list (*this);
+}
+
+// Classdef methods_block
+
+void
+tree_classdef_methods_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_methods_block (*this);
+}
+
+// Classdef event
+
+void
+tree_classdef_event::accept (tree_walker& tw)
+{
+  tw.visit_classdef_event (*this);
+}
+
+// Classdef events_list
+
+tree_classdef_events_list::~tree_classdef_events_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_events_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_events_list (*this);
+}
+
+// Classdef events_block
+
+void
+tree_classdef_events_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_events_block (*this);
+}
+
+// Classdef enum
+
+void
+tree_classdef_enum::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum (*this);
+}
+
+// Classdef enum_list
+
+tree_classdef_enum_list::~tree_classdef_enum_list (void)
+{
+  while (! empty ())
+    {
+      iterator p = begin ();
+      delete *p;
+      erase (p);
+    }
+}
+
+void
+tree_classdef_enum_list::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum_list (*this);
+}
+
+// Classdef enum_block
+
+void
+tree_classdef_enum_block::accept (tree_walker& tw)
+{
+  tw.visit_classdef_enum_block (*this);
+}
+
+// Classdef body
+
+tree_classdef_body::~tree_classdef_body (void)
+{
+  while (! properties_lst.empty ())
+    {
+      properties_list_iterator p = properties_lst.begin ();
+      delete *p;
+      properties_lst.erase (p);
+    }
+
+  while (! methods_lst.empty ())
+    {
+      methods_list_iterator p = methods_lst.begin ();
+      delete *p;
+      methods_lst.erase (p);
+    }
+
+  while (! events_lst.empty ())
+    {
+      events_list_iterator p = events_lst.begin ();
+      delete *p;
+      events_lst.erase (p);
+    }
+
+  while (! enum_lst.empty ())
+    {
+      enum_list_iterator p = enum_lst.begin ();
+      delete *p;
+      enum_lst.erase (p);
+    }
+}
+
+// Classdef
+
+octave_function*
+tree_classdef::make_meta_class (bool is_at_folder)
+{
+  octave_value retval;
+  cdef_class cls = cdef_class::make_meta_class (this, is_at_folder);
+
+  if (cls.ok ())
+    return cls.get_constructor_function ();
+
+  return 0;
+}
+
+tree_classdef *
+tree_classdef::dup (symbol_table::scope_id,
+                    symbol_table::context_id) const
+{
+  // FIXME
+  return 0;
+}
+
+void
+tree_classdef::accept (tree_walker& tw)
+{
+  tw.visit_classdef (*this);
+}
new file mode 100644
--- /dev/null
+++ b/libinterp/parse-tree/pt-classdef.h
@@ -0,0 +1,653 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_tree_classdef_h)
+#define octave_tree_classdef_h 1
+
+class octave_value;
+
+class tree_walker;
+
+#include "pt-cmd.h"
+#include "pt-exp.h"
+#include "pt-id.h"
+
+#include "base-list.h"
+
+#include <list>
+
+class tree_classdef_attribute
+{
+public:
+
+  tree_classdef_attribute (tree_identifier *i = 0, tree_expression *e = 0)
+    : id (i), expr (e), neg (false) { }
+
+  tree_classdef_attribute (tree_identifier *i, bool b)
+    : id (i), expr (0), neg (b) { }
+
+  ~tree_classdef_attribute (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  bool negate (void) { return neg; }
+
+  void accept (tree_walker&);
+
+private:
+  
+  tree_identifier *id;
+  tree_expression *expr;
+  bool neg;
+
+  // No copying!
+
+  tree_classdef_attribute (const tree_classdef_attribute&);
+
+  tree_classdef_attribute& operator = (const tree_classdef_attribute&);
+};
+
+class tree_classdef_attribute_list : public octave_base_list<tree_classdef_attribute *>
+{
+public:
+
+  tree_classdef_attribute_list (void) { }
+
+  tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); }
+
+  tree_classdef_attribute_list (const octave_base_list<tree_classdef_attribute *>& a)
+    : octave_base_list<tree_classdef_attribute *> (a) { }
+
+  ~tree_classdef_attribute_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_attribute_list (const tree_classdef_attribute_list&);
+
+  tree_classdef_attribute_list& operator = (const tree_classdef_attribute_list&);
+};
+
+class tree_classdef_superclass
+{
+public:
+
+  tree_classdef_superclass (const std::string& cname)
+    : cls_name (cname) { }
+
+  ~tree_classdef_superclass (void) { }
+
+  std::string class_name (void) { return cls_name; }
+
+  void accept (tree_walker&);
+
+private:
+
+  std::string cls_name;
+
+  // No copying!
+
+  tree_classdef_superclass (const tree_classdef_superclass&);
+
+  tree_classdef_superclass& operator = (const tree_classdef_superclass&);
+};
+
+class tree_classdef_superclass_list : public octave_base_list<tree_classdef_superclass *>
+{
+public:
+
+  tree_classdef_superclass_list (void) { }
+
+  tree_classdef_superclass_list (tree_classdef_superclass *sc) { append (sc); }
+
+  tree_classdef_superclass_list (const octave_base_list<tree_classdef_superclass *>& a)
+    : octave_base_list<tree_classdef_superclass *> (a) { }
+
+  ~tree_classdef_superclass_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_superclass_list (const tree_classdef_superclass_list&);
+
+  tree_classdef_superclass_list& operator = (const tree_classdef_superclass_list&);
+};
+
+template <typename T>
+class tree_classdef_element : public tree
+{
+public:
+
+  tree_classdef_element (tree_classdef_attribute_list *a,
+                         octave_base_list<T> *elist,
+                         octave_comment_list *lc, octave_comment_list *tc,
+                         int l = -1, int c = -1)
+    : tree (l, c), attr_list (a), elt_list (elist),
+      lead_comm (lc), trail_comm (tc)
+  { }
+
+  ~tree_classdef_element (void)
+  {
+    delete attr_list;
+    delete elt_list;
+    delete lead_comm;
+    delete trail_comm;
+  }
+
+  tree_classdef_attribute_list *attribute_list (void) { return attr_list; }
+
+  octave_base_list<T> *element_list (void) { return elt_list; }
+
+  octave_comment_list *leading_comment (void) { return lead_comm; }
+
+  octave_comment_list *trailing_comment (void) { return trail_comm; }
+
+  void accept (tree_walker&) { }
+
+private:
+
+  // List of attributes that apply to this class.
+  tree_classdef_attribute_list *attr_list;
+
+  // The list of objects contained in this block.
+  octave_base_list<T> *elt_list;
+  
+  // Comment preceding the token marking the beginning of the block.
+  octave_comment_list *lead_comm;
+
+  // Comment preceding END token.
+  octave_comment_list *trail_comm;
+
+  // No copying!
+
+  tree_classdef_element (const tree_classdef_element&);
+
+  tree_classdef_element& operator = (const tree_classdef_element&);
+};
+
+class tree_classdef_property
+{
+public:
+
+  tree_classdef_property (tree_identifier *i = 0, tree_expression *e = 0)
+    : id (i), expr (e) { }
+
+  ~tree_classdef_property (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_expression *expr;
+
+  // No copying!
+
+  tree_classdef_property (const tree_classdef_property&);
+
+  tree_classdef_property& operator = (const tree_classdef_property&);
+};
+
+class tree_classdef_property_list : public octave_base_list<tree_classdef_property *>
+{
+public:
+
+  tree_classdef_property_list (void) { }
+
+  tree_classdef_property_list (tree_classdef_property* p) { append (p); }
+
+  tree_classdef_property_list (const octave_base_list<tree_classdef_property *>& a)
+    : octave_base_list<tree_classdef_property *> (a) { }
+
+  ~tree_classdef_property_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_property_list (const tree_classdef_property_list&);
+
+  tree_classdef_property_list& operator = (const tree_classdef_property_list&);
+};
+
+class tree_classdef_properties_block
+  : public tree_classdef_element<tree_classdef_property *>
+{
+public:
+
+  tree_classdef_properties_block (tree_classdef_attribute_list *a,
+                                  tree_classdef_property_list *plist,
+                                  octave_comment_list *lc,
+                                  octave_comment_list *tc,
+                                  int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_property *> (a, plist, lc, tc, l, c) { }
+
+  ~tree_classdef_properties_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_properties_block (const tree_classdef_properties_block&);
+
+  tree_classdef_properties_block& operator = (const tree_classdef_properties_block&);
+};
+
+class tree_classdef_methods_list : public octave_base_list<octave_value>
+{
+public:
+
+  tree_classdef_methods_list (void) { }
+
+  tree_classdef_methods_list (const octave_value& f) { append (f); }
+
+  tree_classdef_methods_list (const octave_base_list<octave_value>& a)
+    : octave_base_list<octave_value> (a) { }
+
+  ~tree_classdef_methods_list (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_methods_list (const tree_classdef_methods_list&);
+
+  tree_classdef_methods_list& operator = (const tree_classdef_methods_list&);
+};
+
+class tree_classdef_methods_block : public tree_classdef_element<octave_value>
+{
+public:
+
+  tree_classdef_methods_block (tree_classdef_attribute_list *a,
+                               tree_classdef_methods_list *mlist,
+                               octave_comment_list *lc,
+                               octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<octave_value> (a, mlist, lc, tc, l, c) { }
+
+  ~tree_classdef_methods_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_methods_block (const tree_classdef_methods_block&);
+
+  tree_classdef_methods_block& operator = (const tree_classdef_methods_block&);
+};
+
+class tree_classdef_event
+{
+public:
+
+  tree_classdef_event (tree_identifier *i = 0) : id (i) { }
+
+  ~tree_classdef_event (void)
+  {
+    delete id;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+
+  // No copying!
+
+  tree_classdef_event (const tree_classdef_event&);
+
+  tree_classdef_event& operator = (const tree_classdef_event&);
+};
+
+class tree_classdef_events_list : public octave_base_list<tree_classdef_event *>
+{
+public:
+
+  tree_classdef_events_list (void) { }
+
+  tree_classdef_events_list (tree_classdef_event *e) { append (e); }
+
+  tree_classdef_events_list (const octave_base_list<tree_classdef_event *>& a)
+    : octave_base_list<tree_classdef_event *> (a) { }
+
+  ~tree_classdef_events_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_events_list (const tree_classdef_events_list&);
+
+  tree_classdef_events_list& operator = (const tree_classdef_events_list&);
+};
+
+class tree_classdef_events_block
+  : public tree_classdef_element<tree_classdef_event *>
+{
+public:
+
+  tree_classdef_events_block (tree_classdef_attribute_list *a,
+                              tree_classdef_events_list *elist,
+                              octave_comment_list *lc,
+                              octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_event *> (a, elist, lc, tc, l, c) { }
+
+  ~tree_classdef_events_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_events_block (const tree_classdef_events_block&);
+
+  tree_classdef_events_block& operator = (const tree_classdef_events_block&);
+};
+
+class tree_classdef_enum
+{
+public:
+
+  tree_classdef_enum (void) : id (0), expr (0) { }
+
+  tree_classdef_enum (tree_identifier *i, tree_expression *e)
+    : id (i), expr (e) { }
+
+  ~tree_classdef_enum (void)
+  {
+    delete id;
+    delete expr;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_expression *expression (void) { return expr; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_expression *expr;
+
+  // No copying!
+
+  tree_classdef_enum (const tree_classdef_enum&);
+
+  tree_classdef_enum& operator = (const tree_classdef_enum&);
+};
+
+class tree_classdef_enum_list : public octave_base_list<tree_classdef_enum *>
+{
+public:
+
+  tree_classdef_enum_list (void) { }
+
+  tree_classdef_enum_list (tree_classdef_enum *e) { append (e); }
+
+  tree_classdef_enum_list (const octave_base_list<tree_classdef_enum *>& a)
+    : octave_base_list<tree_classdef_enum *> (a) { }
+
+  ~tree_classdef_enum_list (void);
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_enum_list (const tree_classdef_enum_list&);
+
+  tree_classdef_enum_list& operator = (const tree_classdef_enum_list&);
+};
+
+class tree_classdef_enum_block
+  : public tree_classdef_element<tree_classdef_enum *>
+{
+public:
+
+  tree_classdef_enum_block (tree_classdef_attribute_list *a,
+                            tree_classdef_enum_list *elist,
+                            octave_comment_list *lc,
+                            octave_comment_list *tc, int l = -1, int c = -1)
+    : tree_classdef_element<tree_classdef_enum *> (a, elist, lc, tc, l, c) { }
+
+  ~tree_classdef_enum_block (void) { }
+
+  void accept (tree_walker&);
+
+private:
+
+  // No copying!
+
+  tree_classdef_enum_block (const tree_classdef_enum_block&);
+
+  tree_classdef_enum_block& operator = (const tree_classdef_enum_block&);
+};
+
+class tree_classdef_body
+{
+public:
+
+  typedef std::list<tree_classdef_properties_block *>::iterator properties_list_iterator;
+  typedef std::list<tree_classdef_properties_block *>::const_iterator properties_list_const_iterator;
+
+  typedef std::list<tree_classdef_methods_block *>::iterator methods_list_iterator;
+  typedef std::list<tree_classdef_methods_block *>::const_iterator methods_list_const_iterator;
+
+  typedef std::list<tree_classdef_events_block *>::iterator events_list_iterator;
+  typedef std::list<tree_classdef_events_block *>::const_iterator events_list_const_iterator;
+
+  typedef std::list<tree_classdef_enum_block *>::iterator enum_list_iterator;
+  typedef std::list<tree_classdef_enum_block *>::const_iterator enum_list_const_iterator;
+
+  tree_classdef_body (void)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst () { }
+
+  tree_classdef_body (tree_classdef_properties_block *pb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (pb);
+  }
+
+  tree_classdef_body (tree_classdef_methods_block *mb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (mb);
+  }
+
+  tree_classdef_body (tree_classdef_events_block *evb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (evb);
+  }
+
+  tree_classdef_body (tree_classdef_enum_block *enb)
+    : properties_lst (), methods_lst (), events_lst (), enum_lst ()
+  {
+    append (enb);
+  }
+
+  ~tree_classdef_body (void);
+
+  void append (tree_classdef_properties_block *pb)
+  {
+    properties_lst.push_back (pb);
+  }
+
+  void append (tree_classdef_methods_block *mb)
+  {
+    methods_lst.push_back (mb);
+  }
+
+  void append (tree_classdef_events_block *evb)
+  {
+    events_lst.push_back (evb);
+  }
+
+  void append (tree_classdef_enum_block *enb)
+  {
+    enum_lst.push_back (enb);
+  }
+
+  std::list<tree_classdef_properties_block *> properties_list (void)
+  {
+    return properties_lst;
+  }
+
+  std::list<tree_classdef_methods_block *> methods_list (void)
+  {
+    return methods_lst;
+  }
+
+  std::list<tree_classdef_events_block *> events_list (void)
+  {
+    return events_lst;
+  }
+
+  std::list<tree_classdef_enum_block *> enum_list (void)
+  {
+    return enum_lst;
+  }
+
+  void accept (tree_walker&);
+
+private:
+
+  std::list<tree_classdef_properties_block *> properties_lst;
+
+  std::list<tree_classdef_methods_block *> methods_lst;
+
+  std::list<tree_classdef_events_block *> events_lst;
+
+  std::list<tree_classdef_enum_block *> enum_lst;
+
+  // No copying!
+
+  tree_classdef_body (const tree_classdef_body&);
+
+  tree_classdef_body& operator = (const tree_classdef_body&);
+};
+
+// Classdef definition.
+
+class tree_classdef : public tree_command
+{
+public:
+
+  tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i,
+                 tree_classdef_superclass_list *sc,
+                 tree_classdef_body *b, octave_comment_list *lc,
+                 octave_comment_list *tc,
+                 const std::string& pn = std::string (), int l = -1,
+                 int c = -1)
+    : tree_command (l, c), attr_list (a), id (i),
+      supclass_list (sc), element_list (b), lead_comm (lc), trail_comm (tc),
+      pack_name (pn) { }
+
+  ~tree_classdef (void)
+  {
+    delete attr_list;
+    delete id;
+    delete supclass_list;
+    delete element_list;
+    delete lead_comm;
+    delete trail_comm;
+  }
+
+  tree_classdef_attribute_list *attribute_list (void) { return attr_list; }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_classdef_superclass_list *superclass_list (void) { return supclass_list; }
+
+  tree_classdef_body *body (void) { return element_list; }
+
+  octave_comment_list *leading_comment (void) { return lead_comm; }
+  octave_comment_list *trailing_comment (void) { return trail_comm; }
+
+  const std::string& package_name (void) const { return pack_name; }
+
+  octave_function* make_meta_class (bool is_at_folder = false);
+
+  tree_classdef *dup (symbol_table::scope_id scope,
+                      symbol_table::context_id context) const;
+
+  void accept (tree_walker& tw);
+
+private:
+
+  tree_classdef_attribute_list *attr_list;
+
+  tree_identifier *id;
+
+  tree_classdef_superclass_list *supclass_list;
+
+  tree_classdef_body *element_list;
+
+  octave_comment_list *lead_comm;
+  octave_comment_list *trail_comm;
+
+  std::string pack_name;
+
+  // No copying!
+
+  tree_classdef (const tree_classdef&);
+
+  tree_classdef& operator = (const tree_classdef&);
+};
+
+#endif
--- a/libinterp/parse-tree/pt-eval.cc
+++ b/libinterp/parse-tree/pt-eval.cc
@@ -379,7 +379,8 @@
 
         dim_vector dv = rhs.dims ().redim (2);
 
-        octave_idx_type nrows = dv(0), steps = dv(1);
+        octave_idx_type nrows = dv(0);
+        octave_idx_type steps = dv(1);
 
         if (steps > 0)
           {
@@ -637,6 +638,12 @@
 }
 
 void
+tree_evaluator::visit_funcall (tree_funcall&)
+{
+  panic_impossible ();
+}
+
+void
 tree_evaluator::visit_parameter_list (tree_parameter_list&)
 {
   panic_impossible ();
@@ -1114,6 +1121,11 @@
   if (error_state)
     return;
 
+#if HAVE_LLVM
+  if (tree_jit::execute (cmd))
+    return;
+#endif
+
   unwind_protect frame;
 
   frame.protect_var (in_loop_command);
--- a/libinterp/parse-tree/pt-eval.h
+++ b/libinterp/parse-tree/pt-eval.h
@@ -102,6 +102,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-exp.h
+++ b/libinterp/parse-tree/pt-exp.h
@@ -40,7 +40,7 @@
 public:
 
   tree_expression (int l = -1, int c = -1)
-    : tree (l, c), num_parens (0), postfix_indexed (false),
+    : tree (l, c), num_parens (0), postfix_index_type ('\0'),
       print_flag (false) { }
 
   virtual ~tree_expression (void) { }
@@ -87,7 +87,9 @@
 
   int paren_count (void) const { return num_parens; }
 
-  bool is_postfix_indexed (void) const { return postfix_indexed; }
+  bool is_postfix_indexed (void) const { return (postfix_index_type != '\0'); }
+
+  char postfix_index (void) const { return postfix_index_type; }
 
   // Check if the result of the expression should be printed.
   // Should normally be used in conjunction with
@@ -108,9 +110,9 @@
     return this;
   }
 
-  tree_expression *mark_postfix_indexed (void)
+  tree_expression *set_postfix_index (char type)
   {
-    postfix_indexed = true;
+    postfix_index_type = type;
     return this;
   }
 
@@ -123,7 +125,7 @@
   virtual void copy_base (const tree_expression& e)
   {
     num_parens = e.num_parens;
-    postfix_indexed = e.postfix_indexed;
+    postfix_index_type = e.postfix_index_type;
     print_flag = e.print_flag;
   }
 
@@ -137,9 +139,10 @@
   //                  ==> 0 for expression e2
   int num_parens;
 
-  // A flag that says whether this expression has an index associated
-  // with it.  See the code in tree_identifier::rvalue for the rationale.
-  bool postfix_indexed;
+  // The first index type associated with this expression. This field
+  // is 0 (character '\0') if the expression has no associated index.
+  // See the code in tree_identifier::rvalue for the rationale.
+  char postfix_index_type;
 
   // Print result of rvalue for this expression?
   bool print_flag;
new file mode 100644
--- /dev/null
+++ b/libinterp/parse-tree/pt-funcall.cc
@@ -0,0 +1,110 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ov-fcn.h"
+#include "pt-funcall.h"
+#include "pt-walk.h"
+
+// Function call objects.
+
+void
+tree_funcall::print (std::ostream& os, bool pr_as_read_syntax,
+                     bool pr_orig_text)
+{
+  print_raw (os, pr_as_read_syntax, pr_orig_text);
+}
+
+void
+tree_funcall::print_raw (std::ostream& os, bool pr_as_read_syntax,
+                         bool pr_orig_text)
+{
+  if (pr_orig_text)
+    {
+      os << original_text ();
+    }
+  else
+    {
+      octave_function *fp = fcn.function_value ();
+      std::string nm = fp ? fp->name () : std::string ("<invalid-function>");
+
+      os << nm << " (";
+
+      octave_idx_type len = args.length ();
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          args(i).print_raw (os, pr_as_read_syntax);
+
+          if (i < len - 1)
+            os << ", ";
+        }
+
+      os << ")";
+    }
+}
+
+tree_funcall *
+tree_funcall::dup (symbol_table::scope_id, symbol_table::context_id) const
+{
+  tree_funcall *new_fc = new tree_funcall (fcn, args, line (), column ());
+
+  new_fc->copy_base (*new_fc);
+
+  return new_fc;
+}
+
+void
+tree_funcall::accept (tree_walker& tw)
+{
+  tw.visit_funcall (*this);
+}
+
+octave_value_list
+tree_funcall::rvalue (int nargout)
+{
+  octave_value_list retval;
+
+  retval = feval (fcn.function_value (), args, nargout);
+
+  if (retval.length () == 1 && retval(0).is_function ())
+    {
+      // The return object is a function. We may need to re-index it using the
+      // same logic as for identifier. This is primarily used for superclass
+      // references in classdef.
+
+      octave_value val = retval(0);
+      octave_function *f = val.function_value (true);
+
+      if (f && ! (is_postfix_indexed ()
+                  && f->is_postfix_index_handled (postfix_index ())))
+        {
+          octave_value_list tmp_args;
+
+          retval = val.do_multi_index_op (nargout, tmp_args);
+        }
+    }
+
+  return retval;
+}
new file mode 100644
--- /dev/null
+++ b/libinterp/parse-tree/pt-funcall.h
@@ -0,0 +1,98 @@
+/*
+
+Copyright (C) 2012-2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_tree_funcall_h)
+#define octave_tree_funcall_h 1
+
+#include "ov.h"
+#include "oct-obj.h"
+#include "parse.h"
+#include "pt-exp.h"
+
+// Function call.  This class only represents function calls that have
+// known functions (most useful for calls to built-in functions that
+// are generated by the parser) and fixed argument lists, known at
+// compile time.
+
+class
+tree_funcall : public tree_expression
+{
+public:
+
+  tree_funcall (const octave_value& f, const octave_value_list& a,
+                int l = -1, int c = -1)
+    : tree_expression (l, c), fcn (f), args (a)
+  {
+    if (! fcn.is_function ())
+      error ("tree_funcall: invalid function");
+  }
+
+  ~tree_funcall (void) { }
+
+  bool has_magic_end (void) const { return false; }
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false,
+              bool pr_orig_txt = true);
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false,
+                  bool pr_orig_txt = true);
+
+  tree_funcall *dup (symbol_table::scope_id,
+                     symbol_table::context_id context) const;
+
+  octave_value rvalue1 (int nargout)
+  {
+    octave_value retval;
+
+    const octave_value_list tmp = rvalue (nargout);
+
+    if (! tmp.empty ())
+      retval = tmp(0);
+
+    return retval;
+  }
+
+  octave_value_list rvalue (int nargout);
+
+  octave_value function (void) const { return fcn; }
+
+  octave_value_list arguments (void) const { return args; }
+
+  void accept (tree_walker& tw);
+
+private:
+
+  // Function to call.  Error if not a valid function at time of
+  // construction.
+  octave_value fcn;
+
+  // Argument list.
+  octave_value_list args;
+
+  // No copying!
+
+  tree_funcall (const tree_funcall&);
+
+  tree_funcall& operator = (const tree_funcall&);
+};
+
+#endif
--- a/libinterp/parse-tree/pt-id.cc
+++ b/libinterp/parse-tree/pt-id.cc
@@ -76,13 +76,19 @@
       //
       // If this identifier refers to a function, we need to know
       // whether it is indexed so that we can do the same thing
-      // for 'f' and 'f()'.  If the index is present, return the
-      // function object and let tree_index_expression::rvalue
-      // handle indexing.  Otherwise, arrange to call the function
-      // here, so that we don't return the function definition as
-      // a value.
+      // for 'f' and 'f()'.  If the index is present and the function
+      // object declares it can handle it, return the function object
+      // and let tree_index_expression::rvalue handle indexing.
+      // Otherwise, arrange to call the function here, so that we don't
+      // return the function definition as a value.
 
-      if (val.is_function () && ! is_postfix_indexed ())
+      octave_function *fcn = 0;
+
+      if (val.is_function ())
+        fcn = val.function_value (true);
+
+      if (fcn && ! (is_postfix_indexed ()
+                    && fcn->is_postfix_index_handled (postfix_index ())))
         {
           octave_value_list tmp_args;
 
--- a/libinterp/parse-tree/pt-id.h
+++ b/libinterp/parse-tree/pt-id.h
@@ -32,6 +32,7 @@
 
 class tree_walker;
 
+#include "oct-lvalue.h"
 #include "pt-bp.h"
 #include "pt-exp.h"
 #include "symtab.h"
--- a/libinterp/parse-tree/pt-idx.cc
+++ b/libinterp/parse-tree/pt-idx.cc
@@ -363,7 +363,7 @@
                   // that argument list so we can pass the appropriate
                   // value to the built-in end function.
 
-                  const octave_value_list tmp_list
+                  octave_value_list tmp_list
                     = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout);
 
                   tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
@@ -375,6 +375,26 @@
 
                   if (error_state)
                     break;
+
+                  if (tmp.is_function ())
+                    {
+                      octave_function *fcn = tmp.function_value (true);
+
+                      if (fcn && ! fcn->is_postfix_index_handled (type[i]))
+                        {
+                          octave_value_list empty_args;
+
+                          tmp_list = tmp.do_multi_index_op (1, empty_args);
+                          tmp = (tmp_list.length ()
+                                 ? tmp_list(0) : octave_value ());
+
+                          if (tmp.is_cs_list ())
+                            gripe_indexed_cs_list ();
+
+                          if (error_state)
+                            break;
+                        }
+                    }
                 }
             }
 
@@ -412,8 +432,27 @@
         }
 
       if (! error_state)
-        retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
-                              lvalue_list);
+        {
+          retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
+                                lvalue_list);
+
+          octave_value val = retval.length () ? retval(0) : octave_value ();
+
+          if (! error_state && val.is_function ())
+            {
+              octave_function *fcn = val.function_value (true);
+
+              if (fcn)
+                {
+                  octave_value_list empty_args;
+
+                  retval = (lvalue_list
+                            ? val.do_multi_index_op (nargout, empty_args,
+                                                     lvalue_list)
+                            : val.do_multi_index_op (nargout, empty_args));
+                }
+            }
+        }
     }
 
   return retval;
--- a/libinterp/parse-tree/pt-mat.cc
+++ b/libinterp/parse-tree/pt-mat.cc
@@ -683,7 +683,8 @@
 single_type_concat (Array<T>& result,
                     tm_const& tmp)
 {
-  octave_idx_type r = 0, c = 0;
+  octave_idx_type r = 0;
+  octave_idx_type c = 0;
 
   for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
     {
@@ -753,7 +754,8 @@
           return;
         }
 
-      octave_idx_type ncols = row.length (), i = 0;
+      octave_idx_type ncols = row.length ();
+      octave_idx_type i = 0;
       OCTAVE_LOCAL_BUFFER (Array<T>, array_list, ncols);
 
       for (tm_row_const::iterator q = row.begin ();
@@ -791,12 +793,14 @@
   // Sparse matrices require preallocation for efficient indexing; besides,
   // only horizontal concatenation can be efficiently handled by indexing.
   // So we just cat all rows through liboctave, then cat the final column.
-  octave_idx_type nrows = tmp.length (), j = 0;
+  octave_idx_type nrows = tmp.length ();
+  octave_idx_type j = 0;
   OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_row_list, nrows);
   for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
     {
       tm_row_const row = *p;
-      octave_idx_type ncols = row.length (), i = 0;
+      octave_idx_type ncols = row.length ();
+      octave_idx_type i = 0;
       OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, ncols);
 
       for (tm_row_const::iterator q = row.begin ();
@@ -829,12 +833,14 @@
       return;
     }
 
-  octave_idx_type nrows = tmp.length (), j = 0;
+  octave_idx_type nrows = tmp.length ();
+  octave_idx_type j = 0;
   OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);
   for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
     {
       tm_row_const row = *p;
-      octave_idx_type ncols = row.length (), i = 0;
+      octave_idx_type ncols = row.length ();
+      octave_idx_type i = 0;
       OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);
 
       for (tm_row_const::iterator q = row.begin ();
--- a/libinterp/parse-tree/pt-pr-code.cc
+++ b/libinterp/parse-tree/pt-pr-code.cc
@@ -749,6 +749,18 @@
 }
 
 void
+tree_print_code::visit_funcall (tree_funcall& fc)
+{
+  indent ();
+
+  print_parens (fc, "(");
+
+  fc.print_raw (os, true, print_original_text);
+
+  print_parens (fc, ")");
+}
+
+void
 tree_print_code::visit_parameter_list (tree_parameter_list& lst)
 {
   tree_parameter_list::iterator p = lst.begin ();
@@ -1144,7 +1156,7 @@
 
   indent ();
 
-  os << "until";
+  os << "until ";
 
   tree_expression *expr = cmd.condition ();
 
@@ -1188,10 +1200,7 @@
     }
 }
 
-// Each print_code() function should call this before printing
-// anything.
-//
-// This doesn't need to be fast, but isn't there a better way?
+// Each print_code() function should call this before printing anything.
 
 void
 tree_print_code::indent (void)
@@ -1202,8 +1211,7 @@
     {
       os << prefix;
 
-      for (int i = 0; i < curr_print_indent_level; i++)
-        os << " ";
+      os << std::string (curr_print_indent_level, ' ');
 
       beginning_of_line = false;
     }
--- a/libinterp/parse-tree/pt-pr-code.h
+++ b/libinterp/parse-tree/pt-pr-code.h
@@ -109,6 +109,8 @@
 
   void visit_fcn_handle (tree_fcn_handle&);
 
+  void visit_funcall (tree_funcall&);
+
   void visit_parameter_list (tree_parameter_list&);
 
   void visit_postfix_expression (tree_postfix_expression&);
--- a/libinterp/parse-tree/pt-select.cc
+++ b/libinterp/parse-tree/pt-select.cc
@@ -123,7 +123,7 @@
 {
   octave_value label_value = label->rvalue1 ();
 
-  if (! error_state && label_value.is_defined () )
+  if (! error_state && label_value.is_defined ())
     {
       if (label_value.is_cell ())
         {
--- a/libinterp/parse-tree/pt-walk.h
+++ b/libinterp/parse-tree/pt-walk.h
@@ -52,6 +52,7 @@
 class tree_no_op_command;
 class tree_constant;
 class tree_fcn_handle;
+class tree_funcall;
 class tree_parameter_list;
 class tree_postfix_expression;
 class tree_prefix_expression;
@@ -65,6 +66,24 @@
 class tree_while_command;
 class tree_do_until_command;
 
+class tree_classdef_attribute;
+class tree_classdef_attribute_list;
+class tree_classdef_superclass;
+class tree_classdef_superclass_list;
+class tree_classdef_property;
+class tree_classdef_property_list;
+class tree_classdef_properties_block;
+class tree_classdef_methods_list;
+class tree_classdef_methods_block;
+class tree_classdef_event;
+class tree_classdef_events_list;
+class tree_classdef_events_block;
+class tree_classdef_enum;
+class tree_classdef_enum_list;
+class tree_classdef_enum_block;
+class tree_classdef_body;
+class tree_classdef;
+
 class
 tree_walker
 {
@@ -158,6 +177,9 @@
   visit_fcn_handle (tree_fcn_handle&) = 0;
 
   virtual void
+  visit_funcall (tree_funcall&) = 0;
+
+  virtual void
   visit_parameter_list (tree_parameter_list&) = 0;
 
   virtual void
@@ -193,6 +215,57 @@
   virtual void
   visit_do_until_command (tree_do_until_command&) = 0;
 
+  virtual void
+  visit_classdef_attribute (tree_classdef_attribute&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_attribute_list (tree_classdef_attribute_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_superclass (tree_classdef_superclass&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_superclass_list (tree_classdef_superclass_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_property (tree_classdef_property&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_property_list (tree_classdef_property_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_properties_block (tree_classdef_properties_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_methods_list (tree_classdef_methods_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_methods_block (tree_classdef_methods_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_event (tree_classdef_event&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_events_list (tree_classdef_events_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_events_block (tree_classdef_events_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_enum (tree_classdef_enum&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_enum_list (tree_classdef_enum_list&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_enum_block (tree_classdef_enum_block&) { } /* = 0; */
+
+  virtual void
+  visit_classdef_body (tree_classdef_body&) { } /* = 0; */
+
+  virtual void
+  visit_classdef (tree_classdef&) { } /* = 0; */
+
 protected:
 
   tree_walker (void) { }
--- a/libinterp/parse-tree/token.cc
+++ b/libinterp/parse-tree/token.cc
@@ -97,38 +97,29 @@
   sr = s;
 }
 
-token::token (int tv, symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
+token::token (int tv, const std::string& mth, const std::string& cls,
+              int l, int c)
 {
   maybe_cmd = false;
   tspc = false;
   line_num = l;
   column_num = c;
   tok_val = tv;
-  type_tag = meta_rec_token;
-  mc.cr = cls;
-  mc.pr = pkg;
-}
-
-token::token (int tv, symbol_table::symbol_record *mth,
-              symbol_table::symbol_record *cls,
-              symbol_table::symbol_record *pkg, int l, int c)
-{
-  maybe_cmd = false;
-  tspc = false;
-  line_num = l;
-  column_num = c;
-  tok_val = tv;
-  type_tag = scls_rec_token;
-  sc.mr = mth;
-  sc.cr = cls;
-  sc.pr = pkg;
+  type_tag = scls_name_token;
+  sc.method_nm = new std::string (mth);
+  sc.class_nm = new std::string (cls);
 }
 
 token::~token (void)
 {
   if (type_tag == string_token)
     delete str;
+
+  if (type_tag == scls_name_token)
+    {
+      delete sc.method_nm;
+      delete sc.class_nm;
+    }
 }
 
 std::string
@@ -172,39 +163,18 @@
   return sr;
 }
 
-symbol_table::symbol_record *
-token::method_rec (void)
+std::string
+token::superclass_method_name (void)
 {
-  assert (type_tag == scls_rec_token);
-  return sc.mr;
-}
-
-symbol_table::symbol_record *
-token::class_rec (void)
-{
-  assert (type_tag == scls_rec_token);
-  return sc.cr;
+  assert (type_tag == scls_name_token);
+  return *sc.method_nm;
 }
 
-symbol_table::symbol_record *
-token::package_rec (void)
-{
-  assert (type_tag == scls_rec_token);
-  return sc.pr;
-}
-
-symbol_table::symbol_record *
-token::meta_class_rec (void)
+std::string
+token::superclass_class_name (void)
 {
-  assert (type_tag == meta_rec_token);
-  return mc.cr;
-}
-
-symbol_table::symbol_record *
-token::meta_package_rec (void)
-{
-  assert (type_tag == meta_rec_token);
-  return mc.pr;
+  assert (type_tag == scls_name_token);
+  return *sc.class_nm;
 }
 
 std::string
--- a/libinterp/parse-tree/token.h
+++ b/libinterp/parse-tree/token.h
@@ -40,8 +40,7 @@
     double_token,
     ettype_token,
     sym_rec_token,
-    scls_rec_token,
-    meta_rec_token
+    scls_name_token,
   };
 
   enum end_tok_type
@@ -69,11 +68,8 @@
          int l = -1, int c = -1);
   token (int tv, end_tok_type t, int l = -1, int c = -1);
   token (int tv, symbol_table::symbol_record *s, int l = -1, int c = -1);
-  token (int tv, symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
-  token (int tv, symbol_table::symbol_record *mth,
-         symbol_table::symbol_record *cls,
-         symbol_table::symbol_record *pkg, int l = -1, int c = -1);
+  token (int tv, const std::string& mth, const std::string& cls,
+         int l = -1, int c = -1);
 
   ~token (void);
 
@@ -106,12 +102,8 @@
   end_tok_type ettype (void) const;
   symbol_table::symbol_record *sym_rec (void);
 
-  symbol_table::symbol_record *method_rec (void);
-  symbol_table::symbol_record *class_rec (void);
-  symbol_table::symbol_record *package_rec (void);
-
-  symbol_table::symbol_record *meta_class_rec (void);
-  symbol_table::symbol_record *meta_package_rec (void);
+  std::string superclass_method_name (void);
+  std::string superclass_class_name (void);
 
   std::string text_rep (void);
 
@@ -137,15 +129,9 @@
     symbol_table::symbol_record *sr;
     struct
     {
-      symbol_table::symbol_record *mr;
-      symbol_table::symbol_record *cr;
-      symbol_table::symbol_record *pr;
+      std::string *method_nm;
+      std::string *class_nm;
     } sc;
-    struct
-    {
-      symbol_table::symbol_record *cr;
-      symbol_table::symbol_record *pr;
-    } mc;
   };
   std::string orig_text;
 };
--- a/liboctave/array/Array.cc
+++ b/liboctave/array/Array.cc
@@ -688,9 +688,9 @@
       }
     else
       {
-        octave_idx_type sd = sext[lev-1];
-        octave_idx_type dd = dext[lev-1];
-        octave_idx_type k;
+        octave_idx_type sd, dd, k;
+        sd = sext[lev-1];
+        dd = dext[lev-1];
         for (k = 0; k < cext[lev]; k++)
           do_resize_fill (src + k * sd, dest + k * dd, rfv, lev - 1);
 
@@ -2571,9 +2571,8 @@
                     d.xelem (i) = elem (i, i);
                 }
             }
-          else
-            (*current_liboctave_error_handler)
-              ("diag: requested diagonal out of range");
+          else  // Matlab returns [] 0x1 for out-of-range diagonal
+            d.resize (dim_vector (0, 1));
         }
       else
         {
--- a/liboctave/array/CDiagMatrix.cc
+++ b/liboctave/array/CDiagMatrix.cc
@@ -383,7 +383,7 @@
 }
 
 ComplexDiagMatrix
-ComplexDiagMatrix::pseudo_inverse (void) const
+ComplexDiagMatrix::pseudo_inverse (double tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -393,10 +393,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0)
+      double val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0)
+        retval.elem (i, i) = 0.0;
+      else
         retval.elem (i, i) = 1.0 / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0;
     }
 
   return retval;
--- a/liboctave/array/CDiagMatrix.h
+++ b/liboctave/array/CDiagMatrix.h
@@ -116,7 +116,7 @@
 
   ComplexDiagMatrix inverse (octave_idx_type& info) const;
   ComplexDiagMatrix inverse (void) const;
-  ComplexDiagMatrix pseudo_inverse (void) const;
+  ComplexDiagMatrix pseudo_inverse (double tol = 0.0) const;
 
   bool all_elements_are_real (void) const;
 
--- a/liboctave/array/CMatrix.cc
+++ b/liboctave/array/CMatrix.cc
@@ -1722,7 +1722,7 @@
 double
 ComplexMatrix::rcond (MatrixType &mattype) const
 {
-  double rcon;
+  double rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
--- a/liboctave/array/CSparse.cc
+++ b/liboctave/array/CSparse.cc
@@ -1118,7 +1118,6 @@
             {
               // Matrix is either singular or not positive definite
               mattype.mark_as_unsymmetric ();
-              typ = MatrixType::Full;
             }
         }
 
@@ -4529,7 +4528,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -4811,7 +4810,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -5096,7 +5095,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -5383,7 +5382,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -7688,87 +7687,85 @@
 {
   SparseComplexMatrix r;
 
-  if ((a.rows () == b.rows ()) && (a.cols () == b.cols ()))
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nc = a.cols ();
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nr == b_nr && a_nc == b_nc)
     {
-      octave_idx_type a_nr = a.rows ();
-      octave_idx_type a_nc = a.cols ();
-
-      octave_idx_type b_nr = b.rows ();
-      octave_idx_type b_nc = b.cols ();
-
-      if (a_nr == 0 || b_nc == 0 || a.nnz () == 0 || b.nnz () == 0)
-        return SparseComplexMatrix (a_nr, a_nc);
-
-      if (a_nr != b_nr || a_nc != b_nc)
-        gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
-      else
+      r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
+
+      octave_idx_type jx = 0;
+      r.cidx (0) = 0;
+      for (octave_idx_type i = 0 ; i < a_nc ; i++)
         {
-          r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
-
-          octave_idx_type jx = 0;
-          r.cidx (0) = 0;
-          for (octave_idx_type i = 0 ; i < a_nc ; i++)
-            {
-              octave_idx_type  ja = a.cidx (i);
-              octave_idx_type  ja_max = a.cidx (i+1);
-              bool ja_lt_max= ja < ja_max;
-
-              octave_idx_type  jb = b.cidx (i);
-              octave_idx_type  jb_max = b.cidx (i+1);
-              bool jb_lt_max = jb < jb_max;
-
-              while (ja_lt_max || jb_lt_max )
-                {
-                  octave_quit ();
-                  if ((! jb_lt_max) ||
-                      (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+          octave_idx_type  ja = a.cidx (i);
+          octave_idx_type  ja_max = a.cidx (i+1);
+          bool ja_lt_max= ja < ja_max;
+
+          octave_idx_type  jb = b.cidx (i);
+          octave_idx_type  jb_max = b.cidx (i+1);
+          bool jb_lt_max = jb < jb_max;
+
+          while (ja_lt_max || jb_lt_max)
+            {
+              octave_quit ();
+              if ((! jb_lt_max) ||
+                  (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+                {
+                  Complex tmp = xmin (a.data (ja), 0.);
+                  if (tmp != 0.)
                     {
-                      Complex tmp = xmin (a.data (ja), 0.);
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = a.ridx (ja);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
+                      r.ridx (jx) = a.ridx (ja);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else if (( !ja_lt_max ) ||
-                           (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                }
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
+                {
+                  Complex tmp = xmin (0., b.data (jb));
+                  if (tmp != 0.)
                     {
-                      Complex tmp = xmin (0., b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = b.ridx (jb);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.ridx (jx) = b.ridx (jb);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+              else
+                {
+                  Complex tmp = xmin (a.data (ja), b.data (jb));
+                  if (tmp != 0.)
                     {
-                      Complex tmp = xmin (a.data (ja), b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.data (jx) = tmp;
-                          r.ridx (jx) = a.ridx (ja);
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.data (jx) = tmp;
+                      r.ridx (jx) = a.ridx (ja);
+                      jx++;
                     }
-                }
-              r.cidx (i+1) = jx;
-            }
-
-          r.maybe_compress ();
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+            }
+          r.cidx (i+1) = jx;
         }
+
+      r.maybe_compress ();
     }
   else
-    (*current_liboctave_error_handler) ("matrix size mismatch");
+    {
+      if (a_nr == 0 || a_nc == 0)
+        r.resize (a_nr, a_nc);
+      else if (b_nr == 0 || b_nc == 0)
+        r.resize (b_nr, b_nc);
+      else
+        gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
+    }
 
   return r;
 }
@@ -7808,91 +7805,85 @@
 {
   SparseComplexMatrix r;
 
-  if ((a.rows () == b.rows ()) && (a.cols () == b.cols ()))
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nc = a.cols ();
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nr == b_nr && a_nc == b_nc)
     {
-      octave_idx_type a_nr = a.rows ();
-      octave_idx_type a_nc = a.cols ();
-
-      octave_idx_type b_nr = b.rows ();
-      octave_idx_type b_nc = b.cols ();
-
-      if (a_nr == 0 || b_nc == 0)
-        return SparseComplexMatrix (a_nr, a_nc);
-      if (a.nnz () == 0)
-        return SparseComplexMatrix (b);
-      if (b.nnz () == 0)
-        return SparseComplexMatrix (a);
-
-      if (a_nr != b_nr || a_nc != b_nc)
-        gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
-      else
+      r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
+
+      octave_idx_type jx = 0;
+      r.cidx (0) = 0;
+      for (octave_idx_type i = 0 ; i < a_nc ; i++)
         {
-          r = SparseComplexMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
-
-          octave_idx_type jx = 0;
-          r.cidx (0) = 0;
-          for (octave_idx_type i = 0 ; i < a_nc ; i++)
-            {
-              octave_idx_type  ja = a.cidx (i);
-              octave_idx_type  ja_max = a.cidx (i+1);
-              bool ja_lt_max= ja < ja_max;
-
-              octave_idx_type  jb = b.cidx (i);
-              octave_idx_type  jb_max = b.cidx (i+1);
-              bool jb_lt_max = jb < jb_max;
-
-              while (ja_lt_max || jb_lt_max )
-                {
-                  octave_quit ();
-                  if ((! jb_lt_max) ||
-                      (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+          octave_idx_type  ja = a.cidx (i);
+          octave_idx_type  ja_max = a.cidx (i+1);
+          bool ja_lt_max= ja < ja_max;
+
+          octave_idx_type  jb = b.cidx (i);
+          octave_idx_type  jb_max = b.cidx (i+1);
+          bool jb_lt_max = jb < jb_max;
+
+          while (ja_lt_max || jb_lt_max)
+            {
+              octave_quit ();
+              if ((! jb_lt_max) ||
+                  (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+                {
+                  Complex tmp = xmax (a.data (ja), 0.);
+                  if (tmp != 0.)
                     {
-                      Complex tmp = xmax (a.data (ja), 0.);
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = a.ridx (ja);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
+                      r.ridx (jx) = a.ridx (ja);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else if (( !ja_lt_max ) ||
-                           (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                }
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
+                {
+                  Complex tmp = xmax (0., b.data (jb));
+                  if (tmp != 0.)
                     {
-                      Complex tmp = xmax (0., b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = b.ridx (jb);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.ridx (jx) = b.ridx (jb);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+              else
+                {
+                  Complex tmp = xmax (a.data (ja), b.data (jb));
+                  if (tmp != 0.)
                     {
-                      Complex tmp = xmax (a.data (ja), b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.data (jx) = tmp;
-                          r.ridx (jx) = a.ridx (ja);
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.data (jx) = tmp;
+                      r.ridx (jx) = a.ridx (ja);
+                      jx++;
                     }
-                }
-              r.cidx (i+1) = jx;
-            }
-
-          r.maybe_compress ();
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+            }
+          r.cidx (i+1) = jx;
         }
+
+      r.maybe_compress ();
     }
   else
-    (*current_liboctave_error_handler) ("matrix size mismatch");
+    {
+      if (a_nr == 0 || a_nc == 0)
+        r.resize (a_nr, a_nc);
+      else if (b_nr == 0 || b_nc == 0)
+        r.resize (b_nr, b_nc);
+      else
+        gripe_nonconformant ("max", a_nr, a_nc, b_nr, b_nc);
+    }
 
   return r;
 }
--- a/liboctave/array/DiagArray2.cc
+++ b/liboctave/array/DiagArray2.cc
@@ -66,9 +66,8 @@
     d = Array<T> (dim_vector (std::min (cols () - k, rows ()), 1), T ());
   else if (k < 0 && -k < rows ())
     d = Array<T> (dim_vector (std::min (rows () + k, cols ()), 1), T ());
-  else
-    (*current_liboctave_error_handler)
-      ("diag: requested diagonal out of range");
+  else  // Matlab returns [] 0x1 for out-of-range diagonal
+    d.resize (dim_vector (0, 1));
 
   return d;
 }
--- a/liboctave/array/MSparse.cc
+++ b/liboctave/array/MSparse.cc
@@ -68,7 +68,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -80,8 +80,8 @@
                   ja++;
                   ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   r.ridx (jx) = b.ridx (jb);
                   r.data (jx) = op (0., b.data (jb));
@@ -340,7 +340,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -352,8 +352,8 @@
                   ja++;
                   ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   r.ridx (jx) = b.ridx (jb);
                   r.data (jx) = op (0.,  b.data (jb));
@@ -462,7 +462,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -470,8 +470,8 @@
                 {
                   ja++; ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   jb++; jb_lt_max= jb < jb_max;
                 }
@@ -569,7 +569,7 @@
     gripe_nonconformant ("quotient", a_nr, a_nc, b_nr, b_nc);
   else
     {
-      r = MSparse<T>( a_nr, a_nc, (Zero / Zero));
+      r = MSparse<T> (a_nr, a_nc, (Zero / Zero));
 
       for (octave_idx_type i = 0 ; i < a_nc ; i++)
         {
@@ -581,7 +581,7 @@
           octave_idx_type  jb_max = b.cidx (i+1);
           bool jb_lt_max = jb < jb_max;
 
-          while (ja_lt_max || jb_lt_max )
+          while (ja_lt_max || jb_lt_max)
             {
               octave_quit ();
               if ((! jb_lt_max) ||
@@ -590,8 +590,8 @@
                   r.elem (a.ridx (ja),i) = a.data (ja) / Zero;
                   ja++; ja_lt_max= ja < ja_max;
                 }
-              else if (( !ja_lt_max ) ||
-                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
                 {
                   r.elem (b.ridx (jb),i) = Zero / b.data (jb);
                   jb++; jb_lt_max= jb < jb_max;
--- a/liboctave/array/MatrixType.cc
+++ b/liboctave/array/MatrixType.cc
@@ -119,7 +119,7 @@
 MatrixType::matrix_type
 matrix_complex_probe (const MArray<std::complex<T> >& a)
 {
-  MatrixType::matrix_type typ;
+  MatrixType::matrix_type typ = MatrixType::Unknown;
   octave_idx_type nrows = a.rows ();
   octave_idx_type ncols = a.cols ();
 
--- a/liboctave/array/Sparse.cc
+++ b/liboctave/array/Sparse.cc
@@ -2435,7 +2435,7 @@
                 if (elem (i, i+k) != 0.)
                   nel++;
             }
-          else if ( k < 0)
+          else if (k < 0)
             {
               for (octave_idx_type i = 0; i < ndiag; i++)
                 if (elem (i-k, i) != 0.)
@@ -2465,7 +2465,7 @@
                     }
                 }
             }
-          else if ( k < 0)
+          else if (k < 0)
             {
               for (octave_idx_type i = 0; i < ndiag; i++)
                 {
@@ -2491,8 +2491,15 @@
             }
         }
       else
-        (*current_liboctave_error_handler)
-          ("diag: requested diagonal out of range");
+        {
+          // Matlab returns [] 0x1 for out-of-range diagonal
+
+          octave_idx_type nr = 0;
+          octave_idx_type nc = 1;
+          octave_idx_type nz = 0;
+
+          d = Sparse<T> (nr, nc, nz);
+        }
     }
   else if (nnr != 0 && nnc != 0)
     {
--- a/liboctave/array/dDiagMatrix.cc
+++ b/liboctave/array/dDiagMatrix.cc
@@ -292,7 +292,7 @@
 }
 
 DiagMatrix
-DiagMatrix::pseudo_inverse (void) const
+DiagMatrix::pseudo_inverse (double tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -302,10 +302,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0)
+      double val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0)
+        retval.elem (i, i) = 0.0;
+      else
         retval.elem (i, i) = 1.0 / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0;
     }
 
   return retval;
--- a/liboctave/array/dDiagMatrix.h
+++ b/liboctave/array/dDiagMatrix.h
@@ -98,7 +98,7 @@
 
   DiagMatrix inverse (void) const;
   DiagMatrix inverse (octave_idx_type& info) const;
-  DiagMatrix pseudo_inverse (void) const;
+  DiagMatrix pseudo_inverse (double tol = 0.0) const;
 
   // other operations
 
--- a/liboctave/array/dMatrix.cc
+++ b/liboctave/array/dMatrix.cc
@@ -1382,7 +1382,7 @@
 double
 Matrix::rcond (MatrixType &mattype) const
 {
-  double rcon;
+  double rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
--- a/liboctave/array/dSparse.cc
+++ b/liboctave/array/dSparse.cc
@@ -777,7 +777,7 @@
               octave_idx_type  jb_max = y.cidx (i+1);
               bool jb_lt_max = jb < jb_max;
 
-              while (ja_lt_max || jb_lt_max )
+              while (ja_lt_max || jb_lt_max)
                 {
                   octave_quit ();
                   if ((! jb_lt_max) ||
@@ -789,8 +789,8 @@
                       ja++;
                       ja_lt_max= ja < ja_max;
                     }
-                  else if (( !ja_lt_max ) ||
-                           (jb_lt_max && (y.ridx (jb) < x.ridx (ja)) ) )
+                  else if ((! ja_lt_max) ||
+                           (jb_lt_max && (y.ridx (jb) < x.ridx (ja))))
                     {
                       jb++;
                       jb_lt_max= jb < jb_max;
@@ -1216,7 +1216,6 @@
             {
               // Matrix is either singular or not positive definite
               mattype.mark_as_unsymmetric ();
-              typ = MatrixType::Full;
             }
         }
 
@@ -4646,7 +4645,7 @@
               m_band(ridx (i) - j + n_lower + n_upper, j) = data (i);
 
           // Calculate the norm of the matrix, for later use.
-          double anorm;
+          double anorm = 0.0;
           if (calc_cond)
             {
               for (octave_idx_type j = 0; j < nr; j++)
@@ -7801,84 +7800,85 @@
 {
   SparseMatrix r;
 
-  if ((a.rows () == b.rows ()) && (a.cols () == b.cols ()))
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nc = a.cols ();
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nr == b_nr && a_nc == b_nc)
     {
-      octave_idx_type a_nr = a.rows ();
-      octave_idx_type a_nc = a.cols ();
-
-      octave_idx_type b_nr = b.rows ();
-      octave_idx_type b_nc = b.cols ();
-
-      if (a_nr != b_nr || a_nc != b_nc)
-        gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
-      else
+      r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
+
+      octave_idx_type jx = 0;
+      r.cidx (0) = 0;
+      for (octave_idx_type i = 0 ; i < a_nc ; i++)
         {
-          r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
-
-          octave_idx_type jx = 0;
-          r.cidx (0) = 0;
-          for (octave_idx_type i = 0 ; i < a_nc ; i++)
-            {
-              octave_idx_type  ja = a.cidx (i);
-              octave_idx_type  ja_max = a.cidx (i+1);
-              bool ja_lt_max= ja < ja_max;
-
-              octave_idx_type  jb = b.cidx (i);
-              octave_idx_type  jb_max = b.cidx (i+1);
-              bool jb_lt_max = jb < jb_max;
-
-              while (ja_lt_max || jb_lt_max )
-                {
-                  octave_quit ();
-                  if ((! jb_lt_max) ||
-                      (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+          octave_idx_type  ja = a.cidx (i);
+          octave_idx_type  ja_max = a.cidx (i+1);
+          bool ja_lt_max= ja < ja_max;
+
+          octave_idx_type  jb = b.cidx (i);
+          octave_idx_type  jb_max = b.cidx (i+1);
+          bool jb_lt_max = jb < jb_max;
+
+          while (ja_lt_max || jb_lt_max)
+            {
+              octave_quit ();
+              if ((! jb_lt_max) ||
+                  (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+                {
+                  double tmp = xmin (a.data (ja), 0.);
+                  if (tmp != 0.)
                     {
-                      double tmp = xmin (a.data (ja), 0.);
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = a.ridx (ja);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
+                      r.ridx (jx) = a.ridx (ja);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else if (( !ja_lt_max ) ||
-                           (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                }
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
+                {
+                  double tmp = xmin (0., b.data (jb));
+                  if (tmp != 0.)
                     {
-                      double tmp = xmin (0., b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = b.ridx (jb);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.ridx (jx) = b.ridx (jb);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+              else
+                {
+                  double tmp = xmin (a.data (ja), b.data (jb));
+                  if (tmp != 0.)
                     {
-                      double tmp = xmin (a.data (ja), b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.data (jx) = tmp;
-                          r.ridx (jx) = a.ridx (ja);
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.data (jx) = tmp;
+                      r.ridx (jx) = a.ridx (ja);
+                      jx++;
                     }
-                }
-              r.cidx (i+1) = jx;
-            }
-
-          r.maybe_compress ();
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+            }
+          r.cidx (i+1) = jx;
         }
+
+      r.maybe_compress ();
     }
   else
-    (*current_liboctave_error_handler) ("matrix size mismatch");
+    {
+      if (a_nr == 0 || a_nc == 0)
+        r.resize (a_nr, a_nc);
+      else if (b_nr == 0 || b_nc == 0)
+        r.resize (b_nr, b_nc);
+      else
+        gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
+    }
 
   return r;
 }
@@ -7951,84 +7951,85 @@
 {
   SparseMatrix r;
 
-  if ((a.rows () == b.rows ()) && (a.cols () == b.cols ()))
+  octave_idx_type a_nr = a.rows ();
+  octave_idx_type a_nc = a.cols ();
+  octave_idx_type b_nr = b.rows ();
+  octave_idx_type b_nc = b.cols ();
+
+  if (a_nr == b_nr && a_nc == b_nc)
     {
-      octave_idx_type a_nr = a.rows ();
-      octave_idx_type a_nc = a.cols ();
-
-      octave_idx_type b_nr = b.rows ();
-      octave_idx_type b_nc = b.cols ();
-
-      if (a_nr != b_nr || a_nc != b_nc)
-        gripe_nonconformant ("min", a_nr, a_nc, b_nr, b_nc);
-      else
+      r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
+
+      octave_idx_type jx = 0;
+      r.cidx (0) = 0;
+      for (octave_idx_type i = 0 ; i < a_nc ; i++)
         {
-          r = SparseMatrix (a_nr, a_nc, (a.nnz () + b.nnz ()));
-
-          octave_idx_type jx = 0;
-          r.cidx (0) = 0;
-          for (octave_idx_type i = 0 ; i < a_nc ; i++)
-            {
-              octave_idx_type  ja = a.cidx (i);
-              octave_idx_type  ja_max = a.cidx (i+1);
-              bool ja_lt_max= ja < ja_max;
-
-              octave_idx_type  jb = b.cidx (i);
-              octave_idx_type  jb_max = b.cidx (i+1);
-              bool jb_lt_max = jb < jb_max;
-
-              while (ja_lt_max || jb_lt_max )
-                {
-                  octave_quit ();
-                  if ((! jb_lt_max) ||
-                      (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+          octave_idx_type  ja = a.cidx (i);
+          octave_idx_type  ja_max = a.cidx (i+1);
+          bool ja_lt_max= ja < ja_max;
+
+          octave_idx_type  jb = b.cidx (i);
+          octave_idx_type  jb_max = b.cidx (i+1);
+          bool jb_lt_max = jb < jb_max;
+
+          while (ja_lt_max || jb_lt_max)
+            {
+              octave_quit ();
+              if ((! jb_lt_max) ||
+                  (ja_lt_max && (a.ridx (ja) < b.ridx (jb))))
+                {
+                  double tmp = xmax (a.data (ja), 0.);
+                  if (tmp != 0.)
                     {
-                      double tmp = xmax (a.data (ja), 0.);
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = a.ridx (ja);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
+                      r.ridx (jx) = a.ridx (ja);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else if (( !ja_lt_max ) ||
-                           (jb_lt_max && (b.ridx (jb) < a.ridx (ja)) ) )
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                }
+              else if ((! ja_lt_max) ||
+                       (jb_lt_max && (b.ridx (jb) < a.ridx (ja))))
+                {
+                  double tmp = xmax (0., b.data (jb));
+                  if (tmp != 0.)
                     {
-                      double tmp = xmax (0., b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.ridx (jx) = b.ridx (jb);
-                          r.data (jx) = tmp;
-                          jx++;
-                        }
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.ridx (jx) = b.ridx (jb);
+                      r.data (jx) = tmp;
+                      jx++;
                     }
-                  else
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+              else
+                {
+                  double tmp = xmax (a.data (ja), b.data (jb));
+                  if (tmp != 0.)
                     {
-                      double tmp = xmax (a.data (ja), b.data (jb));
-                      if (tmp != 0.)
-                        {
-                          r.data (jx) = tmp;
-                          r.ridx (jx) = a.ridx (ja);
-                          jx++;
-                        }
-                      ja++;
-                      ja_lt_max= ja < ja_max;
-                      jb++;
-                      jb_lt_max= jb < jb_max;
+                      r.data (jx) = tmp;
+                      r.ridx (jx) = a.ridx (ja);
+                      jx++;
                     }
-                }
-              r.cidx (i+1) = jx;
-            }
-
-          r.maybe_compress ();
+                  ja++;
+                  ja_lt_max= ja < ja_max;
+                  jb++;
+                  jb_lt_max= jb < jb_max;
+                }
+            }
+          r.cidx (i+1) = jx;
         }
+
+      r.maybe_compress ();
     }
   else
-    (*current_liboctave_error_handler) ("matrix size mismatch");
+    {
+      if (a_nr == 0 || a_nc == 0)
+        r.resize (a_nr, a_nc);
+      else if (b_nr == 0 || b_nc == 0)
+        r.resize (b_nr, b_nc);
+      else
+        gripe_nonconformant ("max", a_nr, a_nc, b_nr, b_nc);
+    }
 
   return r;
 }
--- a/liboctave/array/fCDiagMatrix.cc
+++ b/liboctave/array/fCDiagMatrix.cc
@@ -387,7 +387,7 @@
 }
 
 FloatComplexDiagMatrix
-FloatComplexDiagMatrix::pseudo_inverse (void) const
+FloatComplexDiagMatrix::pseudo_inverse (float tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -397,10 +397,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0f)
+      float val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0f)
+        retval.elem (i, i) = 0.0f;
+      else
         retval.elem (i, i) = 1.0f / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0f;
     }
 
   return retval;
--- a/liboctave/array/fCDiagMatrix.h
+++ b/liboctave/array/fCDiagMatrix.h
@@ -122,7 +122,7 @@
 
   FloatComplexDiagMatrix inverse (octave_idx_type& info) const;
   FloatComplexDiagMatrix inverse (void) const;
-  FloatComplexDiagMatrix pseudo_inverse (void) const;
+  FloatComplexDiagMatrix pseudo_inverse (float tol = 0.0f) const;
 
   bool all_elements_are_real (void) const;
 
--- a/liboctave/array/fCMatrix.cc
+++ b/liboctave/array/fCMatrix.cc
@@ -1727,7 +1727,7 @@
 float
 FloatComplexMatrix::rcond (MatrixType &mattype) const
 {
-  float rcon;
+  float rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
--- a/liboctave/array/fCNDArray.cc
+++ b/liboctave/array/fCNDArray.cc
@@ -616,6 +616,12 @@
   return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_prod);
 }
 
+ComplexNDArray
+FloatComplexNDArray::dprod (int dim) const
+{
+  return do_mx_red_op<Complex, FloatComplex> (*this, dim, mx_inline_dprod);
+}
+
 FloatComplexNDArray
 FloatComplexNDArray::sum (int dim) const
 {
--- a/liboctave/array/fCNDArray.h
+++ b/liboctave/array/fCNDArray.h
@@ -83,6 +83,7 @@
   FloatComplexNDArray cumprod (int dim = -1) const;
   FloatComplexNDArray cumsum (int dim = -1) const;
   FloatComplexNDArray prod (int dim = -1) const;
+  ComplexNDArray dprod (int dim = -1) const;
   FloatComplexNDArray sum (int dim = -1) const;
   ComplexNDArray dsum (int dim = -1) const;
   FloatComplexNDArray sumsq (int dim = -1) const;
--- a/liboctave/array/fDiagMatrix.cc
+++ b/liboctave/array/fDiagMatrix.cc
@@ -292,7 +292,7 @@
 }
 
 FloatDiagMatrix
-FloatDiagMatrix::pseudo_inverse (void) const
+FloatDiagMatrix::pseudo_inverse (float tol) const
 {
   octave_idx_type r = rows ();
   octave_idx_type c = cols ();
@@ -302,10 +302,11 @@
 
   for (octave_idx_type i = 0; i < len; i++)
     {
-      if (elem (i, i) != 0.0f)
+      float val = std::abs (elem (i, i));
+      if (val < tol || val == 0.0f)
+        retval.elem (i, i) = 0.0f;
+      else
         retval.elem (i, i) = 1.0f / elem (i, i);
-      else
-        retval.elem (i, i) = 0.0f;
     }
 
   return retval;
--- a/liboctave/array/fDiagMatrix.h
+++ b/liboctave/array/fDiagMatrix.h
@@ -99,7 +99,7 @@
 
   FloatDiagMatrix inverse (void) const;
   FloatDiagMatrix inverse (octave_idx_type& info) const;
-  FloatDiagMatrix pseudo_inverse (void) const;
+  FloatDiagMatrix pseudo_inverse (float tol = 0.0f) const;
 
   // other operations
 
--- a/liboctave/array/fMatrix.cc
+++ b/liboctave/array/fMatrix.cc
@@ -1390,7 +1390,7 @@
 float
 FloatMatrix::rcond (MatrixType &mattype) const
 {
-  float rcon;
+  float rcon = octave_NaN;
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
 
--- a/liboctave/array/fNDArray.cc
+++ b/liboctave/array/fNDArray.cc
@@ -627,6 +627,12 @@
   return do_mx_red_op<float, float> (*this, dim, mx_inline_prod);
 }
 
+NDArray
+FloatNDArray::dprod (int dim) const
+{
+  return do_mx_red_op<double, float> (*this, dim, mx_inline_dprod);
+}
+
 FloatNDArray
 FloatNDArray::sum (int dim) const
 {
--- a/liboctave/array/fNDArray.h
+++ b/liboctave/array/fNDArray.h
@@ -90,6 +90,7 @@
   FloatNDArray cumprod (int dim = -1) const;
   FloatNDArray cumsum (int dim = -1) const;
   FloatNDArray prod (int dim = -1) const;
+  NDArray dprod (int dim = -1) const;
   FloatNDArray sum (int dim = -1) const;
   NDArray dsum (int dim = -1) const;
   FloatNDArray sumsq (int dim = -1) const;
--- a/liboctave/array/intNDArray.cc
+++ b/liboctave/array/intNDArray.cc
@@ -213,6 +213,13 @@
 
 template <class T>
 intNDArray<T>
+intNDArray<T>::prod (int dim) const
+{
+  return do_mx_red_op<T, T> (*this, dim, mx_inline_prod);
+}
+
+template <class T>
+intNDArray<T>
 intNDArray<T>::sum (int dim) const
 {
   return do_mx_red_op<T, T> (*this, dim, mx_inline_sum);
--- a/liboctave/array/intNDArray.h
+++ b/liboctave/array/intNDArray.h
@@ -89,6 +89,7 @@
   intNDArray cummin (int dim = -1) const;
   intNDArray cummin (Array<octave_idx_type>& index, int dim = -1) const;
 
+  intNDArray prod (int dim) const;
   intNDArray sum (int dim) const;
   NDArray dsum (int dim) const;
   intNDArray cumsum (int dim) const;
--- a/liboctave/numeric/DASPK-opts.in
+++ b/liboctave/numeric/DASPK-opts.in
@@ -209,7 +209,7 @@
 A vector of the same length as the state vector.  A nonzero element
 indicates that the corresponding element of the state vector is an
 algebraic variable (i.e., its derivative does not appear explicitly
-in the equation set.
+in the equation set).
 
 This option is required by the
 @qcode{\"compute consistent initial condition\"} and
--- a/liboctave/numeric/bsxfun.h
+++ b/liboctave/numeric/bsxfun.h
@@ -41,7 +41,7 @@
       octave_idx_type xk = dx(i);
       octave_idx_type yk = dy(i);
       // Check the three conditions for valid bsxfun dims
-      if (! ( (xk == yk) || (xk == 1 && yk > 1) || (xk > 1 && yk == 1)))
+      if (! ((xk == yk) || (xk == 1 && yk > 1) || (xk > 1 && yk == 1)))
         return false;
     }
 
@@ -71,7 +71,7 @@
       octave_idx_type xk = dx(i);
 
       // Only two valid canditions to check; can't stretch rk
-      if (! ( (rk == xk) || (rk > 1 && xk == 1)))
+      if (! ((rk == xk) || (rk > 1 && xk == 1)))
         return false;
     }
 
--- a/liboctave/numeric/lo-specfun.cc
+++ b/liboctave/numeric/lo-specfun.cc
@@ -2578,12 +2578,8 @@
   err = false;
 
   if (a < 0.0 || x < 0.0)
-    {
-      (*current_liboctave_error_handler)
-        ("gammainc: A and X must be non-negative");
-
-      err = true;
-    }
+    (*current_liboctave_error_handler)
+      ("gammainc: A and X must be non-negative");
   else
     F77_XFCN (xgammainc, XGAMMAINC, (a, x, retval));
 
@@ -2783,12 +2779,8 @@
   err = false;
 
   if (a < 0.0 || x < 0.0)
-    {
-      (*current_liboctave_error_handler)
-        ("gammainc: A and X must be non-negative");
-
-      err = true;
-    }
+    (*current_liboctave_error_handler)
+      ("gammainc: A and X must be non-negative");
   else
     F77_XFCN (xsgammainc, XSGAMMAINC, (a, x, retval));
 
@@ -3641,7 +3633,7 @@
   double sqrt_eps = sqrt (std::numeric_limits<double>::epsilon ());
   if (m < sqrt_eps)
     {
-      // For small m, ( Abramowitz and Stegun, Section 16.13 )
+      // For small m, (Abramowitz and Stegun, Section 16.13)
       si_u = sin (u);
       co_u = cos (u);
       t = 0.25*m*(u - si_u*co_u);
@@ -3651,7 +3643,7 @@
     }
   else if ((1 - m) < sqrt_eps)
     {
-      // For m1 = (1-m) small ( Abramowitz and Stegun, Section 16.15 )
+      // For m1 = (1-m) small (Abramowitz and Stegun, Section 16.15)
       m1 = 1 - m;
       si_u = sinh (u);
       co_u = cosh (u);
@@ -3663,8 +3655,8 @@
     }
   else
     {
-      //  Arithmetic-Geometric Mean (AGM) algorithm
-      //    ( Abramowitz and Stegun, Section 16.4 )
+      // Arithmetic-Geometric Mean (AGM) algorithm
+      //   (Abramowitz and Stegun, Section 16.4)
       a[0] = 1;
       b    = sqrt (1 - m);
       c[0] = sqrt (m);
--- a/liboctave/operators/Sparse-op-defs.h
+++ b/liboctave/operators/Sparse-op-defs.h
@@ -456,7 +456,7 @@
             octave_idx_type  jb_max = m2.cidx (i+1); \
             bool jb_lt_max = jb < jb_max; \
             \
-            while (ja_lt_max || jb_lt_max ) \
+            while (ja_lt_max || jb_lt_max) \
               { \
                 octave_quit (); \
                 if ((! jb_lt_max) || \
@@ -468,8 +468,8 @@
                     ja++; \
                     ja_lt_max= ja < ja_max; \
                   } \
-                else if (( !ja_lt_max ) || \
-                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \
+                else if ((! ja_lt_max) || \
+                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
                   { \
                     r.ridx (jx) = m2.ridx (jb); \
                     r.data (jx) = 0. OP m2.data (jb); \
@@ -564,7 +564,7 @@
             octave_idx_type  jb_max = m2.cidx (i+1); \
             bool jb_lt_max = jb < jb_max; \
             \
-            while (ja_lt_max || jb_lt_max ) \
+            while (ja_lt_max || jb_lt_max) \
               { \
                 octave_quit (); \
                 if ((! jb_lt_max) || \
@@ -572,8 +572,8 @@
                   { \
                      ja++; ja_lt_max= ja < ja_max; \
                   } \
-                else if (( !ja_lt_max ) || \
-                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \
+                else if ((! ja_lt_max) || \
+                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
                   { \
                      jb++; jb_lt_max= jb < jb_max; \
                   } \
@@ -680,7 +680,7 @@
             octave_idx_type  jb_max = m2.cidx (i+1); \
             bool jb_lt_max = jb < jb_max; \
             \
-            while (ja_lt_max || jb_lt_max ) \
+            while (ja_lt_max || jb_lt_max) \
               { \
                 octave_quit (); \
                 if ((! jb_lt_max) || \
@@ -691,8 +691,8 @@
                     ja++; \
                     ja_lt_max= ja < ja_max; \
                   } \
-                else if (( !ja_lt_max ) || \
-                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)) ) ) \
+                else if ((! ja_lt_max) || \
+                     (jb_lt_max && (m2.ridx (jb) < m1.ridx (ja)))) \
                   { \
                     /* keep those kludges coming */ \
                     r.elem (m2.ridx (jb),i) = Complex () OP m2.data (jb);  \
@@ -1836,7 +1836,7 @@
 
 #define SPARSE_ANY_OP(DIM) SPARSE_ANY_ALL_OP (DIM, false, false, !=, true)
 
-#define SPARSE_SPARSE_MUL( RET_TYPE, RET_EL_TYPE, EL_TYPE ) \
+#define SPARSE_SPARSE_MUL(RET_TYPE, RET_EL_TYPE, EL_TYPE) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -2005,7 +2005,7 @@
         } \
     }
 
-#define SPARSE_FULL_MUL( RET_TYPE, EL_TYPE, ZERO ) \
+#define SPARSE_FULL_MUL(RET_TYPE, EL_TYPE, ZERO) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -2040,7 +2040,7 @@
       return retval; \
     }
 
-#define SPARSE_FULL_TRANS_MUL( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \
+#define SPARSE_FULL_TRANS_MUL(RET_TYPE, EL_TYPE, ZERO, CONJ_OP) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -2076,7 +2076,7 @@
       return retval; \
     }
 
-#define FULL_SPARSE_MUL( RET_TYPE, EL_TYPE, ZERO ) \
+#define FULL_SPARSE_MUL(RET_TYPE, EL_TYPE, ZERO) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
@@ -2112,7 +2112,7 @@
       return retval; \
     }
 
-#define FULL_SPARSE_MUL_TRANS( RET_TYPE, EL_TYPE, ZERO, CONJ_OP ) \
+#define FULL_SPARSE_MUL_TRANS(RET_TYPE, EL_TYPE, ZERO, CONJ_OP) \
   octave_idx_type nr = m.rows (); \
   octave_idx_type nc = m.cols (); \
   \
--- a/liboctave/operators/mx-inlines.cc
+++ b/liboctave/operators/mx-inlines.cc
@@ -485,6 +485,14 @@
 #define OP_RED_SUMSQ(ac, el) ac += el*el
 #define OP_RED_SUMSQC(ac, el) ac += cabsq (el)
 
+inline void op_dble_prod (double& ac, float el)
+{ ac *= el; }
+inline void op_dble_prod (Complex& ac, const FloatComplex& el)
+{ ac *= el; } // FIXME: guaranteed?
+template <class T>
+inline void op_dble_prod (double& ac, const octave_int<T>& el)
+{ ac *= el.double_value (); }
+
 inline void op_dble_sum (double& ac, float el)
 { ac += el; }
 inline void op_dble_sum (Complex& ac, const FloatComplex& el)
@@ -514,6 +522,7 @@
 OP_RED_FCN (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)
 OP_RED_FCN (mx_inline_count, bool, T, OP_RED_SUM, 0)
 OP_RED_FCN (mx_inline_prod, T, T, OP_RED_PROD, 1)
+OP_RED_FCN (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 1)
 OP_RED_FCN (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
 OP_RED_FCN (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
 OP_RED_FCN (mx_inline_any, T, bool, OP_RED_ANYC, false)
@@ -539,6 +548,7 @@
 OP_RED_FCN2 (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)
 OP_RED_FCN2 (mx_inline_count, bool, T, OP_RED_SUM, 0)
 OP_RED_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1)
+OP_RED_FCN2 (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 0.0)
 OP_RED_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
 OP_RED_FCN2 (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
 
@@ -612,6 +622,7 @@
 OP_RED_FCNN (mx_inline_dsum, T, PROMOTE_DOUBLE(T))
 OP_RED_FCNN (mx_inline_count, bool, T)
 OP_RED_FCNN (mx_inline_prod, T, T)
+OP_RED_FCNN (mx_inline_dprod, T, PROMOTE_DOUBLE(T))
 OP_RED_FCNN (mx_inline_sumsq, T, T)
 OP_RED_FCNN (mx_inline_sumsq, std::complex<T>, T)
 OP_RED_FCNN (mx_inline_any, T, bool)
@@ -1345,8 +1356,8 @@
 inline T
 mx_inline_xsum (const T *v, octave_idx_type n)
 {
-  T s = 0;
-  T e = 0;
+  T s, e;
+  s = e = 0;
   for (octave_idx_type i = 0; i < n; i++)
     twosum_accum (s, e, v[i]);
 
--- a/liboctave/system/module.mk
+++ b/liboctave/system/module.mk
@@ -18,10 +18,6 @@
   system/sysdir.h \
   system/syswait.h
 
-SYSTEM_C_SRC = \
-  system/tempnam.c \
-  system/tempname.c
-
 SYSTEM_SRC = \
   system/dir-ops.cc \
   system/file-ops.cc \
@@ -33,8 +29,7 @@
   system/oct-passwd.cc \
   system/oct-syscalls.cc \
   system/oct-time.cc \
-  system/oct-uname.cc \
-  $(SYSTEM_C_SRC)
+  system/oct-uname.cc
 
 noinst_LTLIBRARIES += system/libsystem.la
 
deleted file mode 100644
--- a/liboctave/system/tempnam.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (C) 1991, 1993 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library 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
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 51 Franklin Street,
-Fifth Floor, Boston, MA  02110-1301, USA.  */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef HAVE_TEMPNAM
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern char *__stdio_gen_tempname (const char *dir, const char *pfx,
-                                   int dir_search, size_t *lenptr,
-                                   FILE **streamptr);
-
-/* Generate a unique temporary filename using up to five characters of PFX
-   if it is not NULL.  The directory to put this file in is searched for
-   as follows: First the environment variable "TMPDIR" is checked.
-   If it contains the name of a writable directory, that directory is used.
-   If not and if DIR is not NULL, that value is checked.  If that fails,
-   P_tmpdir is tried and finally "/tmp".  The storage for the filename
-   is allocated by `malloc'.  */
-char *
-tempnam (const char *dir, const char *pfx)
-{
-  size_t len;
-  register char *s;
-  register char *t = __stdio_gen_tempname (dir, pfx, 1, &len, (FILE **) NULL);
-
-  if (t == NULL)
-    return NULL;
-
-  s = (char *) malloc (len);
-  if (s == NULL)
-    return NULL;
-
-  (void) memcpy (s, t, len);
-  return s;
-}
-
-#endif
deleted file mode 100644
--- a/liboctave/system/tempname.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library 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 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library 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 the GNU C Library; see the file COPYING.  If
-not, write to the Free Software Foundation, Inc., 51 Franklin Street,
-Fifth Floor, Boston, MA  02110-1301, USA.  */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef HAVE_TEMPNAM
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <fcntl.h>
-
-#include "statdefs.h"
-
-#ifndef FILENAME_MAX
-#ifdef MAXPATHLEN
-#define FILENAME_MAX MAXPATHLEN
-#else
-#define FILENAME_MAX 1024
-#endif
-#endif
-
-#ifndef P_tmpdir
-#define P_tmpdir "/usr/tmp/"
-#endif
-
-/* Return nonzero if DIR is an existent directory.  */
-static int
-diraccess (const char *dir)
-{
-  struct stat buf;
-  return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode);
-}
-
-/* Return nonzero if FILE exists.  */
-static int
-exists (const char *file)
-{
-  /* We can stat the file even if we can't read its data.  */
-  struct stat st;
-  int save = errno;
-  if (stat (file, &st) == 0)
-    return 1;
-  else
-    {
-      /* We report that the file exists if stat failed for a reason other
-         than nonexistence.  In this case, it may or may not exist, and we
-         don't know; but reporting that it does exist will never cause any
-         trouble, while reporting that it doesn't exist when it does would
-         violate the interface of __stdio_gen_tempname.  */
-      int exists = errno != ENOENT;
-      errno = save;
-      return exists;
-    }
-}
-
-
-/* These are the characters used in temporary filenames.  */
-static const char letters[] =
-  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
-/* Generate a temporary filename and return it (in a static buffer).  If
-   STREAMPTR is not NULL, open a stream "w+b" on the file and set
-   *STREAMPTR to it.  If DIR_SEARCH is nonzero, DIR and PFX are used as
-   described for tempnam.  If not, a temporary filename in P_tmpdir with no
-   special prefix is generated.  If LENPTR is not NULL, *LENPTR is set the
-   to length (including the terminating '\0') of the resultant filename,
-   which is returned.  This goes through a cyclic pattern of all possible
-   filenames consisting of five decimal digits of the current pid and three
-   of the characters in `letters'.  Data for tempnam and tmpnam is kept
-   separate, but when tempnam is using P_tmpdir and no prefix (i.e, it is
-   identical to tmpnam), the same data is used.  Each potential filename is
-   tested for an already-existing file of the same name, and no name of an
-   existing file will be returned.  When the cycle reaches its end
-   (12345ZZZ), NULL is returned.  */
-char *
-__stdio_gen_tempname (const char *dir, const char *pfx,
-                      int dir_search, size_t *lenptr,
-                      FILE **streamptr)
-{
-  int saverrno = errno;
-  static const char tmpdir[] = P_tmpdir;
-  static size_t indices[2];
-  size_t *idx;
-  static char buf[FILENAME_MAX];
-  static pid_t oldpid = (pid_t) 0;
-  pid_t pid = getpid ();
-  register size_t len, plen, dlen;
-
-  if (dir_search)
-    {
-      register const char *d = getenv ("TMPDIR");
-      if (d != NULL && !diraccess (d))
-        d = NULL;
-      if (d == NULL && dir != NULL && diraccess (dir))
-        d = dir;
-      if (d == NULL && diraccess (tmpdir))
-        d = tmpdir;
-      if (d == NULL && diraccess ("/tmp"))
-        d = "/tmp";
-      if (d == NULL)
-        {
-          errno = ENOENT;
-          return NULL;
-        }
-      dir = d;
-    }
-  else
-    dir = tmpdir;
-
-  dlen = strlen (dir);
-
-  /* Remove trailing slashes from the directory name.  */
-  while (dlen > 1 && dir[dlen - 1] == '/')
-    --dlen;
-
-  if (pfx != NULL && *pfx != '\0')
-    {
-      plen = strlen (pfx);
-      if (plen > 5)
-        plen = 5;
-    }
-  else
-    plen = 0;
-
-  if (dir != tmpdir && !strcmp (dir, tmpdir))
-    dir = tmpdir;
-  idx = &indices[(plen == 0 && dir == tmpdir) ? 1 : 0];
-
-  if (pid != oldpid)
-    {
-      oldpid = pid;
-      indices[0] = indices[1] = 0;
-    }
-
-  len = dlen + 1 + plen + 5 + 3;
-  for (; *idx < ((sizeof (letters) - 1) * (sizeof (letters) - 1) *
-                 (sizeof (letters) - 1));
-       ++*idx)
-    {
-      /* Construct a file name and see if it already exists.
-
-         We use a single counter in *IDX to cycle each of three
-         character positions through each of 62 possible letters.  */
-
-      if (sizeof (buf) < len)
-        return NULL;
-
-      sprintf (buf, "%.*s/%.*s%.5d%c%c%c",
-               (int) dlen, dir, (int) plen,
-               pfx, pid % 100000,
-               letters[*idx
-                       % (sizeof (letters) - 1)],
-               letters[(*idx / (sizeof (letters) - 1))
-                       % (sizeof (letters) - 1)],
-               letters[(*idx / ((sizeof (letters) - 1) *
-                                (sizeof (letters) - 1)))
-                       % (sizeof (letters) - 1)]
-              );
-
-      if (! buf || strlen (buf) != (int) len)
-        return NULL;
-
-      if (streamptr != NULL)
-        abort ();
-      else if (exists (buf))
-        continue;
-
-      /* If the file already existed we have continued the loop above,
-         so we only get here when we have a winning name to return.  */
-
-      errno = saverrno;
-
-      if (lenptr != NULL)
-        *lenptr = len + 1;
-      return buf;
-    }
-
-  /* We got out of the loop because we ran out of combinations to try.  */
-  errno = EEXIST;               /* ? */
-  return NULL;
-}
-
-#endif
--- a/liboctave/util/base-list.h
+++ b/liboctave/util/base-list.h
@@ -104,8 +104,6 @@
   // For backward compatibility.
   void append (const elt_type& s) { lst.push_back (s); }
 
-protected:
-
   octave_base_list (void) : lst () { }
 
   octave_base_list (const std::list<elt_type>& l) : lst (l) { }
--- a/liboctave/util/caseless-str.h
+++ b/liboctave/util/caseless-str.h
@@ -57,16 +57,16 @@
         char lp1 = std::tolower (*p1);
         char lp2 = std::tolower (*p2);
 
-        if ( lp1 > lp2 )
+        if (lp1 > lp2)
           return false;
-        if ( lp1 < lp2)
+        if (lp1 < lp2)
           return true;
 
         p1++;
         p2++;
       }
 
-    if ( length () >= s.length ())
+    if (length () >= s.length ())
       return false;
     else
       return true;
--- a/liboctave/util/data-conv.cc
+++ b/liboctave/util/data-conv.cc
@@ -409,8 +409,6 @@
 
           if (input_is_output)
             {
-              input_is_output = false;
-
               s1 = s.substr (1, pos-1);
 
               (*current_liboctave_warning_handler)
@@ -587,7 +585,7 @@
       if (len > 0) \
         { \
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
-          std::streamsize n_bytes = size * len; \
+          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
           stream.read (reinterpret_cast<char *> (ptr), n_bytes); \
           if (swap) \
             swap_bytes< size > (ptr, len); \
@@ -610,7 +608,7 @@
           OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
           for (octave_idx_type i = 0; i < len; i++) \
             ptr[i] = static_cast <TYPE> (data[i]);         \
-          std::streamsize n_bytes = size * len; \
+          std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
           stream.write (reinterpret_cast<char *> (ptr), n_bytes); \
         } \
     } \
@@ -809,7 +807,7 @@
     case LS_FLOAT:
       {
         OCTAVE_LOCAL_BUFFER (float, ptr, len);
-        std::streamsize n_bytes = 4 * len;
+        std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
         is.read (reinterpret_cast<char *> (ptr), n_bytes);
         do_float_format_conversion (ptr, len, fmt);
         for (octave_idx_type i = 0; i < len; i++)
@@ -867,7 +865,7 @@
 
     case LS_FLOAT: // No conversion necessary.
       {
-        std::streamsize n_bytes = 4 * len;
+        std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
         is.read (reinterpret_cast<char *> (data), n_bytes);
         do_float_format_conversion (data, len, fmt);
       }
@@ -876,7 +874,7 @@
     case LS_DOUBLE:
       {
         OCTAVE_LOCAL_BUFFER (double, ptr, len);
-        std::streamsize n_bytes = 8 * len;
+        std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
         is.read (reinterpret_cast<char *> (ptr), n_bytes);
         do_double_format_conversion (ptr, len, fmt);
         for (octave_idx_type i = 0; i < len; i++)
@@ -974,7 +972,7 @@
       {
         char tmp_type = static_cast<char> (type);
         os.write (&tmp_type, 1);
-        std::streamsize n_bytes = 4 * len;
+        std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
         os.write (reinterpret_cast <const char *> (data), n_bytes);
       }
       break;
--- a/liboctave/util/str-vec.cc
+++ b/liboctave/util/str-vec.cc
@@ -250,14 +250,10 @@
     nc = 1;
 
   // Calculate the number of rows that will be in each column except
-  // possibly  for a short column on the right.
+  // possibly for a short column on the right.
 
   octave_idx_type nr = total_names / nc + (total_names % nc != 0);
 
-  // Recalculate columns based on rows.
-
-  nc = total_names / nr + (total_names % nr != 0);
-
   octave_idx_type count;
   for (octave_idx_type row = 0; row < nr; row++)
     {
rename from scripts/general/bicubic.m
rename to scripts/deprecated/bicubic.m
--- a/scripts/general/bicubic.m
+++ b/scripts/deprecated/bicubic.m
@@ -19,6 +19,9 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {@var{zi} =} bicubic (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi}, @var{extrapval})
 ##
+## @code{bicubic} is deprecated and will be removed in Octave version 4.6.
+## Use @code{interp2 (@dots{}, "spline")} for the equivalent functionality.
+##
 ## Return a matrix @var{zi} corresponding to the bicubic
 ## interpolations at @var{xi} and @var{yi} of the data supplied
 ## as @var{x}, @var{y} and @var{z}.  Points outside the grid are set
@@ -32,8 +35,17 @@
 ## Bicubic interpolation method.
 ## Author: Hoxide Ma <hoxide_dirac@yahoo.com.cn>
 
+## Deprecated in version 4.2
+
 function zi = bicubic (x, y, z, xi, yi, extrapval, spline_alpha)
 
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "bicubic is obsolete and will be removed from a future version of Octave, please use interp2 instead");
+  endif
+
   if (nargin < 1 || nargin > 7)
     print_usage ();
   endif
@@ -240,9 +252,9 @@
 %! z = cos (6 * xx) + sin (6 * yy);
 %! x = linspace (1, -1, 30);
 %! [xx2, yy2] = meshgrid (x);
-%! z1 = interp2 (xx, yy, z, xx2, yy2, "cubic");
+%! z1 = interp2 (xx, yy, z, xx2, yy2, "spline");
 %! z2 = interp2 (fliplr (xx), flipud (yy), fliplr (flipud(z)),
-%!               fliplr (xx2), flipud (yy2), "cubic");
+%!               fliplr (xx2), flipud (yy2), "spline");
 %! z2 = fliplr (flipud (z2));
 %! assert (z1, z2, 100 * eps ())
 
deleted file mode 100644
--- a/scripts/deprecated/default_save_options.m
+++ /dev/null
@@ -1,42 +0,0 @@
-## Copyright (C) 2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Built-in Function} {@var{val} =} default_save_options ()
-## @deftypefnx {Built-in Function} {@var{old_val} =} default_save_options (@var{new_val})
-## @deftypefnx {Built-in Function} {} default_save_options (@var{new_val}, "local")
-## This function has been deprecated.  Use @code{@file{save_default_options}}
-## instead.
-## @seealso{save_default_options}
-## @end deftypefn
-
-## Deprecated in 3.8
-
-function retval = default_save_options (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "default_save_options is obsolete and will be removed from a future version of Octave, please use save_default_options instead");
-  endif
-
-  retval = save_default_options (varargin{:});
-
-endfunction
-
new file mode 100644
--- /dev/null
+++ b/scripts/deprecated/find_dir_in_path.m
@@ -0,0 +1,40 @@
+## Copyright (C) 2013 John W. Eaton
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Built-in Function} {} find_dir_in_path (@var{dir})
+## @deftypefnx {Built-in Function} {} find_dir_in_path (@var{dir}, "all")
+## This function has been deprecated.  Use @code{dir_in_loadpath} instead.
+## @seealso{dir_in_loadpath}
+## @end deftypefn
+
+## Deprecated in version 4.2
+
+function retval = find_dir_in_path (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "find_dir_in_path is obsolete and will be removed from a future version of Octave, please use dir_in_loadpath instead");
+  endif
+
+  retval = dir_in_loadpath (varargin{:});
+
+endfunction
+
deleted file mode 100644
--- a/scripts/deprecated/gen_doc_cache.m
+++ /dev/null
@@ -1,39 +0,0 @@
-## Copyright (C) 2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} gen_doc_cache (@var{out_file}, @var{directory})
-## This function has been deprecated.  Use @code{doc_cache_create} instead.
-## @seealso{doc_cache_create}
-## @end deftypefn
-
-## Deprecated in 3.8
-
-function gen_doc_cache (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "gen_doc_cache is obsolete and will be removed from a future version of Octave, please use doc_cache_create instead");
-  endif
-
-  doc_cache_create (varargin{:});
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/interp1q.m
+++ /dev/null
@@ -1,81 +0,0 @@
-## Copyright (C) 2008-2013 David Bateman
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{yi} =} interp1q (@var{x}, @var{y}, @var{xi})
-## One-dimensional linear interpolation without error checking.
-## Interpolates @var{y}, defined at the points @var{x}, at the points
-## @var{xi}.  The sample points @var{x} must be a strictly monotonically
-## increasing column vector.  If @var{y} is a matrix or an N-dimensional
-## array, the interpolation is performed on each column of @var{y}.  If
-## @var{y} is a vector, it must be a column vector of the same length as
-## @var{x}.
-##
-## Values of @var{xi} beyond the endpoints of the interpolation result
-## in NA being returned.
-##
-## Note that the error checking is only a significant portion of the
-## execution time of this @code{interp1} if the size of the input arguments
-## is relatively small.  Therefore, the benefit of using @code{interp1q}
-## is relatively small.
-## @seealso{interp1}
-## @end deftypefn
-
-function yi = interp1q (x, y, xi)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "interp1q is obsolete and will be removed from a future version of Octave; use interp1 instead");
-  endif
-
-  x = x(:);
-  nx = rows (x);
-  szy = size (y);
-  y = y(:,:);
-  [ny, nc] = size (y);
-  szx = size (xi);
-  xi = xi (:);
-  dy = diff (y);
-  dx = diff (x);
-  idx = lookup (x, xi, "lr");
-  s = (xi - x (idx)) ./ dx (idx);
-  yi = bsxfun (@times, s, dy(idx,:)) + y(idx,:);
-  range = xi < x(1) | !(xi <= x(nx));
-  yi(range,:) = NA;
-  if (length (szx) == 2 && any (szx == 1))
-    yi = reshape (yi, [max(szx), szy(2:end)]);
-  else
-    yi = reshape (yi, [szx, szy(2:end)]);
-  endif
-endfunction
-
-
-%!shared xp, yp, xi, yi
-%! xp = [0:2:10].';   yp = sin (2*pi*xp/5);
-%! xi = [-1; 0; 2.2; 4; 6.6; 10; 11];
-%! yi = interp1 (xp,yp,xi);
-%!assert (interp1q (xp,yp, [min(xp)-1; max(xp)+1]), [NA; NA]);
-%!assert (interp1q (xp,yp,xp), yp, 100*eps);
-%!assert (isempty (interp1q (xp,yp,[])));
-%!assert (interp1q (xp,yp,xi), yi);
-%!assert (interp1q (xp,[yp,yp],xi), [yi, yi]);
-%!assert (interp1q (xp,yp,[xi,xi]), [yi, yi]);
-%!assert (interp1q (xp,[yp,yp],[xi,xi]), cat (3, [yi, yi], [yi, yi]));
-
deleted file mode 100644
--- a/scripts/deprecated/isequalwithequalnans.m
+++ /dev/null
@@ -1,50 +0,0 @@
-## Copyright (C) 2005-2013 William Poetra Yoga Hadisoeseno
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {} isequalwithequalnans (@var{x1}, @var{x2}, @dots{})
-## This function has been deprecated.  Use @code{@file{isequaln}} instead.
-## @seealso{isequaln}
-## @end deftypefn
-
-## Deprecated in 3.8
-
-function retval = isequalwithequalnans (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "isequalwithequalnans is obsolete and will be removed from a future version of Octave, please use isequaln instead");
-  endif
-
-  retval = isequaln (varargin{:});
-
-endfunction
-
-
-## test for equality
-%!assert (isequalwithequalnans ({1,2,NaN,4},{1,2,NaN,4}), true)
-%!assert (isequalwithequalnans ([1,2,NaN,4],[1,2,NaN,4]), true)
-## test for inequality
-%!assert (isequalwithequalnans ([1,2,NaN,4],[1,NaN,3,4]), false)
-%!assert (isequalwithequalnans ([1,2,NaN,4],[1,2,3,4]), false)
-## test for equality (struct)
-%!assert (isequalwithequalnans (struct ('a',NaN,'b',2),struct ('a',NaN,'b',2),struct ('a',NaN,'b',2)), true)
-%!assert (isequalwithequalnans (1,2,1), false)
-
deleted file mode 100644
--- a/scripts/deprecated/java_convert_matrix.m
+++ /dev/null
@@ -1,48 +0,0 @@
-## Copyright (C) 2012-2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Built-in Function} {@var{val} =} java_convert_matrix ()
-## @deftypefnx {Built-in Function} {@var{old_val} =} java_convert_matrix (@var{new_val})
-## @deftypefnx {Built-in Function} {} java_convert_matrix (@var{new_val}, "local")
-## Query or set the internal variable that controls whether Java arrays are
-## automatically converted to Octave matrices.  The default value is false.
-## 
-## When called from inside a function with the @qcode{"local"} option, the
-## variable is changed locally for the function and any subroutines it calls.
-##  The original variable value is restored when exiting the function.
-## @seealso{java_matrix_autoconversion, java_unsigned_conversion, java_debug}
-## @end deftypefn
-
-function old_val = java_convert_matrix (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java_convert_matrix is obsolete and will be removed from a future version of Octave; use java_matrix_autoconversion instead");
-  endif
-
-  if (nargin > 2)
-    print_usage ();
-  endif
-
-  old_val = java_matrix_autoconversion (varargin{:});
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/java_debug.m
+++ /dev/null
@@ -1,49 +0,0 @@
-## Copyright (C) 2012-2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Built-in Function} {@var{val} =} java_debug ()
-## @deftypefnx {Built-in Function} {@var{old_val} =} java_debug (@var{new_val})
-## @deftypefnx {Built-in Function} {} java_debug (@var{new_val}, "local")
-## Query or set the internal variable that determines whether extra debugging
-## information regarding the initialization of the JVM and any Java exceptions
-## is printed.
-## 
-## When called from inside a function with the @qcode{"local"} option, the
-## variable is changed locally for the function and any subroutines it calls.
-##  The original variable value is restored when exiting the function.
-## @seealso{debug_java, java_convert_matrix, java_unsigned_conversion}
-## @end deftypefn
-
-function old_val = java_debug (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java_debug is obsolete and will be removed from a future version of Octave; use debug_java instead");
-  endif
-
-  if (nargin > 2)
-    print_usage ();
-  endif
-
-  old_val = debug_java (varargin{:});
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/java_get.m
+++ /dev/null
@@ -1,63 +0,0 @@
-## Copyright (C) 2012-2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Loadable Function} {@var{val} =} java_get (@var{obj}, @var{name})
-## Get the value of the field @var{name} of the Java object @var{obj}.  For
-## static fields, @var{obj} can be a string representing the fully qualified
-## name of the corresponding class.
-## 
-## When @var{obj} is a regular Java object, structure-like indexing can be
-## used as a shortcut syntax.  For instance, the two following statements are
-## equivalent
-## 
-## @example
-## @group
-##   java_get (x, "field1")
-##   x.field1
-## @end group
-## @end example
-## 
-## @seealso{java_set, javaMethod, javaObject}
-## @end deftypefn
-
-function retval = java_get (obj, name)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java_get is obsolete and will be removed from a future version of Octave; use structure-like indexing instead");
-  endif
-
-  if (nargin != 2)
-    print_usage ();
-  endif
-
-  if (isjava (obj))
-    retval = obj.(name);
-  elseif (ischar (obj))
-    ## FIXME: Need a solution for getting static fields of class
-    ##        which does not depend on __java_get__ which will be removed.
-    retval = __java_get__ (obj, name);
-  else
-    error ("java_get: OBJ must be a Java object");
-  endif
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/java_invoke.m
+++ /dev/null
@@ -1,57 +0,0 @@
-## Copyright (C) 2007, 2013 Michael Goffioul
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Built-in Function} {@var{ret} =} java_invoke (@var{obj}, @var{methodname})
-## @deftypefnx {Built-in Function} {@var{ret} =} java_invoke (@var{obj}, @var{methodname}, @var{arg1}, @dots{})
-## Invoke the method @var{methodname} on the Java object @var{obj} with the
-## arguments @var{arg1}, @dots{}  For static methods, @var{obj} can be a
-## string representing the fully qualified name of the corresponding class. 
-## The function returns the result of the method invocation.
-## 
-## When @var{obj} is a regular Java object, structure-like indexing can be
-## used as a shortcut syntax.  For instance, the two following statements are
-## equivalent
-## 
-## @example
-## @group
-##   ret = java_invoke (x, "method1", 1.0, "a string")
-##   ret = x.method1 (1.0, "a string")
-## @end group
-## @end example
-## 
-## @seealso{javaMethod, javaObject}
-## @end deftypefn
-
-function retval = java_invoke (obj, methodname, varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java_invoke is obsolete and will be removed from a future version of Octave, please use javaMethod instead");
-  endif
-  
-  if (nargin < 2)
-    print_usage ();
-  endif
-
-  retval = javaMethod (methodname, obj, varargin{:});
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/java_set.m
+++ /dev/null
@@ -1,63 +0,0 @@
-## Copyright (C) 2012-2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Loadable Function} {@var{obj} =} java_set (@var{obj}, @var{name}, @var{val})
-## Set the value of the field @var{name} of the Java object @var{obj} to
-## @var{val}.  For static fields, @var{obj} can be a string representing the
-## fully qualified named of the corresponding Java class.
-## 
-## When @var{obj} is a regular Java object, structure-like indexing can be
-## used as a shortcut syntax.  For instance, the two following statements are
-## equivalent
-## 
-## @example
-## @group
-##   java_set (x, "field1", val)
-##   x.field1 = val
-## @end group
-## @end example
-## 
-## @seealso{java_get, javaMethod, javaObject}
-## @end deftypefn
-
-function retval = java_set (obj, name, val)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java_set is obsolete and will be removed from a future version of Octave; use structure-like indexing instead");
-  endif
-
-  if (nargin != 3)
-    print_usage ();
-  endif
-
-  if (isjava (obj))
-    obj.(name) = val;
-  elseif (ischar (obj))
-    ## FIXME: Need a solution for getting static fields of class
-    ##        which does not depend on __java_set__ which will be removed.
-    retval = __java_set__ (obj, name, val);
-  else
-    error ("java_set: OBJ must be a Java object");
-  endif
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/java_unsigned_conversion.m
+++ /dev/null
@@ -1,50 +0,0 @@
-## Copyright (C) 2012-2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Built-in Function} {@var{val} =} java_unsigned_conversion ()
-## @deftypefnx {Built-in Function} {@var{old_val} =} java_unsigned_conversion (@var{new_val})
-## @deftypefnx {Built-in Function} {} java_unsigned_conversion (@var{new_val}, "local")
-## Query or set the internal variable that controls how integer classes are
-## converted when Java matrix autoconversion is enabled.  When enabled, Java
-## arrays of class Byte or Integer are converted to matrices of class uint8 or
-## uint32 respectively.
-## 
-## When called from inside a function with the @qcode{"local"} option, the
-## variable is changed locally for the function and any subroutines it calls.
-##  The original variable value is restored when exiting the function.
-## @seealso{java_unsigned_autoconversion, java_convert_matrix, debug_java}
-## @end deftypefn
-
-function old_val = java_unsigned_conversion (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "java_unsigned_conversion is obsolete and will be removed from a future version of Octave; use java_unsigned_autoconversion instead");
-  endif
-
-  if (nargin > 2)
-    print_usage ();
-  endif
-
-  old_val = java_unsigned_autoconversion (varargin{:});
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/javafields.m
+++ /dev/null
@@ -1,54 +0,0 @@
-## Copyright (C) 2007, 2013 Michael Goffioul
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} javafields (@var{javaobj})
-## @deftypefnx {Function File} {} javafields ("@var{classname}")
-## @deftypefnx {Function File} {@var{fld_names} =} javafields (@dots{})
-## Return the fields of a Java object or Java class in the form of a cell 
-## array of strings.  If no output is requested, print the result
-## to the standard output.
-## @seealso{fieldnames, methods, javaObject}
-## @end deftypefn
-
-function fld_names = javafields (javaobj)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "javafields is obsolete and will be removed from a future version of Octave, please use fieldnames instead");
-  endif
-  
-  if (nargin != 1)
-    print_usage ();
-  endif
-  
-  c_methods = javaMethod ("getFields", "org.octave.ClassHelper", javaobj);
-  method_list = ostrsplit (c_methods, ';');
-
-  if (nargout == 0)
-    if (! isempty (method_list))
-      disp (method_list);
-    endif
-  else
-    fld_names = cellstr (method_list);
-  endif
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/javamethods.m
+++ /dev/null
@@ -1,54 +0,0 @@
-## Copyright (C) 2007, 2013 Michael Goffioul
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Function File} {} javamethods (@var{javaobj})
-## @deftypefnx {Function File} {} javamethods ("@var{classname}")
-## @deftypefnx {Function File} {@var{mtd_names} =} javamethods (@dots{})
-## Return the methods of a Java object or Java class in the form of a cell 
-## array of strings.  If no output is requested, print the result to the
-## standard output.
-## @seealso{methods, fieldnames, javaMethod, javaObject}
-## @end deftypefn
-
-function mtd_names = javamethods (classname)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "javamethods is obsolete and will be removed from a future version of Octave, please use methods instead");
-  endif
-  
-  if (nargin != 1)
-    print_usage ();
-  endif
-
-  cls_methods = javaMethod ("getMethods", "org.octave.ClassHelper", classname);
-  method_list = ostrsplit (cls_methods, ';');
-
-  if (nargout == 0)
-    if (! isempty (method_list))
-      disp (method_list);
-    endif
-  else
-    mtd_names = cellstr (method_list);
-  endif
-
-endfunction
-
--- a/scripts/deprecated/module.mk
+++ b/scripts/deprecated/module.mk
@@ -1,23 +1,10 @@
 FCN_FILE_DIRS += deprecated
 
 deprecated_FCN_FILES = \
-  deprecated/default_save_options.m \
-  deprecated/gen_doc_cache.m \
-  deprecated/interp1q.m \
-  deprecated/isequalwithequalnans.m \
+  deprecated/bicubic.m \
+  deprecated/find_dir_in_path.m \
   deprecated/isstr.m \
-  deprecated/java_convert_matrix.m \
-  deprecated/java_debug.m \
-  deprecated/java_get.m \
-  deprecated/java_invoke.m \
-  deprecated/java_new.m \
-  deprecated/java_unsigned_conversion.m \
-  deprecated/java_set.m \
-  deprecated/javafields.m \
-  deprecated/javamethods.m \
-  deprecated/re_read_readline_init_file.m \
-  deprecated/read_readline_init_file.m \
-  deprecated/saving_history.m
+  deprecated/nfields.m
 
 FCN_FILES += $(deprecated_FCN_FILES)
 
new file mode 100644
--- /dev/null
+++ b/scripts/deprecated/nfields.m
@@ -0,0 +1,44 @@
+## Copyright (C) 2014 Rik Wehbring
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} nfields (@var{s})
+## Return the number of fields of the structure @var{s}.
+##
+## @strong{Warning:} @code{nfields} is scheduled for removal in version 4.6.
+## Use @code{numfields} instead.
+## @seealso{numfields, fieldnames}
+## @end deftypefn
+
+function retval = nfields (varargin)
+
+  persistent warned = false;
+  if (! warned)
+    warned = true;
+    warning ("Octave:deprecated-function",
+             "nfields is obsolete and will be removed from a future version of Octave; please use numfields instead");
+  endif
+
+  if (nargin < 1)
+    print_usage ();
+  endif
+
+  retval = numfields (varargin{:});
+
+endfunction
+
deleted file mode 100644
--- a/scripts/deprecated/re_read_readline_init_file.m
+++ /dev/null
@@ -1,40 +0,0 @@
-## Copyright (C) 2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} re_read_readline_init_file (@var{file})
-## This function has been deprecated.  Use
-## @code{@file{readline_re_read_init_file}} instead.
-## @seealso{readline_read_init_file}
-## @end deftypefn
-
-## Deprecated in 3.8
-
-function re_read_readline_init_file (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "re_read_readline_init_file is obsolete and will be removed from a future version of Octave, please use readline_re_read_init_file instead");
-  endif
-
-  readline_re_read_init_file (varargin{:});
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/read_readline_init_file.m
+++ /dev/null
@@ -1,40 +0,0 @@
-## Copyright (C) 2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Built-in Function} {} read_readline_init_file (@var{file})
-## This function has been deprecated.  Use
-## @code{@file{readline_read_init_file}} instead.
-## @seealso{readline_read_init_file}
-## @end deftypefn
-
-## Deprecated in 3.8
-
-function read_readline_init_file (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "read_readline_init_file is obsolete and will be removed from a future version of Octave, please use readline_read_init_file instead");
-  endif
-
-  readline_read_init_file (varargin{:});
-
-endfunction
-
deleted file mode 100644
--- a/scripts/deprecated/saving_history.m
+++ /dev/null
@@ -1,41 +0,0 @@
-## Copyright (C) 2013 Rik Wehbring
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn  {Built-in Function} {@var{val} =} saving_history ()
-## @deftypefnx {Built-in Function} {@var{old_val} =} saving_history (@var{new_val})
-## @deftypefnx {Built-in Function} {} saving_history (@var{new_val}, "local")
-## This function has been deprecated.  Use @code{@file{history_save}} instead.
-## @seealso{history_save}
-## @end deftypefn
-
-## Deprecated in 3.8
-
-function retval = saving_history (varargin)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "saving_history is obsolete and will be removed from a future version of Octave, please use history_save instead");
-  endif
-
-  retval = save_default_options (varargin{:});
-
-endfunction
-
--- a/scripts/general/cell2mat.m
+++ b/scripts/general/cell2mat.m
@@ -32,15 +32,14 @@
     print_usage ();
   endif
 
-  if (! iscell (c))
-    error ("cell2mat: C is not a cell array");
-  endif
-
   nb = numel (c);
 
   if (nb == 0)
     m = [];
   else
+    if (! iscell (c))
+      error ("cell2mat: C must be a cell array");
+    endif
 
     ## Check first for valid matrix types
     valid = cellfun ("isnumeric", c);
@@ -94,6 +93,7 @@
 %! cell2mat (C)
 
 %!assert (cell2mat ({}), []);
+%!assert (cell2mat ([]), []);
 %!test
 %! C = {[1], [2 3 4]; [5; 9], [6 7 8; 10 11 12]};
 %! D = C; D(:,:,2) = C;
@@ -115,7 +115,7 @@
 
 %!error cell2mat ()
 %!error cell2mat (1,2)
-%!error <C is not a cell array> cell2mat ([1,2])
+%!error <C must be a cell array> cell2mat ([1,2])
 %!error <mixed cells, structs, and matrices> cell2mat ({[1], struct()})
 %!error <mixed cells, structs, and matrices> cell2mat ({[1], {1}})
 %!error <mixed cells, structs, and matrices> cell2mat ({struct(), {1}})
--- a/scripts/general/cplxpair.m
+++ b/scripts/general/cplxpair.m
@@ -23,7 +23,7 @@
 ## Sort the numbers @var{z} into complex conjugate pairs ordered by
 ## increasing real part.  Place the negative imaginary complex number
 ## first within each pair.  Place all the real numbers (those with
-## @code{abs (imag (@var{z}) / @var{z}) < @var{tol})}) after the
+## @code{abs (imag (@var{z}) / @var{z}) < @var{tol}}) after the
 ## complex pairs.
 ##
 ## If @var{tol} is unspecified the default value is 100*@code{eps}.
--- a/scripts/general/del2.m
+++ b/scripts/general/del2.m
@@ -158,3 +158,164 @@
   D = D ./ nd;
 endfunction
 
+
+## 3x3 constant test
+%!test
+%! a = ones (3,3);
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00]);
+
+## 3x3 planar test
+%!test
+%! a = [1,2,3;2,3,4;3,4,5];
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00]);
+
+## 3x3 corner test
+%!test
+%! a = zeros (3,3);
+%! a(1,1) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [1.00;0.50;0.50]);
+%! assert (b(:,2), [0.50;0.00;0.00]);
+%! assert (b(:,3), [0.50;0.00;0.00]);
+%! assert (b, flipud (2*del2 (flipud (a))));
+%! assert (b, fliplr (2*del2 (fliplr (a))));
+%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));
+
+## 3x3 boundary test
+%!test
+%! a = zeros (3,3);
+%! a(2,1)=1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [-1.00;-0.50;-1.00]);
+%! assert (b(:,2), [0.00;0.50;0.00]);
+%! assert (b(:,3), [0.00;0.50;0.00]);
+%! assert (b, flipud (2*del2 (flipud (a))));
+%! assert (b, fliplr (2*del2 (fliplr (a))));
+%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));
+
+## 3x3 center test
+%!test
+%! a = zeros (3,3);
+%! a(2,2) = 1.0;
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;-0.50;0.00]);
+%! assert (b(:,2), [-0.50;-1.00;-0.50]);
+%! assert (b(:,3), [0.00;-0.50;0.00]);
+
+## 4x4 constant test
+%!test
+%! a = ones (4,4);
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [0.00;0.00;0.00;0.00]);
+
+## 4x4 planar test
+%!test
+%! a = [1,2,3,4;2,3,4,5;3,4,5,6;4,5,6,7];
+%! b = del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [0.00;0.00;0.00;0.00]);
+
+## 4x4 corner test
+%!test
+%! a = zeros (4,4);
+%! a(1,1) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [2.00;0.50;0.00;-0.50]);
+%! assert (b(:,2), [0.50;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [-0.50;0.00;0.00;0.00]);
+%! assert (b, flipud (2*del2 (flipud (a))));
+%! assert (b, fliplr (2*del2 (fliplr (a))));
+%! assert (b, flipud (fliplr (2*del2 (fliplr (flipud (a))))));
+
+## 9x9 center test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,3), [0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);
+%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]);
+%! assert (b(:,6), b(:,4));
+%! assert (b(:,7), b(:,3));
+%! assert (b(:,8), b(:,2));
+%! assert (b(:,9), b(:,1));
+
+## 9x9 boundary test
+%!test
+%! a = zeros (9,9);
+%! a(1,5) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(1,:), [0.00,0.00,0.00,0.50,0.00,0.50,0.00,0.00,0.00]);
+%! assert (b(2,:), [0.00,0.00,0.00,0.00,0.50,0.00,0.00,0.00,0.00]);
+%! assert (b(3:9,:), zeros (7,9));
+%! a(1,5) = 0.0;
+%! a(5,1) = 1.0;
+%! b = 2*del2 (a);
+%! assert (b(:,1), [0.00;0.00;0.00;0.50;0.00;0.50;0.00;0.00;0.00]);
+%! assert (b(:,2), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);
+%! assert (b(:,3:9), zeros (9,7));
+
+## 9x9 dh center test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 8*del2 (a,2);
+%! assert (b(:,1:3), zeros (9,3));
+%! assert (b(:,4), [0.00;0.00;0.00;0.00;0.50;0.00;0.00;0.00;0.00]);
+%! assert (b(:,5), [0.00;0.00;0.00;0.50;-2.00;0.50;0.00;0.00;0.00]);
+%! assert (b(:,6), b(:,4));
+%! assert (b(:,7:9), zeros (9,3));
+
+## 9x9 dx test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 4*del2 (a,2,1);
+%! assert (b(1:3,:), zeros (3,9));
+%! assert (b(4,:), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]');
+%! assert (b(5,:), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]');
+%! assert (b(6,:), b(4,:));
+%! assert (b(7:9,:), zeros (3,9));
+
+## 9x9 dy test
+%!test
+%! a = zeros (9,9);
+%! a(5,5) = 1.0;
+%! b = 4*del2 (a,1,2);
+%! assert (b(:,1:3), zeros (9,3));
+%! assert (b(:,4), [0.00;0.00;0.00;0.00;1.00;0.00;0.00;0.00;0.00]);
+%! assert (b(:,5), [0.00;0.00;0.00;0.25;-2.5;0.25;0.00;0.00;0.00]);
+%! assert (b(:,6), b(:,4));
+%! assert (b(:,7:9), zeros (9,3));
+
+## 3D test
+%!test
+%! a = zeros (9,9,9);
+%! a(5,5,5) = 1.0;
+%! b = 8*3*del2 (a,2);
+%! assert (b(:,:,1:3), zeros (9,9,3));
+%! assert (b(:,1:3,:), zeros (9,3,9));
+%! assert (b(1:3,:,:), zeros (3,9,9));
+%! assert (b(4:5,4,4), [0.0,0.0]');
+%! assert (b(5,5,4), 1.00);
+%! assert (b(4,4,5), 0.00);
+%! assert (b(5,4,5), 1.00);
+%! assert (b(5,5,5),-6.00);
+%! assert (b, flipdim (b,1));
+%! assert (b, flipdim (b,2));
+%! assert (b, flipdim (b,3));
+
--- a/scripts/general/fieldnames.m
+++ b/scripts/general/fieldnames.m
@@ -33,7 +33,7 @@
 ## When the input is a Java object @var{javaobj} or Java classname
 ## @var{jclassname} the name are the public data elements of the object or
 ## class.
-## @seealso{nfields, isfield, orderfields, struct, methods}
+## @seealso{numfields, isfield, orderfields, struct, methods}
 ## @end deftypefn
 
 function names = fieldnames (obj)
--- a/scripts/general/interp1.m
+++ b/scripts/general/interp1.m
@@ -29,28 +29,29 @@
 ## One-dimensional interpolation.
 ##
 ## Interpolate input data to determine the value of @var{yi} at the points
-## @var{xi}.  If not specified, @var{x} is taken to be the indices of @var{y}.
-## If @var{y} is a matrix or an N-dimensional array, the interpolation is
-## performed on each column of @var{y}.
+## @var{xi}.  If not specified, @var{x} is taken to be the indices of @var{y}
+## (@code{1:length (@var{y})}).  If @var{y} is a matrix or an N-dimensional
+## array, the interpolation is performed on each column of @var{y}.
 ##
-## Method is one of:
+## The interpolation @var{method} is one of:
 ##
 ## @table @asis
 ## @item @qcode{"nearest"}
-## Return the nearest neighbor
+## Return the nearest neighbor.
 ##
-## @item @qcode{"linear"}
-## Linear interpolation from nearest neighbors
+## @item @qcode{"linear"} (default)
+## Linear interpolation from nearest neighbors.
 ##
 ## @item @qcode{"pchip"}
-## Piecewise cubic Hermite interpolating polynomial
+## Piecewise cubic Hermite interpolating polynomial---shape-preserving
+## interpolation with smooth first derivative.
 ##
 ## @item @qcode{"cubic"}
-## Cubic interpolation (same as @code{pchip})
+## Cubic interpolation (same as @qcode{"pchip"}).
 ##
 ## @item @qcode{"spline"}
 ## Cubic spline interpolation---smooth first and second derivatives
-## throughout the curve
+## throughout the curve.
 ## @end table
 ##
 ## Adding '*' to the start of any method above forces @code{interp1}
@@ -61,7 +62,7 @@
 ## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values
 ## beyond the endpoints using the current @var{method}.  If @var{extrap} is a
 ## number, then replace values beyond the endpoints with that number.  When
-## unspecified, @var{extrap} defaults to NA.
+## unspecified, @var{extrap} defaults to @code{NA}.
 ##
 ## If the string argument @qcode{"pp"} is specified, then @var{xi} should not
 ## be supplied and @code{interp1} returns a piecewise polynomial object.  This 
@@ -91,16 +92,16 @@
 ## xp = [0:10];
 ## yp = sin (2*pi*xp/5);
 ## lin = interp1 (xp, yp, xf);
+## near = interp1 (xp, yp, xf, "nearest");
+## pch = interp1 (xp, yp, xf, "pchip");
 ## spl = interp1 (xp, yp, xf, "spline");
-## cub = interp1 (xp, yp, xf, "cubic");
-## near = interp1 (xp, yp, xf, "nearest");
-## plot (xf, yf, "r", xf, lin, "g", xf, spl, "b",
-##       xf, cub, "c", xf, near, "m", xp, yp, "r*");
-## legend ("original", "linear", "spline", "cubic", "nearest");
+## plot (xf,yf,"r", xf,near,"g", xf,lin,"b", xf,pch,"c", xf,spl,"m", 
+##       xp,yp,"r*");
+## legend ("original", "nearest", "linear", "pchip", "spline");
 ## @end group
 ## @end example
 ##
-## @seealso{interpft, interp2, interp3, interpn}
+## @seealso{pchip, spline, interpft, interp2, interp3, interpn}
 ## @end deftypefn
 
 ## Author: Paul Kienzle
@@ -130,17 +131,18 @@
       arg = varargin{i};
       if (ischar (arg))
         arg = tolower (arg);
-        if (strcmp ("extrap", arg))
-          extrap = "extrap";
-        elseif (strcmp ("pp", arg))
-          ispp = true;
-        elseif (strcmp (arg, "right") || strcmp (arg, "-right"))
-          rightcontinuous = true;
-        elseif (strcmp (arg, "left") || strcmp (arg, "-left"))
-          rightcontinuous = false;
-        else
-          method = arg;
-        endif
+        switch (arg)
+          case "extrap"
+            extrap = "extrap";
+          case "pp"
+            ispp = true;
+          case {"right", "-right"}
+            rightcontinuous = true;
+          case {"left", "-left"}
+            rightcontinuous = false;
+          otherwise
+            method = arg;
+        endswitch
       else
         if (firstnumeric)
           xi = arg;
@@ -177,7 +179,7 @@
 
   ## determine sizes
   if (nx < 2 || ny < 2)
-    error ("interp1: table too short");
+    error ("interp1: minimum of 2 points required in each dimension");
   endif
 
   ## check whether x is sorted; sort if not.
@@ -193,10 +195,8 @@
     else
       rightcontinuous = true;
     endif
-  endif
-
-  if ((rightcontinuous && (x(end) < x(1)))
-      || (! rightcontinuous && (x(end) > x(1))))
+  elseif ((rightcontinuous && (x(end) < x(1)))
+          || (! rightcontinuous && (x(end) > x(1))))
     ## Switch between left-continuous and right-continuous
     x = flipud (x);
     y = flipud (y);
@@ -215,7 +215,8 @@
           warning ("interp1: multiple discontinuities at the same X value");
         endif
       else
-        error ("interp1: discontinuities not supported for method '%s'", method);
+        error ("interp1: discontinuities not supported for method '%s'",
+                                                                   method);
       endif
     endif
   endif
@@ -238,6 +239,7 @@
       pp = mkpp ([x(1), x(1)+[0.5:(nx-1)]*dx, x(nx)],
                  shiftdim (y, 1), szy(2:end));
       pp.orient = "first";
+
       if (ispp)
         yi = pp;
       else
@@ -245,7 +247,6 @@
       endif
 
     case "linear"
-
       xx = x;
       nxx = nx;
       yy = y;
@@ -323,13 +324,13 @@
 
   endswitch
 
-  if (! ispp && ! ischar (extrap))
+  if (! ispp && isnumeric (extrap))
     ## determine which values are out of range and set them to extrap,
     ## unless extrap == "extrap".
     minx = min (x(1), x(nx));
     maxx = max (x(1), x(nx));
 
-    outliers = xi < minx | ! (xi <= maxx); # this even catches NaNs
+    outliers = xi < minx | ! (xi <= maxx);  # this even catches NaNs
     if (size_equal (outliers, yi))
       yi(outliers) = extrap;
       yi = reshape (yi, szx);
@@ -347,12 +348,13 @@
 %! clf;
 %! xf = 0:0.05:10;  yf = sin (2*pi*xf/5);
 %! xp = 0:10;       yp = sin (2*pi*xp/5);
-%! lin = interp1 (xp,yp,xf, "linear");
-%! spl = interp1 (xp,yp,xf, "spline");
-%! cub = interp1 (xp,yp,xf, "pchip");
-%! near= interp1 (xp,yp,xf, "nearest");
-%! plot (xf,yf,"r",xf,near,"g",xf,lin,"b",xf,cub,"c",xf,spl,"m",xp,yp,"r*");
-%! legend ("original", "nearest", "linear", "pchip", "spline");
+%! lin = interp1 (xp,yp,xf, 'linear');
+%! spl = interp1 (xp,yp,xf, 'spline');
+%! pch = interp1 (xp,yp,xf, 'pchip');
+%! near= interp1 (xp,yp,xf, 'nearest');
+%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*');
+%! legend ('original', 'nearest', 'linear', 'pchip', 'spline');
+%! title ('Interpolation of continuous function sin (x) w/various methods');
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
@@ -360,36 +362,50 @@
 %! clf;
 %! xf = 0:0.05:10;  yf = sin (2*pi*xf/5);
 %! xp = 0:10;       yp = sin (2*pi*xp/5);
-%! lin = interp1 (xp,yp,xf, "*linear");
-%! spl = interp1 (xp,yp,xf, "*spline");
-%! cub = interp1 (xp,yp,xf, "*cubic");
-%! near= interp1 (xp,yp,xf, "*nearest");
-%! plot (xf,yf,"r",xf,near,"g",xf,lin,"b",xf,cub,"c",xf,spl,"m",xp,yp,"r*");
-%! legend ("*original", "*nearest", "*linear", "*cubic", "*spline");
+%! lin = interp1 (xp,yp,xf, '*linear');
+%! spl = interp1 (xp,yp,xf, '*spline');
+%! pch = interp1 (xp,yp,xf, '*pchip');
+%! near= interp1 (xp,yp,xf, '*nearest');
+%! plot (xf,yf,'r',xf,near,'g',xf,lin,'b',xf,pch,'c',xf,spl,'m',xp,yp,'r*');
+%! legend ('*original', '*nearest', '*linear', '*pchip', '*spline');
+%! title ('Interpolation of continuous function sin (x) w/various *methods');
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
 %!demo
 %! clf;
+%! fstep = @(x) x > 1;
+%! xf = 0:0.05:2;  yf = fstep (xf);
+%! xp = linspace (0,2,10);  yp = fstep (xp);
+%! pch = interp1 (xp,yp,xf, 'pchip');
+%! spl = interp1 (xp,yp,xf, 'spline');
+%! plot (xf,yf,'r',xf,pch,'b',xf,spl,'m',xp,yp,'r*');
+%! title ({'Interpolation of step function with discontinuity at x==1', ...
+%!         'Note: "pchip" is shape-preserving, "spline" (continuous 1st, 2nd derivatives) is not'});
+%! legend ('original', 'pchip', 'spline');
+
+%!demo
+%! clf;
 %! t = 0 : 0.3 : pi; dt = t(2)-t(1);
 %! n = length (t); k = 100; dti = dt*n/k;
 %! ti = t(1) + [0 : k-1]*dti;
 %! y = sin (4*t + 0.3) .* cos (3*t - 0.1);
-%! ddyc = diff (diff (interp1 (t,y,ti, "cubic")) ./dti)./dti;
-%! ddys = diff (diff (interp1 (t,y,ti, "spline"))./dti)./dti;
-%! ddyp = diff (diff (interp1 (t,y,ti, "pchip")) ./dti)./dti;
-%! plot (ti(2:end-1),ddyc,'g+', ti(2:end-1),ddys,'b*', ti(2:end-1),ddyp,'c^');
-%! legend ("cubic", "spline", "pchip");
-%! title ("Second derivative of interpolated 'sin (4*t + 0.3) .* cos (3*t - 0.1)'");
+%! ddys = diff (diff (interp1 (t,y,ti, 'spline'))./dti)./dti;
+%! ddyp = diff (diff (interp1 (t,y,ti, 'pchip')) ./dti)./dti;
+%! ddyc = diff (diff (interp1 (t,y,ti, 'cubic')) ./dti)./dti;
+%! plot (ti(2:end-1),ddys,'b*', ti(2:end-1),ddyp,'c^', ti(2:end-1),ddyc,'g+');
+%! title ({'Second derivative of interpolated "sin (4*t + 0.3) .* cos (3*t - 0.1)"', ...
+%!         'Note: "spline" has continous 2nd derivative, others do not'});
+%! legend ('spline', 'pchip', 'cubic');
 
 %!demo
 %! clf;
 %! xf = 0:0.05:10;                yf = sin (2*pi*xf/5) - (xf >= 5);
 %! xp = [0:.5:4.5,4.99,5:.5:10];  yp = sin (2*pi*xp/5) - (xp >= 5);
-%! lin = interp1 (xp,yp,xf, "linear");
-%! near= interp1 (xp,yp,xf, "nearest");
-%! plot (xf,yf,"r", xf,near,"g", xf,lin,"b", xp,yp,"r*");
-%! legend ("original", "nearest", "linear");
+%! lin = interp1 (xp,yp,xf, 'linear');
+%! near= interp1 (xp,yp,xf, 'nearest');
+%! plot (xf,yf,'r', xf,near,'g', xf,lin,'b', xp,yp,'r*');
+%! legend ('original', 'nearest', 'linear');
 %! %--------------------------------------------------------
 %! % confirm that interpolated function matches the original
 
@@ -410,7 +426,7 @@
 %! %--------------------------------------------------------
 %! % red curve is left-continuous and blue is right-continuous at x = 2
 
-##FIXME: add test for n-d arguments here
+##FIXME: add test for N-d arguments here
 
 ## For each type of interpolated test, confirm that the interpolated
 ## value at the knots match the values at the knots.  Points away
@@ -638,12 +654,12 @@
 %% Test input validation
 %!error interp1 ()
 %!error interp1 (1,2,3,4,5,6,7)
-%!error <table too short> interp1 (1,1,1, "linear")
-%!error <table too short> interp1 (1,1,1, "*nearest")
-%!error <table too short> interp1 (1,1,1, "*linear")
+%!error <minimum of 2 points required> interp1 (1,1,1, "linear")
+%!error <minimum of 2 points required> interp1 (1,1,1, "*nearest")
+%!error <minimum of 2 points required> interp1 (1,1,1, "*linear")
 %!warning <multiple discontinuities> interp1 ([1 1 1 2], [1 2 3 4], 1);
 %!error <discontinuities not supported> interp1 ([1 1],[1 2],1, "pchip")
 %!error <discontinuities not supported> interp1 ([1 1],[1 2],1, "cubic")
 %!error <discontinuities not supported> interp1 ([1 1],[1 2],1, "spline")
-%!error <invalid method> interp1 (1:2,1:2,1, "bogus")
+%!error <invalid method 'bogus'> interp1 (1:2,1:2,1, "bogus")
 
--- a/scripts/general/interp2.m
+++ b/scripts/general/interp2.m
@@ -19,63 +19,63 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{zi} =} interp2 (@var{x}, @var{y}, @var{z}, @var{xi}, @var{yi})
-## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{Z}, @var{xi}, @var{yi})
-## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{Z}, @var{n})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z}, @var{xi}, @var{yi})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z}, @var{n})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@var{z})
 ## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method})
-## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrapval})
+## @deftypefnx {Function File} {@var{zi} =} interp2 (@dots{}, @var{method}, @var{extrap})
+##
+## Two-dimensional interpolation.
 ##
-## Two-dimensional interpolation.  @var{x}, @var{y} and @var{z} describe a
-## surface function.  If @var{x} and @var{y} are vectors their length
-## must correspondent to the size of @var{z}.  @var{x} and @var{y} must be
-## monotonic.  If they are matrices they must have the @code{meshgrid}
-## format.
-##
-## @table @code
-## @item interp2 (@var{x}, @var{y}, @var{Z}, @var{xi}, @var{yi}, @dots{})
-## Returns a matrix corresponding to the points described by the
-## matrices @var{xi}, @var{yi}.
+## Interpolate reference data @var{x}, @var{y}, @var{z} to determine @var{zi}
+## at the coordinates @var{xi}, @var{yi}.  The reference data @var{x}, @var{y}
+## can be matrices, as returned by @code{meshgrid}, in which case the sizes of
+## @var{x}, @var{y}, and @var{z} must be equal.  If @var{x}, @var{y} are
+## vectors describing a grid then @code{length (@var{x}) == columns (@var{z})}
+## and @code{length (@var{y}) == rows (@var{z})}.  In either case the input
+## data must be strictly monotonic.
 ##
-## If the last argument is a string, the interpolation method can
-## be specified.  The method can be @qcode{"linear"}, @qcode{"nearest"} or
-## @qcode{"cubic"}.  If it is omitted @qcode{"linear"} interpolation is
-## assumed.
+## If called without @var{x}, @var{y}, and just a single reference data matrix
+## @var{z}, the 2-D region
+## @code{@var{x} = 1:columns (@var{z}), @var{y} = 1:rows (@var{z})} is assumed.
+## This saves memory if the grid is regular and the distance between points is
+## not important.
 ##
-## @item interp2 (@var{z}, @var{xi}, @var{yi})
-## Assumes @code{@var{x} = 1:rows (@var{z})} and @code{@var{y} =
-## 1:columns (@var{z})}
+## If called with a single reference data matrix @var{z} and a refinement
+## value @var{n}, then perform interpolation over a grid where each original
+## interval has been recursively subdivided @var{n} times.  This results in
+## @code{2^@var{n}-1} additional points for every interval in the original
+## grid.  If @var{n} is omitted a value of 1 is used.  As an example, the
+## interval [0,1] with @code{@var{n}==2} results in a refined interval with
+## points at [0, 1/4, 1/2, 3/4, 1].
 ##
-## @item interp2 (@var{z}, @var{n})
-## Interleaves the matrix @var{z} n-times.  If @var{n} is omitted a value
-## of @code{@var{n} = 1} is assumed.
-## @end table
-##
-## The variable @var{method} defines the method to use for the
-## interpolation.  It can take one of the following values
+## The interpolation @var{method} is one of:
 ##
 ## @table @asis
 ## @item @qcode{"nearest"}
 ## Return the nearest neighbor.
 ##
-## @item @qcode{"linear"}
+## @item @qcode{"linear"} (default)
 ## Linear interpolation from nearest neighbors.
 ##
 ## @item @qcode{"pchip"}
-## Piecewise cubic Hermite interpolating polynomial.
+## Piecewise cubic Hermite interpolating polynomial---shape-preserving
+## interpolation with smooth first derivative.
 ##
 ## @item @qcode{"cubic"}
-## Cubic interpolation from four nearest neighbors.
+## Cubic interpolation (same as @qcode{"pchip"}).
 ##
 ## @item @qcode{"spline"}
 ## Cubic spline interpolation---smooth first and second derivatives
 ## throughout the curve.
 ## @end table
 ##
-## If a scalar value @var{extrapval} is defined as the final value, then
-## values outside the mesh as set to this value.  Note that in this case
-## @var{method} must be defined as well.  If @var{extrapval} is not
-## defined then NA is assumed.
-##
-## @seealso{interp1}
+## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values
+## beyond the endpoints using the current @var{method}.  If @var{extrap} is a
+## number, then replace values beyond the endpoints with that number.  When
+## unspecified, @var{extrap} defaults to @code{NA}.  Note that if @var{extrap}
+## is used, @var{method} must be specified as well.
+## @seealso{interp1, interp3, interpn, meshgrid}
 ## @end deftypefn
 
 ## Author:      Kai Habel <kai.habel@gmx.de>
@@ -94,10 +94,14 @@
 ##       "meshgridded") to be consistent with the help message
 ##       above and for compatibility.
 
+## FIXME: Need better input validation.
+##        E.g, interp2 (1,1,1) => A(I): index out of bounds
+
 function ZI = interp2 (varargin)
+
   Z = X = Y = XI = YI = n = [];
   method = "linear";
-  extrapval = NA;
+  extrap = NA;
 
   switch (nargin)
     case 1
@@ -120,36 +124,41 @@
       if (ischar (varargin{4}))
         [Z, XI, YI, method] = deal (varargin{:});
       else
-        [Z, n, method, extrapval] = deal (varargin{:});
+        [Z, n, method, extrap] = deal (varargin{:});
       endif
     case 5
       if (ischar (varargin{4}))
-        [Z, XI, YI, method, extrapval] = deal (varargin{:});
+        [Z, XI, YI, method, extrap] = deal (varargin{:});
       else
         [X, Y, Z, XI, YI] = deal (varargin{:});
       endif
     case 6
         [X, Y, Z, XI, YI, method] = deal (varargin{:});
     case 7
-        [X, Y, Z, XI, YI, method, extrapval] = deal (varargin{:});
+        [X, Y, Z, XI, YI, method, extrap] = deal (varargin{:});
     otherwise
       print_usage ();
   endswitch
 
-  ## Type checking.
-  if (!ismatrix (Z))
-    error ("interp2: Z must be a matrix");
+  ## Type checking
+  if (! (ismatrix (Z) && ndims (Z) == 2))
+    error ("interp2: Z must be a 2-D matrix");
   endif
-  if (!isempty (n) && !isscalar (n))
-    error ("interp2: N must be a scalar");
+  if (! isempty (n) && ! (isscalar (n) && n >= 0 && n == fix (n)))
+    error ("interp2: N must be an integer >= 0");
   endif
-  if (!ischar (method))
+  if (! ischar (method))
     error ("interp2: METHOD must be a string");
+  elseif (method(1) == "*")
+    warning ("interp2: ignoring unsupported '*' flag to METHOD");
+    method(1) = [];
   endif
-  if (ischar (extrapval) || strcmp (extrapval, "extrap"))
-    extrapval = [];
-  elseif (!isscalar (extrapval))
-    error ("interp2: EXTRAPVAL must be a scalar");
+  if (isnumeric (extrap) && isscalar (extrap))
+    ## Typical case
+  elseif (strcmp (extrap, "extrap"))
+    extrap = [];
+  else
+    error ('interp2: EXTRAP must be a numeric scalar or "extrap"');
   endif
 
   ## Define X, Y, XI, YI if needed
@@ -171,21 +180,32 @@
     error ("interp2: XI, YI must be numeric");
   endif
 
-
-  if (strcmp (method, "linear") || strcmp (method, "nearest") ...
-      || strcmp (method, "pchip"))
+  if (isvector (X) && isvector (Y))
+    X = X(:);  Y = Y(:);
+  elseif (size_equal (X, Y))
+    X = X(1,:).';  Y = Y(:,1);
+  else
+    error ("interp2: X and Y must be matrices of equal size");
+  endif
+  if (columns (Z) != length (X) || rows (Z) != length (Y))
+    error ("interp2: X and Y size must match the dimensions of Z");
+  endif
+  dx = diff (X);
+  if (all (dx < 0))
+    X = flipud (X);
+    Z = fliplr (Z); 
+  elseif (any (dx <= 0))
+    error ("interp2: X must be strictly monotonic");
+  endif
+  dy = diff (Y);
+  if (all (dy < 0))
+    Y = flipud (Y);
+    Z = flipud (Z); 
+  elseif (any (dy <= 0))
+    error ("interp2: Y must be strictly monotonic");
+  endif
 
-    ## If X and Y vectors produce a grid from them
-    if (isvector (X) && isvector (Y))
-      X = X(:); Y = Y(:);
-    elseif (size_equal (X, Y))
-      X = X(1,:)'; Y = Y(:,1);
-    else
-      error ("interp2: X and Y must be matrices of same size");
-    endif
-    if (columns (Z) != length (X) || rows (Z) != length (Y))
-      error ("interp2: X and Y size must match the dimensions of Z");
-    endif
+  if (any (strcmp (method, {"nearest", "linear", "pchip", "cubic"})))
 
     ## If Xi and Yi are vectors of different orientation build a grid
     if ((rows (XI) == 1 && columns (YI) == 1)
@@ -244,10 +264,11 @@
       idx = sub2ind (size (Z), yidx+jj, xidx+ii);
       ZI = Z(idx);
 
-    elseif (strcmp (method, "pchip"))
+    elseif (strcmp (method, "pchip") || strcmp (method, "cubic"))
 
       if (length (X) < 2 || length (Y) < 2)
-        error ("interp2: pchip2 requires at least 2 points in each dimension");
+        error ("interp2: %s requires at least 2 points in each dimension",
+               method);
       endif
 
       ## first order derivatives
@@ -303,121 +324,114 @@
 
     endif
 
-    if (! isempty (extrapval))
-      ## set points outside the table to 'extrapval'
-      if (X (1) < X (end))
-        if (Y (1) < Y (end))
-          ZI (XI < X(1,1) | XI > X(end) | YI < Y(1,1) | YI > Y(end)) = ...
-                  extrapval;
+    if (! isempty (extrap))
+      ## set points outside the table to 'extrap'
+      if (X(1) < X(end))
+        if (Y(1) < Y(end))
+          ZI(XI < X(1,1) | XI > X(end) | YI < Y(1,1) | YI > Y(end)) = ...
+                  extrap;
         else
-          ZI (XI < X(1) | XI > X(end) | YI < Y(end) | YI > Y(1)) = ...
-                  extrapval;
+          ZI(XI < X(1) | XI > X(end) | YI < Y(end) | YI > Y(1)) = ...
+                  extrap;
         endif
       else
-        if (Y (1) < Y (end))
-          ZI (XI < X(end) | XI > X(1) | YI < Y(1) | YI > Y(end)) = ...
-                  extrapval;
+        if (Y(1) < Y(end))
+          ZI(XI < X(end) | XI > X(1) | YI < Y(1) | YI > Y(end)) = ...
+                  extrap;
         else
-          ZI (XI < X(1,end) | XI > X(1) | YI < Y(end) | YI > Y(1)) = ...
-                  extrapval;
+          ZI(XI < X(1,end) | XI > X(1) | YI < Y(end) | YI > Y(1)) = ...
+                  extrap;
         endif
       endif
     endif
 
   else
 
-    ## Check dimensions of X and Y
-    if (isvector (X) && isvector (Y))
-      X = X(:).';
-      Y = Y(:);
-      if (!isequal ([length(Y), length(X)], size(Z)))
-        error ("interp2: X and Y size must match the dimensions of Z");
-      endif
-    elseif (!size_equal (X, Y))
-      error ("interp2: X and Y must be matrices of equal size");
-      if (! size_equal (X, Z))
-        error ("interp2: X and Y size must match the dimensions of Z");
-      endif
-    endif
-
     ## Check dimensions of XI and YI
     if (isvector (XI) && isvector (YI) && ! size_equal (XI, YI))
-      XI = XI(:).';
-      YI = YI(:);
-      [XI, YI] = meshgrid (XI, YI);
+      XI = XI(:).';  YI = YI(:);
     elseif (! size_equal (XI, YI))
       error ("interp2: XI and YI must be matrices of equal size");
     endif
 
+    ## FIXME: Previously used algorithm for cubic.
+    ##        This produced results within a few eps of "spline".
+    ##        Matlab compatibility requires "cubic" to be a C1 algorithm
+    ##        equivalent to "pchip" so this was commented out 2014/03/30.
+    ##        This can be removed completely in the future if no problems are
+    ##        encountered.
+    #{
     if (strcmp (method, "cubic"))
       if (isgriddata (XI) && isgriddata (YI'))
-        ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrapval);
+        ZI = bicubic (X, Y, Z, XI (1, :), YI (:, 1), extrap);
       elseif (isgriddata (X) && isgriddata (Y'))
         ## Allocate output
         ZI = zeros (size (X));
 
         ## Find inliers
-        inside = !(XI < X (1) | XI > X (end) | YI < Y (1) | YI > Y (end));
+        inside = !(XI < X(1) | XI > X(end) | YI < Y(1) | YI > Y(end));
 
         ## Scale XI and YI to match indices of Z
-        XI = (columns (Z) - 1) * (XI - X (1)) / (X (end) - X (1)) + 1;
-        YI = (rows (Z) - 1) * (YI - Y (1)) / (Y (end) - Y (1)) + 1;
+        XI = (columns (Z) - 1) * (XI - X(1)) / (X(end) - X(1)) + 1;
+        YI = (rows (Z) - 1) * (YI - Y(1)) / (Y(end) - Y(1)) + 1;
 
         ## Start the real work
         K = floor (XI);
         L = floor (YI);
 
         ## Coefficients
-        AY1  = bc ((YI - L + 1));
-        AX1  = bc ((XI - K + 1));
-        AY0  = bc ((YI - L + 0));
-        AX0  = bc ((XI - K + 0));
-        AY_1 = bc ((YI - L - 1));
-        AX_1 = bc ((XI - K - 1));
-        AY_2 = bc ((YI - L - 2));
-        AX_2 = bc ((XI - K - 2));
+        AY1  = bc (YI - L + 1);
+        AX1  = bc (XI - K + 1);
+        AY0  = bc (YI - L + 0);
+        AX0  = bc (XI - K + 0);
+        AY_1 = bc (YI - L - 1);
+        AX_1 = bc (XI - K - 1);
+        AY_2 = bc (YI - L - 2);
+        AX_2 = bc (XI - K - 2);
 
         ## Perform interpolation
         sz = size (Z);
-        ZI = AY_2 .* AX_2 .* Z (sym_sub2ind (sz, L+2, K+2)) ...
-           + AY_2 .* AX_1 .* Z (sym_sub2ind (sz, L+2, K+1)) ...
-           + AY_2 .* AX0  .* Z (sym_sub2ind (sz, L+2, K))   ...
-           + AY_2 .* AX1  .* Z (sym_sub2ind (sz, L+2, K-1)) ...
-           + AY_1 .* AX_2 .* Z (sym_sub2ind (sz, L+1, K+2)) ...
-           + AY_1 .* AX_1 .* Z (sym_sub2ind (sz, L+1, K+1)) ...
-           + AY_1 .* AX0  .* Z (sym_sub2ind (sz, L+1, K))   ...
-           + AY_1 .* AX1  .* Z (sym_sub2ind (sz, L+1, K-1)) ...
-           + AY0  .* AX_2 .* Z (sym_sub2ind (sz, L,   K+2)) ...
-           + AY0  .* AX_1 .* Z (sym_sub2ind (sz, L,   K+1)) ...
-           + AY0  .* AX0  .* Z (sym_sub2ind (sz, L,   K))   ...
-           + AY0  .* AX1  .* Z (sym_sub2ind (sz, L,   K-1)) ...
-           + AY1  .* AX_2 .* Z (sym_sub2ind (sz, L-1, K+2)) ...
-           + AY1  .* AX_1 .* Z (sym_sub2ind (sz, L-1, K+1)) ...
-           + AY1  .* AX0  .* Z (sym_sub2ind (sz, L-1, K))   ...
-           + AY1  .* AX1  .* Z (sym_sub2ind (sz, L-1, K-1));
-        ZI (!inside) = extrapval;
+        ZI = AY_2 .* AX_2 .* Z(sym_sub2ind (sz, L+2, K+2)) ...
+           + AY_2 .* AX_1 .* Z(sym_sub2ind (sz, L+2, K+1)) ...
+           + AY_2 .* AX0  .* Z(sym_sub2ind (sz, L+2, K))   ...
+           + AY_2 .* AX1  .* Z(sym_sub2ind (sz, L+2, K-1)) ...
+           + AY_1 .* AX_2 .* Z(sym_sub2ind (sz, L+1, K+2)) ...
+           + AY_1 .* AX_1 .* Z(sym_sub2ind (sz, L+1, K+1)) ...
+           + AY_1 .* AX0  .* Z(sym_sub2ind (sz, L+1, K))   ...
+           + AY_1 .* AX1  .* Z(sym_sub2ind (sz, L+1, K-1)) ...
+           + AY0  .* AX_2 .* Z(sym_sub2ind (sz, L,   K+2)) ...
+           + AY0  .* AX_1 .* Z(sym_sub2ind (sz, L,   K+1)) ...
+           + AY0  .* AX0  .* Z(sym_sub2ind (sz, L,   K))   ...
+           + AY0  .* AX1  .* Z(sym_sub2ind (sz, L,   K-1)) ...
+           + AY1  .* AX_2 .* Z(sym_sub2ind (sz, L-1, K+2)) ...
+           + AY1  .* AX_1 .* Z(sym_sub2ind (sz, L-1, K+1)) ...
+           + AY1  .* AX0  .* Z(sym_sub2ind (sz, L-1, K))   ...
+           + AY1  .* AX1  .* Z(sym_sub2ind (sz, L-1, K-1));
+        ZI (!inside) = extrap;
 
       else
         error ("interp2: input data must have 'meshgrid' format");
       endif
+    #}
 
-    elseif (strcmp (method, "spline"))
+    if (strcmp (method, "spline"))
       if (isgriddata (XI) && isgriddata (YI'))
-        ZI = __splinen__ ({Y(:,1).', X(1,:)}, Z, {YI(:,1), XI(1,:)}, extrapval,
-                        "spline");
+        ZI = __splinen__ ({Y, X}, Z, {YI(:,1), XI(1,:)}, extrap,
+                          "spline");
       else
-        error ("interp2: input data must have 'meshgrid' format");
+        error ("interp2: XI, YI must have uniform spacing ('meshgrid' format)");
       endif
     else
-      error ("interp2: interpolation METHOD not recognized");
+      error ("interp2: unrecognized interpolation method '%s'", method);
     endif
 
   endif
+
 endfunction
 
 function b = isgriddata (X)
   d1 = diff (X, 1, 1);
-  b = all (d1 (:) == 0);
+  b = all (d1(:) == 0);
 endfunction
 
 ## Compute the bicubic interpolation coefficients
@@ -432,16 +446,16 @@
 
 ## This version of sub2ind behaves as if the data was symmetrically padded
 function ind = sym_sub2ind (sz, Y, X)
-  Y (Y < 1) = 1 - Y (Y < 1);
-  while (any (Y (:) > 2 * sz (1)))
-    Y (Y > 2 * sz (1)) = round (Y (Y > 2 * sz (1)) / 2);
+  Y(Y < 1) = 1 - Y(Y < 1);
+  while (any (Y(:) > 2*sz(1)))
+    Y(Y > 2*sz(1)) = round (Y(Y > 2*sz(1)) / 2);
   endwhile
-  Y (Y > sz (1)) = 1 + 2 * sz (1) - Y (Y > sz (1));
-  X (X < 1) = 1 - X (X < 1);
-  while (any (X (:) > 2 * sz (2)))
-    X (X > 2 * sz (2)) = round (X (X > 2 * sz (2)) / 2);
+  Y(Y > sz(1)) = 1 + 2*sz(1) - Y(Y > sz(1));
+  X(X < 1) = 1 - X(X < 1);
+  while (any (X(:) > 2*sz(2)))
+    X(X > 2 * sz(2)) = round (X(X > 2*sz(2)) / 2);
   endwhile
-  X (X > sz (2)) = 1 + 2 * sz (2) - X (X > sz (2));
+  X(X > sz(2)) = 1 + 2*sz(2) - X(X > sz(2));
   ind = sub2ind (sz, Y, X);
 endfunction
 
@@ -455,7 +469,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "linear"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -466,7 +480,7 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "linear"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -477,7 +491,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "nearest"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -488,9 +502,10 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "nearest"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
-%!demo
+## 'pchip' commented out since it is the same as 'cubic'
+%!#demo
 %! clf;
 %! colormap ("default");
 %! A = [13,-1,12;5,4,3;1,6,2];
@@ -499,9 +514,10 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "pchip"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
-%!demo
+## 'pchip' commented out since it is the same as 'cubic'
+%!#demo
 %! clf;
 %! colormap ("default");
 %! [x,y,A] = peaks (10);
@@ -510,7 +526,7 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "pchip"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -521,7 +537,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "cubic"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -532,7 +548,7 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "cubic"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -543,7 +559,7 @@
 %! yi = linspace (min (y), max (y), 26)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "spline"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
 %!demo
 %! clf;
@@ -554,68 +570,75 @@
 %! yi = linspace (min (y), max (y), 41)';
 %! mesh (xi,yi,interp2 (x,y,A,xi,yi, "spline"));
 %! [x,y] = meshgrid (x,y);
-%! hold on; plot3 (x(:),y(:),A(:),"b*"); hold off;
+%! hold on; plot3 (x,y,A,"b*"); hold off;
 
-%!test % simple test
+%!test  # simple test
 %! x = [1,2,3];
 %! y = [4,5,6,7];
 %! [X, Y] = meshgrid (x, y);
-%! Orig = X.^2 + Y.^3;
+%! orig = X.^2 + Y.^3;
 %! xi = [1.2,2, 1.5];
 %! yi = [6.2, 4.0, 5.0]';
 %!
-%! Expected = ...
+%! expected = ...
 %!   [243,   245.4,  243.9;
 %!     65.6,  68,     66.5;
 %!    126.6, 129,    127.5];
-%! Result = interp2 (x,y,Orig, xi, yi);
+%! result = interp2 (x,y,orig, xi, yi);
 %!
-%! assert (Result, Expected, 1000*eps);
+%! assert (result, expected, 1000*eps);
 
-%!test % 2^n form
+%!test  # 2^n refinement form
 %! x = [1,2,3];
 %! y = [4,5,6,7];
 %! [X, Y] = meshgrid (x, y);
-%! Orig = X.^2 + Y.^3;
+%! orig = X.^2 + Y.^3;
 %! xi = [1:0.25:3];  yi = [4:0.25:7]';
-%! Expected = interp2 (x,y,Orig, xi, yi);
-%! Result = interp2 (Orig, 2);
+%! expected = interp2 (x,y,orig, xi, yi);
+%! result = interp2 (orig, 2);
 %!
-%! assert (Result, Expected, 10*eps);
+%! assert (result, expected, 10*eps);
 
-%!test % matrix slice
+%!test  # matrix slice
 %! A = eye (4);
 %! assert (interp2 (A,[1:4],[1:4]), [1,1,1,1]);
 
-%!test % non-gridded XI,YI
+%!test  # non-gridded XI,YI
 %! A = eye (4);
 %! assert (interp2 (A,[1,2;3,4],[1,3;2,4]), [1,0;0,1]);
 
-%!test % for values outside of boundaries
+%!test  # for values outside of boundaries
 %! x = [1,2,3];
 %! y = [4,5,6,7];
 %! [X, Y] = meshgrid (x,y);
-%! Orig = X.^2 + Y.^3;
+%! orig = X.^2 + Y.^3;
 %! xi = [0,4];
 %! yi = [3,8]';
-%! assert (interp2 (x,y,Orig, xi, yi), [NA,NA;NA,NA]);
-%! assert (interp2 (x,y,Orig, xi, yi,"linear", 0), [0,0;0,0]);
+%! assert (interp2 (x,y,orig, xi, yi), [NA,NA;NA,NA]);
+%! assert (interp2 (x,y,orig, xi, yi,"linear", 0), [0,0;0,0]);
+%! assert (interp2 (x,y,orig, xi, yi,"linear", "extrap"), [1,17;468,484]);
+%! assert (interp2 (x,y,orig, xi, yi,"nearest", "extrap"), orig([1,end],[1,end]));
 
-%!test % for values at boundaries
-%! A=[1,2;3,4];
-%! x=[0,1];
-%! y=[2,3]';
+%!test  # for values at boundaries
+%! A = [1,2;3,4];
+%! x = [0,1];
+%! y = [2,3]';
 %! assert (interp2 (x,y,A,x,y,"linear"), A);
 %! assert (interp2 (x,y,A,x,y,"nearest"), A);
 
-%!test % for Matlab-compatible rounding for 'nearest'
+%!test  # for Matlab-compatible rounding for 'nearest'
 %! X = meshgrid (1:4);
 %! assert (interp2 (X, 2.5, 2.5, "nearest"), 3);
 
+## re-order monotonically decreasing (bug #41838).
+%!assert (interp2 ([1 2 3], [3 2 1], magic (3), 2.5, 3), 3.5);
+%!assert (interp2 ([3 2 1], [1 2 3], magic (3), 1.5, 1), 3.5);
+
 %!shared z, zout, tol
 %! z = [1 3 5; 3 5 7; 5 7 9];
 %! zout = [1 2 3 4 5; 2 3 4 5 6; 3 4 5 6 7; 4 5 6 7 8; 5 6 7 8 9];
 %! tol = 2 * eps;
+%!
 %!assert (interp2 (z), zout, tol)
 %!assert (interp2 (z, "linear"), zout, tol)
 %!assert (interp2 (z, "pchip"), zout, tol)
@@ -630,3 +653,32 @@
 %!assert (interp2 (z, [2 3 1], [2 2 2], "cubic"), [5 7 3], 10 * tol)
 %!assert (interp2 (z, [2 3 1], [2 2 2], "spline"), [5 7 3], tol)
 
+%% Test input validation
+%!error <Z must be a 2-D matrix> interp2 ({1})
+%!error <Z must be a 2-D matrix> interp2 (ones (2,2,2))
+%!error <N must be an integer .= 0> interp2 (1, ones (2))
+%!error <N must be an integer .= 0> interp2 (1, -1)
+%!error <N must be an integer .= 0> interp2 (1, 1.5)
+%!error <METHOD must be a string> interp2 (1, 1, 1, 1, 1, 2)
+%!warning <ignoring unsupported '\*' flag> interp2 (rand (3,3), 1, "*linear");
+%!error <EXTRAP must be a numeric scalar or "extrap"> interp2 (1, 1, 1, 1, 1, 'linear', {1})
+%!error <EXTRAP must be a numeric scalar or "extrap"> interp2 (1, 1, 1, 1, 1, 'linear', ones (2,2))
+%!error <EXTRAP must be a numeric scalar or "extrap"> interp2 (1, 1, 1, 1, 1, 'linear', "abc")
+%!error <X, Y must be numeric matrices> interp2 ({1}, 1, 1, 1, 1)
+%!error <X, Y must be numeric matrices> interp2 (1, {1}, 1, 1, 1)
+%!error <XI, YI must be numeric> interp2 (1, 1, 1, {1}, 1)
+%!error <XI, YI must be numeric> interp2 (1, 1, 1, 1, {1})
+%!error <X and Y must be matrices of equal size> interp2 (ones(2,2), 1, 1, 1, 1)
+%!error <X and Y must be matrices of equal size> interp2 (ones(2,2), ones(2,3), 1, 1, 1)
+%!error <X and Y size must match the dimensions of Z> interp2 (1:3, 1:3, ones (3,2), 1, 1)
+%!error <X and Y size must match the dimensions of Z> interp2 (1:2, 1:2, ones (3,2), 1, 1)
+%!error <X must be strictly monotonic> interp2 ([1 0 2], 1:3, ones (3,3), 1, 1)
+%!error <Y must be strictly monotonic> interp2 (1:3, [1 0 2], ones (3,3), 1, 1)
+%!error <XI and YI must be matrices of equal size> interp2 (1, 1, 1, ones(2,2), 1)
+%!error <XI and YI must be matrices of equal size> interp2 (1, 1, 1, 1, ones(2,2))
+%!error <pchip requires at least 2 points> interp2 (1, 1, 1, 1, 1, "pchip")
+%!error <cubic requires at least 2 points> interp2 (1, 1, 1, 1, 1, "cubic")
+%!error <XI, YI must have uniform spacing> interp2 (1, 1, 1, [1 2 4], [1 2 3], "spline")
+%!error <XI, YI must have uniform spacing> interp2 (1, 1, 1, [1 2 3], [1 2 4], "spline")
+%!error <unrecognized interpolation method 'foobar'> interp2 (1, 1, 1, 1, 1, "foobar")
+
--- a/scripts/general/interp3.m
+++ b/scripts/general/interp3.m
@@ -19,52 +19,72 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{vi} =} interp3 (@var{x}, @var{y}, @var{z}, @var{v}, @var{xi}, @var{yi}, @var{zi})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{xi}, @var{yi}, @var{zi})
-## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{m})
+## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v}, @var{n})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@var{v})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@dots{}, @var{method})
 ## @deftypefnx {Function File} {@var{vi} =} interp3 (@dots{}, @var{method}, @var{extrapval})
 ##
-## Perform 3-dimensional interpolation.  Each element of the 3-dimensional
-## array @var{v} represents a value at a location given by the parameters
-## @var{x}, @var{y}, and @var{z}.  The parameters @var{x}, @var{x}, and
-## @var{z} are either 3-dimensional arrays of the same size as the array
-## @var{v} in the @qcode{"meshgrid"} format or vectors.  The parameters
-## @var{xi}, etc. respect a similar format to @var{x}, etc., and they
-## represent the points at which the array @var{vi} is interpolated.
+## Three-dimensional interpolation.
+##
+## Interpolate reference data @var{x}, @var{y}, @var{z}, @var{v} to determine
+## @var{vi} at the coordinates @var{xi}, @var{yi}, @var{zi}.  The reference
+## data @var{x}, @var{y}, @var{z} can be matrices, as returned by
+## @code{meshgrid}, in which case the sizes of
+## @var{x}, @var{y}, @var{z}, and @var{v} must be equal.  If @var{x}, @var{y},
+## @var{z} are vectors describing a cubic grid then
+## @code{length (@var{x}) == columns (@var{v})},
+## @code{length (@var{y}) == rows (@var{v})},
+## and @code{length (@var{z}) == size (@var{v}, 3)}.  In either case the input
+## data must be strictly monotonic.
 ##
-## If @var{x}, @var{y}, @var{z} are omitted, they are assumed to be
-## @code{x = 1 : size (@var{v}, 2)}, @code{y = 1 : size (@var{v}, 1)} and
-## @code{z = 1 : size (@var{v}, 3)}.  If @var{m} is specified, then
-## the interpolation adds a point half way between each of the interpolation
-## points.  This process is performed @var{m} times.  If only @var{v} is
-## specified, then @var{m} is assumed to be @code{1}.
+## If called without @var{x}, @var{y}, @var{z}, and just a single reference
+## data matrix @var{v}, the 3-D region
+## @code{@var{x} = 1:columns (@var{v}), @var{y} = 1:rows (@var{v}),
+## @var{z} = 1:size (@var{v}, 3)} is assumed.
+## This saves memory if the grid is regular and the distance between points is
+## not important.
 ##
-## Method is one of:
+## If called with a single reference data matrix @var{v} and a refinement
+## value @var{n}, then perform interpolation over a 3-D grid where each original
+## interval has been recursively subdivided @var{n} times.  This results in
+## @code{2^@var{n}-1} additional points for every interval in the original
+## grid.  If @var{n} is omitted a value of 1 is used.  As an example, the
+## interval [0,1] with @code{@var{n}==2} results in a refined interval with
+## points at [0, 1/4, 1/2, 3/4, 1].
+##
+## The interpolation @var{method} is one of:
 ##
 ## @table @asis
 ## @item @qcode{"nearest"}
 ## Return the nearest neighbor.
 ##
-## @item @qcode{"linear"}
+## @item @qcode{"linear"} (default)
 ## Linear interpolation from nearest neighbors.
 ##
+## @item @qcode{"pchip"}
+## Piecewise cubic Hermite interpolating polynomial---shape-preserving
+## interpolation with smooth first derivative (not implemented yet).
+##
 ## @item @qcode{"cubic"}
-## Cubic interpolation from four nearest neighbors (not implemented yet).
+## Cubic interpolation (same as @qcode{"pchip"} [not implemented yet]).
 ##
 ## @item @qcode{"spline"}
 ## Cubic spline interpolation---smooth first and second derivatives
 ## throughout the curve.
 ## @end table
 ##
-## The default method is @qcode{"linear"}.
-##
-## If @var{extrap} is the string @qcode{"extrap"}, then extrapolate values
-## beyond the endpoints.  If @var{extrap} is a number, replace values beyond
-## the endpoints with that number.  If @var{extrap} is missing, assume NA.
-## @seealso{interp1, interp2, spline, meshgrid}
+## If @var{extrapval} is a number, then replace values beyond the endpoints
+## with that number.  When unspecified, @var{extrapval} defaults to @code{NA}.
+## Note that if @var{extrapval} is used, @var{method} must be specified as well.
+## @seealso{interp1, interp2, interpn, meshgrid}
 ## @end deftypefn
 
+## FIXME: Need to validate N argument (maybe change interpn).
+## FIXME: Need to add support for 'pchip' method (maybe change interpn).
+## FIXME: Need to add support for "extrap" string value (maybe change interpn).
+
 function vi = interp3 (varargin)
+
   method = "linear";
   extrapval = NA;
   nargs = nargin;
@@ -75,112 +95,143 @@
 
   if (ischar (varargin{end}))
     method = varargin{end};
-    nargs = nargs - 1;
-  elseif (nargs > 1 && ischar (varargin{end - 1}))
+    nargs--;
+  elseif (nargs > 1 && ischar (varargin{end-1}))
+    ## FIXME: No support for "extrap" string
     if (! isnumeric (varargin{end}) || ! isscalar (varargin{end}))
-      error ("interp3: extrapal is expected to be a numeric scalar");
+      error ("interp3: EXTRAPVAL must be a numeric scalar");
     endif
     extrapval = varargin{end};
     method = varargin{end-1};
-    nargs = nargs - 2;
+    nargs -= 2;
   endif
 
-  if (nargs < 3 || (nargs == 4 && ! isvector (varargin{1})
-                    && nargs == (ndims (varargin{1}) + 1)))
+  if (method(1) == "*")
+    warning ("interp3: ignoring unsupported '*' flag to METHOD");
+    method(1) = [];
+  endif
+
+  if (nargs < 3)
+    ## Calling form interp3 (v) OR interp3 (v, n)
     v = varargin{1};
     if (ndims (v) != 3)
-      error ("interp3: expect 3-dimensional array of values");
+      error ("interp3: V must be a 3-D array of values");
     endif
-    x = varargin (2:nargs);
-    if (any (! cellfun (@isvector, x)))
-      for i = 2 : 3
-        if (! size_equal (x{1}, x{i}))
-          error ("interp3: dimensional mismatch");
-        endif
-        x{i} = permute (x{i}, [2, 1, 3]);
+    n = varargin(2:nargs);
+    v = permute (v, [2, 1, 3]);
+    vi = ipermute (interpn (v, n{:}, method, extrapval), [2, 1, 3]);
+
+  elseif (nargs == 4 && ! isvector (varargin{1}))
+    ## Calling form interp3 (v, xi, yi, zi)
+    v = varargin{1};
+    if (ndims (v) != 3)
+      error ("interp3: V must be a 3-D array of values");
+    endif
+    xi = varargin(2:4);
+    if (any (! cellfun (@isvector, xi)))
+      ## Meshgridded values rather than vectors
+      if (! size_equal (xi{:}))
+        error ("interp3: XI, YI, and ZI dimensions must be equal");
+      endif
+      for i = 1 : 3
+        xi{i} = permute (xi{i}, [2, 1, 3]);
       endfor
-      x{1} = permute (x{1}, [2, 1, 3]);
     endif
     v = permute (v, [2, 1, 3]);
-    vi = ipermute (interpn (v, x{:}, method, extrapval), [2, 1, 3]);
-  elseif (nargs == 7 && nargs == (2 * ndims (varargin{ceil (nargs / 2)})) + 1)
+    vi = ipermute (interpn (v, xi{:}, method, extrapval), [2, 1, 3]);
+
+  elseif (nargs == 7)
+    ## Calling form interp3 (x, y, z, v, xi, yi, zi)
     v = varargin{4};
     if (ndims (v) != 3)
-      error ("interp3: expect 3-dimensional array of values");
+      error ("interp3: V must be a 3-D array of values");
     endif
-    x = varargin (1:3);
+    x = varargin(1:3);
     if (any (! cellfun (@isvector, x)))
-      for i = 2 : 3
-        if (! size_equal (x{1}, x{i}) || ! size_equal (x{i}, v))
-          error ("interp3: dimensional mismatch");
-        endif
+      ## Meshgridded values rather than vectors
+      if (! size_equal (x{:}, v))
+        error ("interp3: X, Y, Z, and V dimensions must be equal");
+      endif
+      for i = 1 : 3
         x{i} = permute (x{i}, [2, 1, 3]);
       endfor
-      x{1} = permute (x{1}, [2, 1, 3]);
     endif
-    y = varargin (5:7);
-    if (any (! cellfun (@isvector, y)))
-      for i = 2 : 3
-        if (! size_equal (y{1}, y{i}))
-          error ("interp3: dimensional mismatch");
-        endif
-        y{i} = permute (y{i}, [2, 1, 3]);
+    xi = varargin(5:7);
+    if (any (! cellfun (@isvector, xi)))
+      ## Meshgridded values rather than vectors
+      if (! size_equal (xi{:}))
+        error ("interp3: XI, YI, and ZI dimensions must be equal");
+      endif
+      for i = 1 : 3
+        xi{i} = permute (xi{i}, [2, 1, 3]);
       endfor
-      y{1} = permute (y{1}, [2, 1, 3]);
     endif
     v = permute (v, [2, 1, 3]);
-    vi = ipermute (interpn (x{:}, v, y{:}, method, extrapval), [2, 1, 3]);
+    vi = ipermute (interpn (x{:}, v, xi{:}, method, extrapval), [2, 1, 3]);
+
   else
     error ("interp3: wrong number or incorrectly formatted input arguments");
   endif
+
 endfunction
 
 
-%!test
-%! x = y = z = -1:1; y = y + 2;
+%% FIXME: Need some demo blocks here to show off the function like interp2.m.
+
+%!test  # basic test
+%! x = y = z = -1:1;  y = y + 2;
 %! f = @(x,y,z) x.^2 - y - z.^2;
 %! [xx, yy, zz] = meshgrid (x, y, z);
 %! v = f (xx,yy,zz);
-%! xi = yi = zi = -1:0.5:1; yi = yi + 2.1;
+%! xi = yi = zi = -1:0.5:1;  yi = yi + 2.1;
 %! [xxi, yyi, zzi] = meshgrid (xi, yi, zi);
 %! vi = interp3 (x, y, z, v, xxi, yyi, zzi);
 %! [xxi, yyi, zzi] = ndgrid (yi, xi, zi);
 %! vi2 = interpn (y, x, z, v, xxi, yyi, zzi);
-%! tol = 10 * eps;
-%! assert (vi, vi2, tol);
+%! assert (vi, vi2, 10*eps);
 
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
+%!test  # meshgridded xi, yi, zi
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
 %! [xxi3, yyi3, zzi3] = meshgrid (xi, yi, zi);
 %! [xxi, yyi, zzi] = ndgrid (yi, xi, zi);
 %! vi = interp3 (x, y, z, v, xxi3, yyi3, zzi3, "nearest");
-%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi,"nearest");
+%! vi2 = interpn (y, x, z, v, xxi, yyi, zzi, "nearest");
 %! assert (vi, vi2);
 
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
-%! vi = interp3 (x, y, z, v, xi+1, yi, zi, "nearest",3);
-%! vi2 = interpn (y, x, z, v, yi, xi+1, zi,"nearest", 3);
-%! assert (vi, vi2);
-
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
+%!test  # vector xi, yi, zi
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
 %! vi = interp3 (x, y, z, v, xi, yi, zi, "nearest");
 %! vi2 = interpn (y, x, z, v, yi, xi, zi,"nearest");
 %! assert (vi, vi2);
 
-%!test
-%! x=z=1:2; y=1:3;xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
-%! vi = interp3 (v, xi, yi, zi, "nearest",3);
-%! vi2 = interpn (v, yi, xi, zi,"nearest", 3);
+%!test  # vector xi+1 with extrap value
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
+%! vi = interp3 (x, y, z, v, xi+1, yi, zi, "nearest", 3);
+%! vi2 = interpn (y, x, z, v, yi, xi+1, zi, "nearest", 3);
 %! assert (vi, vi2);
 
-%!test
-%! xi=zi=.6:1.6; yi=1; v=ones([3,2,2]);  v(:,2,1)=[7 ;5;4];  v(:,1,2)=[2 ;3;5];
+%!test  # input value matrix--no x,y,z
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
 %! vi = interp3 (v, xi, yi, zi, "nearest");
 %! vi2 = interpn (v, yi, xi, zi,"nearest");
 %! assert (vi, vi2);
 
+%!test  # input value matrix--no x,y,z, with extrap value
+%! x = z = 1:2;  y = 1:3;
+%! v = ones ([3,2,2]);  v(:,2,1) = [7;5;4];  v(:,1,2) = [2;3;5];
+%! xi = zi = .6:1.6;  yi = 1; 
+%! vi = interp3 (v, xi, yi, zi, "nearest", 3);
+%! vi2 = interpn (v, yi, xi, zi, "nearest", 3);
+%! assert (vi, vi2);
+
 %!shared z, zout, tol
 %! z = zeros (3, 3, 3);
 %! zout = zeros (5, 5, 5);
@@ -195,7 +246,21 @@
 %!                  5 6 7 8 9] + (n-1);
 %! end
 %! tol = 10 * eps;
+%!
 %!assert (interp3 (z), zout, tol)
 %!assert (interp3 (z, "linear"), zout, tol)
 %!assert (interp3 (z, "spline"), zout, tol)
 
+%% Test input validation
+%!error interp3 ()
+%!error interp3 ({1})
+%!error <EXTRAPVAL must be a numeric scalar> interp3 (1,2,3,4,1,2,3,"linear", {1})
+%!error <EXTRAPVAL must be a numeric scalar> interp3 (1,2,3,4,1,2,3,"linear", ones (2,2))
+%!warning <ignoring unsupported '\*' flag> interp3 (rand (3,3,3), 1, "*linear");
+%!error <V must be a 3-D array> interp3 (rand (2,2))
+%!error <V must be a 3-D array> interp3 (rand (2,2), 1,1,1)
+%!error <XI, YI, and ZI dimensions must be equal> interp3 (rand (2,2,2), 1,1, ones (2,2))
+%!error <V must be a 3-D array> interp3 (1:2, 1:2, 1:2, rand (2,2), 1,1,1)
+%!error <X, Y, Z, and V dimensions must be equal> interp3 (ones(1,2,2), ones(2,2,2), ones(2,2,2), rand (2,2,2), 1,1,1)
+%!error <XI, YI, and ZI dimensions must be equal> interp3 (1:2, 1:2, 1:2, rand (2,2,2), 1,1, ones (2,2))
+
--- a/scripts/general/interpn.m
+++ b/scripts/general/interpn.m
@@ -86,6 +86,11 @@
     nargs -= 2;
   endif
 
+  if (method(1) == "*")
+    warning ("interpn: ignoring unsupported '*' flag to METHOD");
+    method(1) = [];
+  endif
+
   if (nargs < 3)
     v = varargin{1};
     m = 1;
@@ -318,3 +323,6 @@
 %! assert (interpn (z, "linear"), zout, tol);
 %! assert (interpn (z, "spline"), zout, tol);
 
+%% Test input validation
+%!warning <ignoring unsupported '\*' flag> interpn (rand (3,3), 1, "*linear");
+
--- a/scripts/general/module.mk
+++ b/scripts/general/module.mk
@@ -7,7 +7,6 @@
 general_FCN_FILES = \
   general/accumarray.m \
   general/accumdim.m \
-  general/bicubic.m \
   general/bincoeff.m \
   general/bitcmp.m \
   general/bitget.m \
--- a/scripts/general/private/__isequal__.m
+++ b/scripts/general/private/__isequal__.m
@@ -95,9 +95,9 @@
     if (isstruct (x))
       ## Test the number of fields.
       fn_x = fieldnames (x);
-      l_fn_x = length (fn_x);
+      l_fn_x = numfields (x);
       fn_v = cellfun ("fieldnames", varargin, "uniformoutput", false);
-      t = all (l_fn_x == cellfun ("length", fn_v));
+      t = all (l_fn_x == cellfun ("numfields", varargin));
 
       ## Test that all the names are equal.
       idx = 0;
--- a/scripts/general/profshow.m
+++ b/scripts/general/profshow.m
@@ -1,4 +1,4 @@
-## Copyright (C) 2012-2013 Daniel Kraft
+## Copyright (C) 2012-2014 Daniel Kraft
 ##
 ## This file is part of Octave.
 ##
@@ -54,6 +54,7 @@
   ## times to an array, then sort this, and use the resulting index permutation
   ## to print out our table.
   times = -[ data.FunctionTable.TotalTime ];
+  totalTime = -sum (times);
 
   [~, p] = sort (times);
 
@@ -64,19 +65,21 @@
   for i = 1 : n
     nameLen = max (nameLen, length (data.FunctionTable(p(i)).FunctionName));
   endfor
-  headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%12s\n", nameLen);
-  rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%12d\n", nameLen);
+  headerFormat = sprintf ("%%4s %%%ds %%4s %%12s %%10s %%12s\n", nameLen);
+  rowFormat = sprintf ("%%4d %%%ds %%4s %%12.3f %%10.2f %%12d\n", nameLen);
 
-  printf (headerFormat, "#", "Function", "Attr", "Time (s)", "Calls");
-  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 2 * 13));
+  printf (headerFormat, ...
+          "#", "Function", "Attr", "Time (s)", "Time (%)", "Calls");
+  printf ("%s\n", repmat ("-", 1, nameLen + 2 * 5 + 11 + 2 * 13));
   for i = 1 : n
     row = data.FunctionTable(p(i));
+    timePercent = 100 * row.TotalTime / totalTime;
     attr = "";
     if (row.IsRecursive)
       attr = "R";
     endif
     printf (rowFormat, p(i), row.FunctionName, attr, ...
-            row.TotalTime, row.NumCalls);
+            row.TotalTime, timePercent, row.NumCalls);
   endfor
 
 endfunction
--- a/scripts/geometry/voronoi.m
+++ b/scripts/geometry/voronoi.m
@@ -74,14 +74,13 @@
   endif
 
   narg = 1;
+  hax = NaN;
   if (isscalar (varargin{1}) && ishandle (varargin{1}))
     hax = varargin{1};
-    if (! isaxes (harg))
-      error ("imagesc: HAX argument must be an axes object");
+    if (! isaxes (hax))
+      error ("voronoi: HAX argument must be an axes object");
     endif
     narg++;
-  elseif (nargout < 2)
-    hax = gca ();
   endif
 
   if (nargin < 1 + narg || nargin > 3 + narg)
@@ -108,6 +107,8 @@
 
   if (length (x) != length (y))
     error ("voronoi: X and Y must be vectors of the same length");
+  elseif (length (x) < 2)
+    error ("voronoi: minimum of 2 points needed");
   endif
 
   ## Add box to approximate rays to infinity. For Voronoi diagrams the
@@ -142,19 +143,35 @@
   edges = edges(:, [(edges(1, 1 :end - 1) != edges(1, 2 : end) | ...
                      edges(2, 1 :end - 1) != edges(2, 2 : end)), true]);
 
-  ## Eliminate the edges of the diagram representing the box
-  poutside = (1:rows (p)) ...
-      (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ...
-       p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta);
-  edgeoutside = ismember (edges(1, :), poutside) & ...
-                ismember (edges(2, :), poutside);
-  edges(:, edgeoutside) = [];
+  if (numel (x) > 2)
+    ## Eliminate the edges of the diagram representing the box
+    poutside = (1:rows (p)) ...
+        (p(:, 1) < xmin - xdelta | p(:, 1) > xmax + xdelta | ...
+         p(:, 2) < ymin - ydelta | p(:, 2) > ymax + ydelta);
+    edgeoutside = ismember (edges(1, :), poutside) & ...
+                  ismember (edges(2, :), poutside);
+    edges(:, edgeoutside) = [];
+  else
+    ## look for the edge between the two given points
+    for edge = edges(1:2,:) 
+      if (det ([[[1;1],p(edge,1:2)];1,x(1),y(1)])
+          * det ([[[1;1],p(edge,1:2)];1,x(2),y(2)]) < 0)
+        edges = edge;
+        break;
+      endif
+    endfor
+    ## Use larger plot limits to make it more likely single bisector is shown.
+    xdelta = ydelta = max (xdelta, ydelta);
+  endif
 
   ## Get points of the diagram
   Vvx = reshape (p(edges, 1), size (edges));
   Vvy = reshape (p(edges, 2), size (edges));
 
   if (nargout < 2)
+    if (isnan (hax))
+      hax = gca ();
+    endif
     h = plot (hax, Vvx, Vvy, linespec{:}, x, y, '+');
     lim = [xmin, xmax, ymin, ymax];
     axis (lim + 0.1 * [[-1, 1] * xdelta, [-1, 1] * ydelta]);
@@ -179,5 +196,18 @@
 %! assert (vx(2,:), zeros (1, columns (vx)), eps);
 %! assert (vy(2,:), zeros (1, columns (vy)), eps);
 
-%% FIXME: Need input validation tests
+%!testif HAVE_QHULL
+%! ## Special case of just 2 points
+%! x = [0 1];  y = [1 0];
+%! [vx, vy] = voronoi (x,y);
+%! assert (vx, [-0.7; 1.7], eps);
+%! assert (vy, [-0.7; 1.7], eps);
 
+%% Input validation tests
+%!error voronoi ()
+%!error voronoi (ones (3,1))
+%!error voronoi (ones (3,1), ones (3,1), "bogus1", "bogus2", "bogus3")
+%!error <HAX argument must be an axes object> voronoi (0, ones (3,1), ones (3,1))
+%!error <X and Y must be vectors of the same length> voronoi (ones (3,1), ones (4,1))
+%!error <minimum of 2 points needed> voronoi (2.5, 3.5)
+
--- a/scripts/help/__unimplemented__.m
+++ b/scripts/help/__unimplemented__.m
@@ -635,7 +635,6 @@
   "graymon",
   "griddedInterpolant",
   "gsvd",
-  "guidata",
   "guide",
   "guihandles",
   "handle",
@@ -649,8 +648,6 @@
   "hdfinfo",
   "hdfread",
   "hgexport",
-  "hgload",
-  "hgsave",
   "hgsetget",
   "hgtransform",
   "ichol",
@@ -671,10 +668,8 @@
   "interpstreamspeed",
   "iscom",
   "isinterface",
-  "isjava",
   "isocaps",
   "isstudent",
-  "javachk",
   "ldl",
   "libfunctions",
   "libfunctionsview",
@@ -684,7 +679,6 @@
   "light",
   "lightangle",
   "lighting",
-  "linkaxes",
   "linkdata",
   "listfonts",
   "loadlibrary",
--- a/scripts/help/help.m
+++ b/scripts/help/help.m
@@ -163,7 +163,7 @@
 
   found = false;
 
-  dlist = find_dir_in_path (name, "all");
+  dlist = dir_in_loadpath (name, "all");
 
   for i = 1:numel (dlist)
     fname = make_absolute_filename (fullfile (dlist{i}, "Contents.m"));
--- a/scripts/help/which.m
+++ b/scripts/help/which.m
@@ -28,9 +28,21 @@
   if (nargin > 0 && iscellstr (varargin))
     m = __which__ (varargin{:});
 
+    ## Check whether each name is a variable, variables take precedence over
+    ## functions in name resolution.
+    for i = 1:nargin
+      m(i).is_variable = evalin ("caller",
+                                 ["exist (\"" m(i).name "\", \"var\")"], false);
+      if (m(i).is_variable)
+        m(i).file = "variable";
+      endif
+    endfor
+
     if (nargout == 0)
       for i = 1:nargin
-        if (isempty (m(i).file))
+        if (m(i).is_variable)
+          printf ("'%s' is a variable\n", m(i).name);
+        elseif (isempty (m(i).file))
           if (! isempty (m(i).type))
             printf ("'%s' is a %s\n",
                     m(i).name, m(i).type);
@@ -64,3 +76,17 @@
 
 %!assert (which ("_NO_SUCH_NAME_"), "")
 
+%!test
+%! x = 3;
+%! str = which ("x");
+%! assert (str, "variable");
+
+%!test
+%! str = which ("amd");
+%! assert (str(end-6:end), "amd.oct");
+%! amd = 12;
+%! str = which ("amd");
+%! assert (str, "variable");
+%! clear amd;
+%! str = which ("amd");
+%! assert (str(end-6:end), "amd.oct");
--- a/scripts/image/image.m
+++ b/scripts/image/image.m
@@ -139,13 +139,6 @@
 
 function h = __img__ (hax, do_new, x, y, img, varargin)
 
-  ## FIXME: Hack for integer formats which use zero-based indexing
-  ##        Hack favors correctness of display over size of image in memory.
-  ##        True fix must be done in C++ code for renderer. 
-  if (ndims (img) == 2 && (isinteger (img) || islogical (img)))
-    img = single (img) + 1;
-  endif
-
   if (! isempty (img))
 
     if (isempty (x))
@@ -198,7 +191,7 @@
 
     endif  # ! isempty (img)
 
-    set (hax, "view", [0, 90], "ydir", "reverse", "layer", "bottom");
+    set (hax, "view", [0, 90], "ydir", "reverse", "layer", "top");
 
   endif  # do_new
 
--- a/scripts/image/imfinfo.m
+++ b/scripts/image/imfinfo.m
@@ -18,8 +18,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{info} =} imfinfo (@var{filename})
-## @deftypefnx {Function File} {@var{info} =} imfinfo (@var{filename}, @var{ext})
 ## @deftypefnx {Function File} {@var{info} =} imfinfo (@var{url})
+## @deftypefnx {Function File} {@var{info} =} imfinfo (@dots{}, @var{ext})
 ## Read image information from a file.
 ##
 ## @code{imfinfo} returns a structure containing information about the image
@@ -148,14 +148,32 @@
 
 ## Author: Soren Hauberg <hauberg@gmail.com>
 
-function info = imfinfo (varargin)
+function info = imfinfo (filename, varargin)
   if (nargin < 1 || nargin > 2)
     print_usage ();
-  elseif (! ischar (varargin{1}))
+  elseif (! ischar (filename))
     error ("imfinfo: FILENAME must be a string");
-  elseif (nargin > 1 && ! ischar (varargin{2}))
+  elseif (nargin > 1 && ! ischar (ext))
     error ("imfinfo: EXT must be a string");
   endif
-  info = imageIO (@__imfinfo__, "info", varargin, varargin{:});
+  info = imageIO ("imfinfo", @__imfinfo__, "info", filename, varargin{:});
 endfunction
 
+## This test is the same as the similar one in imread. imfinfo must check
+## if file exists before calling __imfinfo_. This test confirm this.
+%!testif HAVE_MAGICK
+%! fmt = fmt_ori = imformats ("jpg");
+%! fmt.info = @true;
+%! error_thrown = false;
+%! imformats ("update", "jpg", fmt);
+%! unwind_protect
+%!   try
+%!     imread ("I sure hope this file does not exist.jpg");
+%!   catch
+%!     error_thrown = true;
+%!   end_try_catch
+%! unwind_protect_cleanup
+%!   imformats ("update", "jpg", fmt_ori);
+%! end_unwind_protect
+%! assert (error_thrown, true);
+
--- a/scripts/image/imformats.m
+++ b/scripts/image/imformats.m
@@ -266,11 +266,10 @@
 endfunction
 
 function match = find_ext_idx (formats, ext)
-  ## FIXME: is matlab sensitive to file extensions?
   ## XXX: what should we do if there's more than one hit?
   ##      Should this function prevent the addition of
   ##      duplicated extensions?
-  match = cellfun (@(x) any (strcmp (x, ext)), {formats.ext});
+  match = cellfun (@(x) any (strcmpi (x, ext)), {formats.ext});
 endfunction
 
 function bool = isa_magick (coder, filename)
@@ -281,34 +280,68 @@
   end_try_catch
 endfunction
 
+## When imread or imfinfo are called, the file must exist or the
+## function defined by imformats will never be called.  Because
+## of this, we must create a file for the tests to work.
 
-## changing the function to read
+## changing the function that does the reading
 %!testif HAVE_MAGICK
-%! fmt = imformats ("jpg");
-%! fmt.read = @(x) size (x, 2);
-%! imformats ("update", "jpg", fmt);
-%! assert (imread ("this is 30 characters long.jpg"), 30);
+%! fname = [tmpnam() ".jpg"];
+%! def_fmt = imformats ();
+%! fid = fopen (fname, "w");
+%! unwind_protect
+%!   fmt = imformats ("jpg");
+%!   fmt.read = @numel;
+%!   imformats ("update", "jpg", fmt);
+%!   assert (imread (fname), numel (fname));
+%! unwind_protect_cleanup
+%!   fclose (fid);
+%!   unlink (fname);
+%!   imformats (def_fmt);
+%! end_unwind_protect
 
 ## adding a new format
 %!testif HAVE_MAGICK
-%! fmt = imformats ("jpg");
-%! fmt.ext = "junk";
-%! fmt.read = @(x) true();
-%! imformats ("add", fmt);
-%! assert (imread ("some file.junk"), true);
+%! fname = [tmpnam() ".new_fmt"];
+%! def_fmt = imformats ();
+%! fid = fopen (fname, "w");
+%! unwind_protect
+%!   fmt = imformats ("jpg"); # take jpg as template
+%!   fmt.ext = "new_fmt";
+%!   fmt.read = @() true ();
+%!   imformats ("add", fmt);
+%!   assert (imread (fname), true);
+%! unwind_protect_cleanup
+%!   fclose (fid);
+%!   unlink (fname);
+%!   imformats (def_fmt);
+%! end_unwind_protect
 
-## adding multiple formats in one way
+## adding multiple formats at the same time
 %!testif HAVE_MAGICK
-%! fmt = imformats ("jpg");
-%! fmt.ext = "junk1";
-%! fmt.read = @(x) true();
-%! fmt(2) = fmt(1);
-%! fmt(2).ext = "junk2";
-%! imformats ("add", fmt);
-%! assert (imread ("some file.junk1"), true);
-%! assert (imread ("some file.junk2"), true);
+%! fname1 = [tmpnam() ".new_fmt1"];
+%! fid1 = fopen (fname1, "w");
+%! fname2 = [tmpnam() ".new_fmt2"];
+%! fid2 = fopen (fname2, "w");
+%! def_fmt = imformats ();
+%! unwind_protect
+%!   fmt = imformats ("jpg"); # take jpg as template
+%!   fmt.ext = "new_fmt1";
+%!   fmt.read = @() true();
+%!   fmt(2) = fmt(1);
+%!   fmt(2).ext = "new_fmt2";
+%!   imformats ("add", fmt);
+%!   assert (imread (fname1), true);
+%!   assert (imread (fname2), true);
+%! unwind_protect_cleanup
+%!   fclose (fid1);
+%!   fclose (fid2);
+%!   unlink (fname1);
+%!   unlink (fname2);
+%!   imformats (def_fmt);
+%! end_unwind_protect
 
-## changing format
+## changing format and resetting back to default
 %!testif HAVE_MAGICK
 %! ori_fmt = mod_fmt = imformats ("jpg");
 %! mod_fmt.description = "Another description";
@@ -319,10 +352,15 @@
 %! new_fmt = imformats ("jpg");
 %! assert (new_fmt.description, ori_fmt.description);
 
-## FIXME: how to test for error together with testif?
-## update to an invalid format
-#%!testif HAVE_MAGICK
-#%! fmt = imformats ("jpg");
-#%! fmt = rmfield (fmt, "read");
-#%! error imformats ("update", "jpg", fmt);
+## updating to an invalid format should cause an error
+%!testif HAVE_MAGICK
+%! fmt = imformats ("jpg");
+%! fmt = rmfield (fmt, "read");
+%! error_thrown = false;
+%! try
+%!   imformats ("update", "jpg", fmt);
+%! catch
+%!   error_thrown = true;
+%! end_try_catch
+%! assert (error_thrown, true);
 
--- a/scripts/image/imread.m
+++ b/scripts/image/imread.m
@@ -23,16 +23,16 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {[@var{img}, @var{map}, @var{alpha}] =} imread (@var{filename})
-## @deftypefnx {Function File} {[@dots{}] =} imread (@var{filename}, @var{ext})
 ## @deftypefnx {Function File} {[@dots{}] =} imread (@var{url})
+## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{ext})
 ## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{idx})
 ## @deftypefnx {Function File} {[@dots{}] =} imread (@dots{}, @var{param1}, @var{val1}, @dots{})
 ## Read images from various file formats.
 ##
 ## Reads an image as a matrix from the file @var{filename}.  If there is
 ## no file @var{filename}, and @var{ext} was specified, it will look for
-## a file named @var{filename} and extension @var{ext}, i.e., a file named
-## @var{filename}.@var{ext}.
+## a file with the extension @var{ext}.  Finally, it will attempt to download
+## and read an image from @var{url}.
 ##
 ## The size and class of the output depends on the
 ## format of the image.  A color image is returned as an
@@ -75,7 +75,17 @@
 ## Controls the image region that is read.  Takes as value a cell array
 ## with two arrays of 3 elements @code{@{@var{rows} @var{cols}@}}.  The
 ## elements in the array are the start, increment and end pixel to be
-## read.  If the increment value is omitted, defaults to 1.
+## read.  If the increment value is omitted, defaults to 1.  For example,
+## the following are all equivalent:
+##
+## @example
+## @group
+## imread (filename, "PixelRegion", @{[200 600] [300 700]@});
+## imread (filename, "PixelRegion", @{[200 1 600] [300 1 700]@});
+## imread (filename)(200:600, 300:700);
+## @end group
+## @end example
+##
 ## @end table
 ##
 ## @seealso{imwrite, imfinfo, imformats}
@@ -88,23 +98,14 @@
 ## Author: Stefan van der Walt <stefan@sun.ac.za>
 ## Author: Andy Adler
 
-function [img, varargout] = imread (varargin)
+function [img, varargout] = imread (filename, varargin)
   if (nargin < 1)
     print_usage ();
-  elseif (! ischar (varargin{1}))
+  elseif (! ischar (filename))
     error ("imread: FILENAME must be a string");
   endif
-  ## In case the file format was specified as a separate argument we
-  ## do this. imageIO() will ignore the second part if filename on its
-  ## own is enough. And if the second argument was a parameter name instead
-  ## of an extension, it is still going to be passed to the next function
-  ## since we are passing the whole function input as well.
-  filename = {varargin{1}};
-  if (nargin > 1 && ischar (varargin {2}))
-    filename{2} = varargin{2};
-  endif
 
-  [img, varargout{1:nargout-1}] = imageIO (@__imread__, "read", filename, varargin{:});
+  [img, varargout{1:nargout-1}] = imageIO ("imread", @__imread__, "read", filename, varargin{:});
 endfunction
 
 
@@ -139,3 +140,66 @@
 %! assert (A(:,:,2), uint8 ([0, 255, 0; 255,  28, 255; 0, 255, 0]));
 %! assert (A(:,:,3), uint8 ([0, 255, 0; 255,  36, 255; 0, 255, 0]));
 
+%!function [r, cmap, a] = write_and_read (w, varargin)
+%!  filename = [tmpnam() ".tif"];
+%!  unwind_protect
+%!    imwrite (w, filename);
+%!    [r, cmap, a] = imread (filename, varargin{:});
+%!  unwind_protect_cleanup
+%!    unlink (filename);
+%!  end_unwind_protect
+%!endfunction
+
+## test PixelRegion option
+%!testif HAVE_MAGICK
+%! w = randi (255, 100, 100, "uint8");
+%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 70] [20 40]});
+%! assert (r, w(50:70, 20:40))
+%! [r, cmap, a] = write_and_read (w, "PixelRegion", {[50 2 70] [20 3 40]});
+%! assert (r, w(50:2:70, 20:3:40))
+
+## If a file does not exist, it's the job of imread to check the file
+## exists before sending it over to __imread__ or whatever function
+## is defined in imformats to handle that specific format.  This is the
+## same in imfinfo.  So in this test we replace one format in imformats
+## with something that will not give an error if the file is missing
+## and make sure we do get an error.
+%!testif HAVE_MAGICK
+%! fmt = fmt_ori = imformats ("jpg");
+%! fmt.read = @true;
+%! error_thrown = false;
+%! imformats ("update", "jpg", fmt);
+%! unwind_protect
+%!   try
+%!     imread ("I sure hope this file does not exist.jpg");
+%!   catch
+%!     error_thrown = true;
+%!   end_try_catch
+%! unwind_protect_cleanup
+%!   imformats ("update", "jpg", fmt_ori);
+%! end_unwind_protect
+%! assert (error_thrown, true);
+
+## make one of the formats read, return what it received as input to
+## confirm that the input parsing is working correcly
+%!testif HAVE_MAGICK
+%! fname = [tmpnam() ".jpg"];
+%! def_fmt = imformats ();
+%! fid = fopen (fname, "w");
+%! unwind_protect
+%!   fmt = imformats ("jpg");
+%!   fmt.read = @(varargin) varargin;
+%!   imformats ("update", "jpg", fmt);
+%!   assert (imread (fname), {fname});
+%!   assert (imread (fname, "jpg"), {fname});
+%!   assert (imread (fname(1:end-4), "jpg"), {fname});
+%!   extra_inputs = {"some", 89, i, {6 7 8}};
+%!   assert (imread (fname, extra_inputs{:}), {fname, extra_inputs{:}});
+%!   assert (imread (fname, "jpg", extra_inputs{:}), {fname, extra_inputs{:}});
+%!   assert (imread (fname(1:end-4), "jpg", extra_inputs{:}), {fname, extra_inputs{:}});
+%! unwind_protect_cleanup
+%!   fclose (fid);
+%!   unlink (fname);
+%!   imformats (def_fmt);
+%! end_unwind_protect
+
--- a/scripts/image/imshow.m
+++ b/scripts/image/imshow.m
@@ -45,6 +45,9 @@
 ## @table @asis
 ## @item @qcode{"displayrange"}
 ## @var{value1} is the display range as described above.
+##
+## @item @qcode{"colormap"}
+## @var{value1} is the colormap to use when displaying an indexed image.
 ## 
 ## @item @qcode{"xdata"}
 ## If @var{value1} is a two element vector, it must contain horizontal axis
@@ -75,7 +78,7 @@
   endif
 
   display_range = NA;
-  true_color = false;
+  truecolor = false;
   indexed = false;
   xdata = ydata = [];
 
@@ -98,9 +101,9 @@
     endif
   elseif (size (im, 3) == 3)
     if (ismember (class (im), {"uint8", "uint16", "double", "single"}))
-      true_color = true;
+      truecolor = true;
     else
-      error ("imshow: color image must be uint8, uint16, double, or single");
+      error ("imshow: TrueColor image must be uint8, uint16, double, or single");
     endif
   else
     error ("imshow: expecting MxN or MxNx3 matrix for image");
@@ -114,34 +117,47 @@
         display_range = arg;
       elseif (columns (arg) == 3)
         indexed = true;
-        colormap (arg);
+        if (iscolormap (arg))
+          colormap (arg);
+        else
+          error ("imshow: invalid colormap MAP");
+        endif
       elseif (! isempty (arg))
-        error ("imshow: argument number %d is invalid", narg+1);
+        error ("imshow: argument number %d is invalid", narg);
       endif
     elseif (ischar (arg))
       switch (tolower (arg))
-        case "displayrange";
+        case "colormap"
+          map = varargin{narg++};
+          if (iscolormap (map))
+            colormap (map);
+          else
+            error ("imshow: invalid colormap");
+          endif
+        case "displayrange"
           display_range = varargin{narg++};
-        case "xdata";
+        case "parent"
+          warning ("imshow: parent argument is not implemented");
+        case {"truesize", "initialmagnification"}
+          warning ("image: zoom argument ignored -- use GUI features");
+        case "xdata"
           xdata = varargin{narg++};
           if (! isvector (xdata))
             error ("imshow: xdata must be a vector")
           endif
           xdata = [xdata(1) xdata(end)];
-        case "ydata";
+        case "ydata"
           ydata = varargin{narg++};
           if (! isvector (ydata))
-            error ("imshow: expect a vector for ydata")
+            error ("imshow: ydata must be a vector")
           endif
           ydata = [ydata(1) ydata(end)];
-        case {"truesize", "initialmagnification"}
-          warning ("image: zoom argument ignored -- use GUI features");
         otherwise
           warning ("imshow: unrecognized property %s", arg);
           narg++;
       endswitch
     else
-      error ("imshow: argument number %d is invalid", narg+1);
+      error ("imshow: argument number %d is invalid", narg);
     endif
   endwhile
 
@@ -159,46 +175,44 @@
     switch (t)
       case {"double", "single", "logical"}
         display_range = [0, 1];
-      case {"int8", "int16", "int32", "uint8", "uint16", "uint32"}
+      case {"uint8", "uint16", "int16"}
         display_range = [intmin(t), intmax(t)];
       otherwise
         error ("imshow: invalid data type for image");
     endswitch
   endif
 
-  nans = isnan (im(:));
-  if (any (nans))
-    warning ("Octave:imshow-NaN",
-             "imshow: pixels with NaN or NA values are set to minimum pixel value");
-    im(nans) = display_range(1);
-  endif
-
-  ## This is for compatibility.
-  if (! (indexed || (true_color && isinteger (im))) || islogical (im))
-    im = double (im);
+  if (isfloat (im))
+    nans = isnan (im(:));
+    if (any (nans))
+      warning ("Octave:imshow-NaN",
+               "imshow: pixels with NaN or NA values are set to minimum pixel value");
+      im(nans) = display_range(1);
+    endif
   endif
 
+  ## FIXME: Commented out 2014/05/01.  imagesc and 'clim' will automatically
+  ## take care of displaying out-of-range data clamped to the limits.
+  ## Eventually, this can be deleted if no problems arise.
   ## Clamp the image to the range boundaries
-  if (! (true_color || indexed || islogical (im)))
-    low = display_range(1);
-    high = display_range(2);
-    im(im < low) = low;
-    im(im > high) = high;
-  endif
+  ##if (! (truecolor || indexed || islogical (im)))
+  ##  low = display_range(1);
+  ##  high = display_range(2);
+  ##  im(im < low) = low;
+  ##  im(im > high) = high;
+  ##endif
 
-  if (true_color || indexed)
-    tmp = image (xdata, ydata, im);
+  if (truecolor || indexed)
+    htmp = image (xdata, ydata, im);
   else
-    tmp = image (xdata, ydata, im);
-    set (tmp, "cdatamapping", "scaled");
-    ## The backend is responsible for scaling to clim if necessary.
+    htmp = imagesc (xdata, ydata, im, display_range);
     set (gca (), "clim", display_range);
   endif
-  set (gca (), "visible", "off", "ydir", "reverse");
+  set (gca (), "visible", "off", "view", [0, 90], "ydir", "reverse", "layer", "top");
   axis ("image");
 
   if (nargout > 0)
-    h = tmp;
+    h = htmp;
   endif
 
 endfunction
@@ -244,5 +258,22 @@
 %% Test input validation
 %!error imshow ()
 %!error <IM must be an image> imshow ({"cell"})
+%!error <TrueColor image must be uint8> imshow (ones (3,3,3, "uint32"))
+%!error <TrueColor image must be uint8> imshow (ones (3,3,3, "int16"))
 %!error <expecting MxN or MxNx3 matrix> imshow (ones (4,4,4))
 
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   fail ("imshow ([1,1], [2 0 0])", "invalid colormap MAP");
+%!   fail ("imshow ([1,1], [1 0 0 0])", "argument number 2 is invalid"); 
+%!   fail ('imshow ([1,1], "colormap", [2 0 0])', "invalid colormap"); 
+%!   fail ('imshow ([1,1], "xdata", ones (2,2))', "xdata must be a vector"); 
+%!   fail ('imshow ([1,1], "ydata", ones (2,2))', "ydata must be a vector"); 
+%!   fail ('imshow ([1,1], "foobar")', "warning", "unrecognized property foobar")
+%!   fail ("imshow ([1,1], {1})", "argument number 2 is invalid"); 
+%!   fail ("imshow ([1+i,1-i])", "warning", "only showing real part of complex image");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
--- a/scripts/image/imwrite.m
+++ b/scripts/image/imwrite.m
@@ -100,7 +100,7 @@
   fmt = imformats (ext);
   ## When there is no match, fmt will be a 1x1 structure with
   ## no fields, so we can't just use `isempty (fmt)'.
-  if (isempty (fieldnames (fmt)))
+  if (numfields (fmt) == 0)
     if (isempty (ext))
       error ("imwrite: no extension found for %s to identify the image format",
              filename);
--- a/scripts/image/ind2gray.m
+++ b/scripts/image/ind2gray.m
@@ -69,18 +69,19 @@
 
 %!shared i2g
 %! i2g = ind2gray (1:100, gray (100));
-%!assert (i2g, 0:1/99:1, eps);
-%!assert (gray2ind (i2g, 100), uint8 (0:99));
+%!
+%!assert (i2g, 0:1/99:1, eps)
+%!assert (gray2ind (i2g, 100), uint8 (0:99))
 
 %% Test input validation
 %!error ind2gray ()
 %!error ind2gray (1)
 %!error ind2gray (1,2,3)
-%!error <X must be an indexed image> ind2gray ({1}, jet (64))
+%!error <X must be an indexed image> ind2gray (ones (3,3,3), jet (64))
 %!error <X must be an indexed image> ind2gray (1+i, jet (64))
 %!error <X must be an indexed image> ind2gray (sparse (1), jet (64))
-%!error <X must be an indexed image> ind2gray (0, jet (64))
 %!error <X must be an indexed image> ind2gray (1.1, jet (64))
+%!error <X must be an indexed image> ind2gray ({1}, jet (64))
 %!error <MAP must be a valid colormap> ind2gray (1, {1})
 %!error <MAP must be a valid colormap> ind2gray (1, 1+i)
 %!error <MAP must be a valid colormap> ind2gray (1, ones (2,2,2))
@@ -88,3 +89,7 @@
 %!error <MAP must be a valid colormap> ind2gray (1, [-1])
 %!error <MAP must be a valid colormap> ind2gray (1, [2])
 
+%!warning <contains colors outside of colormap> ind2gray ([0 1 2], gray (5));
+%!warning <contains colors outside of colormap> ind2gray ([1 2 6], gray (5));
+%!warning <contains colors outside of colormap> ind2gray (uint8 ([1 2 5]), gray (5));
+
--- a/scripts/image/ind2rgb.m
+++ b/scripts/image/ind2rgb.m
@@ -82,23 +82,28 @@
 %! ## test basic usage with 1 and 3 outputs
 %! [rgb] = ind2rgb (img, map);
 %! [r, g, b] = ind2rgb (img, map);
-%!assert (ergb, rgb);
-%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3]));
+%!
+%!assert (ergb, rgb)
+%!assert (ergb, reshape ([r(:) g(:) b(:)], [size(img) 3]))
+%!test
 %! ## test correction for integers
-%! img = uint8 (img -1);
+%! img = uint8 (img - 1);
 %! [rgb] = ind2rgb (img, map);
-%!assert (ergb, rgb);
-%! ## check it fails when image is a float with an index value of 0
-%!fail ("[rgb] = ind2rgb (double(img), map)")
+%! assert (ergb, rgb);
+%!test
+%! ## Check that values below lower bound are mapped to first color value 
+%! rgb = ind2rgb ([-1 0 2], gray (64));
+%! assert (rgb(:,1:2,:), zeros (1,2,3));
+%! assert (rgb(:,3,:), 1/63 * ones (1,1,3));
 
 %% Test input validation
 %!error ind2rgb ()
 %!error ind2rgb (1,2,3)
-%!error <X must be an indexed image> ind2rgb ({1}, jet (64))
+%!error <X must be an indexed image> ind2rgb (ones (3,3,3), jet (64))
 %!error <X must be an indexed image> ind2rgb (1+i, jet (64))
 %!error <X must be an indexed image> ind2rgb (sparse (1), jet (64))
-%!error <X must be an indexed image> ind2rgb (0, jet (64))
 %!error <X must be an indexed image> ind2rgb (1.1, jet (64))
+%!error <X must be an indexed image> ind2rgb ({1}, jet (64))
 %!error <MAP must be a valid colormap> ind2rgb (1, {1})
 %!error <MAP must be a valid colormap> ind2rgb (1, 1+i)
 %!error <MAP must be a valid colormap> ind2rgb (1, ones (2,2,2))
@@ -106,3 +111,8 @@
 %!error <MAP must be a valid colormap> ind2rgb (1, [-1])
 %!error <MAP must be a valid colormap> ind2rgb (1, [2])
 
+%!warning <contains colors outside of colormap> ind2rgb ([-1 1], jet (64));
+%!warning <contains colors outside of colormap> ind2rgb ([0 1 2], gray (5));
+%!warning <contains colors outside of colormap> ind2rgb ([1 2 6], gray (5));
+%!warning <contains colors outside of colormap> ind2rgb (uint8 ([1 2 5]), gray (5));
+
--- a/scripts/image/private/__imfinfo__.m
+++ b/scripts/image/private/__imfinfo__.m
@@ -17,56 +17,22 @@
 ## along with Octave; see the file COPYING.  If not, see
 ## <http://www.gnu.org/licenses/>.
 
-## This function does al the work of imfinfo. It exists here as private
+## This function does all the work of imfinfo. It exists here as private
 ## function so that imfinfo can use other functions if imformats is
 ## configured to. It is also needed so that imformats can create a
 ## function handle for it.
 
 ## Author: Soren Hauberg <hauberg@gmail.com>
 
-function info = __imfinfo__ (filename, ext)
+function info = __imfinfo__ (filename)
 
-  if (nargin < 1 || nargin > 2)
+  if (nargin != 1)
     print_usage ("imfinfo");
+  elseif (! ischar (filename))
+    error ("imfinfo: FILENAME must be a string");
   endif
 
-  if (! ischar (filename))
-    error ("imfinfo: FILENAME must be a string");
-  elseif (nargin >= 2 && ! ischar (ext))
-    error ("imfinfo: EXT must be a string");
-  endif
-  filename = tilde_expand (filename);
-
-  delete_file = false;
-  unwind_protect
-
-    fn = file_in_path (IMAGE_PATH, filename);
-    if (isempty (fn))
-      ## We couldn't find the file so...
-      if (nargin >= 2)
-        ## try adding a possible file extesion
-        filename  = [filename "." ext];
-        fn        = file_in_path (IMAGE_PATH, filename);
-        if (isempty (fn))
-          error ("imfinfo: cannot find file %s", filename);
-        endif
-      else
-        ## try filename as an URL
-        [fn, status, msg] = urlwrite (filename, tmpnam ());
-        if (! status)
-          error ("imfinfo: cannot find or download %s: %s", filename, msg);
-        endif
-        delete_file = true;
-      endif
-    endif
-
-    info = __magick_finfo__ (fn);
-
-  unwind_protect_cleanup
-    if (delete_file)
-      unlink (fn);
-    endif
-  end_unwind_protect
+  info = __magick_finfo__ (filename);
 
 endfunction
 
--- a/scripts/image/private/__imread__.m
+++ b/scripts/image/private/__imread__.m
@@ -44,18 +44,6 @@
   ## keep track of the varargin offset we're looking at each moment
   offset    = 1;
 
-  filename  = tilde_expand (filename);
-  fn        = file_in_path (IMAGE_PATH, filename);
-  if (isempty (fn) && nargin >= offset + 1 && ischar (varargin{offset}))
-    ## if we can't find the file, check if the next input is the file extension
-    filename  = [filename "." varargin{offset}];
-    fn        = file_in_path (IMAGE_PATH, filename);
-    offset++;
-  endif
-  if (isempty (fn))
-    error ("imread: cannot find %s", filename);
-  endif
-
   ## It is possible for an file with multiple pages to have very different
   ## images on each page. Specifically, they may have different sizes. Because
   ## of this, we need to first find out the index of the images to read so
@@ -90,114 +78,62 @@
     endif
   endif
 
-  try
-    ## Use information from the first image to be read to set defaults.
-    if (ischar (options.index) && strcmpi (options.index, "all"))
-      info = __magick_ping__ (fn, 1);
-    else
-      info = __magick_ping__ (fn, options.index(1));
-    endif
+  ## Use information from the first image to be read to set defaults.
+  if (ischar (options.index) && strcmpi (options.index, "all"))
+    info = __magick_ping__ (filename, 1);
+  else
+    info = __magick_ping__ (filename, options.index(1));
+  endif
 
-    ## Set default for options.
-    options.region = {1:1:info.rows 1:1:info.columns};
+  ## Set default for options.
+  options.region = {1:1:info.rows 1:1:info.columns};
+
+  for idx = offset:2:(numel (varargin) - offset + 1)
+    switch (tolower (varargin{idx}))
 
-    for idx = offset:2:(numel (varargin) - offset + 1)
-      switch (tolower (varargin{idx}))
+      case {"frames", "index"}
+        ## Do nothing. This options were already processed before the loop.
 
-        case {"frames", "index"}
-          ## Do nothing. This options were already processed before the loop.
-
-        case "pixelregion",
-          options.region = varargin{idx+1};
-          if (! iscell (options.region) || numel (options.region) != 2)
-            error ("imread: value for %s must be a 2 element cell array",
+      case "pixelregion",
+        options.region = varargin{idx+1};
+        if (! iscell (options.region) || numel (options.region) != 2)
+          error ("imread: value for %s must be a 2 element cell array",
+                 varargin{idx});
+        endif
+        for reg_idx = 1:2
+          if (numel (options.region{reg_idx}) == 3)
+            ## do nothing
+          elseif (numel (options.region{reg_idx}) == 2)
+            options.region{reg_idx}(3) = options.region{reg_idx}(2);
+            options.region{reg_idx}(2) = 1;
+          else
+            error ("imread: range for %s must be a 2 or 3 element vector",
                    varargin{idx});
           endif
-          for reg_idx = 1:2
-            if (numel (options.region{reg_idx}) == 3)
-              ## do nothing
-            elseif (numel (options.region{reg_idx}) == 2)
-              options.region{reg_idx}(3) = options.region{reg_idx}(2);
-              options.region{reg_idx}(2) = 1;
-            else
-              error ("imread: range for %s must be a 2 or 3 element vector",
-                     varargin{idx});
-            endif
-            options.region{reg_idx} = floor (options.region{reg_idx}(1)): ...
-                                      floor (options.region{reg_idx}(2)): ...
-                                      floor (options.region{reg_idx}(3));
-          endfor
-          if (options.region{1}(end) > info.rows)
-            error ("imread: end ROWS for PixelRegions option is larger than image height");
-          elseif (options.region{2}(end) > info.columns)
-            error ("imread: end COLS for PixelRegions option is larger than image width");
-          endif
-
-        case "info",
-          ## We ignore this option. This parameter exists in Matlab to
-          ## speed up the reading of multipage TIFF by passing a structure
-          ## that contains information about the start on the file of each
-          ## page.  We can't control it through GraphicsMagic but at least
-          ## we allow to load multiple pages with one command.
-
-        otherwise
-          error ("imread: invalid PARAMETER `%s'", varargin{idx});
-
-      endswitch
-    endfor
-
-    [varargout{1:nargout}] = __magick_read__ (fn, options);
+          options.region{reg_idx} = floor (options.region{reg_idx}(1)): ...
+                                    floor (options.region{reg_idx}(2)): ...
+                                    floor (options.region{reg_idx}(3));
+        endfor
+        if (options.region{1}(end) > info.rows)
+          error ("imread: end ROWS for PixelRegions option is larger than image height");
+        elseif (options.region{2}(end) > info.columns)
+          error ("imread: end COLS for PixelRegions option is larger than image width");
+        endif
 
-  catch
-    ## If we can't read it with Magick, maybe the image is in Octave's
-    ## native image format.  This is from back before Octave had 'imread'
-    ## and 'imwrite'. Then we had the functions 'loadimage' and 'saveimage'.
-    ##
-    ## This "image format" seems to be any file that can be read with
-    ## load() and contains 2 variables.  The variable named "map" is a
-    ## colormap and must exist whether the image is indexed or not. The
-    ## other variable must be named "img" or "X" for a "normal" or
-    ## indexed image.
-    ##
-    ## FIXME: this has been deprecated for the next major release (3.8 or 4.0).
-    ##        If someone wants to revive this as yet another image format, a
-    ##        separate Octave package can be written for it, that register the
-    ##        format through imformats.
-
-    magick_error = lasterr ();
-
-    img_field = false;
-    x_field   = false;
-    map_field = false;
+      case "info",
+        ## We ignore this option. This parameter exists in Matlab to
+        ## speed up the reading of multipage TIFF by passing a structure
+        ## that contains information about the start on the file of each
+        ## page.  We can't control it through GraphicsMagic but at least
+        ## we allow to load multiple pages with one command.
 
-    try
-      vars = load (fn);
-      if (isstruct (vars))
-        img_field = isfield (vars, "img");
-        x_field   = isfield (vars, "X");
-        map_field = isfield (vars, "map");
-      endif
-    catch
-      error ("imread: invalid image file: %s", magick_error);
-    end_try_catch
+      otherwise
+        error ("imread: invalid PARAMETER `%s'", varargin{idx});
 
-    if (map_field && (img_field || x_field))
-      varargout{2} = vars.map;
-      if (img_field)
-        varargout{1} = vars.img;
-      else
-        varargout{1} = vars.X;
-      endif
-      persistent warned = false;
-      if (! warned)
-        warning ("Octave's native image format has been deprecated.");
-        warned = true;
-      endif
-    else
-      error ("imread: invalid Octave image file format");
-    endif
+    endswitch
+  endfor
 
-  end_try_catch
+  [varargout{1:nargout}] = __magick_read__ (filename, options);
 
 endfunction
 
@@ -205,10 +141,6 @@
 ## can be defined in two places, but only in one place can it also be the
 ## string "all"
 function bool = is_valid_index_option (arg)
-  ## is the index option
-  bool = false;
-  if (isvector (arg) && isnumeric (arg) && isreal (arg))
-    bool = true;
-  endif
+  bool = isvector (arg) && isnumeric (arg) && isreal (arg);
 endfunction
 
--- a/scripts/image/private/imageIO.m
+++ b/scripts/image/private/imageIO.m
@@ -16,54 +16,111 @@
 ## along with Octave; see the file COPYING.  If not, see
 ## <http://www.gnu.org/licenses/>.
 
-## This function simply connects imread and imfinfo() to the function
-## to be used based on their format. It does it by checking the file extension
-## of the file and redirecting to the appropriate function after checking
-## with imformats.
+## This function the image input functions imread() and imfinfo() to the
+## functions that will actually be used, based on their format.  See below
+## on the details on how it identifies the format, and to what it defaults.
+##
+## It will change the input arguments that were passed to imread() and
+## imfinfo().  It will change the filename to provide the absolute filepath
+## for the file, it will extract the possible format name from the rest of
+## the input arguments (in case there was one), and will give an error if
+## the file can't be found.
 ##
-## First argument is a function handle for the default imageIO function (what
-## to use if the file extension for the image file is not listed by imformats).
-## Second argument is the fieldname in the struct returned by imformats with a
-## function handle for the function to use. Third argument is a cell array, its
-## first element the filename, and the second, an optional file extension to
-## add to filename, if filename alone does not exist. All the others are the
-## original input arguments passed to the original imageIO function which will
-## be passed on to the destination function.
+## Usage:
 ##
-## No input checking whatsoever is performed. That should be performed by the
-## function calling it.
-
-function varargout = imageIO (core_func, fieldname, filename, varargin)
+## func      - Function name to use on error message.
+## core_func - Function handle for the default function to use if we can't
+##             find the format in imformats.
+## fieldname - Name of the field in the struct returned by imformats that
+##             has the function to use.
+## filename  - Most likely the first input argument from the function that
+##             called this. May be missing the file extension which can be
+##             on varargin.
+## varargin  - Followed by all the OTHER arguments passed to imread and
+##             imfinfo.
 
-  ## It should not be this function job to check if the file exists or not.
-  ## However, we need to know the file extension to use with imformats and
-  ## that means we need to know the actual filename that will be used which
-  ## is dependent on whether a file exists.
-  ##
-  ## If a file named filename{1} exists, then that's it, we will use that
-  ## wether it has an extension or not. If it does not exist and we have
-  ## something in filename{2}, then we will consider it the file extension.
-  ## Note the detail that if we find a file using filename{1} only, then we
-  ## should completely ignore filename{2}. It won't even be used by
-  ## imformats() at all, even if filename{1} has no extension to use with
-  ## imformats().
-  if (isscalar (filename) || ! isempty (file_in_path (IMAGE_PATH, filename{1})))
-    [~, ~, ext] = fileparts (filename{1});
-    if (! isempty (ext))
-      ## remove dot from extension
-      ext = ext(2:end);
-    endif
-  else
-    ext = filename{2};
+function varargout = imageIO (func, core_func, fieldname, filename, varargin)
+
+  ## First thing: figure out the filename and possibly download it.
+  ## The first attempt is to try the filename and see if it exists.  If it
+  ## does not, we try to add the next argument since the file extension can
+  ## be given as a separate argument.  If we still can't find the file, it
+  ## can be a URL.  Lastly, if we still didn't found a file, try adding the
+  ## extension to the URL
+
+  file_2_delete = false;  # will we have to remove the file in the end?
+  persistent abs_path = @(x) file_in_path (IMAGE_PATH, tilde_expand (x));
+
+  ## Filename was given with file extension
+  fn = abs_path (filename);
+  if (isempty (fn) && ! isempty (varargin))
+    ## Maybe if we add a file extension
+    fn = abs_path ([filename "." varargin{1}]);
   endif
 
-  fmt = imformats (ext);
-  ## When there is no match, fmt will be a 1x1 structure with no fields,
-  ## so we can't just use `isempty (fmt)'.
-  if (isempty (fieldnames (fmt)))
-    [varargout{1:nargout}] = core_func (varargin{:});
-  else
-    [varargout{1:nargout}] = fmt.(fieldname) (varargin{:});
+  ## Maybe we have an URL
+  if (isempty (fn))
+    file_2_delete = true; # mark file for deletion
+    [fn, ~] = urlwrite (filename, tmpnam ());
+    ## Maybe the URL is missing the file extension
+    if (isempty (fn) && ! isempty (varargin))
+      [fn, ~] = urlwrite ([filename "." varargin{1}], tmpnam ());
+    endif
+
+    if (isempty (fn))
+      error ("%s: unable to find file %s", func, filename);
+    endif
   endif
+
+  ## unwind_protect block because we may have a file to remove in the end
+  unwind_protect
+
+    ## When guessing the format to use, we first check if the second
+    ## argument is a format defined in imformats.  If so, we remove it
+    ## from the rest of arguments before passing them on.  If not, we
+    ## try to guess the format from the file extension.  Finally, if
+    ## we still don't know the format, we use the Octave core functions
+    ## which is the same for all formats.
+    foo = []; # the function we will use
+
+    ## We check if the call to imformats (ext) worked using
+    ## "numfields (fmt) > 0 because when it fails, the returned
+    ## struct is not considered empty.
+
+    ## try the second input argument
+    if (! isempty (varargin) && ischar (varargin{1}))
+      fmt = imformats (varargin{1});
+      if (numfields (fmt) > 0)
+        foo = fmt.(fieldname);
+        varargin(1) = []; # remove format name from arguments
+      endif
+    endif
+
+    ## try extension from file name
+    if (isempty (foo))
+      [~, ~, ext] = fileparts (fn);
+      if (! isempty (ext))
+        ## remove dot from extension
+        ext = ext(2:end);
+      endif
+      fmt = imformats (ext);
+      if (numfields (fmt) > 0)
+        foo = fmt.(fieldname);
+      endif
+    endif
+
+    ## use the core function
+    if (isempty (foo))
+      foo = core_func;
+    endif
+
+    [varargout{1:nargout}] = foo (fn, varargin{:});
+
+  unwind_protect_cleanup
+    if (file_2_delete)
+      unlink (fn);
+    endif
+  end_unwind_protect
+
 endfunction
 
--- a/scripts/image/private/ind2x.m
+++ b/scripts/image/private/ind2x.m
@@ -22,12 +22,13 @@
 function [x, map] = ind2x (caller, x, map)
 
   ## Check if X is an indexed image.
-  ## an indexed image is defined has having only 2D, and that's how Matlab
+  ## An indexed image is defined has having only 2D, and that's how Matlab
   ## behaves.  But we want to support ND images, so we will allow up to 4D
-  ## and check that the 3rd is a singleton
-  if (all (ndims (x) != [2 4]) || size (x, 3) != 1 || issparse (x) ||
-      (isfloat (x) && ! isindex (x)) ||
-      ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"})))
+  ## and check that the 3rd dimension is a singleton.
+  if (all (ndims (x) != [2 4]) || size (x, 3) != 1
+      || iscomplex (x) || issparse (x)
+      || (isfloat (x) && x != fix (x))
+      || ! any (strcmp (class (x), {"uint8", "uint16", "single", "double"})))
     error ("%s: X must be an indexed image", caller);
   endif
 
@@ -36,10 +37,20 @@
     error ("%s: MAP must be a valid colormap", caller);
   endif
 
-  ## Do we have enough colors in the color map?
-  ## there's an offset of 1 when the indexed image is an integer class so we fix
-  ## it now and convert it to float only if really necessary and even then only
-  ## to single precision since that is enough for both uint8 and uint16.
+  ## Any color indices below the lower bound of the color map are modified
+  ## to point to the first color in the map (see bug #41851).
+  if (isfloat (x))
+    invalid_idx = x < 1;
+    if (any (invalid_idx(:)))
+      warning (["Octave:" caller ":invalid-idx-img"],
+               [caller ": indexed image contains colors outside of colormap"]);
+      x(invalid_idx) = 1;
+    endif
+  endif
+
+  ## Switch to using 1-based indexing.
+  ## It is possible that an integer storage class may not have enough room
+  ## to make the switch, in which case we convert the data to single.
   maxidx = max (x(:));
   if (isinteger (x))
     if (maxidx == intmax (class (x)))
@@ -49,9 +60,12 @@
     maxidx += 1;
   endif
 
+  ## When there are more colors in the image, than there are in the map,
+  ## pad the colormap with the last color in the map for Matlab compatibility.
   num_colors = rows (map);
   if (num_colors < maxidx)
-    ## Pad with the last color in the map for Matlab compatibility
+    warning (["Octave:" caller ":invalid-idx-img"],
+             [caller ": indexed image contains colors outside of colormap"]);
     pad = repmat (map(end,:), maxidx - num_colors, 1);
     map(end+1:maxidx, :) = pad;
   endif
--- a/scripts/io/importdata.m
+++ b/scripts/io/importdata.m
@@ -146,8 +146,7 @@
     ## i.e., output = output.onlyFieldLeft
 
     ## Update the list of fields
-    fields = fieldnames (output);
-    if (numel (fields) == 1)
+    if (numfields (output) == 1)
       output = output.(fields{1});
     endif
   endif
@@ -210,11 +209,33 @@
 
   endwhile
 
-  fclose (fid);
+  if (row == -1)
+    ## No numeric data found => return file as cellstr array
+    ## 1. Read as char string
+    fseek (fid, 0, "bof");
+    output = fread (fid, Inf, "*char")';
+    fclose (fid);
+    ## 2. Find EOL type
+    idx = find (output(1:min (4096, length (output))) == "\n", 1) - 1;
+    if (isindex (idx) && output(idx) == "\r")
+      dlm = "\r\n";
+    else
+      dlm = "\n";
+    endif
+    ## 3. Split each line into a cell (column vector)
+    output = strsplit (output, dlm)';
+    ## 4. Remove last cell (for files with -proper- EOL before EOF)
+    if (isempty (output{end}))
+      output(end) = [];
+    endif
+    ## 5. Return after setting some output data
+    delimiter = "";
+    header_rows = numel (output);
+    return;
+  else
+    fclose (fid);
+  endif
 
-  if (row == -1)
-    error ("importdata: Unable to determine delimiter");
-  endif
   if (num_header_rows >= 0)
     header_rows = num_header_rows;
   endif
@@ -498,6 +519,30 @@
 %! assert (d, "\t");
 %! assert (h, 0);
 
+%!test
+%! ## Only text / no numeric data; \n as EOL
+%! fn  = tmpnam ();
+%! fid = fopen (fn, "w");
+%! fputs (fid, "aaaa 11\nbbbbb 22\nccccc 3\n");
+%! fclose (fid);
+%! [a, d, h] = importdata (fn);
+%! unlink (fn);
+%! assert (a, {"aaaa 11"; "bbbbb 22"; "ccccc 3"});
+%! assert (d, "");
+%! assert (h, 3);
+
+%!test
+%! ## Only text / no numeric data; \r\n as EOL; missing last EOL before EOF
+%! fn  = tmpnam ();
+%! fid = fopen (fn, "w");
+%! fputs (fid, "aaaa 11\r\nbbbbb 22\r\nccccc 3");
+%! fclose (fid);
+%! [a, d, h] = importdata (fn);
+%! unlink (fn);
+%! assert (a, {"aaaa 11"; "bbbbb 22"; "ccccc 3"});
+%! assert (d, "");
+%! assert (h, 3);
+
 %!error importdata ()
 %!error importdata (1,2,3,4)
 %!error <FNAME must be a string> importdata (1)
new file mode 100644
--- /dev/null
+++ b/scripts/java/javachk.m
@@ -0,0 +1,151 @@
+## Copyright (C) 2014 Philip Nienhuis
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} javachk (@var{feature})
+## @deftypefnx {Function File} {} javachk (@var{feature}, @var{component})
+## @deftypefnx {Function File} {@var{msg} =} javachk (@dots{})
+## Check for the presence of the Java @var{feature} in the current session
+## and print or return an error message if it is not.
+##
+## Possible features are:
+##
+## @table @asis
+## @item @qcode{"awt"}
+## Abstract Window Toolkit for GUIs.
+##
+## @item @qcode{"desktop"}
+## Interactive desktop is running.
+##
+## @item @qcode{"jvm"}
+## Java Virtual Machine.
+##
+## @item @qcode{"swing"}
+## Swing components for lightweight GUIs.
+## @end table
+##
+## If @var{feature} is supported and:
+##
+## @itemize @bullet
+## @item
+## No output argument is requested:
+##
+## Return an empty string
+##
+## @item
+## An output argument is requested:
+##
+## Return a struct with fields @qcode{"feature"} and @qcode{"identifier"}
+## both empty
+##
+## @end itemize
+##
+## If @var{feature} is not supported and:
+##
+## @itemize @bullet
+## @item
+## No output argument is requested:
+##
+## Emit an error message.
+##
+## @item
+## An output argument is requested:
+##
+## Return a struct with field @qcode{"feature"} set to @var{feature} and
+## field @qcode{"identifier"} set to @var{component}
+##
+## @end itemize
+##
+## The optional input @var{component} will be used in place of @var{feature}
+## in any error messages for greater specificity.
+##
+## @code{javachk} determines if specific Java features are available in an
+## Octave session.  This function is provided for scripts which may alter
+## their behavior based on the availability of Java.  The feature
+## @qcode{"desktop"} is never available as Octave has no Java-based desktop.
+## Other features may be available if Octave was compiled with the Java
+## Interface and Java is installed.
+##
+## @seealso{error, usejava}
+## @end deftypefn
+
+## Author: Philip Nienhuis <prnienhuis at users.sf.net>
+## Created: 2014-04-19
+
+function msg = javachk (feature, component="")
+
+  msg = "";
+  chk = false;
+  switch (feature)
+    ## For each feature, try methods() on a Java class of a feature
+    case "awt"
+      try
+        dum = methods ("java.awt.Frame");
+        chk = true;
+      end_try_catch
+    case "desktop"
+      ## Octave has no Java based GUI/desktop, leave chk = false
+    case "jvm"
+      try
+        dum = methods ("java.lang.Runtime");
+        chk = true;
+      end_try_catch
+    case "swing"
+      try
+        dum = methods ("javax.swing.Popup");
+        chk = true;
+      end_try_catch
+    otherwise
+      error ("javachk: unrecognized feature '%s', can be one of 'awt'|'desktop'|'jvm'|'swing'\n", feature);
+  endswitch
+
+  if (! chk)
+    ## Desired feature not present
+    if (nargout >= 1)
+      msg.message = sprintf ("javachk: %s is not supported", feature);
+      msg.identifier = component;
+    else
+      if (! isempty (component))
+        err = sprintf ("javachk: %s is not supported\n", component);
+      else
+        err = sprintf ("javachk: %s is not supported\n", feature);
+      endif
+      error (err);
+    endif
+  endif
+
+endfunction
+
+
+%!error <javachk: desktop is not supported> javachk ("desktop")
+%!error <Java DESKTOP is not supported> javachk ("desktop", "Java DESKTOP")
+%!test
+%! msg = javachk ("desktop");
+%! assert (msg.message, "javachk: desktop is not supported");
+%! assert (msg.identifier, "");
+%!test
+%! msg = javachk ("desktop", "Java DESKTOP");
+%! assert (msg.message, "javachk: desktop is not supported");
+%! assert (msg.identifier, "Java DESKTOP");
+
+%!testif HAVE_JAVA
+%! assert (javachk ("jvm"), "");
+
+%% Test input validation
+%!error <javachk: unrecognized feature 'foobar'> javachk ("foobar")
+
--- a/scripts/java/javamem.m
+++ b/scripts/java/javamem.m
@@ -36,7 +36,7 @@
 ## determined by the environment variable @w{@env{OCTAVE_JAVA_DIR}}.
 ## If unset, the directory where @file{javaaddpath.m} resides is used instead
 ## (typically
-## @file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}
+## @file{@w{@env{OCTAVE_HOME}}/share/octave/@w{@env{OCTAVE_VERSION}}/m/java/}).
 ##
 ## @file{java.opts} is a plain text file with one option per line.  The
 ## default initial memory size and default maximum memory size (which
--- a/scripts/java/module.mk
+++ b/scripts/java/module.mk
@@ -3,6 +3,7 @@
 java_FCN_FILES = \
   java/javaArray.m \
   java/javaaddpath.m \
+  java/javachk.m \
   java/javaclasspath.m \
   java/javamem.m \
   java/javarmpath.m \
--- a/scripts/java/usejava.m
+++ b/scripts/java/usejava.m
@@ -43,6 +43,7 @@
 ## @qcode{"desktop"} always returns @code{false} as Octave has no Java-based
 ## desktop.  Other features may be available if Octave was compiled with the
 ## Java Interface and Java is installed.
+## @seealso{javachk}
 ## @end deftypefn
 
 ## Author: Rik Wehbring
--- a/scripts/linear-algebra/issymmetric.m
+++ b/scripts/linear-algebra/issymmetric.m
@@ -40,7 +40,8 @@
   retval = isnumeric (x) && issquare (x);
   if (retval)
     if (tol == 0)
-      retval = all ((x == x.')(:));
+      ## Handle large sparse matrices as well as full ones
+      retval = nnz (x != x.') == 0;
     else
       norm_x = norm (x, inf);
       retval = norm_x == 0 || norm (x - x.', inf) / norm_x <= tol;
@@ -59,6 +60,7 @@
 %!assert (issymmetric ([1, 2i; 2i, 1]))
 %!assert (! (issymmetric ("t")))
 %!assert (! (issymmetric (["te"; "et"])))
+%!assert (issymmetric (speye (100000)))
 
 %!test
 %! s.a = 1;
--- a/scripts/miscellaneous/cast.m
+++ b/scripts/miscellaneous/cast.m
@@ -19,27 +19,41 @@
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} cast (@var{val}, @var{type})
 ## Convert @var{val} to data type @var{type}.
-## @seealso{int8, uint8, int16, uint16, int32, uint32, int64, uint64, double}
+##
+## The value @var{val} may be modified to fit within the range of the new type.
+##
+## Examples:
+##
+## @example
+## @group
+## cast (-5, "uint8")
+##    @result{} 0
+## cast (300, "int8")
+##    @result{} 127
+## @end group
+## @end example
+##
+## @seealso{typecast, int8, uint8, int16, uint16, int32, uint32, int64, uint64, double, single, logical, char}
 ## @end deftypefn
 
 ## Author: jwe
 
 function retval = cast (val, typ)
 
-  if (nargin == 2)
-    if (ischar (typ))
-      if (any (strcmp (typ, {"int8"; "uint8"; "int16"; "uint16";
-                             "int32"; "uint32"; "int64"; "uint64";
-                             "double"; "single"; "logical"; "char"})))
-        retval = feval (typ, val);
-      else
-        error ("cast: type name '%s' is not a built-in type", typ);
-      endif
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (ischar (typ))
+    if (any (strcmp (typ, {"int8"; "uint8"; "int16"; "uint16";
+                           "int32"; "uint32"; "int64"; "uint64";
+                           "double"; "single"; "logical"; "char"})))
+      retval = feval (typ, val);
     else
-      error ("cast: expecting TYPE name as second argument");
+      error ("cast: type name '%s' is not a built-in type", typ);
     endif
   else
-    print_usage ();
+    error ("cast: expecting TYPE name as second argument");
   endif
 
 endfunction
--- a/scripts/miscellaneous/edit.m
+++ b/scripts/miscellaneous/edit.m
@@ -330,7 +330,7 @@
 
     ## If editing a new file, prompt for creation if gui is running
     if (isguirunning ())
-      if (! __octave_link_edit_file__ (file,"prompt"));
+      if (! __octave_link_edit_file__ (file, "prompt"));
         return;
       endif
     endif
@@ -344,8 +344,12 @@
     ext = file(idx+1:end);
     if (! any (strcmp (ext, {"cc", "m"})))
       ## Some unknown file.  Create and open it or just open it.
+      ## Add .m file extension per default
+      fileandpath = [fileandpath ".m"];
       if (isguirunning ())
         ## Write the initial file (if there is anything to write)
+        ## Give user the opportunity to change the file extension
+        fileandpath = uiputfile (fileandpath);
         fid = fopen (fileandpath, "wt");
         if (fid < 0)
           error ("edit: could not create %s", fileandpath);
--- a/scripts/miscellaneous/fact.m
+++ b/scripts/miscellaneous/fact.m
@@ -115,7 +115,7 @@
        "When Richard Stallman executes ps -e, you show up.";
        "When Richard Stallman gets angry he doesn't swear; he recurses.";
        "On Richard Stallman's computer the bootloader is contained in his .emacs.";
-       "Richard Satallman can make any operating system free, free from drivers.";
+       "Richard Stallman can make any operating system free, free from drivers.";
        "Richard Stallman programmed Chuck Norris.";
        "Behind Richard Stallman's beard there is another fist, to code faster.";
        "Richard Stallman won a Sudoku that started with only one number in each line.";
--- a/scripts/miscellaneous/genvarname.m
+++ b/scripts/miscellaneous/genvarname.m
@@ -80,7 +80,7 @@
 ## Since variable names may only contain letters, digits and underscores,
 ## genvarname replaces any sequence of disallowed characters with
 ## an underscore.  Also, variables may not begin with a digit; in this
-## case an underscore is added before the variable name.
+## case an x is added before the variable name.
 ##
 ## Variable names beginning and ending with two underscores @qcode{"__"} are
 ## valid but they are used internally by octave and should generally be
@@ -131,22 +131,20 @@
     str{i}(! ismember (str{i}, validchars)) = "_";
     ## do not use keywords
     if (iskeyword (str{i}))
-      str{i} = ["_" str{i}];
-    endif
-    ## double underscores at the beginning and end are reserved variables
-    underscores = (str{i} == "_");
-    if (any (underscores))
-      firstnon = find (!underscores, 1);
-      lastnon = find (!underscores, 1, "last");
-      str{i}([1:firstnon-2, lastnon+2:end]) = [];
+      firstcharacter = toupper (str{i}(1));
+      str{i} = ["x", firstcharacter, str{i}(2:end)];
     endif
     ## The variable cannot be empty
     if (isempty (str{i}))
       str{i} = "x";
     endif
+    ## Leading underscores are not Matlab compatible
+    if (str{i}(1) == "_")
+      str{i} = ["x", str{i}];
+    endif
     ## it cannot start with a number
     if (ismember (str{i}(1), "0":"9"))
-      str{i} = ["_" str{i}];
+      str{i} = ["x", str{i}];
     endif
 
     ## make sure that the variable is unique relative to other variables
@@ -199,12 +197,12 @@
 ## more than one repetition not in order
 %!assert (genvarname ({"a" "b" "a" "b" "a"}), {"a" "b" "a1" "b1" "a2"})
 ## Variable name munging
-%!assert (genvarname ("__x__"), "_x_")
-%!assert (genvarname ("123456789"), "_123456789")
-%!assert (genvarname ("_$1__"), "_1_")
-%!assert (genvarname ("__foo__", "_foo_"), "_foo_1")
-%!assert (genvarname ("1million_and1", "_1million_and1"), "_1million_and1_1")
+%!assert (genvarname ("__x__"), "x__x__")
+%!assert (genvarname ("123456789"), "x123456789")
+%!assert (genvarname ("_$1__"), "x__1__")
+%!assert (genvarname ("__foo__", "x__foo__"), "x__foo__1")
+%!assert (genvarname ("1million_and1", "x1million_and1"), "x1million_and1_1")
 %!assert (genvarname ({"", "", ""}), {"x", "x1", "x2"})
-%!assert (genvarname ("if"), "_if")
-%!assert (genvarname ({"if", "if", "if"}), {"_if", "_if1", "_if2"})
+%!assert (genvarname ("if"), "xIf")
+%!assert (genvarname ({"if", "if", "if"}), {"xIf", "xIf1", "xIf2"})
 
--- a/scripts/miscellaneous/gzip.m
+++ b/scripts/miscellaneous/gzip.m
@@ -58,10 +58,17 @@
 %!     error ("gzipped file cannot be found!");
 %!   endif
 %!   gunzip (entry);
-%!   if (system (sprintf ("diff %s %s%c%s%s", filename, dirname, filesep,
-%!                                            basename, extension)))
+%!   fid = fopen (filename, "rb");
+%!   assert (fid >= 0);
+%!   orig_data = fread (fid);
+%!   fclose (fid);
+%!   fid = fopen ([dirname filesep basename extension], "rb");
+%!   assert (fid >= 0);
+%!   new_data = fread (fid);
+%!   fclose (fid);
+%!   if (orig_data != new_data)
 %!     error ("unzipped file not equal to original file!");
-%!   end
+%!   endif
 %! unwind_protect_cleanup
 %!   delete (filename);
 %!   delete ([dirname, filesep, basename, extension]);
--- a/scripts/miscellaneous/inputname.m
+++ b/scripts/miscellaneous/inputname.m
@@ -57,3 +57,8 @@
 %!assert (inputname (1), "hello")
 %!assert (inputname (2), "worldly")
 
+%!function r = foo (x, y)
+%!  r = inputname (2);
+%!endfunction
+%!assert (foo (pi, e), "e");
+%!assert (feval (@foo, pi, e), "e");
--- a/scripts/miscellaneous/ls.m
+++ b/scripts/miscellaneous/ls.m
@@ -61,14 +61,14 @@
   if (nargin > 0)
     args = tilde_expand (varargin);
     if (ispc () && ! isunix ())
+      idx = ! strncmp (args, '/', 1);
+      ## Enclose paths, potentially having spaces, in double quotes:
+      args(idx) = strcat ('"', args(idx), '"');    
       ## shell (cmd.exe) on MinGW uses '^' as escape character
-      args = regexprep (args, '([^\w.*? -])', '^$1');
-      ## Strip UNIX directory character which looks like an option to dir cmd.
-      if (args{end}(end) == '/')
-        args{end}(end) = "";
-      endif
+      args = regexprep (args, '([^\w.*?])', '^$1');
     else
-      args = regexprep (args, '([^\w.*? -])', '\\$1');
+      ## Escape any special characters in filename
+      args = regexprep (args, '([^\w.*?-[]])', '\\$1');
     endif
     args = sprintf ("%s ", args{:});
   else
--- a/scripts/miscellaneous/mex.m
+++ b/scripts/miscellaneous/mex.m
@@ -23,8 +23,16 @@
 ## @seealso{mkoctfile}
 ## @end deftypefn
 
-function mex (varargin)
-  args = {"--mex", varargin{:}};
-  mkoctfile (args{:});
+function retval = mex (varargin)
+
+  [output, status] = mkoctfile ("--mex", varargin{:});
+
+  if (! isempty (output))
+    disp (output);
+  endif
+  if (nargout > 0)
+    retval = status;
+  endif
+
 endfunction
 
--- a/scripts/miscellaneous/run.m
+++ b/scripts/miscellaneous/run.m
@@ -31,9 +31,10 @@
 ## falling back to the script name without an extension.
 ##
 ## Implementation Note: If @var{script} includes a path component, then
-## @code{run} first changes the directory to the directory where @var{script}
-## is found.  @code{run} then executes the script, and returns to the original
-## directory. 
+## @code{run} first changes the working directory to the directory where
+## @var{script} is found.  Next, the script is executed.  Finally, @code{run}
+## returns to the original working directory unless @code{script} has
+## specifically changed directories.
 ## @seealso{path, addpath, source}
 ## @end deftypefn
 
@@ -65,7 +66,9 @@
         evalin ("caller", sprintf ('source ("%s%s");', f, ext),
                 "rethrow (lasterror ())");
       unwind_protect_cleanup
-        cd (wd);
+        if (strcmp (d, pwd ()))
+          cd (wd);
+        endif
       end_unwind_protect
     else
       error ("run: the path %s doesn't exist", d);
--- a/scripts/miscellaneous/what.m
+++ b/scripts/miscellaneous/what.m
@@ -37,7 +37,7 @@
       if (d(end) == '/' || d(end) == '\')
         d(end) = [];
       endif
-      dtmp = find_dir_in_path (d);
+      dtmp = dir_in_loadpath (d);
       if (isempty (dtmp))
         error ("what: could not find the directory %s", d);
       endif
@@ -45,7 +45,7 @@
     d = dtmp;
   endif
 
-  files = dir (d);
+  files = readdir (d);
   w.path = d;
   w.m = cell (0, 1);
   w.mex = cell (0, 1);
@@ -56,7 +56,7 @@
   w.classes = cell (0, 1);
 
   for i = 1 : length (files)
-    n = files(i).name;
+    n = files{i};
     ## Ignore . and ..
     if (strcmp (n, ".") || strcmp (n, ".."))
       continue;
@@ -71,7 +71,7 @@
         w.mex{end+1} = n;
       elseif (strcmp (e, ".mat"))
         w.mat{end+1} = n;
-      elseif (strcmp (n(1), "@"))
+      elseif (strcmp (n(1), "@") && isdir (n))
         w.classes{end+1} = n;
       endif
     endif
--- a/scripts/optimization/fminbnd.m
+++ b/scripts/optimization/fminbnd.m
@@ -170,7 +170,7 @@
 
     ## update  a, b, v, w, and x
 
-    if (fu <= fval)
+    if (fu < fval)
       if (u < x)
         b = x;
       else
@@ -283,4 +283,5 @@
 %!assert (fminbnd (@(x) (x - 1e-3)^4, -1, 1, opt0), 1e-3, 10e-3*sqrt (eps))
 %!assert (fminbnd (@(x) abs (x-1e7), 0, 1e10, opt0), 1e7, 10e7*sqrt (eps))
 %!assert (fminbnd (@(x) x^2 + sin (2*pi*x), 0.4, 1, opt0), fzero (@(x) 2*x + 2*pi*cos (2*pi*x), [0.4, 1], opt0), sqrt (eps))
+%!assert (fminbnd (@(x) x > 0.3, 0, 1) < 0.3) 
 
--- a/scripts/optimization/fzero.m
+++ b/scripts/optimization/fzero.m
@@ -100,7 +100,7 @@
 
   ## Get default options if requested.
   if (nargin == 1 && ischar (fun) && strcmp (fun, 'defaults'))
-    x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", 1e-8,
+    x = optimset ("MaxIter", Inf, "MaxFunEvals", Inf, "TolX", eps,
                   "OutputFcn", [], "FunValCheck", "off");
     return;
   endif
@@ -117,7 +117,7 @@
   ## displev = optimget (options, "Display", "notify");
   funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on");
   outfcn = optimget (options, "OutputFcn");
-  tolx = optimget (options, "TolX", 1e-8);
+  tolx = optimget (options, "TolX", eps);
   maxiter = optimget (options, "MaxIter", Inf);
   maxfev = optimget (options, "MaxFunEvals", Inf);
 
@@ -302,7 +302,7 @@
     endif
 
     ## If there's an output function, use it now.
-    if (outfcn)
+    if (! isempty (outfcn))
       optv.funccount = nfev;
       optv.fval = fval;
       optv.iteration = niter;
--- a/scripts/optimization/glpk.m
+++ b/scripts/optimization/glpk.m
@@ -123,7 +123,7 @@
 ##
 ## @item @qcode{"D"}
 ## An inequality constraint with both upper and lower bounds
-## (@code{A(i,:)*x >= -b(i)} @emph{and} (@code{A(i,:)*x <= b(i)}).
+## (@code{A(i,:)*x >= -b(i)}) @emph{and} (@code{A(i,:)*x <= b(i)}).
 ## @end table
 ##
 ## @item vartype
--- a/scripts/optimization/optimget.m
+++ b/scripts/optimization/optimget.m
@@ -20,10 +20,12 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} optimget (@var{options}, @var{parname})
 ## @deftypefnx {Function File} {} optimget (@var{options}, @var{parname}, @var{default})
-## Return a specific option from a structure created by
-## @code{optimset}.  If @var{parname} is not a field of the @var{options}
-## structure, return @var{default} if supplied, otherwise return an
-## empty matrix.
+## Return the specific option @var{parname} from the optimization options
+## structure @var{options} created by @code{optimset}.
+##
+## If @var{parname} is not defined then return @var{default} if supplied,
+## otherwise return an empty matrix.
+## @seealso{optimset}
 ## @end deftypefn
 
 function retval = optimget (options, parname, default)
@@ -32,21 +34,22 @@
     print_usage ();
   endif
 
+  ## Expand partial-length names into full names
   opts = __all_opts__ ();
   idx = strncmpi (opts, parname, length (parname));
-
   nmatch = sum (idx);
 
   if (nmatch == 1)
     parname = opts{idx};
   elseif (nmatch == 0)
-    warning ("unrecognized option: %s", parname);
+    warning ("optimget: unrecognized option: %s", parname);
   else
-    fmt = sprintf ("ambiguous option: %%s (%s%%s)",
+    fmt = sprintf ("optimget: ambiguous option: %%s (%s%%s)",
                    repmat ("%s, ", 1, nmatch-1));
     warning (fmt, parname, opts{idx});
   endif
-  if (isfield (options, parname))
+
+  if (isfield (options, parname) && ! isempty (options.(parname)))
     retval = options.(parname);
   elseif (nargin > 2)
     retval = default;
@@ -57,13 +60,20 @@
 endfunction
 
 
-%!error optimget ()
-
 %!shared opts
 %! opts = optimset ("tolx", 0.1, "maxit", 100);
-%!assert (optimget (opts, "TolX"), 0.1);
-%!assert (optimget (opts, "maxit"), 100);
-%!assert (optimget (opts, "MaxITer"), 100);
-%!warning (optimget (opts, "Max"));
-%!warning (optimget (opts, "foobar"));
+%!assert (optimget (opts, "TolX"), 0.1)
+%!assert (optimget (opts, "maxit"), 100)
+%!assert (optimget (opts, "MaxITer"), 100)
+%!assert (optimget (opts, "TolFun"), [])
+%!assert (optimget (opts, "TolFun", 1e-3), 1e-3)
 
+%% Test input validation
+%!error optimget ()
+%!error optimget (1)
+%!error optimget (1,2,3,4,5)
+%!error optimget (1, "name")
+%!error optimget (struct (), 2)
+%!warning <unrecognized option: foobar> (optimget (opts, "foobar"));
+%!warning <ambiguous option: Max> (optimget (opts, "Max"));
+
--- a/scripts/optimization/optimset.m
+++ b/scripts/optimization/optimset.m
@@ -19,10 +19,24 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} optimset ()
-## @deftypefnx {Function File} {} optimset (@var{par}, @var{val}, @dots{})
-## @deftypefnx {Function File} {} optimset (@var{old}, @var{par}, @var{val}, @dots{})
-## @deftypefnx {Function File} {} optimset (@var{old}, @var{new})
-## Create options struct for optimization functions.
+## @deftypefnx {Function File} {@var{options} =} optimset ()
+## @deftypefnx {Function File} {@var{options} =} optimset (@var{par}, @var{val}, @dots{})
+## @deftypefnx {Function File} {@var{options} =} optimset (@var{old}, @var{par}, @var{val}, @dots{})
+## @deftypefnx {Function File} {@var{options} =} optimset (@var{old}, @var{new})
+## Create options structure for optimization functions.
+##
+## When called without any input or output arguments, @code{optimset} prints
+## a list of all valid optimization parameters.
+##
+## When called with one output and no inputs, return an options structure with
+## all valid option parameters initialized to @code{[]}.
+##
+## When called with a list of parameter/value pairs, return an options
+## structure with only the named parameters initialized.
+##
+## When the first input is an existing options structure @var{old}, the values
+## are updated from either the @var{par}/@var{val} list or from the options
+## structure @var{new}.
 ##
 ## Valid parameters are:
 ##
@@ -96,13 +110,13 @@
 ##
 ## @item Updating
 ## @end table
+## @seealso{optimget}
 ## @end deftypefn
 
 function retval = optimset (varargin)
 
   nargs = nargin ();
 
-  ## Add more as needed.
   opts = __all_opts__ ();
 
   if (nargs == 0)
@@ -124,8 +138,8 @@
       error ("optimset: no defaults for function '%s'", fcn);
     end_try_catch
   elseif (nargs == 2 && isstruct (varargin{1}) && isstruct (varargin{2}))
-    ## Set slots in old from nonempties in new.  Should we be checking
-    ## to ensure that the field names are expected?
+    ## Set slots in old from non-empties in new.
+    ## Should we be checking to ensure that the field names are expected?
     old = varargin{1};
     new = varargin{2};
     fnames = fieldnames (old);
@@ -140,9 +154,9 @@
         if (nmatch == 1)
           key = opts{find (i)};
         elseif (nmatch == 0)
-          warning ("unrecognized option: %s", key);
+          warning ("optimset: unrecognized option: %s", key);
         else
-          fmt = sprintf ("ambiguous option: %%s (%s%%s)",
+          fmt = sprintf ("optimset: ambiguous option: %%s (%s%%s)",
                          repmat ("%s, ", 1, nmatch-1));
           warning (fmt, key, opts{i});
         endif
@@ -155,8 +169,8 @@
     pairs = reshape (varargin(2:end), 2, []);
     retval = optimset (varargin{1}, cell2struct (pairs(2, :), pairs(1, :), 2));
   elseif (rem (nargs, 2) == 0)
-    ## Create struct.  Default values are replaced by those specified by
-    ## name/value pairs.
+    ## Create struct.
+    ## Default values are replaced by those specified by name/value pairs.
     pairs = reshape (varargin, 2, []);
     retval = optimset (struct (), cell2struct (pairs(2, :), pairs(1, :), 2));
   else
@@ -166,10 +180,13 @@
 endfunction
 
 
-%!assert (optimget (optimset ("tolx", 1e-2), "tOLx"), 1e-2)
+%!assert (isfield (optimset (), "TolFun"))
 %!assert (isfield (optimset ("tolFun", 1e-3), "TolFun"))
-%!warning (optimset ("Max", 10));
-%!warning (optimset ("foobar", 13));
+%!assert (optimget (optimset ("tolx", 1e-2), "tOLx"), 1e-2)
 
-%!error (optimset ("%NOT_A_REAL_FUNCTION_NAME%"))
+%% Test input validation
+%!error optimset ("1_Parameter")
+%!error <no defaults for function> optimset ("%NOT_A_REAL_FUNCTION_NAME%")
+%!warning <unrecognized option: foobar> optimset ("foobar", 13);
+%!warning <ambiguous option: Max> optimset ("Max", 10);
 
--- a/scripts/optimization/sqp.m
+++ b/scripts/optimization/sqp.m
@@ -1,4 +1,5 @@
 ## Copyright (C) 2005-2013 John W. Eaton
+## Copyright (C) 2013 Arun Giridhar
 ##
 ## This file is part of Octave.
 ##
@@ -128,8 +129,17 @@
 ##
 ## @table @asis
 ## @item 101
-## The algorithm terminated normally.
-## Either all constraints meet the requested tolerance, or the stepsize,
+## The algorithm terminated normally. 
+## All constraints meet the specified tolerance.
+##
+## @item 102
+## The BFGS update failed.
+##
+## @item 103
+## The maximum number of iterations was reached.
+##
+## @item 104
+## The stepsize has become too small, i.e., 
 ## @tex
 ## $\Delta x,$
 ## @end tex
@@ -137,12 +147,6 @@
 ## delta @var{x},
 ## @end ifnottex
 ## is less than @code{@var{tol} * norm (x)}.
-##
-## @item 102
-## The BFGS update failed.
-##
-## @item 103
-## The maximum number of iterations was reached.
 ## @end table
 ##
 ## An example of calling @code{sqp}:
@@ -394,6 +398,8 @@
     t3 = all (lambda_i >= 0);
     t4 = norm (lambda .* con);
 
+    ## Normal convergence.  All constraints are satisfied
+    ## and objective has converged.
     if (t2 && t3 && max ([t0; t1; t4]) < tol)
       info = 101;
       break;
@@ -408,8 +414,8 @@
 
     info = INFO.info;
 
-    ## FIXME -- check QP solution and attempt to recover if it has
-    ## failed.  For now, just warn about possible problems.
+    ## FIXME: check QP solution and attempt to recover if it has failed.
+    ##        For now, just warn about possible problems.
     
     id = "Octave:SQP-QP-subproblem";
     switch (info)
@@ -453,8 +459,9 @@
 
     delx = x_new - x;
 
+    ## Check if step size has become too small (indicates lack of progress).
     if (norm (delx) < tol * norm (x))
-      info = 101;
+      info = 104;
       break;
     endif
 
@@ -483,6 +490,8 @@
 
       d2 = delxt*r;
 
+      ## Check if the next BFGS update will work properly.
+      ## If d1 or d2 vanish, the BFGS update will fail.
       if (d1 == 0 || d2 == 0)
         info = 102;
         break;
@@ -510,6 +519,7 @@
 
   endwhile
 
+  ## Check if we've spent too many iterations without converging.
   if (iter >= iter_max)
     info = 103;
   endif
--- a/scripts/pkg/module.mk
+++ b/scripts/pkg/module.mk
@@ -5,6 +5,7 @@
   pkg/private/configure_make.m \
   pkg/private/copy_files.m \
   pkg/private/create_pkgadddel.m \
+  pkg/private/default_prefix.m \
   pkg/private/describe.m \
   pkg/private/dirempty.m \
   pkg/private/extract_pkg.m \
--- a/scripts/pkg/pkg.m
+++ b/scripts/pkg/pkg.m
@@ -280,14 +280,7 @@
   global_install = ((ispc () && ! isunix ()) || (geteuid () == 0));
 
   if (isbool (prefix))
-    if (global_install)
-      prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
-      archprefix = fullfile (octave_config_info ("libdir"),
-                             "octave", "packages");
-    else
-      prefix = fullfile ("~", "octave");
-      archprefix = prefix;
-    endif
+    [prefix, archprefix] = default_prefix (global_install);
     prefix = tilde_expand (prefix);
     archprefix = tilde_expand (archprefix);
   endif
@@ -326,15 +319,12 @@
       case "-local"
         global_install = false;
         if (! user_prefix)
-          prefix = tilde_expand (fullfile ("~", "octave"));
-          archprefix = prefix;
+          [prefix, archprefix] = default_prefix (global_install);
         endif
       case "-global"
         global_install = true;
         if (! user_prefix)
-          prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
-          archprefix = fullfile (octave_config_info ("libdir"),
-                                 "octave", "packages");
+          [prefix, archprefix] = default_prefix (global_install);
         endif
       case available_actions
         if (strcmp (action, "none"))
--- a/scripts/pkg/private/configure_make.m
+++ b/scripts/pkg/private/configure_make.m
@@ -32,11 +32,6 @@
     mkoctfile_program = fullfile (octave_bindir, sprintf ("mkoctfile-%s%s", ver, ext));
     octave_config_program = fullfile (octave_bindir, sprintf ("octave-config-%s%s", ver, ext));
     octave_binary = fullfile (octave_bindir, sprintf ("octave-%s%s", ver, ext));
-    cenv = {"MKOCTFILE"; mkoctfile_program;
-            "OCTAVE_CONFIG"; octave_config_program;
-            "OCTAVE"; octave_binary;
-            "INSTALLDIR"; desc.dir};
-    scenv = sprintf ("%s=\"%s\" ", cenv{:});
 
     if (! exist (mkoctfile_program, "file"))
       __gripe_missing_component__ ("pkg", "mkoctfile");
@@ -48,6 +43,16 @@
       __gripe_missing_component__ ("pkg", "octave");
     endif
 
+    if (verbose)
+      mkoctfile_program = [mkoctfile_program " --verbose"];
+    endif
+
+    cenv = {"MKOCTFILE"; mkoctfile_program;
+            "OCTAVE_CONFIG"; octave_config_program;
+            "OCTAVE"; octave_binary;
+            "INSTALLDIR"; desc.dir};
+    scenv = sprintf ("%s=\"%s\" ", cenv{:});
+
     ## Configure.
     if (exist (fullfile (src, "configure"), "file"))
       flags = "";
new file mode 100644
--- /dev/null
+++ b/scripts/pkg/private/default_prefix.m
@@ -0,0 +1,40 @@
+## Copyright (C) 2014 Carlo de Falco
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{prefix}, @var{archprefix} =} @
+## default_prefix (@var{global_install})
+## Undocumented internal function.
+## @end deftypefn
+
+function [prefix, archprefix] = default_prefix (global_install, desc)
+  if (global_install)
+    prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
+    if (nargin == 2)
+      archprefix = fullfile (octave_config_info ("libdir"), "octave",
+                             "packages", [desc.name "-" desc.version]);
+    else
+      archprefix = fullfile (octave_config_info ("libdir"), "octave",
+                             "packages");
+    endif
+  else
+    prefix = tilde_expand (fullfile ("~", "octave"));
+    archprefix = prefix;
+  endif
+endfunction
+
--- a/scripts/pkg/private/getarchprefix.m
+++ b/scripts/pkg/private/getarchprefix.m
@@ -24,8 +24,7 @@
 
 function archprefix = getarchprefix (desc, global_install)
   if (global_install)
-    archprefix = fullfile (octave_config_info ("libdir"), "octave",
-                           "packages", [desc.name "-" desc.version]);
+    [~, archprefix] = default_prefix (global_install, desc);
   else
     archprefix = desc.dir;
   endif
--- a/scripts/plot/appearance/__getlegenddata__.m
+++ b/scripts/plot/appearance/__getlegenddata__.m
@@ -29,7 +29,7 @@
   if (numel (ca) == 1)
     kids = get (ca, "children");
   else
-    kids = [get(kids, "children"){:}];
+    kids = [get(ca, "children"){:}];
   endif
 
   for i = numel (kids):-1:1
--- a/scripts/plot/appearance/axis.m
+++ b/scripts/plot/appearance/axis.m
@@ -30,7 +30,9 @@
 ## The argument @var{limits} should be a 2-, 4-, or 6-element vector.  The
 ## first and second elements specify the lower and upper limits for the
 ## x-axis.  The third and fourth specify the limits for the y-axis, and the
-## fifth and sixth specify the limits for the z-axis.
+## fifth and sixth specify the limits for the z-axis.  The special values
+## -Inf and Inf may be used to indicate that the limit should automatically be
+## computed based on the data in the axis.
 ##
 ## Without any arguments, @code{axis} turns autoscaling on.
 ##
@@ -297,15 +299,15 @@
     endfor
 
     if (len > 1)
-      set (ca, "xlim", [ax(1), ax(2)]);
+      xlim (ca, ax(1:2));
     endif
 
     if (len > 3)
-      set (ca, "ylim", [ax(3), ax(4)]);
+      ylim (ca, ax(3:4));
     endif
 
     if (len > 5)
-      set (ca, "zlim", [ax(5), ax(6)]);
+      zlim (ca, ax(5:6));
     endif
 
   else
--- a/scripts/plot/appearance/datetick.m
+++ b/scripts/plot/appearance/datetick.m
@@ -45,8 +45,8 @@
 
   unwind_protect
     ## FIXME: This will bring the axes to the top of the stack.
-    ##        This may not always be desirable if there are multiple axes
-    ##        objects.
+    ##        This may not be desirable if there are multiple axes objects,
+    ##        such as can occur with plotyy.
     axes (hax);
     __datetick__ (varargin{:});
   unwind_protect_cleanup
--- a/scripts/plot/appearance/diffuse.m
+++ b/scripts/plot/appearance/diffuse.m
@@ -18,11 +18,11 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {Function File} {} diffuse (@var{sx}, @var{sy}, @var{sz}, @var{lv})
-## Calculate diffuse reflection strength of a surface defined by the normal
+## Calculate the diffuse reflection strength of a surface defined by the normal
 ## vector elements @var{sx}, @var{sy}, @var{sz}.
 ##
-## The light source location vector @var{lv} can be given as 2-element vector
-## [azimuth, elevation] in degrees or as 3-element vector [lx, ly, lz].
+## The light source location vector @var{lv} can be given as a 2-element vector
+## [azimuth, elevation] in degrees or as a 3-element vector [x, y, z].
 ## @seealso{specular, surfl}
 ## @end deftypefn
 
@@ -34,13 +34,13 @@
     print_usage ();
   endif
 
-  ## check for normal vector
-  if (!size_equal (sx, sy, sz))
-    error ("diffuse: SX, SY, and SZ must have same size");
+  ## Check normal vectors
+  if (! size_equal (sx, sy, sz))
+    error ("diffuse: SX, SY, and SZ must be the same size");
   endif
 
-  ## check for light vector (lv) argument
-  if (length (lv) < 2 || length (lv) > 3)
+  ## Check light vector (lv) argument
+  if (! isvector (lv) || length (lv) < 2 || length (lv) > 3)
     error ("diffuse: light vector LV must be a 2- or 3-element vector");
   elseif (length (lv) == 2)
     [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0);
@@ -48,7 +48,7 @@
 
   ## Normalize view and light vector.
   if (sum (abs (lv)) > 0)
-    lv  /= norm (lv);
+    lv /= norm (lv);
   endif
 
   ns = sqrt (sx.^2 + sy.^2 + sz.^2);
--- a/scripts/plot/appearance/legend.m
+++ b/scripts/plot/appearance/legend.m
@@ -166,11 +166,27 @@
   nargs = numel (varargin);
   nkids = numel (kids);
 
+  ## Find any existing legend object on figure
+  hlegend = [];
+  fkids = get (fig, "children");
+  for i = 1 : numel (fkids)
+    if (   strcmp (get (fkids(i), "type"), "axes")
+        && strcmp (get (fkids(i), "tag"), "legend"))
+      udata = get (fkids(i), "userdata");
+      if (any (ismember (udata.handle, ca)))
+        hlegend = fkids(i);
+        break;
+      endif
+    endif
+  endfor
+
   orientation = "default";
   location = "default";
   show = "create";
   textpos = "default";
   box = "default";
+  delete_leg = false;
+  find_leg_hdl = (nargs == 0);
 
   ## Process old way of specifying location with a number rather than a string.
   if (nargs > 0)
@@ -229,20 +245,6 @@
       error ("legend: unrecognized legend location");
   endswitch
 
-  ## Find any existing legend object on figure
-  hlegend = [];
-  fkids = get (fig, "children");
-  for i = 1 : numel (fkids)
-    if (   strcmp (get (fkids(i), "type"), "axes")
-        && strcmp (get (fkids(i), "tag"), "legend"))
-      udata = get (fkids(i), "userdata");
-      if (any (udata.handle == ca))
-        hlegend = fkids(i);
-        break;
-      endif
-    endif
-  endfor
-
   if (nargs == 1)
     arg = varargin{1};
     if (ischar (arg))
@@ -250,8 +252,7 @@
         str = tolower (strtrim (arg));
         switch (str)
           case "off"
-            delete (hlegend);
-            return;
+            delete_leg = true;
           case "hide"
             show = "off";
             nargs--;
@@ -305,24 +306,26 @@
   endif
 
   have_labels = (nargs > 0);
+  hobjects = [];
+  hplots  = [];
+  text_strings = {};
 
-  if (strcmp (show, "off"))
+  if (delete_leg)
+    delete (hlegend);
+    hlegend = [];
+  elseif (find_leg_hdl)
+    ## Don't change anything about legend.
+    ## hleg output will be assigned hlegend value at end of function.
+  elseif (strcmp (show, "off"))
     if (! isempty (hlegend))
       set (findobj (hlegend), "visible", "off");
       hlegend = [];
     endif
-    hobjects = [];
-    hplots  = [];
-    text_strings = {};
   elseif (strcmp (show, "on"))
     if (! isempty (hlegend))
       set (findobj (hlegend), "visible", "on");
-      ## NOTE - Matlab sets both "visible", and "box" to "on"
+      ## NOTE: Matlab sets both "visible" and "box" to "on"
       set (hlegend, "visible", get (hlegend, "box"));
-    else
-      hobjects = [];
-      hplots  = [];
-      text_strings = {};
     endif
   elseif (strcmp (box, "on"))
     if (! isempty (hlegend))
@@ -332,26 +335,24 @@
     if (! isempty (hlegend))
       set (hlegend, "box", "off", "visible", "off");
     endif
-  elseif (! have_labels && ! (strcmp (location, "default") &&
-                              strcmp (orientation, "default")))
+  elseif (! have_labels && ! isempty (hlegend)
+          && ! (strcmp (location, "default") && strcmp (orientation, "default")))
     ## Changing location or orientation of existing legend
-    if (! isempty (hlegend))
-      if (strcmp (location, "default"))
-        set (hlegend, "orientation", orientation);
-      elseif (strcmp (orientation, "default"))
-        if (outside)
-          set (hlegend, "location", [location "outside"]);
-        else
-          set (hlegend, "location", location);
-        endif
+    if (strcmp (location, "default"))
+      set (hlegend, "orientation", orientation);
+    elseif (strcmp (orientation, "default"))
+      if (outside)
+        set (hlegend, "location", [location "outside"]);
       else
-        if (outside)
-          set (hlegend, "location", [location "outside"],
-                        "orientation", orientation);
-        else
-          set (hlegend, "location", location,
-                        "orientation", orientation);
-        endif
+        set (hlegend, "location", location);
+      endif
+    else
+      if (outside)
+        set (hlegend, "location", [location "outside"],
+                      "orientation", orientation);
+      else
+        set (hlegend, "location", location,
+                      "orientation", orientation);
       endif
     endif
   else
@@ -565,6 +566,12 @@
       linelength = 15;
 
       ## Create the axis first
+      oldfig = get (0, "currentfigure");
+      if (oldfig != fig)
+        set (0, "currentfigure", fig);
+      else
+        oldfig = [];
+      endif
       curaxes = get (fig, "currentaxes");
       unwind_protect
         ud = ancestor (hplots, "axes");
@@ -829,10 +836,11 @@
             case "line"
               color = get (hplots(k), "color");
               style = get (hplots(k), "linestyle");
+              lwidth = min (get (hplots(k), "linewidth"), 5);
               if (! strcmp (style, "none"))
                 l1 = line ("xdata", ([xoffset, xoffset + linelength] + xk * xstep) / lpos(3),
                            "ydata", [1, 1] .* (lpos(4) - yoffset - yk * ystep) / lpos(4),
-                           "color", color, "linestyle", style,
+                           "color", color, "linestyle", style, "linewidth", lwidth,
                            "marker", "none",
                            "userdata", hplots(k));
                 hobjects(end+1) = l1;
@@ -841,11 +849,11 @@
               if (! strcmp (marker, "none"))
                 l1 = line ("xdata", (xoffset + 0.5 * linelength  + xk * xstep) / lpos(3),
                            "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4),
-                           "color", color, "linestyle", "none",
+                           "color", color, "linestyle", "none", "linewidth", lwidth,
                            "marker", marker,
                            "markeredgecolor",get (hplots(k), "markeredgecolor"),
                            "markerfacecolor",get (hplots(k), "markerfacecolor"),
-                           "markersize", get (hplots(k), "markersize"),
+                           "markersize", min (get (hplots(k), "markersize"),10),
                            "userdata", hplots(k));
                 hobjects(end+1) = l1;
               endif
@@ -855,6 +863,8 @@
                              {@updateline, hlegend, linelength, false});
                 addlistener (hplots(k), "linestyle",
                              {@updateline, hlegend, linelength, false});
+                addlistener (hplots(k), "linewidth",
+                             {@updateline, hlegend, linelength, false});
                 addlistener (hplots(k), "marker",
                              {@updateline, hlegend, linelength, false});
                 addlistener (hplots(k), "markeredgecolor",
@@ -876,13 +886,24 @@
                                       xoffset + xk * xstep) / lpos(3),
                             "ydata", (lpos(4) - yoffset -
                                       [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4),
-                           "facecolor", facecolor, "edgecolor", edgecolor,
-                           "cdata", cdata, "userdata", hplots(k));
-                hobjects(end+1) = p1;
-                ## Copy clim from axes so that colors work out.
-                set (hlegend, "clim", get (ca(1), "clim"));
+                            "facecolor", facecolor, "edgecolor", edgecolor,
+                            "cdata", cdata, "userdata", hplots(k));
+              else
+                ## non-standard patch only making use of marker styles
+                ## such as scatter plot.
+                p1 = patch ("xdata", (xoffset + 0.5 * linelength  + xk * xstep) / lpos(3),
+                            "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4),
+                            "marker", get (hplots(k), "marker"),
+                            "markeredgecolor",get (hplots(k),"markeredgecolor"),
+                            "markerfacecolor",get (hplots(k),"markerfacecolor"),
+                            "markersize", min (get (hplots(k),"markersize"),10),
+                            "cdata", cdata, "userdata", hplots(k));
               endif
-              ## FIXME: Probably need listeners, as for line objects
+              hobjects(end+1) = p1;
+              ## Copy clim from axes so that colors work out.
+              set (hlegend, "clim", get (ca(1), "clim"));
+
+              ## FIXME: Need listeners, as for line objects.
               ##        Changing clim, for example, won't update colors
 
             case "surface"
@@ -894,11 +915,11 @@
                                       xoffset + xk * xstep) / lpos(3),
                             "ydata", (lpos(4) - yoffset -
                                       [yk-0.3, yk-0.3, yk+0.3, yk+0.3] .* ystep) / lpos(4),
-                           "facecolor", facecolor, "edgecolor", edgecolor,
-                           "cdata", cdata, "userdata", hplots(k));
+                            "facecolor", facecolor, "edgecolor", edgecolor,
+                            "cdata", cdata, "userdata", hplots(k));
                 hobjects(end+1) = p1;
               endif
-              ## FIXME: Probably need listeners, as for line objects
+              ## FIXME: Need listeners, as for line objects.
 
           endswitch
 
@@ -1032,6 +1053,9 @@
         endif
       unwind_protect_cleanup
         set (fig, "currentaxes", curaxes);
+        if (! isempty (oldfig))
+          set (0, "currentfigure", oldfig);
+        endif
       end_unwind_protect
     endif
   endif
@@ -1065,8 +1089,10 @@
           set (hax, "position", position);
           set (hax, "outerposition", outerposition);
       endswitch
-      set (hax, "units", units);
-      h = legend (hax, hplots, get (h, "string"));
+      ## Crazy syntax because set() only seems to support row vectors
+      set (hax, repmat ({"units"}, [1 numel(hax)]), units(:)');
+
+      h = legend (hax(1), hplots, get (h, "string"));
     unwind_protect_cleanup
       recursive = false;
     end_unwind_protect
@@ -1149,6 +1175,7 @@
     if (ishandle (hplots(i)) && strcmp (get (hplots(i), "type"), "line"))
       dellistener (hplots(i), "color");
       dellistener (hplots(i), "linestyle");
+      dellistener (hplots(i), "linewidth");
       dellistener (hplots(i), "marker");
       dellistener (hplots(i), "markeredgecolor");
       dellistener (hplots(i), "markerfacecolor");
@@ -1163,7 +1190,7 @@
   if (update_name)
     ## When string changes, have to rebuild legend completely
     [hplots, text_strings] = __getlegenddata__ (hlegend);
-    legend (hplots, text_strings);
+    legend (get (hplots(1), "parent"), hplots, text_strings);
   else
     kids = get (hlegend, "children");
     ll = lm = [];
@@ -1198,14 +1225,18 @@
 
     if (! strcmp (linestyle, "none"))
       line ("xdata", xpos1, "ydata", ypos1, "color", get (h, "color"),
-            "linestyle", get (h, "linestyle"), "marker", "none",
+            "linestyle", get (h, "linestyle"),
+            "linewidth", min (get (h, "linewidth"), 5),
+            "marker", "none",
             "userdata", h, "parent", hlegend);
     endif
     if (! strcmp (marker, "none"))
       line ("xdata", xpos2, "ydata", ypos2, "color", get (h, "color"),
             "marker", marker, "markeredgecolor", get (h, "markeredgecolor"),
             "markerfacecolor", get (h, "markerfacecolor"),
-            "markersize", get (h, "markersize"), "linestyle", "none",
+            "markersize", min (get (h, "markersize"), 10),
+            "linestyle", "none",
+            "linewidth", min (get (h, "linewidth"), 5),
             "userdata", h, "parent", hlegend);
     endif
   endif
@@ -1223,8 +1254,8 @@
 %!demo
 %! clf;
 %! plot (rand (3));
-%! title ('legend() without inputs creates default labels');
-%! h = legend ();
+%! title ('legend("show") without inputs creates default labels');
+%! h = legend ('show');
 
 %!demo
 %! clf;
@@ -1605,3 +1636,20 @@
 %!   graphics_toolkit (toolkit);
 %! end_unwind_protect
 
+%!test
+%! ## bug #42035
+%! h = figure ("visible", "off");
+%! unwind_protect
+%!   hax1 = subplot (1,2,1);
+%!   plot (1:10);
+%!   hax2 = subplot (1,2,2);
+%!   plot (1:10);
+%!   hleg1 = legend (hax1, "foo");
+%!   assert (get (hleg1, "userdata").handle, hax1)
+%!   assert (gca (), hax2);
+%!   hleg2 = legend ("bar");
+%!   assert (get (hleg2, "userdata").handle, gca ())
+%! unwind_protect_cleanup
+%!   close (h);
+%! end_unwind_protect
+
--- a/scripts/plot/appearance/private/__axis_limits__.m
+++ b/scripts/plot/appearance/private/__axis_limits__.m
@@ -48,6 +48,11 @@
         if (arg(1) >= arg(2))
           error ("%s: axis limits must be increasing", fcn);
         else
+          autoscale = isinf (arg);
+          if (any (autoscale))
+            set (hax, fcnmode, "auto");
+            arg(autoscale) = get (hax, fcn)(autoscale);
+          endif
           set (hax, fcn, arg(:));
         endif
       endif
--- a/scripts/plot/appearance/specular.m
+++ b/scripts/plot/appearance/specular.m
@@ -19,15 +19,17 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv})
 ## @deftypefnx {Function File} {} specular (@var{sx}, @var{sy}, @var{sz}, @var{lv}, @var{vv}, @var{se})
-## Calculate specular reflection strength of a surface defined by the normal
-## vector elements @var{sx}, @var{sy}, @var{sz} using Phong's approximation.
+## Calculate the specular reflection strength of a surface defined by the
+## normal vector elements @var{sx}, @var{sy}, @var{sz} using Phong's
+## approximation.
 ##
-## The light source location and viewer location vectors can be specified using
-## parameter @var{lv} and @var{vv} respectively.  The location vectors can
+## The light source location and viewer location vectors are specified using
+## parameters @var{lv} and @var{vv} respectively.  The location vectors can
 ## given as 2-element vectors [azimuth, elevation] in degrees or as 3-element
 ## vectors [x, y, z].
 ##
-## An optional sixth argument describes the specular exponent (spread) @var{se}.
+## An optional sixth argument specifies the specular exponent (spread) @var{se}.
+## If not given, @var{se} defaults to 10.
 ## @seealso{diffuse, surfl}
 ## @end deftypefn
 
@@ -39,54 +41,52 @@
     print_usage ();
   endif
 
-  ## Checks for specular exponent (se).
-  if (nargin < 6)
-    se = 10;
-  else
-    if (!isnumeric (se) || numel (se) != 1 || se <= 0)
-      error ("specular: exponent must be positive scalar");
-    endif
+  ## Check normal vectors
+  if (! size_equal (sx, sy, sz))
+    error ("specular: SX, SY, and SZ must be the same size");
   endif
 
-  ## Checks for normal vector.
-  if (!size_equal (sx, sy, sz))
-    error ("specular: SX, SY, and SZ must have same size");
-  endif
-
-  ## Check for light vector (lv) argument.
-  if (length (lv) < 2 || length (lv) > 3)
+  ## Check light vector (lv) argument
+  if (! isvector (lv) || length (lv) < 2 || length (lv) > 3)
     error ("specular: light vector LV must be a 2- or 3-element vector");
   elseif (length (lv) == 2)
     [lv(1), lv(2), lv(3)] = sph2cart (lv(1) * pi/180, lv(2) * pi/180, 1.0);
   endif
 
-  ## Check for view vector (vv) argument.
-  if (length (vv) < 2 || length (lv) > 3)
+  ## Check view vector (vv) argument
+  if (! isvector (vv) || length (vv) < 2 || length (lv) > 3)
     error ("specular: view vector VV must be a 2- or 3-element vector");
   elseif (length (vv) == 2)
     [vv(1), vv(2), vv(3)] = sph2cart (vv(1) * pi / 180, vv(2) * pi / 180, 1.0);
   endif
 
-  ## Normalize view and light vector.
+  ## Check specular exponent (se) argument
+  if (nargin < 6)
+    se = 10;
+  elseif (! (isnumeric (se) && numel (se) == 1 && se > 0))
+    error ("specular: exponent SE must be a positive scalar");
+  endif
+
+  ## Normalize view and light vectors
   if (sum (abs (lv)) > 0)
-    lv  /= norm (lv);
+    lv /= norm (lv);
   endif
   if (sum (abs (vv)) > 0)
-    vv  /= norm (vv);
+    vv /= norm (vv);
   endif
 
-  ## Calculate normal vector lengths and dot-products.
+  ## Calculate normal vector lengths and dot-products
   ns = sqrt (sx.^2 + sy.^2 + sz.^2);
   l_dot_n = (sx * lv(1) + sy * lv(2) + sz * lv(3)) ./ ns;
   v_dot_n = (sx * vv(1) + sy * vv(2) + sz * vv(3)) ./ ns;
 
-  ## Calculate specular reflection using Phong's approximation.
+  ## Calculate specular reflection using Phong's approximation
   retval = 2 * l_dot_n .* v_dot_n - dot (lv, vv);
 
-  ## Set zero if light is on the other side.
+  ## Set reflectance to zero if light is on the other side
   retval(l_dot_n < 0) = 0;
 
-  ## Allow postive values only.
+  ## Allow postive values only
   retval(retval < 0) = 0;
   retval = retval .^ se;
 
--- a/scripts/plot/draw/area.m
+++ b/scripts/plot/draw/area.m
@@ -49,7 +49,7 @@
 ## @example
 ## @group
 ## t = linspace (0, 2*pi, 100)';
-## y = [sin(t).^2, cos(t).^2)];
+## y = [sin(t).^2, cos(t).^2];
 ## area (t, y);
 ## legend ("sin^2", "cos^2", "location", "NorthEastOutside");
 ## @end group
--- a/scripts/plot/draw/colorbar.m
+++ b/scripts/plot/draw/colorbar.m
@@ -310,24 +310,6 @@
       set (hi, "xdata", [cmin, cmax]);
       set (hiax, "xlim", cext);
     endif
-
-    ## FIXME: Setting xlim or ylim from within a listener callback
-    ##        causes the axis to change size rather than change limits.
-    ##        Workaround it by jiggling the position property which forces
-    ##        a redraw of the axis object.
-    ##
-    ## Debug Example:
-    ## Uncomment the line below.
-    ##   keyboard;
-    ## Now run the the following code.
-    ##   clf; colorbar (); contour (peaks ())
-    ## Once the keyboard command has been hit in the debugger try
-    ##   set (hiax, "ylim", [0 0.5]) 
-    pos = get (hiax, "position");
-    pos(1) += eps;
-    set (hiax, "position", pos);
-    pos(1) -= eps;
-    set (hiax, "position", pos);
   endif
 endfunction
 
--- a/scripts/plot/draw/fill.m
+++ b/scripts/plot/draw/fill.m
@@ -92,17 +92,28 @@
       set (hax, "nextplot", "add");
 
       for i = 1 : length (iargs)
+        x = varargin{iargs(i)};
+        y = varargin{iargs(i) + 1};
         cdata = varargin{iargs(i) + 2};
+
+        if (! size_equal (x,y))
+          if (iscolumn (y) && rows (y) == rows (x))
+            y = repmat (y, [1, columns(x)]);
+          elseif (iscolumn (x) && rows (x) == rows (y))
+            x = repmat (x, [1, columns(y)]);
+          else
+            error ("fill: X annd Y must have same number of rows");
+          endif
+        endif
         ## For Matlab compatibility, replicate cdata to match size of data
-        if (iscolumn (cdata))
-          sz = size (varargin{iargs(i)});
+        if (iscolumn (cdata) && ! ischar (cdata))
+          sz = size (x);
           if (all (sz > 1))
             cdata = repmat (cdata, [1, sz(2)]);
           endif
         endif
 
-        [htmp, fail] = __patch__ (hax, varargin{iargs(i)+(0:1)}, cdata,
-                                       opts{:});
+        [htmp, fail] = __patch__ (hax, x, y, cdata, opts{:});
         if (fail)
           print_usage ();
         endif
@@ -160,4 +171,30 @@
 %! x2 = sin (t2) + 0.8;
 %! y2 = cos (t2);
 %! h = fill (x1,y1,'r', x2,y2,'g');
+%! title ({'fill() function'; 'cdata specified with string'});
 
+%!demo
+%! clf;
+%! t1 = (1/16:1/8:1) * 2*pi;
+%! t2 = ((1/16:1/8:1) + 1/32) * 2*pi;
+%! x1 = sin (t1) - 0.8;
+%! y1 = cos (t1);
+%! x2 = sin (t2) + 0.8;
+%! y2 = cos (t2);
+%! h = fill (x1,y1,1, x2,y2,2);
+%! title ({'fill() function'; 'cdata = row vector produces FaceColor = "flat"'});
+
+%!demo
+%! clf;
+%! x = [0 0
+%!      1 0.5
+%!      1 0.5
+%!      0 0];
+%! y = [0 0
+%!      0 0
+%!      1 0.5
+%!      1 0.5];
+%! c = [1 2 3 4]';
+%! fill (x, y, c);
+%! title ({'fill() function'; 'cdata = column vector produces FaceColor = "interp"'});
+
--- a/scripts/plot/draw/peaks.m
+++ b/scripts/plot/draw/peaks.m
@@ -27,7 +27,7 @@
 ## The function has the form
 ##
 ## @tex
-## $$f(x,y) = 3 (1 - x) ^ 2 e ^ {\left(-x^2 - (y+1)^2\right)} - 10 \left({x \over 5} - x^3 - y^5)\right) - {1 \over 3} e^{\left(-(x+1)^2 - y^2\right)}$$
+## $$f(x,y) = 3 (1 - x) ^ 2 e ^ {\left(-x^2 - (y+1)^2\right)} - 10 \left({x \over 5} - x^3 - y^5\right) - {1 \over 3} e^{\left(-(x+1)^2 - y^2\right)}$$
 ## @end tex
 ## @ifnottex
 ## @verbatim
--- a/scripts/plot/draw/plotyy.m
+++ b/scripts/plot/draw/plotyy.m
@@ -22,7 +22,7 @@
 ## @deftypefnx {Function File} {} plotyy (@dots{}, @var{fun1}, @var{fun2})
 ## @deftypefnx {Function File} {} plotyy (@var{hax}, @dots{})
 ## @deftypefnx {Function File} {[@var{ax}, @var{h1}, @var{h2}] =} plotyy (@dots{})
-## Plot two sets of data with independent y-axes.
+## Plot two sets of data with independent y-axes and a common x-axis.
 ##
 ## The arguments @var{x1} and @var{y1} define the arguments for the first plot
 ## and @var{x1} and @var{y2} for the second.
@@ -40,7 +40,7 @@
 ## the principal axis in which to plot the @var{x1} and @var{y1} data.
 ##
 ## The return value @var{ax} is a vector with the axis handles of the two
-## y axes.  @var{h1} and @var{h2} are handles to the objects generated by the
+## y-axes.  @var{h1} and @var{h2} are handles to the objects generated by the
 ## plot commands.
 ##
 ## @example
@@ -57,113 +57,66 @@
 ## @seealso{plot}
 ## @end deftypefn
 
-function [Ax, H1, H2] = plotyy (varargin)
+function [ax, h1, h2] = plotyy (varargin)
 
-  ## Don't use __plt_get_axis_arg__ here as ax is a two vector for plotyy
-  if (nargin > 1 && length (varargin{1}) == 2 && ishandle (varargin{1}(1))
-      && ishandle (varargin{1}(2))
-      && all (floor (varargin{1}) != varargin{1}))
-    obj1 = get (varargin{1}(1));
-    obj2 = get (varargin{1}(2));
-    if (strcmp (obj1.type, "axes") || strcmp (obj2.type, "axes"))
-      ax = [obj1, obj2];
-      varargin(1) = [];
-      if (isempty (varargin))
-        varargin = {};
-      endif
-    else
-      error ("plotyy: expecting first argument to be axes handle");
-    endif
-    oldh = gca ();
-  else
-    f = get (0, "currentfigure");
-    if (isempty (f))
-      f = figure ();
-    endif
-    ca = get (f, "currentaxes");
-    if (isempty (ca))
-      ax = [];
-    elseif (ishandle (ca) && isprop (ca, "__plotyy_axes__"))
-      ax = get (ca, "__plotyy_axes__");
-    else
-      ax = ca;
-    endif
-    if (length (ax) > 2)
-      for i = 3 : length (ax)
-        delete (ax (i));
-      endfor
-      ax = ax(1:2);
-    elseif (length (ax) == 1)
-      ax(2) = axes ();
-      set (ax(2), "nextplot", get (ax(1), "nextplot"));
-    elseif (isempty (ax))
-      ax(1) = axes ();
-      ax(2) = axes ();
-      ca = ax(2);
-    endif
-    if (nargin < 2)
-      varargin = {};
-    endif
-    oldh = ca;
-  endif
+  [hax, varargin] = __plt_get_axis_arg__ ("plotyy", varargin{:});
 
-  if (nargin < 4)
+  nargin = numel (varargin);
+  if (nargin < 4 || nargin > 6)
     print_usage ();
   endif
 
+  oldfig = [];
+  if (! isempty (hax))
+    oldfig = get (0, "currentfigure");
+  endif
   unwind_protect
-    [ax, h1, h2] = __plotyy__ (ax, varargin{:});
+    hax = newplot (hax);
+
+    ## FIXME: Second conditional test shouldn't be required.
+    ##        'cla reset' needs to delete user properties like __plotyy_axes__.
+    if (isprop (hax, "__plotyy_axes__")
+        && isaxes (get (hax, "__plotyy_axes__")) == [true true])
+      hax = get (hax, "__plotyy_axes__");
+    else
+      hax(2) = axes ("nextplot", get (hax(1), "nextplot"));
+    endif
+
+    [axtmp, h1tmp, h2tmp] = __plotyy__ (hax, varargin{:});
+
+    set (gcf, "currentaxes", hax(1));
+     
   unwind_protect_cleanup
-    ## Only change back to the old axis if we didn't delete it
-    if (isaxes (oldh))
-      axes (oldh);
+    if (! isempty (oldfig))
+      set (0, "currentfigure", oldfig);
     endif
   end_unwind_protect
 
   if (nargout > 0)
-    Ax = ax;
-    H1 = h1;
-    H2 = h2;
+    ax = axtmp;
+    h1 = h1tmp;
+    h2 = h2tmp;
   endif
 
 endfunction
 
-function [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, varargin)
-  if (nargin > 5)
-    fun1 = varargin{1};
-  else
-    fun1 = @plot;
-  endif
-  if (nargin > 6)
-    fun2 = varargin{2};
-  else
+function [ax, h1, h2] = __plotyy__ (ax, x1, y1, x2, y2, fun1 = @plot, fun2)
+
+  if (nargin < 7)
     fun2 = fun1;
   endif
 
   xlim = [min([x1(:); x2(:)]), max([x1(:); x2(:)])];
 
-  if (isaxes (ax(1)))
-    axes (ax(1));
-  else
-    ax(1) = axes ();
-  endif
-  newplot ();
+  axes (ax(1));
+
   h1 = feval (fun1, x1, y1);
 
-  set (ax(1), "ycolor", getcolor (h1(1)));
-  set (ax(1), "xlim", xlim);
-  set (ax(1), "color", "none");
-
-  cf = gcf ();
-  set (cf, "nextplot", "add");
+  set (ax(1), "color", "none", "ycolor", getcolor (h1(1)), "xlim", xlim);
 
-  if (isaxes (ax(2)))
-    axes (ax(2));
-  else
-    ax(2) = axes ();
-    set (ax(2), "nextplot", get (ax(1), "nextplot"));
-  endif
-  newplot ();
+  set (gcf (), "nextplot", "add");
+
+  axes (ax(2));
 
   colors = get (ax(1), "colororder");
   set (ax(2), "colororder", [colors(2:end,:); colors(1,:)]);
@@ -174,35 +127,38 @@
     set (ax, "activepositionproperty", "position");
   endif
 
-  ## Kluge, until __plt_get_axis_arg__ and newplot are reworked. 
-  set (ax(2), "nextplot", "replacechildren");
+  ## Don't replace axis which has colororder property already modified
+  if (strcmp (get (ax(1), "nextplot"), "replace"))
+    set (ax(2), "nextplot", "replacechildren");
+  endif
   h2 = feval (fun2, ax(2), x2, y2);
-  set (ax(2), "yaxislocation", "right");
-  set (ax(2), "ycolor", getcolor (h2(1)));
+
+  set (ax(2), "yaxislocation", "right", "color", "none",
+              "ycolor", getcolor (h2(1)), "box", "off", "xlim", xlim);
 
   if (strcmp (get(ax(1), "activepositionproperty"), "position"))
     set (ax(2), "position", get (ax(1), "position"));
   else
-    set (ax(2), "outerposition", get (ax(1), "outerposition"));
-    set (ax(2), "looseinset", get (ax(1), "looseinset"));
+    set (ax(2), {"outerposition", "looseinset"},
+                get (ax(1), {"outerposition", "looseinset"}));
   endif
 
-  set (ax(2), "xlim", xlim);
-  set (ax(2), "color", "none");
-  set (ax(2), "box", "off");
+  ## Restore nextplot value by copying value from axis #1
+  set (ax(2), "nextplot", get (ax(1), "nextplot"));
 
   ## Add invisible text objects that when destroyed,
   ## also remove the other axis
   t1 = text (0, 0, "", "parent", ax(1), "tag", "plotyy",
-             "handlevisibility", "off", "visible", "off",
+             "visible", "off", "handlevisibility", "off",
              "xliminclude", "off", "yliminclude", "off");
   t2 = text (0, 0, "", "parent", ax(2), "tag", "plotyy",
-             "handlevisibility", "off", "visible", "off",
+             "visible", "off", "handlevisibility", "off",
              "xliminclude", "off", "yliminclude", "off");
 
   set (t1, "deletefcn", {@deleteplotyy, ax(2), t2});
   set (t2, "deletefcn", {@deleteplotyy, ax(1), t1});
 
+  ## Add cross-listeners so a change in one axes' attributes updates the other.
   addlistener (ax(1), "position", {@update_position, ax(2)});
   addlistener (ax(2), "position", {@update_position, ax(1)});
   addlistener (ax(1), "outerposition", {@update_position, ax(2)});
@@ -235,6 +191,80 @@
   endif
 endfunction
 
+function deleteplotyy (h, ~, ax2, t2)
+  if (isaxes (ax2)
+      && (isempty (gcbf ()) || strcmp (get (gcbf (), "beingdeleted"), "off"))
+      && strcmp (get (ax2, "beingdeleted"), "off"))
+    set (t2, "deletefcn", []);
+    delete (ax2);
+  endif
+endfunction
+
+function update_nextplot (h, ~, ax2)
+  persistent recursion = false;
+  if (! recursion)
+    unwind_protect
+      recursion = true;
+      set (ax2, "nextplot", get (h, "nextplot"));
+    unwind_protect_cleanup
+      recursion = false;
+    end_unwind_protect
+  endif
+endfunction
+
+function update_position (h, ~, ax2)
+  persistent recursion = false;
+
+  ## Don't allow recursion
+  if (! recursion)
+    unwind_protect
+      recursion = true;
+      view = get (h, "view");
+      oldview = get (ax2, "view");
+      plotboxaspectratio = get (h, "plotboxaspectratio");
+      oldplotboxaspectratio = get (ax2, "plotboxaspectratio");
+      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
+      oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode");
+
+      if (strcmp (get (h, "activepositionproperty"), "position"))
+        position = get (h, "position");
+        oldposition = get (ax2, "position");
+        if (! (isequal (position, oldposition) && isequal (view, oldview)))
+          set (ax2, "position", position, "view", view);
+        endif
+      else
+        outerposition = get (h, "outerposition");
+        oldouterposition = get (ax2, "outerposition");
+        if (! (isequal (outerposition, oldouterposition)
+               && isequal (view, oldview)))
+          set (ax2, "outerposition", outerposition, "view", view);
+        endif
+      endif
+
+      if (! (isequal (plotboxaspectratio, oldplotboxaspectratio)
+             && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode)))
+        set (ax2, "plotboxaspectratio", plotboxaspectratio,
+                  "plotboxaspectratiomode", plotboxaspectratiomode);
+      endif
+    unwind_protect_cleanup
+      recursion = false;
+    end_unwind_protect
+  endif
+endfunction
+
+function color = getcolor (ax)
+  obj = get (ax);
+  if (isfield (obj, "color"))
+    color = obj.color;
+  elseif (isfield (obj, "facecolor") && ! ischar (obj.facecolor))
+    color = obj.facecolor;
+  elseif (isfield (obj, "edgecolor") && ! ischar (obj.edgecolor))
+    color = obj.edgecolor;
+  else
+    color = [0, 0, 0];
+  endif
+endfunction
+
 
 %!demo
 %! clf;
@@ -245,12 +275,11 @@
 %! xlabel ('X');
 %! ylabel (ax(1), 'Axis 1');
 %! ylabel (ax(2), 'Axis 2');
-%! axes (ax(1));
 %! text (0.5, 0.5, 'Left Axis', ...
-%!       'color', [0 0 1], 'horizontalalignment', 'center');
-%! axes (ax(2));
+%!       'color', [0 0 1], 'horizontalalignment', 'center', 'parent', ax(1));
 %! text (4.5, 80, 'Right Axis', ...
-%!       'color', [0 0.5 0], 'horizontalalignment', 'center');
+%!       'color', [0 0.5 0], 'horizontalalignment', 'center', 'parent', ax(2));
+%! title ({"plotyy() example"; "Left axis uses @plot, Right axis uses @semilogy"});
 
 %!demo
 %! clf;
@@ -267,14 +296,6 @@
 %! axis square;
 
 %!demo
-%! clf;
-%! x = linspace (-1, 1, 201);
-%! hax = plotyy (x, sin (pi*x), x, cos (pi*x));
-%! ylabel (hax(1), 'Blue on the Left');
-%! ylabel (hax(2), 'Green on the Right');
-%! xlabel ('xlabel');
-
-%!demo
 %! clf
 %! hold on
 %! t = (0:0.1:9);
@@ -284,81 +305,7 @@
 %! [~, h3, h4] = plotyy (t+1, x, t+1, y);
 %! set ([h3, h4], 'linestyle', '--');
 %! xlabel (hax(1), 'xlabel');
-%! title (hax(2), 'title');
+%! title (hax(2), 'Two plotyy graphs on same figure using "hold on"');
 %! ylabel (hax(1), 'Left axis is Blue');
 %! ylabel (hax(2), 'Right axis is Green');
 
-function deleteplotyy (h, d, ax2, t2)
-  if (isaxes (ax2)
-      && (isempty (gcbf ()) || strcmp (get (gcbf (), "beingdeleted"),"off"))
-      && strcmp (get (ax2, "beingdeleted"), "off"))
-    set (t2, "deletefcn", []);
-    delete (ax2);
-  endif
-endfunction
-
-function update_nextplot (h, d, ax2)
-  persistent recursion = false;
-  prop = "nextplot";
-  if (! recursion)
-    unwind_protect
-      recursion = true;
-      set (ax2, prop, get (h, prop));
-    unwind_protect_cleanup
-      recursion = false;
-    end_unwind_protect
-  endif
-endfunction
-
-function update_position (h, d, ax2)
-  persistent recursion = false;
-
-  ## Don't allow recursion
-  if (! recursion)
-    unwind_protect
-      recursion = true;
-      view = get (h, "view");
-      oldview = get (ax2, "view");
-      plotboxaspectratio = get (h, "plotboxaspectratio");
-      oldplotboxaspectratio = get (ax2, "plotboxaspectratio");
-      plotboxaspectratiomode = get (h, "plotboxaspectratiomode");
-      oldplotboxaspectratiomode = get (ax2, "plotboxaspectratiomode");
-
-      if (strcmp (get(h, "activepositionproperty"), "position"))
-        position = get (h, "position");
-        oldposition = get (ax2, "position");
-        if (! (isequal (position, oldposition) && isequal (view, oldview)))
-          set (ax2, "position", position, "view", view);
-        endif
-      else
-        outerposition = get (h, "outerposition");
-        oldouterposition = get (ax2, "outerposition");
-        if (! (isequal (outerposition, oldouterposition) && isequal (view, oldview)))
-          set (ax2, "outerposition", outerposition, "view", view);
-        endif
-      endif
-
-      if (! (isequal (plotboxaspectratio, oldplotboxaspectratio)
-             && isequal (plotboxaspectratiomode, oldplotboxaspectratiomode)))
-        set (ax2, "plotboxaspectratio", plotboxaspectratio);
-        set (ax2, "plotboxaspectratiomode", plotboxaspectratiomode);
-      endif
-    unwind_protect_cleanup
-      recursion = false;
-    end_unwind_protect
-  endif
-endfunction
-
-function color = getcolor (ax)
-  obj = get (ax);
-  if (isfield (obj, "color"))
-    color = obj.color;
-  elseif (isfield (obj, "facecolor") && ! ischar (obj.facecolor))
-    color = obj.facecolor;
-  elseif (isfield (obj, "edgecolor") && !  ischar (obj.edgecolor))
-    color = obj.edgecolor;
-  else
-    color = [0, 0, 0];
-  endif
-endfunction
-
--- a/scripts/plot/draw/polar.m
+++ b/scripts/plot/draw/polar.m
@@ -36,6 +36,14 @@
 ##
 ## The optional return value @var{h} is a graphics handle to the created plot.
 ##
+## Implementation Note: The polar axis is drawn using line and text objects
+## encapsulated in an hggroup.  The hggroup properties are linked to the
+## original axes object such that altering an appearance property, for example
+## @code{fontname}, will update the polar axis.  Two new properties are
+## added to the original axes--@code{rtick}, @code{ttick}--which replace
+## @code{xtick}, @code{ytick}.  The first is a list of tick locations in the
+## radial (rho) direction; The second is a list of tick locations in the
+## angular (theta) direction specified in degrees, i.e., in the range 0--359.
 ## @seealso{rose, compass, plot}
 ## @end deftypefn
 
@@ -87,9 +95,46 @@
       print_usage ();
     endif
 
-    set (hax, "xlim", [-maxr, maxr], "ylim", [-maxr, maxr],
-              "xaxislocation", "zero", "yaxislocation", "zero",
-              "plotboxaspectratio", [1, 1, 1]);
+    ## FIXME: Should more gracefully handle "hold on" and not override props.
+    set (hax, "visible", "off", "plotboxaspectratio", [1, 1, 1],
+              "zlim", [-1 1]);
+
+    if (! isprop (hax, "rtick"))
+      addproperty ("rtick", hax, "data");
+    endif
+
+    ## calculate r(ho)tick from xtick
+    xtick = get (hax, "xtick");
+    rtick = xtick(find (xtick > 0, 1):find (xtick >= maxr, 1));
+    if (isempty (rtick))
+      rtick = [0.5 1];
+    endif
+    set (hax, "rtick", rtick);
+
+    ## add t(heta)tick
+    if (! isprop (hax, "ttick"))
+      addproperty ("ttick", hax, "data");
+    endif
+
+    ## theta(angular) ticks in degrees
+    set (hax, "ttick", 0:30:330);
+
+    ## Create hggroup to hold text/line objects and attach listeners
+    hg = hggroup (hax, "tag", "polar_grid", "handlevisibility", "off");
+    __update_polar_grid__(hax, [], hg);
+
+    addlistener (hax, "rtick", {@__update_polar_grid__, hg});
+    addlistener (hax, "ttick", {@__update_polar_grid__, hg});
+    addlistener (hax, "color", {@__update_patch__, hg});
+    addlistener (hax, "fontangle", {@__update_text__, hg, "fontangle"});
+    addlistener (hax, "fontname", {@__update_text__, hg, "fontname"});
+    addlistener (hax, "fontsize", {@__update_text__, hg, "fontsize"});
+    addlistener (hax, "fontunits", {@__update_text__, hg, "fontunits"});
+    addlistener (hax, "fontweight", {@__update_text__, hg, "fontweight"});
+    addlistener (hax, "interpreter", {@__update_text__, hg, "interpreter"});
+    addlistener (hax, "layer", {@__update_layer__, hg});
+    addlistener (hax, "gridlinestyle", {@__update_lines__, hg,"gridlinestyle"});
+    addlistener (hax, "linewidth", {@__update_lines__, hg, "linewidth"});
 
   unwind_protect_cleanup
     if (! isempty (oldfig))
@@ -193,6 +238,116 @@
 
 endfunction
 
+## Callback functions for listeners
+
+function __update_text__ (hax, ~, hg, prop)
+
+  kids = get (hg, "children");
+  idx = strcmp (get (kids, "type"), "text");
+  set (kids(idx).', prop, get (hax, prop));
+
+endfunction
+
+function __update_lines__ (hax,  ~, hg, prop)
+
+  kids = get (hg, "children");
+  idx = strcmp (get (kids, "type"), "line");
+  lprop = prop;
+  if (strcmp (prop, "gridlinestyle"))
+    lprop = "linestyle";
+  endif
+  set (kids(idx).', lprop, get (hax, prop));
+
+endfunction
+
+function __update_patch__ (hax, ~, hg)
+
+  kids = get (hg, "children");
+  idx = strcmp (get (kids, "type"), "patch");
+  set (kids(idx).', "facecolor", get (hax, "color"));
+
+endfunction
+
+function __update_layer__ (hax,  ~, hg)
+
+  set (hg, "handlevisibility", "on");
+  kids = get (hax, "children");
+  if (strcmp (get (hax, "layer"), "bottom"))
+    set (hax, "children", [kids(kids != hg); hg]); 
+  else
+    set (hax, "children", [hg; kids(kids != hg)]); 
+  endif
+  set (hg, "handlevisibility", "off");
+
+endfunction
+
+function __update_polar_grid__ (hax, ~, hg)
+
+  ## Delete existing polar grid
+  delete (get (hg, "children"));
+
+  rtick = unique (get (hax, "rtick")(:)');
+  rtick = rtick(rtick > 0);
+  if (isempty (rtick))
+    rtick = [0.5 1];
+  endif
+
+  ttick = unique (get (hax, "ttick")(:)');
+  ttick = ttick(ttick >= 0);
+  if (isempty (ttick))
+    ttick = 0:30:330;
+  endif
+
+  lprops = {"linestyle", get(hax, "gridlinestyle"), ...
+            "linewidth", get(hax, "linewidth")};
+  ## "fontunits" should be first because it affects "fontsize" property.
+  tprops(1:2:12) = {"fontunits", "fontangle", "fontname", "fontsize", ...
+                    "fontweight", "interpreter"};
+  tprops(2:2:12) = get (hax, tprops(1:2:12));
+
+  ## The number of points used for a circle
+  circle_points = 50;
+  t = linspace (0, 2*pi, circle_points)';
+  x = kron (cos (t), rtick);
+  y = kron (sin (t), rtick);
+
+  ## Draw colored disk under axes at Z-depth = -1
+  patch (x(:,end), y(:,end), -ones (circle_points, 1),
+         get (hax, "color"), "parent", hg);
+
+  ## Plot dotted circles
+  line (x(:,1:end-1), y(:,1:end-1), lprops{:}, "parent", hg);
+
+  ## Outer circle is drawn solid
+  line (x(:,end), y(:,end), lprops{:}, "linestyle", "-", "parent", hg);
+
+  ## Add radial labels
+  [x, y] = pol2cart (0.42 * pi, rtick);
+  text (x, y, num2cell (rtick), "verticalalignment", "bottom", tprops{:},
+        "parent", hg);
+
+  ## add radial lines
+  s = rtick(end) * sin (ttick * pi / 180);
+  c = rtick(end) * cos (ttick * pi / 180);
+  x = [zeros(1, numel (ttick)); c];
+  y = [zeros(1, numel (ttick)); s];
+  line (x, y, "linestyle", ":", lprops{:}, "parent", hg);
+
+  ## add angular labels
+  tticklabel = num2cell (ttick);
+  ## FIXME: This tm factor does not work as fontsize increases
+  tm = 1.08;
+  text (tm * c, tm * s, tticklabel, "horizontalalignment", "center",
+        tprops{:}, "parent", hg);
+
+  lim = 1.1 * rtick(end);
+  set (hax, "xlim", [-lim, lim], "ylim", [-lim, lim]);
+
+  ## Put polar grid behind or ahead of plot
+  __update_layer__ (hax, [], hg);
+
+endfunction
+
 
 %!demo
 %! clf;
@@ -210,8 +365,25 @@
 
 %!demo
 %! clf;
+%! theta = linspace (0,2*pi,1000);
+%! rho = sin (2*theta).*cos (2*theta);
+%! polar (theta, rho, '--r');
+%! set (gca, "rtick", 0.1:0.1:0.6, "ttick", 0:20:340);
+%! title ('polar() plot with finer grid');
+
+%!demo
+%! clf;
+%! theta = linspace (0,2*pi,1000);
+%! rho = sin (2*theta).*cos (2*theta);
+%! polar (theta, rho, '--b');
+%! set (gca, "fontsize", 12, "linewidth", 2, "color", [0.8 0.8 0.8]);
+%! title ('polar() plot with modified axis appearance');
+
+%!demo
+%! clf;
 %! theta = linspace (0,8*pi,1000);
 %! rho = sin (5/4*theta);
 %! polar (theta, rho);
+%! set (gca, "rtick", 0.2:0.2:1);
 %! title ('polar() plot');
 
--- a/scripts/plot/draw/private/__ezplot__.m
+++ b/scripts/plot/draw/private/__ezplot__.m
@@ -448,8 +448,12 @@
       axis (hax, domain);
     elseif (isplot || ispolar)
       h = feval (pltfunc, hax, X, Z);
-      if (isplot && ! parametric)
-        axis (hax, domain);
+      if (isplot)
+        if (! parametric)
+          axis (hax, domain);
+        else
+          axis ("equal");
+        endif
       endif
     elseif (isplot3)
       if (animate)
--- a/scripts/plot/draw/private/__patch__.m
+++ b/scripts/plot/draw/private/__patch__.m
@@ -70,7 +70,7 @@
         y = varargin{2};
         iarg = 4;
         if (rem (nargin - iarg, 2) == 1)
-          c = varargin {iarg};
+          c = varargin{iarg};
           z = varargin{3};
           iarg = 5;
         else
@@ -83,7 +83,7 @@
         z = [];
         iarg = 3;
         if (rem (nargin - iarg, 2) == 1)
-          c = varargin {iarg};
+          c = varargin{iarg};
           iarg++; 
         else
           c = [];
@@ -127,7 +127,7 @@
             args{9} = "cdata";
             args{10} = c;
           else
-            error ("patch: color value not valid");
+            error ("patch: color data C must be numeric");
           endif
         elseif (isvector (c) && numel (c) == 3)
           args{7} = "facecolor";
@@ -150,7 +150,7 @@
             args{9} = "cdata";
             args{10} = c;
           else
-            error ("patch: color value not valid");
+            error ("patch: Invalid TrueColor data C");
           endif
         else
           ## Color Vectors
@@ -159,18 +159,17 @@
             args{8} = "interp";
             args{9} = "cdata";
             args{10} = [];
-          elseif (isequal (size (c), size (x)) && isequal (size (c), size (y)))
+          elseif (size_equal (c, x) && size_equal (c, y))
             args{7} = "facecolor";
             args{8} = "interp";
             args{9} = "cdata";
             args{10} = c;
           else
-            error ("patch: size of x, y, and c must be equal");
+            error ("patch: size of X, Y, and C must be equal");
           endif
         endif
       elseif (ischar (c) && rem (nargin - iarg, 2) == 0)
-        ## Assume that any additional argument over an even number is
-        ## color string.
+        ## Assume any additional argument over an even number is a color string.
         args{7} = "facecolor";
         args{8} =  tolower (c);
         args{9} = "cdata";
@@ -195,7 +194,7 @@
   endif
 
   if (!failed)
-    h = __go_patch__ (p, args {:});
+    h = __go_patch__ (p, args{:});
 
     ## Setup listener functions
     addlistener (h, "xdata", @update_data);
@@ -229,19 +228,19 @@
   if (idx > nargs)
     faces = [];
   else
-    faces = args {idx};
+    faces = args{idx};
   endif
   idx = find (strcmpi (args, "vertices"), 1, "last") + 1;
   if (idx > nargs)
     vert = [];
   else
-    vert = args {idx};
+    vert = args{idx};
   endif
   idx = find (strcmpi (args, "facevertexcdata"), 1, "last") + 1;
   if (isempty (idx) || idx > nargs)
     fvc = [];
   else
-    fvc = args {idx};
+    fvc = args{idx};
   endif
   idx = find (strcmpi (args, "facecolor"), 1, "last") + 1;
   if (isempty (idx) || idx > nargs)
@@ -254,7 +253,7 @@
   endif
 
   nc = rows (faces);
-  idx = faces .';
+  idx = faces.';
   t1 = isnan (idx);
   for i = find (any (t1))
     first_idx_in_column = find (t1(:,i), 1);
@@ -273,11 +272,11 @@
   else
     if (columns (fvc) == 3)
       c = cat (3, reshape (fvc(idx, 1), size (idx)),
-               reshape (fvc(idx, 2), size (idx)),
-               reshape (fvc(idx, 3), size (idx)));
+                  reshape (fvc(idx, 2), size (idx)),
+                  reshape (fvc(idx, 3), size (idx)));
     elseif (isempty (fvc))
       c = [];
-    else ## if (columnns (fvc) == 1)
+    else  ## if (columnns (fvc) == 1)
       c = permute (fvc(faces), [2, 1]);
     endif
   endif
@@ -293,25 +292,25 @@
   if (idx > nargs)
     x = [];
   else
-    x = args {idx};
+    x = args{idx};
   endif
   idx = find (strcmpi (args, "ydata"), 1, "last") + 1;
   if (idx > nargs)
     y = [];
   else
-    y = args {idx};
+    y = args{idx};
   endif
   idx = find (strcmpi (args, "zdata"), 1, "last") + 1;
   if (isempty (idx) || idx > nargs)
     z = [];
   else
-    z = args {idx};
+    z = args{idx};
   endif
   idx = find (strcmpi (args, "cdata"), 1, "last") + 1;
   if (isempty (idx) || idx > nargs)
     c = [];
   else
-    c = args {idx};
+    c = args{idx};
   endif
   idx = find (strcmpi (args, "facecolor"), 1, "last") + 1;
   if (isempty (idx) || idx > nargs)
@@ -328,13 +327,13 @@
     nr = nc;
     nc = 1;
   endif
-  if (!isempty (z))
+  if (isempty (z))
+    vert = [x(:), y(:)];
+  else
     vert = [x(:), y(:), z(:)];
-  else
-    vert = [x(:), y(:)];
   endif
   faces = reshape (1:numel (x), nr, nc);
-  faces = faces';
+  faces = faces.';
 
   if (ndims (c) == 3)
     fvc = reshape (c, rows (c) * columns (c), size (c, 3));
--- a/scripts/plot/draw/private/__scatter__.m
+++ b/scripts/plot/draw/private/__scatter__.m
@@ -84,6 +84,21 @@
     c = [];
   endif
 
+  ## Validate inputs
+  if (nd == 2 && ! size_equal (x, y)) 
+    error ([fcn ": X and Y must have the same size"]);
+  elseif (nd == 3 && ! size_equal (x, y, z)) 
+    error ([fcn ": X, Y, and Z must have the same size"]);
+  endif
+
+  if (! isscalar (s) && ! size_equal (x, s))
+    error ([fcn ": size of S must match X, Y, and Z"]);
+  endif
+
+  if (rows (c) > 1 && rows (c) != rows (x))
+    error ([fcn ": number of colors in C must match number of points in X"]);
+  endif
+
   newargs = {};
   filled = false;
   have_marker = false;
--- a/scripts/plot/draw/private/__stem__.m
+++ b/scripts/plot/draw/private/__stem__.m
@@ -48,6 +48,8 @@
 
     h = [];
     nx = rows (x);
+    h_baseline = [];
+    
     for i = 1 : columns (x)
       if (have_z)
         xt = x(:)';
@@ -90,19 +92,19 @@
         __line__ (hax, xt, yt, zt, "color", lc, "linestyle", ls, "parent", hg);
         __line__ (hax, x, y, z, "color", mc, "linestyle", "none",
                        "marker", ms, "markerfacecolor", fc, "parent", hg);
-        h_baseline = [];
       else
         __line__ (hax, xt, yt, "color", lc, "linestyle", ls, "parent", hg);
         __line__ (hax, x(:,i), y(:, i), "color", mc, "linestyle", "none",
                        "marker", ms, "markerfacecolor", fc, "parent", hg);
+        
         x_axis_range = get (hax, "xlim");
-        h_baseline = line (hax, x_axis_range, [0, 0], "color", [0, 0, 0]);
-        set (h_baseline, "handlevisibility", "off", "xliminclude", "off");
-        addlistener (hax, "xlim", @update_xlim);
-        addproperty ("basevalue", h_baseline, "data", 0);
-        addlistener (h_baseline, "basevalue", {@update_baseline, 0});
-        addlistener (h_baseline, "ydata", {@update_baseline, 1});
-        addlistener (h_baseline, "visible", {@update_baseline, 2});
+        if (isempty (h_baseline))
+          h_baseline = line (hax, x_axis_range, [0, 0], "color", [0, 0, 0]);
+          set (h_baseline, "handlevisibility", "off", "xliminclude", "off");
+          addproperty ("basevalue", h_baseline, "data", 0);
+        else
+          set (h_baseline, "xdata", x_axis_range);
+        endif
       endif
 
       ## Setup the hggroup and listeners.
@@ -110,11 +112,6 @@
       addproperty ("baseline", hg, "data", h_baseline);
       addproperty ("basevalue", hg, "data", 0);
 
-      if (! have_z)
-        addlistener (hg, "showbaseline", @show_baseline);
-        addlistener (hg, "basevalue", @move_baseline);
-      endif
-
       addproperty ("color", hg, "linecolor", lc);
       addproperty ("linestyle", hg, "linelinestyle", ls);
       addproperty ("linewidth", hg, "linelinewidth", 0.5);
@@ -146,14 +143,28 @@
       ## Matlab property, although Octave does not implement it.
       addproperty ("hittestarea", hg, "radio", "on|{off}", "off");
 
-      if (! isempty (args))
-        set (hg, args{:});
-      endif
-      if (i == 1 && ! isempty (h_baseline))
-        set (h_baseline, "parent", get (hg, "parent"));
-      endif
     endfor
 
+    ## baseline listeners
+    if (! isempty (h_baseline))
+      addlistener (hax, "xlim", @update_xlim);
+      for hg = h'
+        addlistener (hg, "showbaseline", @show_baseline);
+        addlistener (hg, "visible", {@show_baseline, h});
+        addlistener (hg, "basevalue", @move_baseline);
+      endfor
+      
+      addlistener (h_baseline, "basevalue", {@update_baseline, 0});
+      addlistener (h_baseline, "ydata", {@update_baseline, 1});
+      addlistener (h_baseline, "visible", {@update_baseline, 2});
+      set (h_baseline, "parent", get (hg(1), "parent"));
+    endif
+
+    ## property/value pairs
+    if (! isempty (args))
+        set (h, args{:});
+    endif
+
     if (! strcmp (hold_state, "add") && have_z)
       set (hax, "view", [-37.5 30],
                 "xgrid", "on", "ygrid", "on", "zgrid", "on");
@@ -365,8 +376,16 @@
   endfor
 endfunction
 
-function show_baseline (h, ~)
-  set (get (h, "baseline"), "visible", get (h, "showbaseline"));
+function show_baseline (h, ~, hg = [])
+  if (isempty (hg))
+    set (get (h, "baseline"), "visible", get (h, "showbaseline"));
+  else
+    if (all (strcmp (get (hg, "visible"), "off")))
+      set (get (h, "baseline"), "visible", "off");
+    else
+      set (get (h, "baseline"), "visible", "on");
+    endif
+  endif
 endfunction
 
 function move_baseline (h, ~)
@@ -374,6 +393,7 @@
   bl = get (h, "baseline");
 
   set (bl, "ydata", [b0, b0]);
+  set (bl, "basevalue", b0);
 
   kids = get (h, "children");
   yt = get (h, "ydata")(:)';
--- a/scripts/plot/draw/shrinkfaces.m
+++ b/scripts/plot/draw/shrinkfaces.m
@@ -23,24 +23,29 @@
 ## @deftypefnx {Function File} {@var{nfv} =} shrinkfaces (@var{f}, @var{v}, @var{sf})
 ## @deftypefnx {Function File} {[@var{nf}, @var{nv}] =} shrinkfaces (@dots{})
 ##
-## Reduce the faces area for a given patch, structure or explicit faces
-## and points matrices by a scale factor @var{sf}.  The structure
-## @var{fv} must contain the fields @qcode{"faces"} and @qcode{"vertices"}. 
-## If the factor @var{sf} is omitted then a default of 0.3 is used.
+## Reduce the size of faces in a patch by the shrink factor @var{sf}.
+##
+## The patch object can be specified by a graphics handle (@var{p}), a patch
+## structure (@var{fv}) with the fields @qcode{"faces"} and @qcode{"vertices"},
+## or as two separate matrices (@var{f}, @var{v}) of faces and vertices.
 ##
-## Given a patch handle as the first input argument and no output
-## parameters, perform the shrinking of the patch faces in place and
-## redraw the patch.
+## The shrink factor @var{sf} is a positive number specifying the percentage
+## of the original area the new face will occupy.  If no factor is given the
+## default is 0.3 (a reduction to 30% of the original size).  A factor greater
+## than 1.0 will result in the expansion of faces.
+##
+## Given a patch handle as the first input argument and no output parameters,
+## perform the shrinking of the patch faces in place and redraw the patch.
 ##
 ## If called with one output argument, return a structure with fields
 ## @qcode{"faces"}, @qcode{"vertices"}, and @qcode{"facevertexcdata"}
-## containing the data after shrinking which can then directly be used as an
-## input argument for the @code{patch} function.
+## containing the data after shrinking.  This structure can be used directly
+## as an input argument to the @code{patch} function.
 ##
-## Performing the shrinking on faces which are not convex can lead to
-## undesired results.
+## @strong{Caution:}: Performing the shrink operation on faces which are not
+## convex can lead to undesirable results.
 ##
-## For example,
+## Example: a triangulated 3/4 circle and the corresponding shrunken version.
 ##
 ## @example
 ## @group
@@ -56,9 +61,6 @@
 ## @end group
 ## @end example
 ##
-## @noindent
-## draws a triangulated 3/4 circle and the corresponding shrunken
-## version.
 ## @seealso{patch}
 ## @end deftypefn
 
@@ -71,8 +73,8 @@
   endif
   
   sf = 0.3;
+  colors = [];
   p = varargin{1};
-  colors = [];
 
   if (ishandle (p) && nargin < 3)
     faces = get (p, "Faces");
@@ -104,8 +106,8 @@
     error ("shrinkfaces: scale factor must be a positive scalar");
   endif
 
-  n = columns (vertices);
-  if (n < 2 || n > 3)
+  nc = columns (vertices);
+  if (nc < 2 || nc > 3)
     error ("shrinkfaces: only 2-D and 3-D patches are supported");
   endif
 
@@ -120,14 +122,12 @@
   elseif (rows (colors) == rows (vertices))
     c = colors(faces'(:), :);
   else
-    ## Discard inconsistent color data.
-    c = [];
+    c = [];  # Discard inconsistent color data.
   endif
   sv = rows (v);
-  ## we have to deal with a probably very large number of vertices, so
-  ## use sparse we use as midpoint (1/m, ..., 1/m) in generalized
-  ## barycentric coordinates.
-  midpoints = full (kron ( speye (sv / m), ones (m, m) / m) * sparse (v));
+  ## We have to deal with a possibly very large number of vertices, so use
+  ## sparse as midpoint (1/m, ..., 1/m) in generalized barycentric coordinates.
+  midpoints = full (kron (speye (sv / m), ones (m, m) / m) * sparse (v));
   v = sqrt (sf) * (v - midpoints) + midpoints;
   f = reshape (1:sv, m, sv / m)';
   
@@ -216,3 +216,13 @@
 %!assert (size (nfv.vertices), [3 3])
 %!assert (norm (nfv2.vertices - vertices), 0, 2*eps)
 
+%% Test input validation
+%!error shrinkfaces ()
+%!error shrinkfaces (1,2,3,4)
+%!error [a,b,c] = shrinkfaces (1)
+%!error <scale factor must be a positive scalar> shrinkfaces (nfv, ones (2))
+%!error <scale factor must be a positive scalar> shrinkfaces (nfv, 0)
+%!error <only 2-D and 3-D patches are supported> shrinkfaces (faces, ones (3,1))
+%!error <only 2-D and 3-D patches are supported> shrinkfaces (faces, ones (3,4))
+%!error <faces must consist of at least 3 vertices> shrinkfaces (faces(1:2), vertices)
+
--- a/scripts/plot/draw/stem.m
+++ b/scripts/plot/draw/stem.m
@@ -187,7 +187,7 @@
 %! y = [sin(x), cos(x)];
 %! h = stem (x, y);
 %! set (h(2), 'color', 'g');
-%! set (h(1), 'basevalue', -1);
+%! set (h(1), 'basevalue', -0.75);
 %! title ('stem plots modified through hggroup handle');
 
 %!demo
@@ -213,3 +213,18 @@
 %!error <inconsistent sizes for X and Y> stem (ones (2,2), ones (3,3))
 %!error <No value specified for property "FOO"> stem (1, "FOO")
 
+%!test
+%! ## stemseries share the same baseline and basevalue
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   h = stem ([1 2; 1.5 2.5], [1 1;2 2]);
+%!   assert (get (h(1), "baseline"), get (h(2), "baseline"))
+%!   bv = 0.3;
+%!   set (h(1), "basevalue", bv)
+%!   assert (get (get (h(1), "baseline"), "basevalue"), bv)
+%!   assert (get (h(1), "basevalue"), bv)
+%!   assert (get (h(2), "basevalue"), bv)
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
--- a/scripts/plot/draw/stemleaf.m
+++ b/scripts/plot/draw/stemleaf.m
@@ -185,7 +185,7 @@
   hl = xs(hlidx);               # lower hinge
   hu = xs(huidx);               # upper hinge
   h_spread = hu - hl;           # h_spread: difference between hinges
-  step = 1.5*h_spread;          # step: 1.5 * h_spread
+  step = fix(1.5*h_spread);     # step: 1.5 * h_spread
   i_fence_l = hl - step;        # inner fences: outside hinges + step
   o_fence_l = hl - 2*step;      # outer fences: outside hinges + 2*step
   i_fence_h = hu + step;
@@ -349,13 +349,13 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     #138|___________________"      ,     
-%! "     M 69|          52      |"      ,     
+%! "     #138|___________________"      ,
+%! "     M 69|          52      |"      ,
 %! "     H 35|   30          116|   86" ,
 %! "     1   |  -28          146|"      ,
 %! "               _______"             ,
 %! "         ______|  129|_______"      ,
-%! "        f|  -99          245|"      ,     
+%! "        f|  -99          245|"      ,
 %! "         |    0            0|  out" ,
 %! "        F| -228          374|"      ,
 %! "         |    0            0|  far" ,
@@ -389,13 +389,13 @@
 %! " "                                   ,
 %! "         Fenced Letter Display"      ,
 %! " "                                   ,
-%! "     # 14|___________________"       ,     
-%! "     M  7|          22      |"       ,     
+%! "     # 14|___________________"       ,
+%! "     M  7|          22      |"       ,
 %! "     H  4|   12           42|   30"  ,
 %! "     1   |    5           52|"       ,
 %! "               _______"              ,
 %! "         ______|   45|_______"       ,
-%! "        f|  -33           87|"       ,     
+%! "        f|  -33           87|"       ,
 %! "         |    0            0|  out"  ,
 %! "        F|  -78          132|"       ,
 %! "         |    0            0|  far"  ,
@@ -418,13 +418,13 @@
 %! " "                                   ,
 %! "         Fenced Letter Display"      ,
 %! " "                                   ,
-%! "     # 14|___________________"       ,     
-%! "     M  7|         -28      |"       ,     
+%! "     # 14|___________________"       ,
+%! "     M  7|         -28      |"       ,
 %! "     H  4|  -42          -12|   30"  ,
 %! "     1   |  -52           -5|"       ,
 %! "               _______"              ,
 %! "         ______|   45|_______"       ,
-%! "        f|  -87           33|"       ,     
+%! "        f|  -87           33|"       ,
 %! "         |    0            0|  out"  ,
 %! "        F| -132           78|"       ,
 %! "         |    0            0|  far"  ,
@@ -446,15 +446,15 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     # 15|___________________"      ,     
-%! "     M  8|          22      |"      ,     
+%! "     # 15|___________________"      ,
+%! "     M  8|          22      |"      ,
 %! "     H  4|   11           42|   31" ,
 %! "     1   |    0           52|"      ,
 %! "               _______"             ,
 %! "         ______|   46|_______"      ,
-%! "        f|  -35           88|"      ,     
+%! "        f|  -35           88|"      ,
 %! "         |    0            0|  out" ,
-%! "        F|  -82          135|"      ,
+%! "        F|  -81          134|"      ,
 %! "         |    0            0|  far" ,
 %! " "                                  ,
 %! "   0 | 20"                          ,
@@ -475,15 +475,15 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     # 15|___________________"      ,     
-%! "     M  8|         -22      |"      ,     
+%! "     # 15|___________________"      ,
+%! "     M  8|         -22      |"      ,
 %! "     H  4|  -42          -11|   31" ,
 %! "     1   |  -52            0|"      ,
 %! "               _______"             ,
 %! "         ______|   46|_______"      ,
-%! "        f|  -88           35|"      ,     
+%! "        f|  -88           35|"      ,
 %! "         |    0            0|  out" ,
-%! "        F| -135           82|"      ,
+%! "        F| -134           81|"      ,
 %! "         |    0            0|  far" ,
 %! " "                                  ,
 %! "  -5 | 2"                           ,
@@ -503,15 +503,15 @@
 %! " "                                  ,
 %! "         Fenced Letter Display"     ,
 %! " "                                  ,
-%! "     #  5|___________________"      ,     
-%! "     M  3|           0      |"      ,     
+%! "     #  5|___________________"      ,
+%! "     M  3|           0      |"      ,
 %! "     H  2|   -7            0|   7"  ,
 %! "     1   |   -9            0|"      ,
 %! "               _______"             ,
 %! "         ______|   10|_______"      ,
-%! "        f|  -17           10|"      ,     
+%! "        f|  -17           10|"      ,
 %! "         |    0            0|  out" ,
-%! "        F|  -28           21|"      ,
+%! "        F|  -27           20|"      ,
 %! "         |    0            0|  far" ,
 %! " "                                  ,
 %! "  -0 | 9700"                        ,
@@ -527,15 +527,15 @@
 %! " "                                    ,
 %! "         Fenced Letter Display"       ,
 %! " "                                    ,
-%! "     #  4|___________________"        ,     
-%! "     M  2|          -7      |"        ,     
+%! "     #  4|___________________"        ,
+%! "     M  2|          -7      |"        ,
 %! "     H  1|   -9            0|   9"    ,
 %! "     1   |   -9            0|"        ,
 %! "               _______"               ,
 %! "         ______|   13|_______"        ,
-%! "        f|  -22           13|"        ,     
+%! "        f|  -22           13|"        ,
 %! "         |    0            0|  out"   ,
-%! "        F|  -36           27|"        ,
+%! "        F|  -35           26|"        ,
 %! "         |    0            0|  far"   ,
 %! " "                                    ,
 %! "  -0 | 970"                           ,
@@ -552,7 +552,7 @@
 %! " "                                      ,
 %! "         Fenced Letter Display"         ,
 %! " "                                      ,
-%! "     # 17|___________________"          ,          
+%! "     # 17|___________________"          ,
 %! "     M  9|         895      |"          ,
 %! "     H  5|  795         1499|   704"    ,
 %! "     1   |  150         1995|"          ,
--- a/scripts/plot/draw/surface.m
+++ b/scripts/plot/draw/surface.m
@@ -73,109 +73,110 @@
 
   h = 0;
   bad_usage = false;
-  firststring = nargin;
-  for i = 1 : (nargin - 1)
-    if (ischar (varargin{i}))
-      firststring = i;
-      break;
-    endif
-  endfor
+  firststring = find (cellfun ("isclass", varargin, "char"), 1);
+  if (isempty (firststring))
+    firststring = nargin;
+  endif
 
-  if (firststring > 5)
-    bad_usage = true;
-    return;
-  elseif (firststring == 5)
-    x = varargin{1};
-    y = varargin{2};
-    z = varargin{3};
-    c = varargin{4};
+  switch (firststring)
+    case 5
+      x = varargin{1};
+      y = varargin{2};
+      z = varargin{3};
+      c = varargin{4};
 
-    if (iscomplex (x) || iscomplex (y) || iscomplex (z) || iscomplex (c))
-      error ("mesh: X, Y, Z, C arguments must be real");
-    endif
+      if (iscomplex (x) || iscomplex (y) || iscomplex (z) || iscomplex (c))
+        error ("mesh: X, Y, Z, C arguments must be real");
+      endif
+
+      [z_nr, z_nc] = size (z);
+      [c_nr, c_nc, c_np] = size (c);
+      if (! (z_nr == c_nr && z_nc == c_nc && (c_np == 1 || c_np == 3)))
+        error ("surface: Z and C must have the same size");
+      endif
 
-    [z_nr, z_nc] = size (z);
-    [c_nr, c_nc, c_np] = size (c);
-    if (! (z_nr == c_nr && z_nc == c_nc && (c_np == 1 || c_np == 3)))
-      error ("surface: Z and C must have the same size");
-    endif
-
-    if (isvector (x) && isvector (y) && ismatrix (z))
-      if (rows (z) == length (y) && columns (z) == length (x))
-        x = x(:)';
-        y = y(:);
+      if (isvector (x) && isvector (y) && ismatrix (z))
+        if (rows (z) == length (y) && columns (z) == length (x))
+          x = x(:)';
+          y = y(:);
+        else
+          error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
+        endif
+      elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
+        if (! size_equal (x, y, z))
+          error ("surface: X, Y, and Z must have the same dimensions");
+        endif
       else
-        error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
+        error ("surface: X and Y must be vectors and Z must be a matrix");
       endif
-    elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
-      if (! size_equal (x, y, z))
-        error ("surface: X, Y, and Z must have the same dimensions");
+
+    case 4
+      x = varargin{1};
+      y = varargin{2};
+      z = varargin{3};
+      c = z;
+
+      if (iscomplex (x) || iscomplex (y) || iscomplex (z))
+        error ("mesh: X, Y, Z arguments must be real");
       endif
-    else
-      error ("surface: X and Y must be vectors and Z must be a matrix");
-    endif
-  elseif (firststring == 4)
-    x = varargin{1};
-    y = varargin{2};
-    z = varargin{3};
-    c = z;
-
-    if (iscomplex (x) || iscomplex (y) || iscomplex (z))
-      error ("mesh: X, Y, Z arguments must be real");
-    endif
 
-    if (isvector (x) && isvector (y) && ismatrix (z))
-      if (rows (z) == length (y) && columns (z) == length (x))
-        x = x(:)';
-        y = y(:);
+      if (isvector (x) && isvector (y) && ismatrix (z))
+        if (rows (z) == length (y) && columns (z) == length (x))
+          x = x(:)';
+          y = y(:);
+        else
+          error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
+        endif
+      elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
+        if (! size_equal (x, y, z))
+          error ("surface: X, Y, and Z must have the same dimensions");
+        endif
       else
-        error ("surface: rows (Z) must be the same as length (Y) and columns (Z) must be the same as length (X)");
-      endif
-    elseif (ismatrix (x) && ismatrix (y) && ismatrix (z))
-      if (! size_equal (x, y, z))
-        error ("surface: X, Y, and Z must have the same dimensions");
+        error ("surface: X and Y must be vectors and Z must be a matrix");
       endif
-    else
-      error ("surface: X and Y must be vectors and Z must be a matrix");
-    endif
-  elseif (firststring == 3)
-    z = varargin{1};
-    c = varargin{2};
 
-    if (iscomplex (z) || iscomplex (c))
-      error ("mesh: X, C arguments must be real");
-    endif
+    case 3
+      z = varargin{1};
+      c = varargin{2};
+
+      if (iscomplex (z) || iscomplex (c))
+        error ("mesh: X, C arguments must be real");
+      endif
 
-    if (ismatrix (z) && !isvector (z) && !isscalar (z))
-      [nr, nc] = size (z);
-      x = 1:nc;
-      y = (1:nr)';
-    else
-      error ("surface: Z argument must be a matrix");
-    endif
-  elseif (firststring == 2)
-    z = varargin{1};
-    c = z;
+      if (ismatrix (z) && !isvector (z) && !isscalar (z))
+        [nr, nc] = size (z);
+        x = 1:nc;
+        y = (1:nr)';
+      else
+        error ("surface: Z argument must be a matrix");
+      endif
 
-    if (iscomplex (z))
-      error ("mesh: Z argument must be real");
-    endif
+    case 2
+      z = varargin{1};
+      c = z;
+
+      if (iscomplex (z))
+        error ("mesh: Z argument must be real");
+      endif
 
-    if (ismatrix (z) && !isvector (z) && !isscalar (z))
-      [nr, nc] = size (z);
-      x = 1:nc;
-      y = (1:nr)';
-    else
-      error ("surface: Z argument must be a matrix");
-    endif
-  elseif (firststring == 1)
-    x = 1:3;
-    y = x';
-    c = z = eye (3);
-  else
-    bad_usage = true;
-    return;
-  endif
+      if (ismatrix (z) && !isvector (z) && !isscalar (z))
+        [nr, nc] = size (z);
+        x = 1:nc;
+        y = (1:nr)';
+      else
+        error ("surface: Z argument must be a matrix");
+      endif
+
+    case 1
+      x = 1:3;
+      y = x';
+      c = z = eye (3);
+
+    otherwise
+      bad_usage = true;
+      return;
+  
+  endswitch
 
   if (firststring < nargin)
     other_args = varargin(firststring:end);
--- a/scripts/plot/draw/surfl.m
+++ b/scripts/plot/draw/surfl.m
@@ -164,7 +164,7 @@
     endif
 
     vn = get (htmp, "vertexnormals");
-    dar = get (hax, "plotboxaspectratio");
+    dar = get (hax, "dataaspectratio");
     vn(:,:,1) *= dar(1);
     vn(:,:,2) *= dar(2);
     vn(:,:,3) *= dar(3);
@@ -206,8 +206,7 @@
 %! clf;
 %! [X,Y,Z] = sombrero ();
 %! colormap (copper (64));
-%! [az, el] = view ();
-%! surfl (X,Y,Z, [az+225,el], [0.2 0.6 0.4 25]);
+%! surfl (X,Y,Z, [62.50,30], [0.2 0.6 0.4 25]);
 %! shading interp;
 %! title ('surfl() with lighting vector and material properties');
 
--- a/scripts/plot/util/colstyle.m
+++ b/scripts/plot/util/colstyle.m
@@ -36,10 +36,7 @@
   try
     opt = __pltopt__ ("colstyle", style);
     l = opt.linestyle;
-    c = opt.color;
-    m = opt.marker;
-    msg = [];
-    switch (c)
+    switch (opt.color)
       case [0 0 0]
         c = "k";
       case [1 0 0]
@@ -56,7 +53,11 @@
         c = "c";
       case [0 1 1]
         c = "w";
+      otherwise
+        c = opt.color;
     endswitch
+    m = opt.marker;
+    msg = [];
   catch
     l = c = m = [];
     msg = lasterr ();
@@ -86,5 +87,5 @@
 %% Test input validation
 %!error colstyle ()
 %!error colstyle (1, 2)
-%!error colstyle (1.5)
+%!error <STYLE must be a string> colstyle (1.5)
 
--- a/scripts/plot/util/copyobj.m
+++ b/scripts/plot/util/copyobj.m
@@ -46,7 +46,7 @@
 
   ## current figure and axes
   cf = gcf ();
-  ca = gca ();
+  ca = get (cf, "currentaxes");
   
   ## compatibility of input handles
   kididx = find (strcmp (alltypes, get (horig).type));
@@ -65,16 +65,18 @@
 
   ## reset current figure (and eventually axes) to original
   set (0, "currentfigure", cf);
-  if (get (hnew, "parent") == cf)
+  if (get (hnew, "parent") == cf && ! isempty (ca))
     set (cf, "currentaxes", ca)
   endif
   
 endfunction
 
 
+## Absurd number of drawnow() function calls in demos is due to problem
+## with FLTK backend which is not respecting the set ('position') call.
+
 %!demo
-%! hdl = figure (1234);
-%! clf;
+%! hobj = figure ('name', 'Original', 'numbertitle', 'off');
 %! hold on;
 %! x = 1:10;
 %! y = x.^2;
@@ -84,34 +86,46 @@
 %! set (hg, 'marker', '^', 'markerfacecolor', rand (1,3));
 %! plot (x, y2, 'ok-');
 %! legend ('errorbar', 'line');
-%! hnew = copyobj (hdl);
+%! drawnow ();
+%! pos = get (hobj, 'position');
+%! scrn = get (0, 'screensize');
+%! set (hobj, 'position', [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
+%! hnew = copyobj (hobj);
+%! drawnow ();
+%! set (hnew, 'name', 'Copyobj');
+%! drawnow ();
+%! set (hnew, 'position', [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
 
-%!#demo
-%! ## FIXME: This demo fails for an obscure reason.
-%! ## It appears that there is something wrong with Octave code for patches.
-%! ## This demo must remain commented out until patch() has been reworked.
-%! unwind_protect
-%!   hdl = figure (1234);
-%!   clf;
-%!   subplot (2,2,1);
-%!   hold on;
-%!   contourf (rand (10, 10));
-%!   colorbar ();
-%!   subplot (2,2,2);
-%!   quiver (rand (10, 10), rand (10, 10));
-%!   subplot (2,2,3);
-%!   colormap (jet (64));
-%!   hold on;
-%!   sombrero ();
-%!   colorbar ('peer', gca, 'NorthOutside');
-%!   subplot (2,2,4);
-%!   imagesc (rand (30, 30));
-%!   text (15, 15, 'Rotated text', ...
-%!         'HorizontAlalignment', 'Center', 'Rotation', 30);
-%!   hnew = copyobj (hdl);
-%! unwind_protect_cleanup
-%!   close all;
-%! end_unwind_protect
+%!demo
+%! hobj = figure ('name', 'Original', 'numbertitle', 'off');
+%! subplot (2,2,1);
+%! hold on;
+%! contourf (rand (10, 10));
+%! colorbar ();
+%! subplot (2,2,2);
+%! quiver (rand (10, 10), rand (10, 10));
+%! subplot (2,2,3);
+%! colormap (jet (64));
+%! hold on;
+%! sombrero ();
+%! colorbar ('peer', gca, 'NorthOutside');
+%! subplot (2,2,4);
+%! imagesc (rand (30, 30));
+%! text (15, 15, 'Rotated text', ...
+%!       'HorizontAlalignment', 'Center', 'Rotation', 30);
+%! drawnow ();
+%! pos = get (hobj, 'position');
+%! scrn = get (0, 'screensize');
+%! set (hobj, 'position', [scrn(3)/2-pos(3)-10, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
+%! hnew = copyobj (hobj);
+%! drawnow ();
+%! set (hnew, 'name', 'Copyobj');
+%! drawnow ();
+%! set (hnew, 'position', [scrn(3)/2, scrn(4)/2-pos(4)/2, pos(3:4)]);
+%! drawnow ();
 
 %!testif HAVE_MAGICK
 %! toolkit = graphics_toolkit ();
@@ -154,3 +168,17 @@
 %!   graphics_toolkit (toolkit);
 %! end_unwind_protect
 
+%!test 
+%! unwind_protect
+%!   tag = "foo";
+%!   hf = figure ("visible", "off");
+%!   hax = axes ("tag", tag);
+%!   hpa = patch ();
+%!   set (hpa, "facecolor", [.5 .5 .5], "tag", tag)
+%!   hax2 = copyobj (hax, hf);
+%!   assert (get (hax2, "tag"), tag)
+%!   hpa2 = get (hax2, "children");
+%!   assert (get (hpa2, "facecolor"), [.5 .5 .5])
+%! unwind_protect_cleanup
+%!   close (hf)
+%! end_unwind_protect
--- a/scripts/plot/util/hdl2struct.m
+++ b/scripts/plot/util/hdl2struct.m
@@ -23,7 +23,7 @@
 ##
 ## The fields of the structure @var{s} are @qcode{"type"}, @qcode{"handle"},
 ## @qcode{"properties"}, @qcode{"children"}, and @qcode{"special"}.
-## @seealso{struct2hdl, findobj}
+## @seealso{struct2hdl, hgsave, findobj}
 ## @end deftypefn
 
 ## Author: pdiribarne <pdiribarne@new-host.home>
new file mode 100644
--- /dev/null
+++ b/scripts/plot/util/hgload.m
@@ -0,0 +1,69 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{h} =} hgload (@var{filename})
+## Load the graphics object in @var{filename} into the graphics handle @var{h}.
+##
+## If @var{filename} has no extension, Octave will try to find the file with
+## and without the standard extension of @file{.ofig}.
+## @seealso{hgsave, struct2hdl}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function h = hgload (filename)
+
+  ## Check input arguments
+  if (nargin != 1)
+    print_usage ();
+  endif
+
+  ## Check file existence
+  [~, ~, ext] = fileparts (filename);
+  if (isempty (ext))
+    if (! isempty (file_in_loadpath ([filename ".ofig"])))
+      filename = [filename ".ofig"];
+    elseif (isempty (file_in_loadpath (filename)))
+      error ("hgload: unable to locate file %s", filename);
+    endif
+  else
+    if (isempty (file_in_loadpath (filename)))
+      error ("hgload: unable to locate file %s", filename);
+    endif
+  endif
+    
+  ## Load the handle
+  try
+    stmp = load (filename, "s_oct40");
+  catch
+    error ("hgload: could not load hgsave-formatted object in file %s", filename);
+  end_try_catch
+
+  h = struct2hdl (stmp.s_oct40);
+  
+endfunction
+
+
+## Functional test for hgload/hgsave pair is in hgsave.m
+
+%% Test input validation
+%!error hgload ()
+%!error hgload (1, 2)
+%!error <unable to locate file> hgload ("%%_A_REALLY_UNLIKELY_FILENAME_%%")
+
new file mode 100644
--- /dev/null
+++ b/scripts/plot/util/hgsave.m
@@ -0,0 +1,123 @@
+## Copyright (C) 2014 Massimiliano Fasi
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {} hgsave (@var{filename})
+## @deftypefnx {Function File} {} hgsave (@var{h}, @var{filename})
+## @deftypefnx {Function File} {} hgsave (@var{h}, @var{filename}, @var{fmt})
+## Save the graphics handle @var{h} to the file @var{filename} in the format
+## @var{fmt}.
+##
+## If unspecified, @var{h} is the current figure as returned by @code{gcf}. 
+## When @var{filename} does not have an extension the default filename
+## extension @file{.ofig} will be appended.  If present, @var{fmt} should 
+## should be one of the following:
+##
+## @itemize @bullet
+## @item @code{-binary}, @code{-float-binary}
+## @item @code{-hdf5}, @code{-float-hdf5}
+## @item @code{-V7}, @code{-v7}, @code{-7}, @code{-mat7-binary}
+## @item @code{-V6}, @code{-v6}, @code{-6}, @code{-mat6-binary}
+## @item @code{-text}
+## @item @code{-zip}, @code{-z}
+## @end itemize
+##
+## When producing graphics for final publication use @code{print} or
+## @code{saveas}.  When it is important to be able to continue to edit a
+## figure as an Octave object, use @code{hgsave}/@code{hgload}.
+## @seealso{hgload, hdl2struct, saveas, print}
+## @end deftypefn
+
+## Author: Massimiliano Fasi
+
+function hgsave (h, filename, fmt = "-binary")
+
+  if (nargin < 1 || nargin > 3)
+    print_usage ();
+  endif
+
+  ## Check input arguments
+  if (nargin == 1 && ischar (h))
+    filename = h;
+    h = get (0, "currentfigure");
+    if (isempty (h))
+      error ("hgsave: No current figure to save");
+    endif
+  elseif (! (ishandle (h) && ischar (filename)))
+    print_usage ();
+  endif
+
+  ## Check file extension
+  [~, ~, ext] = fileparts (filename);
+  if (isempty (ext))
+    filename = [filename ".ofig"];
+  endif
+
+  s_oct40 = hdl2struct (h);
+  save (fmt, filename, "s_oct40");
+
+endfunction
+
+
+%!testif HAVE_MAGICK
+%! toolkit = graphics_toolkit ();
+%! graphics_toolkit ("gnuplot");
+%! unwind_protect
+%!   h1 = figure ("visible", "off");
+%!   x = 0:0.1:2*pi;
+%!   y1 = sin (x);
+%!   y2 = exp (x - 1);
+%!   ax = plotyy (x,y1, x-1,y2, @plot, @semilogy);
+%!   xlabel ("X");
+%!   ylabel (ax(1), "Axis 1");
+%!   ylabel (ax(2), "Axis 2");
+%!   axes (ax(1));
+%!   text (0.5, 0.5, "Left Axis", ...
+%!         "color", [0 0 1], "horizontalalignment", "center");
+%!   axes (ax(2));
+%!   text (4.5, 80, "Right Axis", ...
+%!         "color", [0 0.5 0], "horizontalalignment", "center");
+%!   ftmp = [tmpnam() ".ofig"];
+%!   png1 = [tmpnam() ".png"];
+%!   png2 = [tmpnam() ".png"];
+%!   unwind_protect
+%!     hgsave (h1, ftmp);
+%!     print (h1, png1);
+%!     [img1, map1, alpha1] = imread (png1);
+%!     h2 = hgload (ftmp);
+%!     print (h2, png2);
+%!     [img2, map2, alpha2] = imread (png2);
+%!   unwind_protect_cleanup
+%!     unlink (ftmp);
+%!     unlink (png1);
+%!     unlink (png2);
+%!   end_unwind_protect
+%!   assert (img1, img2);
+%!   assert (map1, map2);
+%!   assert (alpha1, alpha2);
+%! unwind_protect_cleanup
+%!   close (h1);
+%!   close (h2);
+%!   graphics_toolkit (toolkit);
+%! end_unwind_protect
+
+%% Test input validation
+%!error hgsave ()
+%!error hgsave (1, 2, 3, 4)
+%!error hgsave ("abc", "def")
+
--- a/scripts/plot/util/isprop.m
+++ b/scripts/plot/util/isprop.m
@@ -17,11 +17,14 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{res} =} isprop (@var{h}, "@var{prop}")
-## Return true if @var{prop} is a property of the object with handle @var{h}.
+## @deftypefn {Function File} {@var{res} =} isprop (@var{obj}, "@var{prop}")
+## Return true if @var{prop} is a property of the object @var{obj}.
 ##
-## @var{h} may also be an array of handles in which case @var{res} will be a
+## @var{obj} may also be an array of objects in which case @var{res} will be a
 ## logical array indicating whether each handle has the property @var{prop}.
+## 
+## For plotting, @var{obj} is a handle to a graphics object.  Otherwise,
+## @var{obj} should be an instance of a class.
 ## @seealso{get, set, ismethod, isobject}
 ## @end deftypefn
 
new file mode 100644
--- /dev/null
+++ b/scripts/plot/util/linkaxes.m
@@ -0,0 +1,167 @@
+## Copyright (C) 2014 Willem Atsma
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} linkaxes (@var{hax})
+## @deftypefnx {Function File} linkaxes (@var{hax}, @var{optstr})
+## Link the axis limits of 2-D plots such that a change in one is
+## propagated to the others.
+##
+## The axes handles to be linked are passed as the first argument @var{hax}.
+##
+## The optional second argument is a string which defines which axis limits
+## will be linked.  The possible values for @var{optstr} are:
+##
+## @table @asis
+## @item @qcode{"x"}
+## Link x-axes
+##
+## @item @qcode{"y"}
+## Link y-axes
+##
+## @item @qcode{"xy"} (default)
+## Link both axes
+##
+## @item @qcode{"off"}
+## Turn off linking
+## @end table
+##
+## If unspecified the default is to link both X and Y axes.
+##
+## When linking, the limits from the first axes in @var{hax} are applied to the
+## other axes in the list.  Subsequent changes to any one of the axes will be
+## propagated to the others.
+##
+## @seealso{linkprop, addproperty}
+## @end deftypefn
+
+## Author: Willem Atsma willem.atsma at tanglebridge.com
+## Created: 2014-03-18
+
+function linkaxes (hax, optstr = "xy")
+
+  if  (nargin < 1 || nargin > 2)
+    print_usage ();
+  endif
+
+  if (numel (hax) < 2)
+    error ("linkaxes: HAX must contain at least 2 handles");
+  elseif (! all (isaxes (hax(:))))
+    error ("linkaxes: HAX must be a vector of axes handles");
+  endif
+
+  ## Check if axes are linked already and clear if found.
+  ## Otherwise, add the necessary linkaxes_data property.
+  for i = 1:length (hax)
+    if (isprop (hax(i), "linkaxes_data"))
+      hld = get (hax(i), "linkaxes_data");
+      try
+        rmappdata (hld, "linkprop_data");
+      end_try_catch
+    else
+      addproperty ("linkaxes_data", hax(i), "any");
+    endif
+  endfor
+
+  switch  (optstr)
+    case "x"
+      hlink = linkprop (hax, "xlim");
+    case "y"
+      hlink = linkprop (hax, "ylim");
+    case "xy"
+      hlink = linkprop (hax, {"xlim" "ylim"});
+    case "off"
+      ## do nothing - link already deleted
+      hlink = [];
+    otherwise
+      error ("linkaxes: unrecognized OPTSTR '%s'", optstr);
+  endswitch
+
+  if (! isempty (hlink))
+    setappdata (hax(1), "linkprop_data", hlink);
+    set (hax, "linkaxes_data", hax(1));
+  else
+    set (hax, "linkaxes_data", []);
+  endif
+
+endfunction
+
+
+%!demo
+%! clf;
+%! hax1 = subplot (3,1,1);
+%! bar (rand (4, 1), 'facecolor', 'r');
+%! hax2 = subplot (3,1,2);
+%! bar (5*rand (4, 1), 'facecolor', 'g');
+%! hax3 = subplot (3,1,3);
+%! bar (10*rand (4, 1), 'facecolor', 'b');
+%! input ('Type <RETURN> to link axes');
+%! linkaxes ([hax1, hax2, hax3]);
+%! input ('Type <RETURN> to change ylim');
+%! ylim (hax3, [0 10]);
+
+%!test
+%! hf1 = figure ("visible", "off");
+%! hax1 = axes ();
+%! plot (1:10);
+%! hf2 = figure ("visible", "off");
+%! hax2 = axes ();
+%! plot (10:-1:1, "-*g");
+%! hf3 = figure ("visible", "off");
+%! hax3 = axes ();
+%! plot (1:10:100, "-xb");
+%!  unwind_protect
+%!   linkaxes ([hax1, hax2, hax3]);
+%!   ## Test initial values taken from first object in list
+%!   assert (xlim (hax3), [0 10]);
+%!   assert (ylim (hax3), [0 10]);
+%!   ## Test linking
+%!   xlim (hax2, [2 8]);
+%!   assert (xlim (hax1), [2 8]);
+%!   assert (xlim (hax3), [2 8]);
+%!   ylim (hax3, "auto");
+%!   assert (ylim (hax1), [0 100]);
+%!   assert (ylim (hax2), [0 100]);
+%!   ## Test re-linking removes old link
+%!   linkaxes ([hax1, hax2]);
+%!   ylim (hax3, [0 50]);
+%!   assert (ylim (hax1), [0 100]);
+%!   assert (ylim (hax2), [0 100]);
+%!   xlim (hax1, [0 4]);
+%!   assert (xlim (hax2), [0 4]);
+%!   ## Test linking of remaining objects after deletion of one object
+%!   linkaxes ([hax1, hax2, hax3]);
+%!   xlim (hax2, [0 1]);
+%!   assert (xlim (hax1), [0 1]);
+%!   assert (xlim (hax3), [0 1]);
+%!   delete (hax2);
+%!   xlim (hax3, [0 2]);
+%!   assert (xlim (hax1), [0 2]);
+%!   ## Test deletion of link
+%!   linkaxes ([hax1, hax3], "off");
+%!   xlim (hax3, [0 3]);
+%!   assert (xlim (hax1), [0 2]);
+%!  unwind_protect_cleanup
+%!   close ([hf1 hf2 hf3]);
+%!  end_unwind_protect
+
+%% Test input validation
+%!error linkaxes ()
+%!error linkaxes (1,2,3)
+%!error <HAX must be a vector of axes handles> linkaxes ([pi, e])
+
--- a/scripts/plot/util/linkprop.m
+++ b/scripts/plot/util/linkprop.m
@@ -17,14 +17,24 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {@var{hlink} =} linkprop (@var{h}, @var{prop})
-## @deftypefnx {Function File} {@var{hlink} =} linkprop (@var{h}, @{@var{prop1}, @var{prop2}, @dots{}@})
-## Link graphics object properties, such that a change in one is
-## propagated to the others.
+## @deftypefn  {Function File} {@var{hlink} =} linkprop (@var{h}, "@var{prop}")
+## @deftypefnx {Function File} {@var{hlink} =} linkprop (@var{h}, @{"@var{prop1}", "@var{prop2}", @dots{}@})
+## Link graphic object properties, such that a change in one is propagated to
+## the others.
+##
+## The input @var{h} is a vector of graphic handles to link.
 ##
-## @var{prop} can be a string for a single property, or a cell array of strings
-## for multiple properties.  @var{h} is an array of graphics handles which
-## will have their properties linked.
+## @var{prop} may be a string when linking a single property, or a cell array
+## of strings for multiple properties.  During the linking process all
+## properties in @var{prop} will initially be set to the values that exist on
+## the first object in the list @var{h}.
+##
+## The function returns @var{hlink} which is a special object describing the
+## link.  As long as the reference @var{hlink} exists the link between graphic
+## objects will be active.  This means that @var{hlink} must be preserved in
+## a workspace variable, a global variable, or otherwise stored using a
+## function such as @code{setappdata}, @code{guidata}.  To unlink properties,
+## execute @code{clear @var{hlink}}.
 ##
 ## An example of the use of @code{linkprop} is
 ##
@@ -41,62 +51,122 @@
 ## @end group
 ## @end example
 ##
+## @seealso{linkaxes}
 ## @end deftypefn
 
 function hlink = linkprop (h, prop)
+
+  if (nargin != 2)
+    print_usage ();
+  endif
+
+  if (numel (h) < 2)
+    error ("linkprop: H must contain at least 2 handles");
+  elseif (! all (ishandle (h(:))))
+    error ("linkprop: invalid graphic handle in input H");
+  endif
+
   if (ischar (prop))
     prop = {prop};
-  elseif (!iscellstr (prop))
-    error ("linkprop: properties must be a string or cell string array");
+  elseif (! iscellstr (prop))
+    error ("linkprop: PROP must be a string or cell string array");
   endif
 
+  h = h(:)';  # set() prefers column vectors
+  ## Match all objects to the first one in the list before linking 
+  for j = 1 : numel (prop)
+    set (h(2:end), prop{j}, get (h(1), prop{j})); 
+  endfor
+
+  ## Add listeners to all objects
   for i = 1 : numel (h)
     for j = 1 : numel (prop)
-      addlistener (h(i), prop{j}, {@update_prop, h, prop{j}});
+      addlistener (h(i), prop{j},
+                   {@update_prop, [h(1:i-1),h(i+1:end)], prop{j}});
     endfor
   endfor
 
-  ## This should be an object that when destroyed removes the links
-  ## The below is not quite right. As when you call "clear hlink" the
-  ## hggroup continues to exist.
-  hlink = hggroup ();
-  set (hlink, "deletefcn", {@delete_prop, h, prop});
+  hlink = onCleanup (@() delete_linkprop (h, prop));
+
 endfunction
 
-function update_prop (h, d, hlist, prop)
+function update_prop (h, ~, hlist, prop)
   persistent recursion = false;
 
   ## Don't allow recursion
   if (! recursion)
     unwind_protect
       recursion = true;
-      val = get (h, prop);
-      for hh = hlist(:)'
-        if (hh != h)
-          oldval = get (hh, prop);
-          if (! isequal (val, oldval))
-            set (hh, prop, val);
-          endif
-        endif
-      endfor
+      set (hlist(ishandle (hlist)), prop, get (h, prop));
     unwind_protect_cleanup
       recursion = false;
     end_unwind_protect
   endif
 endfunction
 
-function delete_prop (h, d, hlist, prop)
-  ## FIXME. Actually need to delete the linked properties.
-  ## However, only warn if the graphics objects aren't being deleted.
-  warn = false;
-  for h = hlist(:)'
-    if (ishandle (h) && !strcmpi (get (h, "beingdeleted"), "on"))
-      warn = true;
-      break;
+function delete_linkprop (hlist, prop)
+
+  for i = 1 : numel (hlist)
+    if (ishandle (hlist(i)))
+      for j = 1 : numel (prop)
+        dellistener (hlist(i), prop{j}),
+      endfor
     endif
   endfor
-  if (warn)
-    warning ("linkprop: can not remove linked properties");
-  endif
+
 endfunction
 
+
+%!demo
+%! clf;
+%! x = 0:0.1:10;
+%! subplot (1,2,1);
+%! h1 = plot (x, sin (x), 'r');
+%! subplot (1,2,2);
+%! h2 = plot (x, cos (x), 'b');
+%! input ('Type <RETURN> to link plots');
+%! hlink = linkprop ([h1, h2], {'color', 'linestyle'});
+%! input ('Type <RETURN> to change color');
+%! set (h1, 'color', 'green');
+%! input ('Type <RETURN> to change linestyle');
+%! set (h2, 'linestyle', '--');
+
+%!test
+%! hf1 = figure ("visible", "off");
+%! hl1 = plot (1:10, "or");
+%! hf2 = figure ("visible", "off");
+%! hl2 = plot (1:10, "-*g");
+%! hf3 = figure ("visible", "off");
+%! hl3 = plot (1:10, "-xb");
+%! unwind_protect
+%!   hlink = linkprop ([hl1, hl2, hl3], {"color", "linestyle"});
+%!   ## Test initial values taken from first object in list
+%!   assert (get (hl2, "color"), [1 0 0]);
+%!   assert (get (hl3, "linestyle"), "none");
+%!   ## Test linking
+%!   set (hl2, "color", "b");
+%!   assert (get (hl1, "color"), [0 0 1]);
+%!   assert (get (hl3, "color"), [0 0 1]);
+%!   set (hl3, "linestyle", "--");
+%!   assert (get (hl1, "linestyle"), "--");
+%!   assert (get (hl2, "linestyle"), "--");
+%!   ## Test linking of remaining objects after deletion of one object
+%!   delete (hl2);
+%!   set (hl1, "linestyle", ":");
+%!   assert (get (hl3, "linestyle"), ":");
+%!   ## Test deletion of link
+%!   clear hlink;
+%!   set (hl1, "color", "g");
+%!   assert (get (hl3, "color"), [0 0 1]);
+%! unwind_protect_cleanup
+%!   close ([hf1 hf2 hf3]);
+%! end_unwind_protect
+
+%% Test input validation
+%!error linkprop ()
+%!error linkprop (1)
+%!error linkprop (1,2,3)
+%!error <H must contain at least 2 handles> linkprop (1, "color")
+%!error <invalid graphic handle in input H> linkprop ([pi, e], "color")
+%!error <PROP must be a string or cell string array> linkprop ([0, 0], 1)
+
--- a/scripts/plot/util/module.mk
+++ b/scripts/plot/util/module.mk
@@ -48,12 +48,15 @@
   plot/util/graphics_toolkit.m \
   plot/util/hdl2struct.m \
   plot/util/hggroup.m \
+  plot/util/hgload.m \
+  plot/util/hgsave.m \
   plot/util/hold.m \
   plot/util/isaxes.m \
   plot/util/isfigure.m \
   plot/util/ishghandle.m \
   plot/util/ishold.m \
   plot/util/isprop.m \
+  plot/util/linkaxes.m \
   plot/util/linkprop.m \
   plot/util/meshgrid.m \
   plot/util/ndgrid.m \
--- a/scripts/plot/util/print.m
+++ b/scripts/plot/util/print.m
@@ -103,18 +103,29 @@
 ##     Encapsulated PostScript (level 1 and 2, mono and color).  The FLTK
 ## graphic toolkit generates PostScript level 3.0.
 ##
-##   @item  tex
+##   @item  pslatex
 ##   @itemx epslatex
-##   @itemx epslatexstandalone
-##   @itemx pstex
-##   @itemx pslatex
 ##   @itemx pdflatex
-##     Generate a @LaTeX{} (or @TeX{}) file for labels and eps/ps/pdf
-## for graphics.  The file produced by @code{epslatexstandalone} can be
-## processed directly by @LaTeX{}.  The other formats are intended to
-## be included in a @LaTeX{} (or @TeX{}) document.  The @code{tex} device
-## is the same as the @code{epslatex} device.  The @code{pdflatex} device
-## is only available for the FLTK graphics toolkit.
+##   @itemx pslatexstandalone
+##   @itemx epslatexstandalone
+##   @itemx pdflatexstandalone
+##     Generate a @LaTeX{} file @file{@var{filename}.tex} for the text
+## portions of a plot and a file @file{@var{filename}.(ps|eps|pdf)} for the
+## remaining graphics.  The graphics file suffix .ps|eps|pdf is determined
+## by the specified device type.  The @LaTeX{} file produced by the
+## @samp{standalone} option can be processed directly by @LaTeX{}.  The file
+## generated without the @samp{standalone} option is intended to be included
+## from another @LaTeX{} document.  In either case, the @LaTeX{} file
+## contains an @code{\includegraphics} command so that the generated graphics
+## file is automatically included when the @LaTeX{} file is processed.  The
+## text that is written to the @LaTeX{} file contains the strings
+## @strong{exactly} as they were specified in the plot.  If any special
+## characters of the @TeX{} mode interpreter were used, the file must be
+## edited before @LaTeX{} processing.  Specifically, the special characters
+## must be enclosed with dollar signs (@code{$ @dots{} $}), and other
+## characters that are recognized by @LaTeX{} may also need editing (.e.g.,
+## braces).  The @samp{pdflatex} device, and any of the @samp{standalone}
+## formats, are not available with the Gnuplot toolkit.
 ##
 ##   @item tikz
 ##     Generate a @LaTeX{} file using PGF/TikZ@.  For the FLTK toolkit
@@ -175,29 +186,17 @@
 ## Some examples are;
 ##
 ##   @table @code
+##   @item pdfwrite
+##     Produces pdf output from eps
+##
 ##   @item ljet2p
 ##     HP LaserJet @nospell{IIP}
 ##
-##   @item ljet3
-##     HP LaserJet III
-##
-##   @item deskjet
-##     HP DeskJet and DeskJet Plus
-##
-##   @item cdj550
-##     HP DeskJet 550C
-##
-##   @item paintjet
-##     HP PointJet
-##
 ##   @item pcx24b
 ##     24-bit color PCX file format
 ##
 ##   @item ppm
 ##     Portable Pixel Map file format
-##
-##   @item pdfwrite
-##     Produces pdf output from eps
 ##   @end table
 ##
 ##   For a complete list, type @code{system ("gs -h")} to see what formats
@@ -254,28 +253,38 @@
 ##
 ## The filename and options can be given in any order.
 ##
-## Example: Print to a file using the svg device.
+## Example: Print to a file using the pdf device.
 ##
 ## @example
 ## @group
 ## figure (1);
 ## clf ();
 ## surf (peaks);
-## print -dsvg figure1.svg
+## print figure1.pdf
 ## @end group
 ## @end example
 ##
-## Example: Print to an HP DeskJet 550C.
+## Example: Print to a file using jpg device.
 ##
 ## @example
 ## @group
 ## clf ();
 ## surf (peaks);
-## print -dcdj550
+## print -djpg figure2.jpg
 ## @end group
 ## @end example
 ##
-## @seealso{saveas, orient, figure}
+## Example: Print to printer named PS_printer using ps format.
+##
+## @example
+## @group
+## clf ();
+## surf (peaks);
+## print -dpswrite -PPS_printer 
+## @end group
+## @end example
+##
+## @seealso{saveas, hgsave, orient, figure}
 ## @end deftypefn
 
 function print (varargin)
@@ -288,7 +297,7 @@
   opts.lpr_cmd = @lpr;
   opts.epstool_cmd = @epstool;
 
-  if (! isfigure (opts.figure))
+  if (isempty (opts.figure) || ! isfigure (opts.figure))
     error ("print: no figure to print");
   endif
 
@@ -414,7 +423,7 @@
       endif
     endif
 
-    ## call the graphcis toolkit print script
+    ## call the graphics toolkit print script
     switch (get (opts.figure, "__graphics_toolkit__"))
       case "gnuplot"
         opts = __gnuplot_print__ (opts);
@@ -689,7 +698,7 @@
       cmd = sprintf ("%s %s", cmd, opts.lpr_options);
     endif
     if (! isempty (opts.printer))
-      cmd = sprintf ("%s -P %s", cmd, opts.printer);
+      cmd = sprintf ("%s %s", cmd, opts.printer);
     endif
   elseif (isempty (opts.lpr_binary))
     error ("print:nolpr", "print.m: 'lpr' not found in PATH");
--- a/scripts/plot/util/private/__print_parse_opts__.m
+++ b/scripts/plot/util/private/__print_parse_opts__.m
@@ -334,10 +334,9 @@
     else
       error ("print: a file name may not specified when spooling to a printer")
     endif
-    if (! any (strcmp (arg_st.devopt, gs_device_list))
-      || ! any (strcmp (arg_st.devopt, {"pswrite", "ps2write"})))
-      ## Only postscript and supported ghostscript devices
-      error ("print: invalid format for spooling to a printer")
+    if (! any (strcmp (arg_st.devopt, gs_device_list)))
+      ## Only supported ghostscript devices
+      error ("print: format must be a valid Ghostscript format for spooling to a printer")
     endif
   elseif (isempty (arg_st.name))
     error ("print: an output file name must be specified")
--- a/scripts/plot/util/saveas.m
+++ b/scripts/plot/util/saveas.m
@@ -56,7 +56,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{print, orient}
+## @seealso{print, hgsave, orient}
 ## @end deftypefn
 
 ## Author: Kai Habel
--- a/scripts/plot/util/struct2hdl.m
+++ b/scripts/plot/util/struct2hdl.m
@@ -32,7 +32,7 @@
 ## A third boolean argument @var{hilev} can be passed to specify whether
 ## the function should preserve listeners/callbacks, e.g., for legends or
 ## hggroups.  The default is false.
-## @seealso{hdl2struct, findobj}
+## @seealso{hdl2struct, hgload, findobj}
 ## @end deftypefn
 
 ## Author: pdiribarne <pdiribarne@new-host.home>
@@ -177,7 +177,7 @@
 
 function [h, sout] = createaxes (s, p, par)
   ## regular axes
-  if (strcmp (s.properties.tag, ""))
+  if (! any (strcmpi (s.properties.tag, {"colorbar", "legend"})))
     propval = {"position", s.properties.position};
     hid = {"autopos_tag", "looseinset"};
     for ii = 1:numel (hid)
@@ -297,7 +297,11 @@
   h = patch (prp);
   set (h, "parent", par);
   s.properties = rmfield (s.properties,
-                            {"faces", "vertices", "facevertexcdata"});
+                          {"faces", "vertices", "facevertexcdata"});
+  ## Also remove derived properties.  Otherwise there is a possibility for
+  ## a segfault when 'set (h, properties)' is used to restore properties
+  ## which do not match in size the ones created with from the call to patch().
+  s.properties = rmfield (s.properties, {"xdata", "ydata", "zdata", "cdata"});
   addmissingprops (h, s.properties);
   sout = s;
 endfunction
@@ -547,8 +551,7 @@
 endfunction
 
 function setprops (s, h, p, hilev)
-  more off;
-  if (strcmpi (s.properties.tag, ""))
+  if (! any (strcmpi (s.properties.tag, {"colorbar", "legend"})))
     specs = s.children(s.special);
     if (isempty (specs))
       hdls = [];
@@ -613,8 +616,7 @@
       endif
     endif
 
-  elseif (strcmpi (s.properties.tag, "legend")
-          || strcmpi (s.properties.tag, "colorbar"))
+  else
     set (h, s.properties);
   endif
 
--- a/scripts/set/ismember.m
+++ b/scripts/set/ismember.m
@@ -118,14 +118,19 @@
       a_idx = zeros (rows (A), 1);
     else
 
-      ## FIXME: lookup does not support "rows", so we just use unique.
-      [xx, ii, jj] = unique ([A; s], "rows", "last");
-      na = rows (A);
-      jj = ii(jj(1:na));
-      tf = jj > na;
+      if (rows (s) == 1)
+        tf = all (bsxfun (@eq, A, s), 2);
+        a_idx = double (tf);
+      else
+        ## FIXME: lookup does not support "rows", so we just use unique.
+        [~, ii, jj] = unique ([A; s], "rows", "last");
+        na = rows (A);
+        jj = ii(jj(1:na));
+        tf = jj > na;
 
-      if (nargout > 1)
-        a_idx = max (0, jj - na);
+        if (nargout > 1)
+          a_idx = max (0, jj - na);
+        endif
       endif
 
     endif
@@ -214,3 +219,8 @@
 %! assert (result, [true; false; true]);
 %! assert (a_idx, [1; 0; 2]);
 
+%!test
+%! [result, a_idx] = ismember ([1:3; 5:7; 4:6; 0:2; 1:3; 2:4], [1:3], "rows");
+%! assert (result, logical ([1 0 0 0 1 0]'));
+%! assert (a_idx, [1 0 0 0 1 0]');
+
--- a/scripts/sparse/private/__sprand_impl__.m
+++ b/scripts/sparse/private/__sprand_impl__.m
@@ -22,7 +22,8 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} __sprand_impl__ (@var{s}, @var{randfun})
-## @deftypefnx {Function File} {} __sprand_impl__ (@var{m}, @var{n}, @var{d}, @var{funname}, @var{randfun})
+## @deftypefnx {Function File} {} __sprand_impl__ (@var{m}, @var{n}, @var{d}, @var{fcnname}, @var{randfun})
+## @deftypefnx {Function File} {} __sprand_impl__ (@var{m}, @var{n}, @var{d}, @var{rc}, @var{fcnname}, @var{randfun})
 ## Undocumented internal function.
 ## @end deftypefn
 
@@ -31,52 +32,114 @@
 function S = __sprand_impl__ (varargin)
 
   if (nargin == 2)
-    m = varargin{1};
-    randfun = varargin{2};
+    [m, randfun] = deal (varargin{1:2});
     [i, j] = find (m);
     [nr, nc] = size (m);
     S = sparse (i, j, randfun (size (i)), nr, nc);
-    return;
-  endif
+  else
+    if (nargin == 5)
+      [m, n, d, fcnname, randfun] = deal (varargin{:});
+    else
+      [m, n, d, rc, fcnname, randfun] = deal (varargin{:});
+    endif
 
-  [m, n, d, funname, randfun] = deal (varargin{:});
+    if (! (isscalar (m) && m == fix (m) && m > 0))
+      error ("%s: M must be an integer greater than 0", fcnname);
+    endif
+    if (! (isscalar (n) && n == fix (n) && n > 0))
+      error ("%s: N must be an integer greater than 0", fcnname);
+    endif
+    if (d < 0 || d > 1)
+      error ("%s: density D must be between 0 and 1", fcnname);
+    endif
+
+    if (nargin == 5)
+      mn = m*n;
+      k = round (d*mn);
+      if (mn > sizemax ())
+        ## randperm will overflow, so use alternative methods
 
-  if (!(isscalar (m) && m == fix (m) && m > 0))
-    error ("%s: M must be an integer greater than 0", funname);
-  endif
+        idx = unique (fix (rand (1.01*k, 1) * mn)) + 1;
+
+        ## idx contains random numbers in [1,mn]
+        ## Generate 1% more random values than necessary in order to reduce the
+        ## probability that there are less than k distinct values; maybe a
+        ## better strategy could be used but I don't think it's worth the price.
 
-  if (!(isscalar (n) && n == fix (n) && n > 0))
-    error ("%s: N must be an integer greater than 0", funname);
-  endif
+        ## actual number of entries in S
+        k = min (length (idx), k);
+        j = floor ((idx(1:k) - 1) / m);
+        i = idx(1:k) - j * m;
+        j++;
+      else
+        idx = randperm (mn, k);
+        [i, j] = ind2sub ([m, n], idx);
+      endif
 
-  if (d < 0 || d > 1)
-    error ("%s: density D must be between 0 and 1", funname);
-  endif
+      S = sparse (i, j, randfun (k, 1), m, n);
+
+    elseif (nargin == 6)
+      ## Create a matrix with specified reciprocal condition number.
+
+      if (! isscalar (rc) && ! isvector (rc))
+        error ("%s: RC must be a scalar or vector", fcnname);
+      endif
 
-  mn = m*n;
-  k = round (d*mn);
-  if (mn > sizemax ())
-    ## randperm will overflow, so use alternative methods
+      ## We want to reverse singular valued decomposition A=U*S*V'.
+      ## First, first S is constructed and then U = U1*U2*..Un and
+      ## V' = V1*V2*..Vn are seen as Jacobi rotation matrices with angles and
+      ## planes of rotation randomized.  Repeatedly apply rotations until the
+      ## required density for A is achieved.
 
-    idx = unique (fix (rand (min (k*1.01, k+10), 1) * mn)) + 1;
+      if (isscalar (rc))
+        if (rc < 0 || rc > 1)
+          error ("%s: reciprocal condition number RC must be between 0 and 1", fcnname);
+        endif
+        ## Reciprocal condition number is ratio of smallest SV to largest SV
+        ## Generate singular values randomly and sort them to build S
+        ## Random singular values in range [rc, 1].
+        v = rand (1, min (m,n)) * (1 - rc) + rc;
+        v(1) = 1;
+        v(end) = rc;
+        v = sort (v, "descend");
+        S = sparse (diag (v, m, n));
+      else
+        ## Only the min (m, n) greater singular values from rc vector are used.
+        if (length (rc) > min (m,n))
+          rc = rc(1:min(m, n));
+        endif
+        S = sparse (diag (sort (rc, "descend"), m, n));
+      endif
 
-    ## idx contains random numbers in [1,mn]
-    ## generate 1% or 10 more random values than necessary in order to
-    ## reduce the probability that there are less than k distinct
-    ## values; maybe a better strategy could be used but I don't think
-    ## it's worth the price
-    
-    ## actual number of entries in S
-    k = min (length (idx), k);
-    j = floor ((idx(1:k) - 1) / m);
-    i = idx(1:k) - j * m;
-    j++;
-  else
-    idx = randperm (mn, k);
-    [i, j] = ind2sub ([m, n], idx);
+      Uinit = speye (m);
+      Vinit = speye (n);
+      k = round (d*m*n);
+      while (nnz (S) < k)
+        if (m > 1)
+          ## Construct U randomized rotation matrix
+          rot_angleu = 2 * pi * rand ();
+          cu = cos (rot_angleu); su = sin (rot_angleu);
+          rndtmp = randperm (m, 2);
+          i = rndtmp(1); j = rndtmp(2);
+          U = Uinit;
+          U(i, i) = cu; U(i, j) = -su;
+          U(j, i) = su; U(j, j) = cu;
+          S = U * S;
+        endif
+        if (n > 1)
+          ## Construct V' randomized rotation matrix
+          rot_anglev = 2 * pi * rand ();
+          cv = cos (rot_anglev); sv = sin (rot_anglev);
+          rndtmp = randperm (n, 2);
+          i = rndtmp(1); j = rndtmp(2);
+          V = Vinit;
+          V(i, i) = cv;  V(i, j) = sv;
+          V(j, i) = -sv; V(j, j) = cv;
+          S = S * V;
+        endif
+      endwhile
+    endif
   endif
 
-  S = sparse (i, j, randfun (k, 1), m, n);
-
 endfunction
 
--- a/scripts/sparse/spdiags.m
+++ b/scripts/sparse/spdiags.m
@@ -17,24 +17,25 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {[@var{b}, @var{c}] =} spdiags (@var{A})
-## @deftypefnx {Function File} {@var{b} =} spdiags (@var{A}, @var{c})
-## @deftypefnx {Function File} {@var{b} =} spdiags (@var{v}, @var{c}, @var{A})
-## @deftypefnx {Function File} {@var{b} =} spdiags (@var{v}, @var{c}, @var{m}, @var{n})
+## @deftypefn  {Function File} {@var{B} =} spdiags (@var{A})
+## @deftypefnx {Function File} {[@var{B}, @var{d}] =} spdiags (@var{A})
+## @deftypefnx {Function File} {@var{B} =} spdiags (@var{A}, @var{d})
+## @deftypefnx {Function File} {@var{A} =} spdiags (@var{v}, @var{d}, @var{A})
+## @deftypefnx {Function File} {@var{A} =} spdiags (@var{v}, @var{d}, @var{m}, @var{n})
 ## A generalization of the function @code{diag}.  Called with a single
-## input argument, the non-zero diagonals @var{c} of @var{A} are extracted.
+## input argument, the non-zero diagonals @var{d} of @var{A} are extracted.
 ## With two arguments the diagonals to extract are given by the vector
-## @var{c}.
+## @var{d}.
 ##
 ## The other two forms of @code{spdiags} modify the input matrix by
 ## replacing the diagonals.  They use the columns of @var{v} to replace
-## the columns represented by the vector @var{c}.  If the sparse matrix
+## the diagonals represented by the vector @var{d}.  If the sparse matrix
 ## @var{A} is defined then the diagonals of this matrix are replaced.
 ## Otherwise a matrix of @var{m} by @var{n} is created with the
-## diagonals given by @var{v}.
+## diagonals given by the columns of @var{v}.
 ##
-## Negative values of @var{c} represent diagonals below the main
-## diagonal, and positive values of @var{c} diagonals above the main
+## Negative values of @var{d} represent diagonals below the main
+## diagonal, and positive values of @var{d} diagonals above the main
 ## diagonal.
 ##
 ## For example:
@@ -52,43 +53,86 @@
 ##
 ## @end deftypefn
 
-function [A, c] = spdiags (v, c, m, n)
+function [B, d] = spdiags (v, d, m, n)
+
+  if (nargin < 1 || nargin > 4)
+    print_usage ();
+  endif
 
   if (nargin == 1 || nargin == 2)
-    ## extract nonzero diagonals of v into A,c
+    ## extract nonzero diagonals of A into B,d
     [nr, nc] = size (v);
-    [i, j, v] = find (v);
+    [i, j] = find (v);
 
     if (nargin == 1)
-      ## c contains the active diagonals
-      c = unique (j-i);
+      ## d contains the active diagonals
+      d = unique (j-i);
     endif
-    ## FIXME: we can do this without a loop if we are clever
-    offset = max (min (c, nc-nr), 0);
-    A = zeros (min (nr, nc), length (c));
-    for k = 1:length (c)
-      idx = find (j-i == c(k));
-      A(j(idx)-offset(k),k) = v(idx);
+
+    ## FIXME: Maybe this could be done faster using [i,j,v] = find (v)
+    ##        and then massaging the indices i, j.  However, some
+    ##        benchmarking has shown that diag() written in C++ makes
+    ##        the following code faster even with the for loop.
+    Brows = min (nr, nc);
+    B = zeros (Brows, length (d));
+    for k = 1:length (d)
+      dn = d(k);
+      if (dn <= -nr || dn > nc)
+        continue;
+      endif
+      dv = diag (v, dn);
+      len = rows (dv);
+      if (dn < 0)
+        offset = Brows - len + 1;
+        B(offset:Brows, k) = dv;
+      else
+        B(1:len, k) = dv;
+      endif
     endfor
+
   elseif (nargin == 3)
-    ## Replace specific diagonals c of m with v,c
+    ## Replace specific diagonals d of m with v,d
     [nr, nc] = size (m);
-    B = spdiags (m, c);
-    A = m - spdiags (B, c, nr, nc) + spdiags (v, c, nr, nc);
+    A = spdiags (m, d);
+    B = m - spdiags (A, d, nr, nc) + spdiags (v, d, nr, nc);
+
   else
-    ## Create new matrix of size mxn using v,c
+    ## Create new matrix of size mxn using v,d
     [j, i, v] = find (v);
-    offset = max (min (c(:), n-m), 0);
+    offset = max (min (d(:), n-m), 0);
     j = j(:) + offset(i(:));
-    i = j - c(:)(i(:));
+    i = j - d(:)(i(:));
     idx = i > 0 & i <= m & j > 0 & j <= n;
-    A = sparse (i(idx), j(idx), v(idx), m, n);
+    B = sparse (i(idx), j(idx), v(idx), m, n);
+
   endif
 
 endfunction
 
 
+%!test
+%! [B,d] = spdiags (magic (3));
+%! assert (d, [-2 -1 0 1 2]');
+%! assert (B, [0 0 8 1 6
+%!             0 3 5 7 0
+%!             4 9 2 0 0]);
+
+%! B = spdiags (magic (3), [-2 1]);
+%! assert (B, [0 1; 0 7; 4 0]);
+
+%!test
+%! ## Test zero filling for supra- and super-diagonals
+%! A(1,3) = 13;
+%! A(3,1) = 31;
+%! [B, d] = spdiags (A);
+%! assert (d, [-2 2]');
+%! assert (B, [0 13; 0 0; 31 0]);
+
 %!assert (spdiags (zeros (1,0),1,1,1), sparse (0))
 %!assert (spdiags (zeros (0,1),1,1,1), sparse (0))
-%!assert (spdiags ([0.5 -1 0.5], 0:2, 1, 1), sparse(0.5))
+%!assert (spdiags ([0.5 -1 0.5], 0:2, 1, 1), sparse (0.5))
 
+%% Test input validation
+%!error spdiags ()
+%!error spdiags (1,2,3,4,5)
+
--- a/scripts/sparse/sprand.m
+++ b/scripts/sparse/sprand.m
@@ -21,15 +21,23 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} sprand (@var{m}, @var{n}, @var{d})
+## @deftypefnx {Function File} {} sprand (@var{m}, @var{n}, @var{d}, @var{rc})
 ## @deftypefnx {Function File} {} sprand (@var{s})
-## Generate a random sparse matrix.  The size of the matrix will be
-## @var{m} by @var{n}, with a density of values given by @var{d}.
-## @var{d} should be between 0 and 1.  Values will be uniformly
-## distributed between 0 and 1.
+## Generate a sparse matrix with uniformly distributed random values.
+##
+## The size of the matrix is @var{m}x@var{n} with a density of values @var{d}.
+## @var{d} must be between 0 and 1.  Values will be uniformly distributed on
+## the interval (0, 1).
 ##
-## If called with a single matrix argument, a random sparse matrix is
-## generated wherever the matrix @var{S} is non-zero.
-## @seealso{sprandn, sprandsym}
+## If called with a single matrix argument, a sparse matrix is generated with
+## random values wherever the matrix @var{s} is non-zero.
+##
+## If called with a scalar fourth argument @var{rc}, a random sparse matrix
+## with reciprocal condition number @var{rc} is generated.  If @var{rc} is
+## a vector, then it specifies the first singular values of the generated
+## matrix (@code{length (@var{rc}) <= min (@var{m}, @var{n})}).
+##
+## @seealso{sprandn, sprandsym, rand}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
@@ -42,12 +50,14 @@
 ## David Bateman
 ##      2004-10-20      Texinfo help and copyright message
 
-function S = sprand (m, n, d)
+function s = sprand (m, n, d, rc)
 
   if (nargin == 1 )
-    S = __sprand_impl__ (m, @rand);
+    s = __sprand_impl__ (m, @rand);
   elseif ( nargin == 3)
-    S = __sprand_impl__ (m, n, d, "sprand", @rand);
+    s = __sprand_impl__ (m, n, d, "sprand", @rand);
+  elseif (nargin == 4)
+    s = __sprand_impl__ (m, n, d, rc, "sprand", @rand);
   else
     print_usage ();
   endif
@@ -55,11 +65,25 @@
 endfunction
 
 
+%% Test 3-input calling form
 %!test
 %! s = sprand (4, 10, 0.1);
 %! assert (size (s), [4, 10]);
 %! assert (nnz (s) / numel (s), 0.1);
 
+%% Test 4-input calling form
+%!test
+%! d = rand ();
+%! s1 = sprand (100, 100, d, 0.4);
+%! rc = [5, 4, 3, 2, 1, 0.1];
+%! s2 = sprand (100, 100, d, rc);
+%! s3 = sprand (6, 4, d, rc);
+%! assert (svd (s2)'(1:length (rc)), rc, sqrt (eps)); 
+%! assert (1/cond (s1), 0.4, sqrt (eps));
+%! assert (nnz (s1) / (100*100), d, 0.02);
+%! assert (nnz (s2) / (100*100), d, 0.02); 
+%! assert (svd (s3)', [5 4 3 2], sqrt (eps));
+
 %% Test 1-input calling form
 %!test
 %! s = sprand (sparse ([1 2 3], [3 2 3], [2 2 2]));
@@ -72,16 +96,19 @@
 %!error sprand ()
 %!error sprand (1, 2)
 %!error sprand (1, 2, 3, 4)
-%!error sprand (ones (3), 3, 0.5)
-%!error sprand (3.5, 3, 0.5)
-%!error sprand (0, 3, 0.5)
-%!error sprand (3, ones (3), 0.5)
-%!error sprand (3, 3.5, 0.5)
-%!error sprand (3, 0, 0.5)
-%!error sprand (3, 3, -1)
-%!error sprand (3, 3, 2)
+%!error <M must be an integer greater than 0> sprand (ones (3), 3, 0.5)
+%!error <M must be an integer greater than 0> sprand (3.5, 3, 0.5)
+%!error <M must be an integer greater than 0> sprand (0, 3, 0.5)
+%!error <N must be an integer greater than 0> sprand (3, ones (3), 0.5)
+%!error <N must be an integer greater than 0> sprand (3, 3.5, 0.5)
+%!error <N must be an integer greater than 0> sprand (3, 0, 0.5)
+%!error <D must be between 0 and 1> sprand (3, 3, -1)
+%!error <D must be between 0 and 1> sprand (3, 3, 2)
+%!error <RC must be a scalar or vector> sprand (2, 2, 0.2, ones (3,3))
+%!error <RC must be between 0 and 1> sprand (2, 2, 0.2, -1)
+%!error <RC must be between 0 and 1> sprand (2, 2, 0.2, 2)
 
 %% Test very large, very low density matrix doesn't fail 
 %!test
-%! s = sprand(1e6,1e6,1e-7);
+%! s = sprand (1e6, 1e6, 1e-7);
 
--- a/scripts/sparse/sprandn.m
+++ b/scripts/sparse/sprandn.m
@@ -21,25 +21,35 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {} sprandn (@var{m}, @var{n}, @var{d})
+## @deftypefnx {Function File} {} sprandn (@var{m}, @var{n}, @var{d}, @var{rc})
 ## @deftypefnx {Function File} {} sprandn (@var{s})
-## Generate a random sparse matrix.  The size of the matrix will be
-## @var{m} by @var{n}, with a density of values given by @var{d}.
-## @var{d} should be between 0 and 1.  Values will be normally
-## distributed with mean of zero and variance 1.
+## Generate a sparse matrix with normally distributed random values.
+##
+## The size of the matrix is @var{m}x@var{n} with a density of values @var{d}.
+## @var{d} must be between 0 and 1.  Values will be normally distributed with a
+## mean of 0 and a variance of 1.
 ##
-## If called with a single matrix argument, a random sparse matrix is
-## generated wherever the matrix @var{S} is non-zero.
-## @seealso{sprand, sprandsym}
+## If called with a single matrix argument, a sparse matrix is generated with
+## random values wherever the matrix @var{s} is non-zero.
+##
+## If called with a scalar fourth argument @var{rc}, a random sparse matrix
+## with reciprocal condition number @var{rc} is generated.  If @var{rc} is
+## a vector, then it specifies the first singular values of the generated
+## matrix (@code{length (@var{rc}) <= min (@var{m}, @var{n})}).
+## 
+## @seealso{sprand, sprandsym, randn}
 ## @end deftypefn
 
 ## Author: Paul Kienzle <pkienzle@users.sf.net>
 
-function S = sprandn (m, n, d)
+function s = sprandn (m, n, d, rc)
 
   if (nargin == 1 )
-    S = __sprand_impl__ (m, @randn);
+    s = __sprand_impl__ (m, @randn);
   elseif ( nargin == 3)
-    S = __sprand_impl__ (m, n, d, "sprandn", @randn);
+    s = __sprand_impl__ (m, n, d, "sprandn", @randn);
+  elseif (nargin == 4)
+    s = __sprand_impl__ (m, n, d, rc, "sprandn", @randn);
   else
     print_usage ();
   endif
@@ -47,11 +57,25 @@
 endfunction
 
 
+%% Test 3-input calling form
 %!test
 %! s = sprandn (4, 10, 0.1);
 %! assert (size (s), [4, 10]);
 %! assert (nnz (s) / numel (s), 0.1);
 
+%% Test 4-input calling form
+%!test
+%! d = rand ();
+%! s1 = sprandn (100, 100, d, 0.4);
+%! rc = [5, 4, 3, 2, 1, 0.1];
+%! s2 = sprandn (100, 100, d, rc);
+%! s3 = sprandn (6, 4, d, rc);
+%! assert (svd (s2)'(1:length (rc)), rc, sqrt (eps)); 
+%! assert (1/cond (s1), 0.4, sqrt (eps));
+%! assert (nnz (s1) / (100*100), d, 0.02); 
+%! assert (nnz (s2) / (100*100), d, 0.02); 
+%! assert (svd (s3)', [5 4 3 2], sqrt (eps));
+
 %% Test 1-input calling form
 %!test
 %! s = sprandn (sparse ([1 2 3], [3 2 3], [2 2 2]));
@@ -63,16 +87,19 @@
 %!error sprandn ()
 %!error sprandn (1, 2)
 %!error sprandn (1, 2, 3, 4)
-%!error sprandn (ones (3), 3, 0.5)
-%!error sprandn (3.5, 3, 0.5)
-%!error sprandn (0, 3, 0.5)
-%!error sprandn (3, ones (3), 0.5)
-%!error sprandn (3, 3.5, 0.5)
-%!error sprandn (3, 0, 0.5)
-%!error sprandn (3, 3, -1)
-%!error sprandn (3, 3, 2)
+%!error <M must be an integer greater than 0> sprandn (ones (3), 3, 0.5)
+%!error <M must be an integer greater than 0> sprandn (3.5, 3, 0.5)
+%!error <M must be an integer greater than 0> sprandn (0, 3, 0.5)
+%!error <N must be an integer greater than 0> sprandn (3, ones (3), 0.5)
+%!error <N must be an integer greater than 0> sprandn (3, 3.5, 0.5)
+%!error <N must be an integer greater than 0> sprandn (3, 0, 0.5)
+%!error <D must be between 0 and 1> sprandn (3, 3, -1)
+%!error <D must be between 0 and 1> sprandn (3, 3, 2)
+%!error <RC must be a scalar or vector> sprandn (2, 2, 0.2, ones (3,3))
+%!error <RC must be between 0 and 1> sprandn (2, 2, 0.2, -1)
+%!error <RC must be between 0 and 1> sprandn (2, 2, 0.2, 2)
 
 %% Test very large, very low density matrix doesn't fail 
 %!test
-%! s = sprandn(1e6,1e6,1e-7);
+%! s = sprandn (1e6,1e6,1e-7);
 
--- a/scripts/statistics/base/prctile.m
+++ b/scripts/statistics/base/prctile.m
@@ -30,10 +30,8 @@
 ##
 ## If @var{p} is unspecified, return the quantiles for @code{[0 25 50 75 100]}.
 ## The optional argument @var{dim} determines the dimension along which
-## the percentiles are calculated.  If @var{dim} is omitted, and @var{x} is
-## a vector or matrix, it defaults to 1 (column-wise quantiles).  When
-## @var{x} is an N-D array, @var{dim} defaults to the first non-singleton
-## dimension.
+## the percentiles are calculated.  If @var{dim} is omitted it defaults to the
+## the first non-singleton dimension.
 ## @seealso{quantile}
 ## @end deftypefn
 
@@ -59,14 +57,10 @@
   endif
 
   nd = ndims (x);
+  sz = size (x);
   if (nargin < 3)
-    if (nd == 2)
-      ## If a matrix or vector, always use 1st dimension.
-      dim = 1;
-    else
-      ## If an N-d array, find the first non-singleton dimension.
-      (dim = find (sz > 1, 1)) || (dim = 1);
-    endif
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
   else
     if (!(isscalar (dim) && dim == fix (dim))
         || !(1 <= dim && dim <= nd))
@@ -84,11 +78,26 @@
 
 %!test
 %! pct = 50;
+%! q = prctile (1:4, pct);
+%! qa = 2.5;
+%! assert (q, qa);
 %! q = prctile (1:4, pct, 1);
 %! qa = [1, 2, 3, 4];
 %! assert (q, qa);
 %! q = prctile (1:4, pct, 2);
-%! qa = 2.5000;
+%! qa = 2.5;
+%! assert (q, qa);
+
+%!test
+%! pct = [50 75];
+%! q = prctile (1:4, pct);
+%! qa = [2.5 3.5];
+%! assert (q, qa);
+%! q = prctile (1:4, pct, 1);
+%! qa = [1, 2, 3, 4; 1, 2, 3, 4];
+%! assert (q, qa);
+%! q = prctile (1:4, pct, 2);
+%! qa = [2.5 3.5];
 %! assert (q, qa);
 
 %!test
--- a/scripts/statistics/base/qqplot.m
+++ b/scripts/statistics/base/qqplot.m
@@ -62,7 +62,7 @@
     print_usage ();
   endif
 
-  if (!(isnumeric (x) && isvector (x)))
+  if (! (isnumeric (x) && isvector (x)))
     error ("qqplot: X must be a numeric vector");
   endif
 
@@ -97,7 +97,7 @@
   endif
 
   if (nargout == 0)
-    plot (q, s);
+    plot (q, s, "-x");
     q_label = strrep (q_label, '_inv', '\_inv');
     if (q_label(1) == '@')
       q_label = q_label(6:end);  # Strip "@(y) " from anon. function
@@ -111,4 +111,3 @@
 
 endfunction
 
-
--- a/scripts/statistics/base/quantile.m
+++ b/scripts/statistics/base/quantile.m
@@ -32,10 +32,8 @@
 ## If @var{p} is unspecified, return the quantiles for
 ## @code{[0.00 0.25 0.50 0.75 1.00]}.
 ## The optional argument @var{dim} determines the dimension along which
-## the quantiles are calculated.  If @var{dim} is omitted, and @var{x} is
-## a vector or matrix, it defaults to 1 (column-wise quantiles).  If
-## @var{x} is an N-D array, @var{dim} defaults to the first non-singleton
-## dimension.
+## the quantiles are calculated.  If @var{dim} is omitted it defaults to
+## the first non-singleton dimension.
 ##
 ## The methods available to calculate sample quantiles are the nine methods
 ## used by R (@url{http://www.r-project.org/}).  The default value is
@@ -108,7 +106,7 @@
 ## Author: Ben Abbott <bpabbott@mac.com>
 ## Description: Matlab style quantile function of a discrete/continuous distribution
 
-function q = quantile (x, p = [], dim = 1, method = 5)
+function q = quantile (x, p = [], dim, method = 5)
 
   if (nargin < 1 || nargin > 4)
     print_usage ();
@@ -126,9 +124,14 @@
     error ("quantile: P must be a numeric vector");
   endif
 
-  if (!(isscalar (dim) && dim == fix (dim))
-      || !(1 <= dim && dim <= ndims (x)))
-    error ("quantile: DIM must be an integer and a valid dimension");
+  if (nargin < 3)
+    ## Find the first non-singleton dimension.
+    (dim = find (size (x) > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= ndims (x)))
+      error ("quantile: DIM must be an integer and a valid dimension");
+    endif
   endif
 
   ## Set the permutation vector.
@@ -158,6 +161,30 @@
 
 
 %!test
+%! p = 0.50;
+%! q = quantile (1:4, p);
+%! qa = 2.5;
+%! assert (q, qa);
+%! q = quantile (1:4, p, 1);
+%! qa = [1, 2, 3, 4];
+%! assert (q, qa);
+%! q = quantile (1:4, p, 2);
+%! qa = 2.5;
+%! assert (q, qa);
+
+%!test
+%! p = [0.50 0.75];
+%! q = quantile (1:4, p);
+%! qa = [2.5 3.5];
+%! assert (q, qa);
+%! q = quantile (1:4, p, 1);
+%! qa = [1, 2, 3, 4; 1, 2, 3, 4];
+%! assert (q, qa);
+%! q = quantile (1:4, p, 2);
+%! qa = [2.5 3.5];
+%! assert (q, qa);
+
+%!test
 %! p = 0.5;
 %! x = sort (rand (11));
 %! q = quantile (x, p);
--- a/scripts/statistics/distributions/empirical_pdf.m
+++ b/scripts/statistics/distributions/empirical_pdf.m
@@ -37,7 +37,16 @@
     error ("empirical_pdf: DATA must be a vector");
   endif
 
-  pdf = discrete_pdf (x, data, ones (size (data)));
+  uniq_vals = unique (data);
+  if (numel (data) != numel (uniq_vals))
+    ## Handle ties, multiple elements with same value
+    p = histc (data, uniq_vals);
+    data = uniq_vals;
+  else
+    p = ones (size (data));
+  endif
+
+  pdf = discrete_pdf (x, data, p);
 
 endfunction
 
@@ -52,6 +61,9 @@
 %!assert (empirical_pdf (single (x), v), single (y))
 %!assert (empirical_pdf (x, single (v)), single (y))
 
+%% Test distribution with ties
+%!assert (empirical_pdf (2, [1 2 3 2]), 0.5)
+
 %% Test input validation
 %!error empirical_pdf ()
 %!error empirical_pdf (1)
--- a/scripts/statistics/distributions/normrnd.m
+++ b/scripts/statistics/distributions/normrnd.m
@@ -83,7 +83,7 @@
   endif
 
   if (isscalar (mu) && isscalar (sigma))
-    if (isfinite (mu) && (sigma > 0) && (sigma < Inf))
+    if (isfinite (mu) && (sigma >= 0) && (sigma < Inf))
       rnd =  mu + sigma * randn (sz, cls);
     else
       rnd = NaN (sz, cls);
--- a/scripts/statistics/tests/hotelling_test_2.m
+++ b/scripts/statistics/tests/hotelling_test_2.m
@@ -26,7 +26,7 @@
 ## Hotelling's two-sample @math{T^2} is returned in @var{tsq}.  Under the null,
 ## @tex
 ## $$
-## {n_x+n_y-p-1) T^2 \over p(n_x+n_y-2)}
+## {(n_x+n_y-p-1) T^2 \over p(n_x+n_y-2)}
 ## $$
 ## @end tex
 ## @ifnottex
--- a/scripts/strings/validatestring.m
+++ b/scripts/strings/validatestring.m
@@ -100,22 +100,21 @@
   ## Make static part of error string that uses funcname, varname, and position
   errstr = "";
   if (! isempty (funcname))
-    errstr = sprintf ("Function: %s ", funcname);
+    errstr = [funcname ": "];
   endif
   if (! isempty (varname))
-    errstr = sprintf ("%sVariable: %s ", errstr, varname);
+    errstr = [errstr varname " "];
+  else
+    errstr = sprintf ("%s'%s' ", errstr, str);
   endif
   if (position > 0)
-    errstr = sprintf ("%sArgument position %d ", errstr, position);
-  endif
-  if (! isempty (errstr))
-    errstr(end:end+1) = ":\n";
+    errstr = sprintf ("%s(argument #%i) ", errstr, position);
   endif
 
   matches = strncmpi (str, strarray(:), length (str));
   nmatches = sum (matches);
   if (nmatches == 0)
-    error ("validatestring: %s'%s' does not match any of\n%s", errstr, str,
+    error ("%sdoes not match any of\n%s", errstr,
            sprintf ("%s, ", strarray{:})(1:end-2));
   elseif (nmatches == 1)
     str = strarray{matches};
@@ -130,8 +129,8 @@
     if (all (submatch))
       str = short_str;
     else
-      error ("validatestring: %smultiple unique matches were found for '%s':\n%s",
-             errstr, str, sprintf ("%s, ", strarray{match_idx})(1:end-2));
+      error ("%sallows multiple unique matches:\n%s",
+             errstr, sprintf ("%s, ", strarray{match_idx})(1:end-2));
     endif
   endif
 
@@ -147,10 +146,10 @@
 %!assert (validatestring ("d", strarray), "def")
 
 %!error <'xyz' does not match any> validatestring ("xyz", strarray)
-%!error <Function: DUMMY_TEST> validatestring ("xyz", strarray, "DUMMY_TEST")
-%!error <Function: DUMMY_TEST Variable: DUMMY_VAR:> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR")
-%!error <Function: DUMMY_TEST Variable: DUMMY_VAR Argument position 5> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR", 5)
-%!error <multiple unique matches were found for 'abc'> validatestring ("abc", strarray)
+%!error <DUMMY_TEST: 'xyz' does not> validatestring ("xyz", strarray, "DUMMY_TEST")
+%!error <DUMMY_TEST: DUMMY_VAR does> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR")
+%!error <DUMMY_TEST: DUMMY_VAR \(argument #5\) does> validatestring ("xyz", strarray, "DUMMY_TEST", "DUMMY_VAR", 5)
+%!error <'abc' allows multiple unique matches> validatestring ("abc", strarray)
 
 %% Test input validation
 %!error validatestring ("xyz")
--- a/scripts/testfun/__run_test_suite__.m
+++ b/scripts/testfun/__run_test_suite__.m
@@ -66,7 +66,7 @@
       dsk += sk;
     endfor
     puts ("\nSummary:\n\n");
-    nfail = dn - dp;
+    nfail = dn - dp - dxf;
     printf ("  PASS    %6d\n", dp);
     printf ("  FAIL    %6d\n", nfail);
     if (dxf > 0)
@@ -116,16 +116,22 @@
 endfunction
 
 function print_test_file_name (nm)
-  filler = repmat (".", 1, 55-length (nm));
+  filler = repmat (".", 1, 60-length (nm));
   printf ("  %s %s", nm, filler);
 endfunction
 
-function print_pass_fail (n, p)
-  if (n > 0)
-    printf (" PASS %4d/%-4d", p, n);
-    nfail = n - p;
+function print_pass_fail (p, n, xf, sk)
+  if ((n + sk) > 0)
+    printf (" PASS   %4d/%-4d", p, n);
+    nfail = n - p - xf;
     if (nfail > 0)
-      printf (" FAIL %d", nfail);
+      printf ("\n%71s %3d", "FAIL ", nfail);
+    endif    
+    if (sk > 0)
+      printf ("\n%71s %3d", "SKIP ", sk);
+    endif
+    if (xf > 0)
+      printf ("\n%71s %3d", "XFAIL", xf);
     endif
   endif
   puts ("\n");
@@ -190,7 +196,7 @@
         if (has_tests (ffnm))
           print_test_file_name (nm);
           [p, n, xf, sk] = test (nm, "quiet", fid);
-          print_pass_fail (n, p);
+          print_pass_fail (p, n, xf, sk);
           files_with_tests(end+1) = ffnm;
         else
           files_with_no_tests(end+1) = ffnm;
@@ -241,7 +247,7 @@
         tmp = strrep (tmp, [topbuilddir, filesep], "");
         print_test_file_name (tmp);
         [p, n, xf, sk] = test (f, "quiet", fid);
-        print_pass_fail (n, p);
+        print_pass_fail (p, n, xf, sk);
         dp += p;
         dn += n;
         dxf += xf;
--- a/scripts/testfun/assert.m
+++ b/scripts/testfun/assert.m
@@ -162,7 +162,7 @@
           err.reason{end+1} = ["Expected struct, but observed " class(cond)];
         elseif (ndims (cond) != ndims (expected)
                 || any (size (cond) != size (expected))
-                || rows (fieldnames (cond)) != rows (fieldnames (expected)))
+                || numfields (cond) != numfields (expected))
 
           err.index{end+1} = ".";
           err.observed{end+1} = ["O(" sprintf("%dx", size(cond))(1:end-1) ")"];
--- a/scripts/testfun/rundemos.m
+++ b/scripts/testfun/rundemos.m
@@ -42,7 +42,7 @@
       if (directory(end) == '/' || directory(end) == '\')
         directory(end) = [];
       endif
-      fullname = find_dir_in_path (directory);
+      fullname = dir_in_loadpath (directory);
       if (isempty (fullname))
         error ("rundemos: DIRECTORY argument must be a valid pathname");
       endif
--- a/scripts/testfun/runtests.m
+++ b/scripts/testfun/runtests.m
@@ -42,7 +42,7 @@
       if (directory(end) == '/' || directory(end) == '\')
         directory(end) = [];
       endif
-      fullname = find_dir_in_path (directory);
+      fullname = dir_in_loadpath (directory);
       if (isempty (fullname))
         error ("runtests: DIRECTORY argument must be a valid pathname");
       endif
--- a/scripts/testfun/test.m
+++ b/scripts/testfun/test.m
@@ -265,6 +265,7 @@
     ## Assume the block will succeed.
     __success = 1;
     __msg = [];
+    __isxtest = 0;
 
 ### DEMO
 
@@ -492,10 +493,17 @@
 
 ### TEST
 
-    elseif (strcmp (__type, "test") || strcmp (__type, "xtest"))
+    elseif (strcmp (__type, "test"))
       __istest = 1;
       ## Code will be evaluated below.
 
+### XTEST
+
+    elseif (strcmp (__type, "xtest"))
+      __istest = 0;
+      __isxtest = 1;
+      ## Code will be evaluated below.
+
 ### Comment block.
 
     elseif (strcmp (__block(1:1), "#"))
@@ -529,6 +537,7 @@
         if (strcmp (__type, "xtest"))
            __msg = sprintf ("%sknown failure\n%s", __signal_fail, lasterr ());
            __xfail++;
+           __success = 0;
         else
            __msg = sprintf ("%stest failed\n%s", __signal_fail, lasterr ());
            __success = 0;
@@ -558,7 +567,7 @@
         fflush (__fid);
       endif
     endif
-    if (__success == 0)
+    if (__success == 0 && !__isxtest)
       __all_success = 0;
       ## Stop after one error if not in batch mode.
       if (! __batch)
@@ -571,8 +580,8 @@
         return;
       endif
     endif
-    __tests += __istest;
-    __successes += __success * __istest;
+    __tests += (__istest || __isxtest);
+    __successes += __success * (__istest || __isxtest);
   endfor
   ## Clear any test functions created
   eval (__clear, "");
--- a/scripts/time/datestr.m
+++ b/scripts/time/datestr.m
@@ -252,7 +252,8 @@
 
     df = regexprep (df, '[Ss][Ss]', "%S");
 
-    df = strrep (df, "FFF", sprintf ("%03d", 1000 * (v(i,6) - fix (v(i,6)))));
+    df = strrep (df, "FFF", sprintf ("%03d",
+                                     round (1000 * (v(i,6) - fix (v(i,6))))));
 
     df = strrep (df, 'QQ', sprintf ("Q%d", fix ((v(i,2) + 2) / 3)));
 
--- a/scripts/time/datevec.m
+++ b/scripts/time/datevec.m
@@ -113,6 +113,8 @@
     p = (localtime (time ())).year + 1900 - 50;
   endif
 
+  do_resize = false;
+
   if (iscell (date))
 
     nd = numel (date);
@@ -146,6 +148,10 @@
 
   else   # datenum input
 
+    if (! iscolumn (date))
+      date_sz = size (date);
+      do_resize = true;
+    endif
     date = date(:);
 
     ## Move day 0 from midnight -0001-12-31 to midnight 0000-3-1
@@ -182,6 +188,13 @@
 
   if (nargout <= 1)
     y = [y, m, d, h, mi, s];
+  elseif (do_resize)
+    y = reshape (y, date_sz);
+    m = reshape (m, date_sz);
+    d = reshape (d, date_sz);
+    h = reshape (h, date_sz);
+    mi = reshape (mi, date_sz);
+    s = reshape (s, date_sz);
   endif
 
 endfunction
@@ -306,12 +319,23 @@
 %!assert (datevec ("03:38 PM"), [yr,1,1,15,38,0])
 %!assert (datevec ("03/13/1962"), [1962,3,13,0,0,0])
 
-%% Test millisecond format FFF
+## Test millisecond format FFF
 %!assert (datevec ("15:38:21.25", "HH:MM:SS.FFF"), [yr,1,1,15,38,21.025])
 
-# Other tests
+## Test structure of return value (bug #42334)
+%!test
+%! [~, ~, d] = datevec ([1 2; 3 4]);
+%! assert (d, [1 2; 3 4]);
+
+## Other tests
 %!assert (datenum (datevec ([-1e4:1e4])), [-1e4:1e4]');
 %!test
 %! t = linspace (-2e5, 2e5, 10993);
 %! assert (all (abs (datenum (datevec (t)) - t') < 1e-5));
 
+%% Test input validation
+%!error datevec ()
+%!error datevec (1,2,3,4)
+%!error <none of the standard formats match> datevec ("foobar")
+%!error <DATE not parsed correctly with given format> datevec ("foobar", "%d")
+
--- a/src/main.in.cc
+++ b/src/main.in.cc
@@ -603,8 +603,8 @@
 
               retval = 1;
             }
-
-          retval = octave_exec (file, new_argv);
+          else
+            retval = octave_exec (file, new_argv);
         }
       else
         {
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -56,6 +56,7 @@
 include bug-36025/module.mk
 include bug-38236/module.mk
 include bug-38691/module.mk
+include classdef/module.mk
 include classes/module.mk
 include class-concat/module.mk
 include ctor-vs-method/module.mk
@@ -70,6 +71,11 @@
 check: sparse.tst bc-overload-tests.stamp
 	$(top_builddir)/run-octave $(RUN_OCTAVE_OPTIONS) --norc --silent --no-history $(srcdir)/fntests.m $(srcdir)
 
+if AMCOND_HAVE_LLVM
+check-jit: sparse.tst bc-overload-tests.stamp
+	$(top_builddir)/run-octave $(RUN_OCTAVE_OPTIONS) --jit-compiler --norc --silent --no-history $(srcdir)/fntests.m $(srcdir)
+endif
+
 sparse.tst: build-sparse-tests.sh
 	$(srcdir)/build-sparse-tests.sh
 
--- a/test/build-sparse-tests.sh
+++ b/test/build-sparse-tests.sh
@@ -513,14 +513,13 @@
 # Specific tests for certain mapper functions
     cat >>$TESTS <<EOF
 
-%% These mapper functions always return a full matrix
 %!test
 %! wn2s = warning ("query", "Octave:num-to-str");
 %! warning ("off", "Octave:num-to-str");
 %! if (isreal (af))
 %!   assert (toascii (as), toascii (af));
-%!   assert (tolower (as), tolower (af));
-%!   assert (toupper (as), toupper (af));
+%!   assert (tolower (as), as);
+%!   assert (toupper (as), as);
 %! endif
 %! warning (wn2s.state, "Octave:num-to-str");
 
new file mode 100644
--- /dev/null
+++ b/test/classdef/classdef.tst
@@ -0,0 +1,73 @@
+## Copyright (C) 2013 Ben Abbott
+##
+## 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/>.
+
+%%  Test script for classdef OOP.
+%%  Requires the path to contain the test classes.
+%%
+%%  Note: This script and all classes are also intended to run
+%%        in MATLAB to test compatibility.  Don't break that!
+%%
+%%  To Do:  This script tests to ensure that things done correctly work
+%%          corrrectly.  It should also check that things done incorrectly
+%%          error properly.
+%%
+%%  The classes used for the tests reside in the test/classdef with others
+%%  in the test directory.
+%%
+%%  The classes provide the ability to test most of the major features
+%%  of the classdef OOP facilities.  There are a number of classes, mostly
+%%  kind of the same, that create a hierarchy.
+
+%%  Basic classdef tests for value class
+%!shared p, q, i, amt
+%! q = foo_value_class ();
+%! p = foo_value_class (4, 4*12, 50e3);
+%! i = p.rate / (12 * 100);
+%! amt = (p.principle * i) / (1 - (1 + i)^(-p.term));
+%!assert (isempty (q.rate));
+%!assert (isempty (q.principle));
+%!assert (isempty (q.term));
+%!assert (class (p), "foo_value_class");
+%!assert (p.term, 48);
+%!assert (p.rate, 4.0);
+%!assert (p.principle, 50e3);
+%!assert (p.amount, amt, eps ())
+%!assert (amount (p), amt, eps ())
+%!xtest
+%! assert (properties (p), {'rate'; 'term'; 'principle'})
+%!xtest
+%! assert (methods (p), {'amount'; 'foo_value_class'})
+%!assert (isempty (foo_value_class().rate))
+%!error <property `rate' is not constant> foo_value_class.rate
+
+%%  Static method and Constant Property
+%!assert (foo_static_method_constant_property.radians_per_cycle, 2*pi);
+%!assert (foo_static_method_constant_property().radians_per_cycle, 2*pi);
+%!assert (foo_static_method_constant_property().pie, pi);
+%!error <property `frequency' is not constant> foo_static_method_constant_property.frequency
+%!error <method `cosine' is not static> foo_static_method_constant_property.cosine
+%!test
+%! obj = foo_static_method_constant_property;
+%! obj.frequency = 10;
+%! assert (obj.cosine (0.1), cos (2 * pi * 10 * 0.1), eps ())
+%! assert (obj.sine (0.1), sin (2 * pi * 10 * 0.1), eps ())
+
+%!test
+%! obj = foo_method_changes_property_size (3);
+%! obj = obj.move_element_to_end (2);
+%! assert (obj.element, [1 3 2])
new file mode 100644
--- /dev/null
+++ b/test/classdef/foo_method_changes_property_size.m
@@ -0,0 +1,14 @@
+classdef foo_method_changes_property_size
+  properties
+    element;
+  end
+  methods
+    function obj = foo_method_changes_property_size (n)
+      obj.element = 1:n;
+    end
+    function obj = move_element_to_end (obj, n)
+      obj.element(end+1) = obj.element(n);
+      obj.element(n) = [];
+    end
+  end
+end
new file mode 100644
--- /dev/null
+++ b/test/classdef/foo_static_method_constant_property.m
@@ -0,0 +1,30 @@
+classdef foo_static_method_constant_property
+  properties
+    frequency;
+  end
+  properties (Constant = true)
+    pie = pi;
+  end
+  methods
+    function obj = foo_static_method_constant_property (f)
+      if (nargin == 1)
+        obj.frequency = f;
+      elseif (nargin ~= 0)
+        error ('foo_static_method_constant_property:SyntaxError', ...
+               'foo_static_method_constant_property: Invalid syntax')
+      end
+    end
+    function res = cosine (obj, t)
+      res = cos (obj.radians_per_cycle () * obj.frequency * t);
+    end
+    function res = sine (obj, t)
+      res = sin (obj.radians_per_cycle () * obj.frequency * t);
+    end
+  end
+  methods (Static)
+    function res = radians_per_cycle ()
+      res = 2 * foo_static_method_constant_property.pie;
+    end
+  end
+end
+
new file mode 100644
--- /dev/null
+++ b/test/classdef/foo_value_class.m
@@ -0,0 +1,28 @@
+classdef foo_value_class
+  properties
+    rate;
+    term;
+    principle;
+  end
+  methods
+    function obj = foo_value_class (r, t, p)
+      if (nargin == 3)
+        obj.rate = r;
+        obj.term = t;
+        obj.principle = p;
+      elseif (nargin ~= 0)
+        error ('foo_value_class:SyntaxError', ...
+               'foo_value_class: Invalid syntax')
+      end
+    end
+    function amt = amount (obj)
+      i = obj.rate / (12 * 100);
+      if (i == 0 && obj.term == 0)
+        amt = obj.principle;
+      else
+        amt = (obj.principle * i) / (1 - (1 + i)^(-obj.term));
+      end
+    end
+  end
+end
+
new file mode 100644
--- /dev/null
+++ b/test/classdef/module.mk
@@ -0,0 +1,7 @@
+classdef_FCN_FILES = \
+  classdef/foo_method_changes_property_size.m \
+  classdef/foo_static_method_constant_property.m \
+  classdef/foo_value_class.m \
+  classdef/classdef.tst
+
+FCN_FILES += $(classdef_FCN_FILES)
rename from test/fcn-handle-derived-resolution/@derived/derived.m
rename to test/fcn-handle-derived-resolution/@fhdr_derived/fhdr_derived.m
--- a/test/fcn-handle-derived-resolution/@derived/derived.m
+++ b/test/fcn-handle-derived-resolution/@fhdr_derived/fhdr_derived.m
@@ -1,5 +1,5 @@
-function r = derived (n)
+function r = fhdr_derived (n)
   s.a = n;
-  p = parent (n);
-  r = class (s, 'derived', p);
+  p = fhdr_parent (n);
+  r = class (s, 'fhdr_derived', p);
 end
rename from test/fcn-handle-derived-resolution/@other/other.m
rename to test/fcn-handle-derived-resolution/@fhdr_other/fhdr_other.m
--- a/test/fcn-handle-derived-resolution/@other/other.m
+++ b/test/fcn-handle-derived-resolution/@fhdr_other/fhdr_other.m
@@ -1,4 +1,4 @@
-function r = other (n)
-  s.d = derived (n);
-  r = class (s, 'other');
+function r = fhdr_other (n)
+  s.d = fhdr_derived (n);
+  r = class (s, 'fhdr_other');
 end
rename from test/fcn-handle-derived-resolution/@other/getsize_arrayfun.m
rename to test/fcn-handle-derived-resolution/@fhdr_other/getsize_arrayfun.m
rename from test/fcn-handle-derived-resolution/@other/getsize_cellfun.m
rename to test/fcn-handle-derived-resolution/@fhdr_other/getsize_cellfun.m
rename from test/fcn-handle-derived-resolution/@other/getsize_loop.m
rename to test/fcn-handle-derived-resolution/@fhdr_other/getsize_loop.m
rename from test/fcn-handle-derived-resolution/@parent/parent.m
rename to test/fcn-handle-derived-resolution/@fhdr_parent/fhdr_parent.m
--- a/test/fcn-handle-derived-resolution/@parent/parent.m
+++ b/test/fcn-handle-derived-resolution/@fhdr_parent/fhdr_parent.m
@@ -1,4 +1,4 @@
-function r = parent (n)
+function r = fhdr_parent (n)
   s.a = rand (n, 1);
-  r = class (s, 'parent');
+  r = class (s, 'fhdr_parent');
 end
rename from test/fcn-handle-derived-resolution/@parent/numel.m
rename to test/fcn-handle-derived-resolution/@fhdr_parent/numel.m
--- a/test/fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst
+++ b/test/fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst
@@ -22,38 +22,46 @@
 %%  Note: This script and all classes are also intended to run
 %%        in Matlab to test compatibility.  Don't break that!
 
-%!shared
-%! clear -classes
+%% FIXME: Can't use 'clear -classes' because it also clears all functions in the
+%% namespace of test.m (bug #35881).  This is a problem only if Octave would
+%% re-use a class definition that was defined somewhere else.  Unfortunately,
+%% that is exactly the case when running 'make check' since the ctor-vs-method
+%% test also uses an @parent, @derived, and @other class.
+%% Until the bug is fixed, it suffices to make the class names unique so that
+%% there is no re-use.  Using the prefix fhdr (fcn-handle-derived-resolution)
+%% for this directory.
+%%!shared
+%%! #clear -classes
 
 %!test
-%! p = parent (7);
+%! p = fhdr_parent (7);
 %! assert (numel (p), 7)
 
 %!test
-%! d = derived (13);
+%! d = fhdr_derived (13);
 %! assert (numel (d), 13)
 
 %!test
-%! p = parent (11);
+%! p = fhdr_parent (11);
 %! f = @numel;
 %! assert (f (p), 11)
 
 %!test
-%! d = parent (21);
+%! d = fhdr_parent (21);
 %! f = @numel;
 %! assert (f (d), 21)
 
 %!test
-%! o(1) = other (13);
-%! o(2) = other (42);
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
 %! assert (getsize_loop (o), [13, 42])
 
 %!test
-%! o(1) = other (13);
-%! o(2) = other (42);
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
 %! assert (getsize_cellfun (o), [13, 42])
 
 %!test
-%! o(1) = other (13);
-%! o(2) = other (42);
+%! o(1) = fhdr_other (13);
+%! o(2) = fhdr_other (42);
 %! assert (getsize_arrayfun (o), [13, 42])
--- a/test/fcn-handle-derived-resolution/module.mk
+++ b/test/fcn-handle-derived-resolution/module.mk
@@ -1,11 +1,11 @@
 fcn_handle_derived_resolution_FCN_FILES = \
-  fcn-handle-derived-resolution/@derived/derived.m \
-  fcn-handle-derived-resolution/@other/getsize_arrayfun.m \
-  fcn-handle-derived-resolution/@other/getsize_cellfun.m \
-  fcn-handle-derived-resolution/@other/getsize_loop.m \
-  fcn-handle-derived-resolution/@other/other.m \
-  fcn-handle-derived-resolution/@parent/numel.m \
-  fcn-handle-derived-resolution/@parent/parent.m \
+  fcn-handle-derived-resolution/@fhdr_derived/fhdr_derived.m \
+  fcn-handle-derived-resolution/@fhdr_other/getsize_arrayfun.m \
+  fcn-handle-derived-resolution/@fhdr_other/getsize_cellfun.m \
+  fcn-handle-derived-resolution/@fhdr_other/getsize_loop.m \
+  fcn-handle-derived-resolution/@fhdr_other/fhdr_other.m \
+  fcn-handle-derived-resolution/@fhdr_parent/numel.m \
+  fcn-handle-derived-resolution/@fhdr_parent/fhdr_parent.m \
   fcn-handle-derived-resolution/fcn-handle-derived-resolution.tst
 
 FCN_FILES += $(fcn_handle_derived_resolution_FCN_FILES)
--- a/test/jit.tst
+++ b/test/jit.tst
@@ -26,8 +26,8 @@
 %! __old_jit_startcnt__ = jit_startcnt (1000);
 
 ## Test some simple cases that compile.
-
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! for i=1:1e6
 %!   if (i < 5)
 %!     break;
@@ -36,8 +36,10 @@
 %!   endif
 %! endfor
 %! assert (i, 1);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! while (1)
 %!   if (1)
 %!     break;
@@ -45,33 +47,133 @@
 %!     break;
 %!   endif
 %! endwhile
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   break;
+%! until (0)
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   if (1)
+%!     break;
+%!   end;
+%! until (0)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! i=1;
+%! do
+%!   continue;
+%!   i=i+1;
+%! until (1)
+%! assert (i, 1);
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! for i=1:1e6
 %!   if (i == 100)
 %!     break;
 %!   endif
 %! endfor
 %! assert (i, 100);
+%! assert (jit_failure_count, 0);
 
 ## Also test parfor keyword
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! parfor i=1:1e6
 %!   if (i == 100)
 %!     break;
 %!   endif
 %! endparfor
 %! assert (i, 100);
+%! assert (jit_failure_count, 0);
+## Test some switch statements
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   case 1
+%!     break;
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   otherwise
+%!     break;
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! do
+%!   switch (1)
+%!   case 1
+%!     break;
+%!   otherwise
+%!     break;
+%!   end;
+%! until(1)
+%! assert (jit_failure_count, 0);
+
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
+%! i=0;
+%! a=0;
+%! b=0;
+%! do
+%!   i=i+1;
+%!   switch (i)
+%!   case 1
+%!     continue;
+%!   case 2
+%!     b=1;
+%!     continue;
+%!   case 4
+%!     break;
+%!   otherwise
+%!     a=a+5;
+%!   end;
+%!   a=a+1;
+%! until(0);
+%! assert (i, 4);
+%! assert (a, 6);
+%! assert (b, 1);
+%! assert (jit_failure_count, 0);
+
+## Some more complex calculations
+%!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! inc = 1e-5;
 %! result = 0;
 %! for ii = 0:inc:1
 %!   result = result + inc * (1/3 * ii * ii);
 %! endfor
 %! assert (abs (result - 1/9) < 1e-5);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! inc = 1e-5;
 %! result = 0;
 %! for ii = 0:inc:1
@@ -79,8 +181,10 @@
 %!   result = result + inc * (1/3 * ii ^ 2);
 %! endfor
 %! assert (abs (result - 1/9) < 1e-5);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! temp = 1+1i;
 %! nan = NaN;
 %! while (1)
@@ -89,8 +193,10 @@
 %!   break;
 %! endwhile
 %! assert (imag (temp), 0);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! temp = 1+1i;
 %! nan = NaN+1i;
 %! while (1)
@@ -100,24 +206,30 @@
 %!   break;
 %! endwhile
 %! assert (imag (temp), 0);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! temp = 1+1i;
 %! while (1)
 %!   temp = temp * 5;
 %!   break;
 %! endwhile
 %! assert (temp, 5+5i);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! nr = 1001;
 %! mat = zeros (1, nr);
 %! for i = 1:nr
 %!   mat(i) = i;
 %! endfor
 %! assert (mat == 1:nr);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! nr = 1001;
 %! mat = 1:nr;
 %! mat(end) = 0; # force mat to a matrix
@@ -126,8 +238,10 @@
 %!   total = mat(i) + total;
 %! endfor
 %! assert (sum (mat) == total);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! nr = 1001;
 %! mat = [3 1 5];
 %! try
@@ -141,6 +255,7 @@
 %! catch
 %! end_try_catch
 %! assert (result == 500);
+%! assert (jit_failure_count, 0);
 
 %!function result = gen_test (n)
 %!  result = double (rand (1, n) > .01);
@@ -176,18 +291,23 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! test_set = gen_test (10000);
 %! assert (all (vectorized (test_set, 3) == loopy (test_set, 3)));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! niter = 1001;
 %! i = 0;
 %! while (i < niter)
 %!   i = i + 1;
 %! endwhile
 %! assert (i == niter);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! niter = 1001;
 %! result = 0;
 %! m = [5 10];
@@ -195,8 +315,10 @@
 %!   result = result + m(end);
 %! endfor
 %! assert (result == m(end) * niter);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! ndim = 100;
 %! result = 0;
 %! m = zeros (ndim);
@@ -209,8 +331,10 @@
 %!   i = i + 1;
 %! endwhile
 %! assert (result == sum (sum (m)));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! ndim = 100;
 %! m = zeros (ndim);
 %! i = 1;
@@ -223,8 +347,10 @@
 %! m2 = zeros (ndim);
 %! m2(:) = 1:(ndim^2);
 %! assert (all (m == m2));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! ndim = 2;
 %! m = zeros (ndim, ndim, ndim, ndim);
 %! result = 0;
@@ -244,6 +370,7 @@
 %! expected = ones (ndim, ndim, ndim, ndim);
 %! assert (all (m == expected));
 %! assert (result == sum (expected (:)));
+%! assert (jit_failure_count, 0);
 
 %!function test_divide ()
 %! state = warning ("query", "Octave:divide-by-zero").state;
@@ -259,21 +386,26 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   test_divide ();
 %! end_try_catch
 %! assert (strcmp (lasterr (), "division by zero"));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! while (1)
 %!   a = 0;
 %!   result = a / 1;
 %!   break;
 %! endwhile
 %! assert (result, 0);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! m = zeros (2, 1001);
 %! for i=1:1001
 %!   m(end, i) = i;
@@ -283,38 +415,49 @@
 %! m2(1, :) = fliplr (1:1001);
 %! m2(2, :) = 1:1001;
 %! assert (m, m2);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! m = [1 2 3];
 %! for i=1:1001
 %!   m = sin (m);
 %!   break;
 %! endfor
 %! assert (m == sin ([1  2 3]));
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! i = 0;
 %! while i < 10
 %!   i += 1;
 %! endwhile
 %! assert (i == 10);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! i = 0;
 %! while i < 10
 %!   a = ++i;
 %! endwhile
 %! assert (i == 10);
 %! assert (a == 10);
+%! jit_failure_count (0)
+
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! i = 0;
 %! while i < 10
 %!   a = i++;
 %! endwhile
 %! assert (i == 10);
 %! assert (a == 9);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! num = 2;
 %! a = zeros (1, num);
 %! i = 1;
@@ -323,6 +466,7 @@
 %!   ++i;
 %! endwhile
 %! assert (a, ones (1, num));
+%! assert (jit_failure_count, 0);
 
 %!function test_compute_idom ()
 %! while (li <= length (l1) && si <= length (s1))
@@ -337,11 +481,13 @@
 %! endwhile
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   test_compute_idom ();
 %! end_try_catch
 %! assert (! isempty (lasterr ()));
+%! assert (jit_failure_count, 0);
 
 %!function x = test_overload (a)
 %!  while (1)
@@ -351,8 +497,10 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! assert (test_overload (1), 1);
 %! assert (test_overload ([1 2]), [1 2]);
+%! assert (jit_failure_count, 0);
 
 %!function a = bubble (a = [3 2 1])
 %!  swapped = 1;
@@ -371,9 +519,12 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! assert (bubble (), [1 2 3]);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! a = 0;
 %! b = 1;
 %! for i=1:1e3
@@ -383,8 +534,10 @@
 %! endfor
 %! assert (a, 2000);
 %! assert (b, 1);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! a = [1+1i 1+2i];
 %! b = 0;
 %! while (1)
@@ -392,6 +545,7 @@
 %!   break;
 %! endwhile
 %! assert (b, a(1));
+%! assert (jit_failure_count, 0);
 
 %!function test_undef ()
 %!  for i=1:1e7
@@ -400,26 +554,32 @@
 %!endfunction
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   test_undef ();
 %! end_try_catch
 %! assert (strncmp (lasterr (), "'XXX' undefined near", 20));
+%! assert (jit_failure_count, 0);
 
 %!shared id
 %! id = @(x) x;
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! assert (id (1), 1);
 %! assert (id (1+1i), 1+1i);
 %! assert (id (1, 2), 1);
+%! assert (jit_failure_count, 0);
 
 %!testif HAVE_LLVM
+%! jit_failure_count (0)
 %! lasterr ("");
 %! try
 %!   id ();
 %! end_try_catch
 %! assert (strncmp (lasterr (), "'x' undefined near", 18));
+%! assert (jit_failure_count, 0);
 
 ## Restore JIT settings
 %!testif HAVE_LLVM
--- a/test/null-assign.tst
+++ b/test/null-assign.tst
@@ -61,3 +61,49 @@
 %!test
 %! a = ones (3); b = []; fail ("subsasgn (a, substruct ('()', {':',1:2}), b)", ".")
 
+%!test
+%! classes = {@int8, @int16, @int32, @int64, ...
+%!   @uint8, @uint16, @uint32, @uint64, ...
+%!   @single, @double, @logical};
+%! for i = 1:numel (classes)
+%!   cls = classes{i};
+%!   x = cls ([1, 2, 3]);
+%!   cls_nm = class (x);
+%!   x(2) = [];
+%!   assert (x, cls ([1, 3]));
+%!   assert (class (x), cls_nm);
+%!   x(2) = [];
+%!   assert (x, cls (1));
+%!   assert (class (x), cls_nm);
+%!   x(1) = [];
+%!   assert (x, cls (zeros (1, 0)));
+%!   assert (class (x), cls_nm);
+%! endfor
+%! for i = 1:numel (classes)
+%!   cls = classes{i};
+%!   x = cls ([1, 2, 3]);
+%!   cls_nm = class (x);
+%!   x(2) = '';
+%!   assert (x, cls ([1, 3]));
+%!   assert (class (x), cls_nm);
+%!   x(2) = '';
+%!   assert (x, cls (1));
+%!   assert (class (x), cls_nm);
+%!   x(1) = '';
+%!   assert (x, cls (zeros (1, 0)));
+%!   assert (class (x), cls_nm);
+%! endfor
+%! for i = 1:numel (classes)
+%!   cls = classes{i};
+%!   x = cls ([1, 2, 3]);
+%!   cls_nm = class (x);
+%!   x(2) = "";
+%!   assert (x, cls ([1, 3]));
+%!   assert (class (x), cls_nm);
+%!   x(2) = "";
+%!   assert (x, cls (1));
+%!   assert (class (x), cls_nm);
+%!   x(1) = "";
+%!   assert (x, cls (zeros (1, 0)));
+%!   assert (class (x), cls_nm);
+%! endfor