changeset 18226:1af5ee5f3076

maint: Periodic merge of gui-release to default.
author John W. Eaton <jwe@octave.org>
date Mon, 06 Jan 2014 14:34:56 -0500
parents cda4bd2fd0c0 (diff) 9a0f996a358a (current diff)
children 3cad99b56fa7
files configure.ac libinterp/corefcn/max.cc libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/pt-eval.cc
diffstat 180 files changed, 9504 insertions(+), 2186 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Jan 06 14:21:26 2014 -0500
+++ b/NEWS	Mon Jan 06 14:34:56 2014 -0500
@@ -1,3 +1,47 @@
+Summary of important user-visible changes for version 4.2:
+---------------------------------------------------------
+
+ ** Other new functions added in 4.2:
+
+      dir_in_loadpath
+
+ ** Deprecated functions.
+
+    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 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):
+
+      find_dir_in_path
+
+
+    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:
 ---------------------------------------------------------
 
@@ -23,7 +67,7 @@
 
  ** Other new functions added in 4.0.0:
 
-    validateattributes
+      validateattributes
 
  ** Deprecated functions.
 
--- a/build-aux/common.mk	Mon Jan 06 14:21:26 2014 -0500
+++ b/build-aux/common.mk	Mon Jan 06 14:34:56 2014 -0500
@@ -105,8 +105,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@
@@ -129,8 +127,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@
@@ -516,7 +512,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/configure.ac	Mon Jan 06 14:34:56 2014 -0500
@@ -19,7 +19,7 @@
 ### <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 PACKAGE_VERSION is set by the AC_INIT VERSION arg
 OCTAVE_VERSION="$PACKAGE_VERSION"
@@ -305,10 +305,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
@@ -355,10 +351,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.
 
--- a/doc/interpreter/func.txi	Mon Jan 06 14:21:26 2014 -0500
+++ b/doc/interpreter/func.txi	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/doc/interpreter/grammar.txi	Mon Jan 06 14:34:56 2014 -0500
@@ -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/macros.texi	Mon Jan 06 14:21:26 2014 -0500
+++ b/doc/interpreter/macros.texi	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/doc/interpreter/plot.txi	Mon Jan 06 14:34:56 2014 -0500
@@ -1226,18 +1226,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)
 
--- a/doc/interpreter/var.txi	Mon Jan 06 14:21:26 2014 -0500
+++ b/doc/interpreter/var.txi	Mon Jan 06 14:34:56 2014 -0500
@@ -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/libgui/src/m-editor/find-dialog.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libgui/src/m-editor/find-dialog.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/qtinfo/parser.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libgui/src/qtinfo/parser.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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);
--- a/libinterp/corefcn/__contourc__.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/__contourc__.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/__pchip_deriv__.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/balance.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/besselj.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/bsxfun.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/bsxfun.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/cellfun.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/data.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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 ())
@@ -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)
@@ -1836,7 +1842,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 +1856,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)
                 {
@@ -6708,7 +6714,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 ())
             {
@@ -6790,7 +6797,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 +6877,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 +6888,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 +6974,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 +7253,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);
--- a/libinterp/corefcn/dlmread.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/dlmread.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/dot.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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 ())
@@ -291,13 +293,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/eig.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/file-io.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/file-io.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/find.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
--- a/libinterp/corefcn/gcd.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/gcd.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/gl-render.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
 
@@ -441,7 +442,7 @@
     // 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))
+    if (color_mode == 2)
       {
         Matrix col = v->color;
 
@@ -458,7 +459,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);
               }
           }
       }
@@ -1002,7 +1003,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;
 
@@ -1110,7 +1112,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__"));
@@ -1209,7 +1212,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 ());
@@ -1562,7 +1566,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 ();
@@ -2332,7 +2337,38 @@
               tess.begin_polygon (true);
               tess.begin_contour ();
 
-              for (int j = 0; j < count_f(i); j++)
+              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);
+                }
+
+              // Add remaining vertices.
+              for (int j = 1; j < count_f(i); j++)
                 {
                   vertex_data::vertex_data_rep *vv = vdata[i+j*fr].get_rep ();
 
@@ -2552,7 +2588,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 ();
@@ -2610,8 +2647,9 @@
   // 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;
+  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;
--- a/libinterp/corefcn/gl2ps-renderer.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/gl2ps-renderer.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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);
@@ -222,7 +223,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/graphics.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -1012,7 +1012,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 +1027,10 @@
             retval += " | " + *it;
         }
     }
-  if (retval != "")
+
+  if (! retval.empty ())
     retval = "[ " + retval + " ]";
+
   return retval;
 }
 
@@ -1044,10 +1046,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);
@@ -2976,7 +2981,8 @@
                 }
             }
         }
-      if (retval != "")
+
+      if (! retval.empty ())
         retval += "\n";
     }
   else
@@ -2985,6 +2991,33 @@
   return retval;
 }
 
+std::string
+base_graphics_object::value_as_string (const std::string& prop)
+{
+  std::string retval;
+
+  if (valid_object ())
+    {
+      if (prop != "children")
+        {
+          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)
 {
@@ -4704,7 +4737,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 +4763,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 +4826,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 +4933,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);
 
@@ -5139,7 +5177,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 +5280,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 +5375,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)
@@ -6402,7 +6446,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++)
     {
@@ -6878,14 +6923,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 +7270,8 @@
 {
 #ifdef HAVE_FREETYPE
 
-  int halign = 0, valign = 0;
+  int halign = 0;
+  int valign = 0;
 
   if (horizontalalignment_is ("center"))
     halign = 1;
@@ -7368,9 +7414,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 +8192,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 +8396,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 +8446,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;
@@ -8706,6 +8754,29 @@
                     {
                       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 (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 +8819,7 @@
 }
 
 static std::string
-get_graphics_object_type (const double val)
+get_graphics_object_type (double val)
 {
   std::string retval;
 
@@ -9379,7 +9450,7 @@
     {
       graphics_handle h = octave_NaN;
 
-      const NDArray vals = args (0).array_value ();
+      const NDArray vals = args(0).array_value ();
 
       if (! error_state)
         {
@@ -10176,7 +10247,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/graphics.in.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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);
   }
@@ -2600,7 +2600,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);
@@ -2706,6 +2706,8 @@
 
   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
@@ -2977,6 +2979,11 @@
 
   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 (); }
@@ -5389,11 +5396,11 @@
 // ---------------------------------------------------------------------
 
 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);
 
 // ---------------------------------------------------------------------
 
@@ -5864,12 +5871,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/help.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -1075,7 +1075,7 @@
 
   if (args.length () == 1)
     {
-      const std::string name = args (0).string_value ();
+      const std::string name = args(0).string_value ();
 
       if (! error_state)
         {
@@ -1364,7 +1364,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/kron.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/kron.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/load-path.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/load-path.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/load-save.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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++)
     {
--- a/libinterp/corefcn/lookup.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/lookup.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/ls-hdf5.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -738,7 +738,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 +866,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-mat5.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/ls-mat5.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -929,7 +929,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 +958,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 +983,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)
                       {
@@ -1560,7 +1560,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);
--- a/libinterp/corefcn/lu.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/lu.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -158,7 +158,7 @@
   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 ();
 
@@ -588,7 +588,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/mappers.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/mappers.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/matrix_type.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/max.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/oct-map.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/oct-map.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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)
--- a/libinterp/corefcn/oct-obj.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/oct-obj.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/oct-obj.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/oct-stream.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -1053,7 +1053,8 @@
     {
       std::istream& is = *isp;
 
-      int c = 0, lastc = -1;
+      int c = 0;
+      int lastc = -1;
       cnt = 0;
 
       while (is && (c = is.get ()) != EOF)
@@ -2357,15 +2358,15 @@
   return retval;
 }
 
-#define DO_DOUBLE_CONV(TQUAL) \
+#define DO_DOUBLE_CONV_1(TYPE) \
   do \
     { \
-      if (val > std::numeric_limits<TQUAL long>::max () \
-          || val < std::numeric_limits<TQUAL long>::min ()) \
+      if (val > std::numeric_limits<TYPE>::max () \
+          || val < std::numeric_limits<TYPE>::min ()) \
         { \
           std::string tfmt = fmt; \
  \
-          tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \
+          tfmt.replace (tfmt.rfind (elt->type), 1, ".g"); \
  \
           if (elt->modifier == 'l') \
             tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \
@@ -2375,7 +2376,17 @@
         } \
       else \
         retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \
-                                  static_cast<TQUAL long> (val), who); \
+                                  static_cast<TYPE> (val), who); \
+    } \
+  while (0)
+
+#define DO_DOUBLE_CONV(TQUAL) \
+  do \
+    { \
+       if (elt->modifier == 'l') \
+         DO_DOUBLE_CONV_1 (TQUAL long); \
+       else \
+         DO_DOUBLE_CONV_1 (TQUAL int); \
     } \
   while (0)
 
@@ -2478,15 +2489,19 @@
 
                           const char *tval;
                           if (xisinf (val))
-                            if (elt->flags.find ('+') != std::string::npos)
-                              tval = (val < 0 ? "-Inf" : "+Inf");
-                            else
-                              tval = (val < 0 ? "-Inf" : "Inf");
+                            {
+                              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");
+                            {
+                              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,
--- a/libinterp/corefcn/pr-output.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/pr-output.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -3542,7 +3542,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");
 
--- a/libinterp/corefcn/pt-jit.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/pt-jit.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -683,6 +683,12 @@
 }
 
 void
+jit_convert::visit_funcall (tree_funcall&)
+{
+  throw jit_fail_exception ();
+}
+
+void
 jit_convert::visit_parameter_list (tree_parameter_list&)
 {
   throw jit_fail_exception ();
--- a/libinterp/corefcn/pt-jit.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/pt-jit.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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/sparse.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/sparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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 ())
@@ -125,7 +125,8 @@
     }
   else if (nargin == 2)
     {
-      octave_idx_type m = 0, n = 0;
+      octave_idx_type m = 0;
+      octave_idx_type n = 0;
       if (args(0).is_scalar_type () && args(1).is_scalar_type ())
         {
           m = args(0).idx_type_value ();
@@ -160,7 +161,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/sqrtm.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/str2double.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/strfind.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/strfns.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/symtab.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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"
@@ -383,11 +384,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 +399,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 +434,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 +825,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 +1020,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 +1043,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 +1059,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 +1135,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/symtab.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/syscalls.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/toplev.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -1251,8 +1251,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 },
@@ -1275,8 +1273,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/tril.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/tril.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/txt-eng-ft.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/utils.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/utils.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/variables.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
--- a/libinterp/corefcn/xdiv.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/corefcn/xdiv.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/dldfcn/__delaunayn__.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/qr.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/dldfcn/qr.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/dldfcn/symrcm.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/dldfcn/tsearch.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/octave-value/module.mk	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/module.mk	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-base-diag.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -441,7 +441,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)
--- a/libinterp/octave-value/ov-base-int.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-base-int.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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-mat.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-base-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
--- a/libinterp/octave-value/ov-base-sparse.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-base-sparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -440,27 +440,55 @@
 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-bool-mat.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-bool-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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-sparse.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
--- a/libinterp/octave-value/ov-bool.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-bool.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-cell.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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-class.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-class.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -1279,7 +1279,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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -0,0 +1,3608 @@
+/*
+
+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 "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
+check_access (const cdef_class& cls, const octave_value& acc)
+{
+  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")
+            return is_superclass (cls, ctx);
+          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;
+}
+
+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);
+
+  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;
+
+  // FIXME: should check "subsref" method first
+
+  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;
+
+  // FIXME: should check "subsref" method first
+  // ? not sure this still applied with auto_add version of subsref
+
+  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)
+{
+  // FIXME: should check "subsasgn" method first
+
+  return object.subsasgn (type, idx, rhs);
+}
+
+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 ();
+}
+
+//----------------------------------------------------------------------------
+
+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); }
+
+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_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 pname = args(1).string_value ();
+          std::string cname = args(2).string_value ();
+
+          std::string cls_name = (pname.empty () ?
+                                  cname : pname + "." + cname);
+          cdef_class cls = lookup_class (cls_name);
+
+          if (! error_state)
+            {
+              if (in_constructor)
+                {
+                  if (is_direct_superclass (cls, ctx))
+                    {
+                      if (is_constructed_object (mname))
+                        {
+                          octave_value& sym = symbol_table::varref (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'",
+                             cls_name.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 (), cls_name.c_str ());
+                        }
+                      else
+                        ::error ("`%s' is not a superclass of `%s'",
+                                 cls_name.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 package_name = args(1).string_value ();
+                      std::string class_name = args(2).string_value ();
+
+                      std::string ctor_name = (package_name.empty ()
+                                               ? class_name
+                                               : package_name + "." + class_name);
+
+                      cdef_class cls = lookup_class (ctor_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)
+{
+  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)->package () ? (*it)->package ()->name () + "." : std::string ())
+            + (*it)->ident ()->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);
+                    }
+                }
+            }
+        }
+
+      // 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 ())
+                    {
+                      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 ())
+                    {
+                      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"));
+
+  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"));
+
+  return false;
+}
+
+void
+cdef_method::cdef_method_rep::check_method (void)
+{
+  // FIXME: check whether re-load is needed
+}
+
+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 (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 ();
+
+      octave_value_list new_args;
+
+      if (function.is_defined ())
+	{
+	  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"));
+
+  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)
+                        {
+                          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
+                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 () << ", "
+            << args(1).string_value () << ")"
+            << std::endl;
+
+  if (args.length () == 2)
+    {
+      std::string pkg = args(0).string_value ();
+      std::string cls = args(1).string_value ();
+
+      if (! pkg.empty ())
+        cls = pkg + "." + cls;
+
+      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: ***
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-classdef.h	Mon Jan 06 14:34:56 2014 -0500
@@ -0,0 +1,1653 @@
+/*
+
+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_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);
+
+  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 () { }
+
+    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;
+
+    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) { }
+
+    void check_method (void);
+
+    cdef_method wrap (void)
+      {
+        refcount++;
+        return cdef_method (this);
+      }
+
+  private:
+    octave_value function;
+  };
+
+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 (); }
+
+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 print_as_scalar (void) const { return true; }
+
+  void print(std::ostream& os, bool pr_as_read_syntax = false) const
+    {
+      // FIXME: should call "display" method
+      print_raw(os, pr_as_read_syntax);
+      newline(os);
+    }
+
+  void print_raw(std::ostream& os, bool /* pr_as_read_syntax */ = false) const
+    {
+      if (object.is_array ())
+        os << "array (" << object.dims ().str () << ") of "
+          << object.class_name () << " objects";
+      else
+        os << object.class_name () << " object";
+    }
+
+  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
+    {
+      warning ("trying to cast non-object into object");
+      return cdef_object ();
+    }
+}
+
+inline cdef_object&
+to_cdef_ref (octave_value& val)
+{
+  static cdef_object empty;
+
+  if (val.type_name () == "object")
+    return dynamic_cast<octave_classdef *> (val.internal_rep ())->get_object_ref ();
+  else
+    {
+      warning ("trying to cast non-object into object");
+      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-complex.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-complex.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-cx-diag.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-cx-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
--- a/libinterp/octave-value/ov-fcn-handle.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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);
--- a/libinterp/octave-value/ov-fcn-inline.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -291,7 +291,8 @@
     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,
--- a/libinterp/octave-value/ov-fcn.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-fcn.h	Mon Jan 06 14:34:56 2014 -0500
@@ -85,6 +85,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; }
 
@@ -160,6 +164,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,
--- a/libinterp/octave-value/ov-float.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-float.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-flt-complex.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-flt-cx-diag.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-flt-re-diag.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-intx.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-java.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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)
                 {
--- a/libinterp/octave-value/ov-range.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-range.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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);
--- a/libinterp/octave-value/ov-re-diag.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-re-diag.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-re-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-re-sparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-scalar.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-str-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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-usr-fcn.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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
@@ -470,7 +470,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 +481,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 +541,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.
@@ -743,7 +779,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave-value/ov.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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"
--- a/libinterp/octave.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/octave.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/operators/op-b-b.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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-int.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/operators/op-int.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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/parse-tree/lex.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/lex.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
--- a/libinterp/parse-tree/lex.ll	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/lex.ll	Mon Jan 06 14:34:56 2014 -0500
@@ -1169,7 +1169,7 @@
           {
             curr_lexer->looking_for_object_index = true;
 
-            return curr_lexer->count_token_internal (SUPERCLASSREF);
+            return curr_lexer->count_token_internal (id_tok);
           }
       }
   }
@@ -1196,7 +1196,7 @@
           {
             curr_lexer->looking_for_object_index = true;
 
-            return curr_lexer->count_token_internal (METAQUERY);
+            return curr_lexer->count_token_internal (id_tok);
           }
       }
   }
@@ -1926,8 +1926,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;
@@ -2327,20 +2329,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;
@@ -2696,36 +2684,30 @@
 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);
-
+  std::string cls = meth.substr (pos + 1);
+  meth = meth.substr (0, pos);
+
+  std::string pkg;
   pos = cls.find (".");
   if (pos != std::string::npos)
     {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
+      pkg = cls.substr (0, pos);
+      cls = cls.substr (pos + 1);
     }
 
   int kw_token = (is_keyword_token (meth) || is_keyword_token (cls)
                   || is_keyword_token (pkg));
   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, pkg, cls,
+                         input_line_number, current_input_column));
 
   current_input_column += flex_yyleng ();
 
@@ -2735,31 +2717,25 @@
 int
 octave_base_lexer::handle_meta_identifier (void)
 {
+  std::string cls = std::string(flex_yytext ()).substr (1);
+
   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)
     {
-      pkg = cls.substr (pos).substr (1);
-      cls = cls.substr (0, pos - 1);
+      pkg = cls.substr (0, pos);
+      cls = cls.substr (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, pkg, cls, input_line_number,
+                         current_input_column));
 
   current_input_column += flex_yyleng ();
 
--- a/libinterp/parse-tree/module.mk	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/module.mk	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/oct-parse.in.yy	Mon Jan 06 14:34:56 2014 -0500
@@ -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,6 +231,7 @@
 %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
@@ -218,13 +240,12 @@
 
 // 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 +257,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 +279,25 @@
 %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
 
 // 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
@@ -439,11 +461,26 @@
 
 superclass_identifier
                 : SUPERCLASSREF
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string method_nm = $1->superclass_method_name ();
+                    std::string package_nm = $1->superclass_package_name ();
+                    std::string class_nm = $1->superclass_class_name ();
+
+                    $$ = parser.make_superclass_ref
+                                       (method_nm, package_nm, class_nm,
+                                        $1->line (), $1->column ());
+                  }
                 ;
 
 meta_identifier : METAQUERY
-                  { $$ = new tree_identifier ($1->line (), $1->column ()); }
+                  {
+                    std::string package_nm = $1->meta_package_name ();
+                    std::string class_nm = $1->meta_class_name ();
+
+                    $$ = parser.make_meta_class_query
+                                       (package_nm, class_nm,
+                                        $1->line (), $1->column ());
+                  }
                 ;
 
 string          : DQ_STRING
@@ -867,8 +904,6 @@
                   { $$ = $1; }
                 | file
                   { $$ = $1; }
-                | classdef
-                  { $$ = $1; }
                 ;
 
 // =====================
@@ -1294,6 +1329,13 @@
 
                     $$ = 0;
                   }
+                | INPUT_FILE opt_nl classdef opt_sep END_OF_INPUT
+                  {
+                    if (lexer.reading_classdef_file)
+                      parser.classdef_object = $3;
+
+                    $$ = 0;
+                  }
                 ;
 
 // ===================
@@ -1336,12 +1378,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 +1396,11 @@
 
                     delete $1;
 
+                    if (lexer.parsing_classdef_get_method)
+                      fname.insert (0, "get.");
+                    else if (lexer.parsing_classdef_set_method)
+                      fname.insert (0, "set.");
+
                     $$ = parser.frob_function (fname, $2);
                   }
                 ;
@@ -1411,158 +1460,217 @@
 // 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; }
-                ;
-
 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 superclass
+                  { $$ = new tree_classdef_superclass_list ($2); }
+                | superclass_list EXPR_AND superclass
+                  {
+                    $1->append ($3);
+                    $$ = $1;
+                  }
+                ;
+
+superclass      : identifier
+                  { $$ = new tree_classdef_superclass ($1); }
+                | identifier '.' identifier
+                  { $$ = new tree_classdef_superclass ($3, $1); }
                 ;
 
 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_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_beg opt_attr_list opt_sep methods_list opt_sep END
-                  { $$ = 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_list    : function
-                  { $$ = 0; }
+                  {
+                    octave_value fcn;
+                    if ($1)
+                      fcn = $1->function ();
+                    delete $1;
+                    $$ = new tree_classdef_methods_list (fcn);
+                  }
                 | methods_list opt_sep function
-                  { $$ = 0; }
+                  {
+                    octave_value fcn;
+                    if ($3)
+                      fcn = $3->function ();
+                    delete $3;
+
+                    $1->append (fcn);
+                    $$ = $1;
+                  }
                 ;
 
-events_beg      : EVENTS stash_comment
-                  { $$ = 0; }
-                ;
-
-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_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;
+                      }
+                  }
                 ;
 
 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 +1768,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 +1940,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 +1995,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 +2207,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 +2236,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 +2277,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 +2314,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 +3008,197 @@
   lexer.looking_at_parameter_list = false;
 }
 
+tree_funcall *
+octave_base_parser::make_superclass_ref (const std::string& method_nm,
+                                         const std::string& package_nm,
+                                         const std::string& class_nm,
+                                         int l, int c)
+{
+  octave_value_list args;
+
+  args(2) = class_nm;
+  args(1) = package_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& package_nm,
+                                           const std::string& class_nm,
+                                           int l, int c)
+{
+  octave_value_list args;
+
+  args(1) = class_nm;
+  args(0) = package_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 ();
+
+      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 ();
+
+      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 ();
+
+      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 ();
+
+      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 ();
+
+      retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
+    }
+  else
+    {
+      delete a;
+      delete elist;
+    }
+
+  return retval;
+}
+
 // Make an index expression.
 
 tree_index_expression *
@@ -3024,7 +3221,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 +3249,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 +3271,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 +3669,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 +3703,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 +3718,34 @@
 
       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 ();
+
+              fcn_ptr = parser.classdef_object->make_meta_class ();
+            }
+          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 +3786,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 +3851,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 +3899,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,8 +3912,8 @@
     }
   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)
@@ -3903,7 +4127,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)
@@ -4626,7 +4850,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/octave.gperf	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/parse.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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,47 @@
   void
   recover_from_parsing_function (void);
 
+  tree_funcall *
+  make_superclass_ref (const std::string& method_nm,
+                       const std::string& package_nm,
+                       const std::string& class_nm,
+                       int l, int c);
+
+  tree_funcall *
+  make_meta_class_query (const std::string& package_nm,
+                         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);
+
   // Make an index expression.
   tree_index_expression *
   make_index_expression (tree_expression *expr,
@@ -372,6 +427,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 +444,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-all.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-bp.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-bp.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-cbinop.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-check.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-check.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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&);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-classdef.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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 (void)
+{
+  octave_value retval;
+  cdef_class cls = cdef_class::make_meta_class (this);
+
+  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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-classdef.h	Mon Jan 06 14:34:56 2014 -0500
@@ -0,0 +1,660 @@
+/*
+
+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 (tree_identifier *i = 0, tree_identifier *p = 0)
+    : id (i), pkg (p) { }
+
+  ~tree_classdef_superclass (void)
+  {
+    delete id;
+    delete pkg;
+  }
+
+  tree_identifier *ident (void) { return id; }
+
+  tree_identifier * package (void) { return pkg; }
+
+  void accept (tree_walker&);
+
+private:
+
+  tree_identifier *id;
+  tree_identifier *pkg;
+
+  // 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 (void);
+
+  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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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 ();
--- a/libinterp/parse-tree/pt-eval.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-eval.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-exp.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-funcall.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -0,0 +1,83 @@
+/*
+
+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 context) 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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-funcall.h	Mon Jan 06 14:34:56 2014 -0500
@@ -0,0 +1,101 @@
+/*
+
+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)
+  {
+    return feval (fcn.function_value (), args, 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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-id.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-id.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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-mat.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-mat.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-pr-code.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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 ();
--- a/libinterp/parse-tree/pt-pr-code.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-pr-code.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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-walk.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/pt-walk.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/token.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -97,38 +97,50 @@
   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& pkg, 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_name_token;
+  mc.package_nm = new std::string (pkg);
+  mc.class_nm = new std::string (cls);
+}
+
+token::token (int tv, const std::string& mth, const std::string& pkg,
+              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.package_nm = new std::string (pkg);
+  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.package_nm;
+      delete sc.class_nm;
+    }
+
+  if (type_tag == meta_name_token)
+    {
+      delete mc.package_nm;
+      delete mc.class_nm;
+    }
 }
 
 std::string
@@ -172,39 +184,39 @@
   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;
+  assert (type_tag == scls_name_token);
+  return *sc.method_nm;
 }
 
-symbol_table::symbol_record *
-token::class_rec (void)
+std::string
+token::superclass_package_name (void)
 {
-  assert (type_tag == scls_rec_token);
-  return sc.cr;
+  assert (type_tag == scls_name_token);
+  return *sc.package_nm;
 }
 
-symbol_table::symbol_record *
-token::package_rec (void)
+std::string
+token::superclass_class_name (void)
 {
-  assert (type_tag == scls_rec_token);
-  return sc.pr;
+  assert (type_tag == scls_name_token);
+  return *sc.class_nm;
 }
 
-symbol_table::symbol_record *
-token::meta_class_rec (void)
+std::string
+token::meta_package_name (void)
 {
-  assert (type_tag == meta_rec_token);
-  return mc.cr;
+  assert (type_tag == meta_name_token);
+  return *mc.package_nm;
 }
 
-symbol_table::symbol_record *
-token::meta_package_rec (void)
+std::string
+token::meta_class_name (void)
 {
-  assert (type_tag == meta_rec_token);
-  return mc.pr;
+  assert (type_tag == meta_name_token);
+  return *mc.class_nm;
 }
 
 std::string
--- a/libinterp/parse-tree/token.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/libinterp/parse-tree/token.h	Mon Jan 06 14:34:56 2014 -0500
@@ -40,8 +40,8 @@
     double_token,
     ettype_token,
     sym_rec_token,
-    scls_rec_token,
-    meta_rec_token
+    scls_name_token,
+    meta_name_token
   };
 
   enum end_tok_type
@@ -69,11 +69,10 @@
          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& pkg, const std::string& cls,
+         int l = -1, int c = -1);
+  token (int tv, const std::string& mth, const std::string& pkg,
+         const std::string& cls, int l = -1, int c = -1);
 
   ~token (void);
 
@@ -106,12 +105,12 @@
   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);
+  std::string superclass_method_name (void);
+  std::string superclass_package_name (void);
+  std::string superclass_class_name (void);
 
-  symbol_table::symbol_record *meta_class_rec (void);
-  symbol_table::symbol_record *meta_package_rec (void);
+  std::string meta_package_name (void);
+  std::string meta_class_name (void);
 
   std::string text_rep (void);
 
@@ -137,14 +136,14 @@
     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 *package_nm;
+      std::string *class_nm;
     } sc;
     struct
     {
-      symbol_table::symbol_record *cr;
-      symbol_table::symbol_record *pr;
+      std::string *package_nm;
+      std::string *class_nm;
     } mc;
   };
   std::string orig_text;
--- a/liboctave/array/Array.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/liboctave/array/Array.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/CSparse.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/liboctave/array/CSparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -7688,87 +7688,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 +7806,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	Mon Jan 06 14:21:26 2014 -0500
+++ b/liboctave/array/DiagArray2.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -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/Sparse.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/liboctave/array/Sparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -2490,9 +2490,8 @@
                 }
             }
         }
-      else
-        (*current_liboctave_error_handler)
-          ("diag: requested diagonal out of range");
+      else  // Matlab returns [] 0x1 for out-of-range diagonal
+        d = Sparse<T> (0, 1, 0);
     }
   else if (nnr != 0 && nnc != 0)
     {
--- a/liboctave/array/dSparse.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/liboctave/array/dSparse.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -7801,84 +7801,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 +7952,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/operators/mx-inlines.cc	Mon Jan 06 14:21:26 2014 -0500
+++ b/liboctave/operators/mx-inlines.cc	Mon Jan 06 14:34:56 2014 -0500
@@ -1345,8 +1345,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/util/base-list.h	Mon Jan 06 14:21:26 2014 -0500
+++ b/liboctave/util/base-list.h	Mon Jan 06 14:34:56 2014 -0500
@@ -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/scripts/deprecated/default_save_options.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/deprecated/find_dir_in_path.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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
+
--- a/scripts/deprecated/gen_doc_cache.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/interp1q.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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]));
-
--- a/scripts/deprecated/isequalwithequalnans.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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)
-
--- a/scripts/deprecated/java_convert_matrix.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/java_debug.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/java_get.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/java_invoke.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/java_set.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/java_unsigned_conversion.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/javafields.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/javamethods.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/deprecated/module.mk	Mon Jan 06 14:34:56 2014 -0500
@@ -1,23 +1,8 @@
 FCN_FILE_DIRS += deprecated
 
 deprecated_FCN_FILES = \
-  deprecated/default_save_options.m \
-  deprecated/gen_doc_cache.m \
-  deprecated/interp1q.m \
-  deprecated/isequalwithequalnans.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/find_dir_in_path.m \
+  deprecated/isstr.m
 
 FCN_FILES += $(deprecated_FCN_FILES)
 
--- a/scripts/deprecated/re_read_readline_init_file.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/read_readline_init_file.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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
-
--- a/scripts/deprecated/saving_history.m	Mon Jan 06 14:21:26 2014 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/general/cell2mat.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/geometry/voronoi.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/geometry/voronoi.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/help.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/help/help.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/image/private/__imread__.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/image/private/__imread__.m	Mon Jan 06 14:34:56 2014 -0500
@@ -90,114 +90,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__ (fn, 1);
+  else
+    info = __magick_ping__ (fn, 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__ (fn, options);
 
 endfunction
 
@@ -205,10 +153,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/miscellaneous/inputname.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/miscellaneous/inputname.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/miscellaneous/ls.m	Mon Jan 06 14:34:56 2014 -0500
@@ -60,7 +60,16 @@
 
   if (nargin > 0)
     args = tilde_expand (varargin);
-    if (ispc () && ! isunix ())
+    is_dos = (ispc () && ! isunix ());
+    if (is_dos)
+      optsep = "/";
+    else
+      optsep = "-";
+    endif
+    idx = ! strncmp (args, optsep, 1);
+    ## Enclose paths, potentially having spaces, in double quotes:
+    args(idx) = strcat ('"', args(idx), '"');    
+    if (is_dos)
       ## 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.
--- a/scripts/miscellaneous/mex.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/miscellaneous/mex.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/what.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/miscellaneous/what.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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
--- a/scripts/optimization/fzero.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/optimization/fzero.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/plot/draw/private/__scatter__.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/plot/draw/private/__scatter__.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/sparse/spdiags.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/sparse/spdiags.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/statistics/base/prctile.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/statistics/base/prctile.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/quantile.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/statistics/base/quantile.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/statistics/distributions/empirical_pdf.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/testfun/__run_test_suite__.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/testfun/__run_test_suite__.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/rundemos.m	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/testfun/rundemos.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/testfun/runtests.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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	Mon Jan 06 14:21:26 2014 -0500
+++ b/scripts/testfun/test.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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/test/Makefile.am	Mon Jan 06 14:21:26 2014 -0500
+++ b/test/Makefile.am	Mon Jan 06 14:34:56 2014 -0500
@@ -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
--- a/test/build-sparse-tests.sh	Mon Jan 06 14:21:26 2014 -0500
+++ b/test/build-sparse-tests.sh	Mon Jan 06 14:34:56 2014 -0500
@@ -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");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/classdef.tst	Mon Jan 06 14:34:56 2014 -0500
@@ -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])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/foo_method_changes_property_size.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/foo_static_method_constant_property.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/foo_value_class.m	Mon Jan 06 14:34:56 2014 -0500
@@ -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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classdef/module.mk	Mon Jan 06 14:34:56 2014 -0500
@@ -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)
--- a/test/null-assign.tst	Mon Jan 06 14:21:26 2014 -0500
+++ b/test/null-assign.tst	Mon Jan 06 14:34:56 2014 -0500
@@ -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